Tue, 28 Mar 2017 06:08:41 -0400
[C2] Add patchable_jump for MIPS.
1.1 --- a/src/cpu/mips/vm/compiledIC_mips.cpp Wed Mar 22 11:43:05 2017 -0400 1.2 +++ b/src/cpu/mips/vm/compiledIC_mips.cpp Tue Mar 28 06:08:41 2017 -0400 1.3 @@ -109,9 +109,7 @@ 1.4 1.5 cbuf.set_insts_mark(); 1.6 address call_pc = (address)-1; 1.7 - __ patchable_set48(AT, (long)call_pc); 1.8 - __ jr(AT); 1.9 - __ nop(); 1.10 + __ patchable_jump(call_pc); 1.11 __ align(16); 1.12 __ end_a_stub(); 1.13 // Update current stubs pointer and restore code_end.
2.1 --- a/src/cpu/mips/vm/icBuffer_mips.cpp Wed Mar 22 11:43:05 2017 -0400 2.2 +++ b/src/cpu/mips/vm/icBuffer_mips.cpp Tue Mar 28 06:08:41 2017 -0400 2.3 @@ -63,13 +63,13 @@ 2.4 2.5 __ lui(T9, Assembler::split_high((int)entry_point)); 2.6 __ addiu(T9, T9, Assembler::split_low((int)entry_point)); 2.7 + __ jr(T9); 2.8 + __ delayed()->nop(); 2.9 #else 2.10 __ patchable_set48(T1, (long)cached_value); 2.11 2.12 - __ patchable_set48(T9, (long)entry_point); 2.13 + __ patchable_jump(entry_point); 2.14 #endif 2.15 - __ jr(T9); 2.16 - __ delayed()->nop(); 2.17 __ flush(); 2.18 #undef __ 2.19 }
3.1 --- a/src/cpu/mips/vm/icache_mips.cpp Wed Mar 22 11:43:05 2017 -0400 3.2 +++ b/src/cpu/mips/vm/icache_mips.cpp Tue Mar 28 06:08:41 2017 -0400 3.3 @@ -40,34 +40,18 @@ 3.4 void ICacheStubGenerator::generate_icache_flush(ICache::flush_icache_stub_t* flush_icache_stub) {}; 3.5 3.6 void ICache::call_flush_stub(address start, int lines) { 3.7 - //in fact, the current os implementation simply flush all ICACHE&DCACHE 3.8 -#ifndef CACHE_OPT 3.9 - /* Loongson3A supports automatic synchronization between Icache and Dcache. 3.10 - * No manual synchronization is needed. */ 3.11 - cacheflush(start, lines * line_size , ICACHE); 3.12 -#endif 3.13 -// sysmips(3, 0, 0, 0); 3.14 + cacheflush(start, lines * line_size , ICACHE); 3.15 } 3.16 3.17 void ICache::invalidate_word(address addr) { 3.18 - //cacheflush(addr, 4, ICACHE); 3.19 - 3.20 -#ifndef CACHE_OPT 3.21 - cacheflush(addr,4, ICACHE); 3.22 -#endif 3.23 -// sysmips(3, 0, 0, 0); 3.24 + cacheflush(addr,4, ICACHE); 3.25 } 3.26 3.27 void ICache::invalidate_range(address start, int nbytes) { 3.28 -#ifndef CACHE_OPT 3.29 - cacheflush(start, nbytes, ICACHE); 3.30 -#endif 3.31 -// sysmips(3, 0, 0, 0); 3.32 + cacheflush(start, nbytes, ICACHE); 3.33 } 3.34 3.35 void ICache::invalidate_all() { 3.36 -#ifndef CACHE_OPT 3.37 - sysmips(3, 0, 0, 0); 3.38 -#endif 3.39 + sysmips(3, 0, 0, 0); 3.40 } 3.41
4.1 --- a/src/cpu/mips/vm/mips_64.ad Wed Mar 22 11:43:05 2017 -0400 4.2 +++ b/src/cpu/mips/vm/mips_64.ad Tue Mar 28 06:08:41 2017 -0400 4.3 @@ -536,18 +536,6 @@ 4.4 // Emit exception handler code. 4.5 // Stuff framesize into a register and call a VM stub routine. 4.6 int HandlerImpl::emit_exception_handler(CodeBuffer& cbuf) { 4.7 -/* 4.8 - // Note that the code buffer's insts_mark is always relative to insts. 4.9 - // That's why we must use the macroassembler to generate a handler. 4.10 - MacroAssembler _masm(&cbuf); 4.11 - address base = __ start_a_stub(size_exception_handler()); 4.12 - if (base == NULL) return 0; // CodeBuffer::expand failed 4.13 - int offset = __ offset(); 4.14 - __ jump(RuntimeAddress(OptoRuntime::exception_blob()->entry_point())); 4.15 - assert(__ offset() - offset <= (int) size_exception_handler(), "overflow"); 4.16 - __ end_a_stub(); 4.17 - return offset; 4.18 -*/ 4.19 // Note that the code buffer's insts_mark is always relative to insts. 4.20 // That's why we must use the macroassembler to generate a handler. 4.21 MacroAssembler _masm(&cbuf); 4.22 @@ -558,24 +546,9 @@ 4.23 4.24 __ block_comment("; emit_exception_handler"); 4.25 4.26 - /* 2012/9/25 FIXME Jin: According to X86, we should use direct jumpt. 4.27 - * * However, this will trigger an assert after the 40th method: 4.28 - * * 4.29 - * * 39 b java.lang.Throwable::<init> (25 bytes) 4.30 - * * --- ns java.lang.Throwable::fillInStackTrace 4.31 - * * 40 !b java.net.URLClassLoader::findClass (29 bytes) 4.32 - * * /vm/opto/runtime.cpp, 900 , assert(caller.is_compiled_frame(),"must be") 4.33 - * * 40 made not entrant (2) java.net.URLClassLoader::findClass (29 bytes) 4.34 - * * 4.35 - * * If we change from JR to JALR, the assert will disappear, but WebClient will 4.36 - * * fail after the 403th method with unknown reason. 4.37 - * */ 4.38 cbuf.set_insts_mark(); 4.39 __ relocate(relocInfo::runtime_call_type); 4.40 - 4.41 - __ patchable_set48(T9, (long)OptoRuntime::exception_blob()->entry_point()); 4.42 - __ jr(T9); 4.43 - __ delayed()->nop(); 4.44 + __ patchable_jump((address)OptoRuntime::exception_blob()->entry_point()); 4.45 __ align(16); 4.46 assert(__ offset() - offset <= (int) size_exception_handler(), "overflow"); 4.47 __ end_a_stub(); 4.48 @@ -598,10 +571,7 @@ 4.49 4.50 cbuf.set_insts_mark(); 4.51 __ relocate(relocInfo::runtime_call_type); 4.52 - 4.53 - __ patchable_set48(T9, (long)SharedRuntime::deopt_blob()->unpack()); 4.54 - __ jalr(T9); 4.55 - __ delayed()->nop(); 4.56 + __ patchable_call(SharedRuntime::deopt_blob()->unpack()); 4.57 __ align(16); 4.58 assert(__ offset() - offset <= (int) size_deopt_handler(), "overflow"); 4.59 __ end_a_stub(); 4.60 @@ -651,13 +621,6 @@ 4.61 4.62 __ relocate(static_stub_Relocation::spec(mark), 0); 4.63 4.64 - /* 2012/10/29 Jin: Rmethod contains methodOop, it should be relocated for GC */ 4.65 -/* 4.66 - int oop_index = __ oop_recorder()->allocate_index(NULL); 4.67 - RelocationHolder rspec = oop_Relocation::spec(oop_index); 4.68 - __ relocate(rspec); 4.69 -*/ 4.70 - 4.71 // static stub relocation also tags the methodOop in the code-stream. 4.72 __ patchable_set48(S3, (long)0); 4.73 // This is recognized as unresolved by relocs/nativeInst/ic code 4.74 @@ -666,9 +629,7 @@ 4.75 4.76 cbuf.set_insts_mark(); 4.77 address call_pc = (address)-1; 4.78 - __ patchable_set48(AT, (long)call_pc); 4.79 - __ jr(AT); 4.80 - __ nop(); 4.81 + __ patchable_jump(call_pc); 4.82 __ align(16); 4.83 __ end_a_stub(); 4.84 // Update current stubs pointer and restore code_end. 4.85 @@ -1574,9 +1535,7 @@ 4.86 __ nop(); 4.87 4.88 __ relocate(relocInfo::runtime_call_type); 4.89 - __ patchable_set48(T9, (long)SharedRuntime::get_ic_miss_stub()); 4.90 - __ jr(T9); 4.91 - __ nop(); 4.92 + __ patchable_jump((address)SharedRuntime::get_ic_miss_stub()); 4.93 4.94 /* WARNING these NOPs are critical so that verified entry point is properly 4.95 * 8 bytes aligned for patching by NativeJump::patch_verified_entry() */ 4.96 @@ -5388,9 +5347,7 @@ 4.97 cbuf.relocate(cbuf.insts_mark(), runtime_call_Relocation::spec()); 4.98 4.99 // call OptoRuntime::rethrow_stub to get the exception handler in parent method 4.100 - __ patchable_set48(T9, (jlong)OptoRuntime::rethrow_stub()); 4.101 - __ jr(T9); 4.102 - __ nop(); 4.103 + __ patchable_jump((address)OptoRuntime::rethrow_stub()); 4.104 %} 4.105 ins_pipe( pipe_jump ); 4.106 %}
5.1 --- a/src/cpu/mips/vm/nativeInst_mips.cpp Wed Mar 22 11:43:05 2017 -0400 5.2 +++ b/src/cpu/mips/vm/nativeInst_mips.cpp Tue Mar 28 06:08:41 2017 -0400 5.3 @@ -45,7 +45,11 @@ 5.4 void NativeInstruction::set_long_at(int offset, long i) { 5.5 address addr = addr_at(offset); 5.6 *(long*)addr = i; 5.7 - //ICache::invalidate_word(addr); 5.8 +#ifdef _LP64 5.9 + ICache::invalidate_range(addr, 8); 5.10 +#else 5.11 + ICache::invalidate_word(addr); 5.12 +#endif 5.13 } 5.14 5.15 static int illegal_instruction_bits = 0; 5.16 @@ -445,12 +449,10 @@ 5.17 5.18 void NativeCall::patch_on_jalr_gs(address dst) { 5.19 patch_set48_gs(dst); 5.20 - ICache::invalidate_range(addr_at(0), 16); 5.21 } 5.22 5.23 void NativeCall::patch_on_jalr(address dst) { 5.24 patch_set48(dst); 5.25 - ICache::invalidate_range(addr_at(0), 16); 5.26 } 5.27 5.28 void NativeCall::patch_set48_gs(address dest) { 5.29 @@ -532,6 +534,8 @@ 5.30 5.31 atomic_store128_ptr func = get_atomic_store128_func(); 5.32 (*func)((long *)addr_at(0), 0, *(long *)&insts[0], *(long *)&insts[2]); 5.33 + 5.34 + ICache::invalidate_range(addr_at(0), 16); 5.35 } 5.36 5.37 void NativeCall::patch_set32_gs(address dest) { 5.38 @@ -649,6 +653,8 @@ 5.39 //nop(); 5.40 set_int_at(count << 2, 0); 5.41 } 5.42 + 5.43 + ICache::invalidate_range(addr_at(0), 16); 5.44 } 5.45 5.46 void NativeCall::patch_set32(address dest) { 5.47 @@ -1131,6 +1137,89 @@ 5.48 ((NativeInstruction *)this)->is_cond_jump(), "not a general jump instruction"); 5.49 } 5.50 5.51 +void NativeGeneralJump::patch_set48_gs(address dest) { 5.52 + jlong value = (jlong) dest; 5.53 + int rt_reg = (int_at(0) & (0x1f << 16)); 5.54 + 5.55 + if (rt_reg == 0) rt_reg = 25 << 16; // r25 is T9 5.56 + 5.57 + int rs_reg = rt_reg << 5; 5.58 + int rd_reg = rt_reg >> 5; 5.59 + 5.60 + int hi = (int)(value >> 32); 5.61 + int lo = (int)(value & ~0); 5.62 + 5.63 + int count = 0; 5.64 + 5.65 + int insts[4] = {0, 0, 0, 0}; 5.66 + 5.67 + if (value == lo) { // 32-bit integer 5.68 + if (Assembler::is_simm16(value)) { 5.69 + //daddiu(d, R0, value); 5.70 + //set_int_at(count << 2, (Assembler::daddiu_op << 26) | rt_reg | Assembler::split_low(value)); 5.71 + insts[count] = (Assembler::daddiu_op << 26) | rt_reg | Assembler::split_low(value); 5.72 + count += 1; 5.73 + } else { 5.74 + //lui(d, split_low(value >> 16)); 5.75 + //set_int_at(count << 2, (Assembler::lui_op << 26) | rt_reg | Assembler::split_low(value >> 16)); 5.76 + insts[count] = (Assembler::lui_op << 26) | rt_reg | Assembler::split_low(value >> 16); 5.77 + count += 1; 5.78 + if (Assembler::split_low(value)) { 5.79 + //ori(d, d, split_low(value)); 5.80 + //set_int_at(count << 2, (Assembler::ori_op << 26) | rs_reg | rt_reg | Assembler::split_low(value)); 5.81 + insts[count] = (Assembler::ori_op << 26) | rs_reg | rt_reg | Assembler::split_low(value); 5.82 + count += 1; 5.83 + } 5.84 + } 5.85 + } else if (hi == 0) { // hardware zero-extends to upper 32 5.86 + //ori(d, R0, julong(value) >> 16); 5.87 + //set_int_at(count << 2, (Assembler::ori_op << 26) | rt_reg | Assembler::split_low(julong(value) >> 16)); 5.88 + insts[count] = (Assembler::ori_op << 26) | rt_reg | Assembler::split_low(julong(value) >> 16); 5.89 + count += 1; 5.90 + //dsll(d, d, 16); 5.91 + //set_int_at(count << 2, (Assembler::dsll_op) | rt_reg | rd_reg | (16 << 6)); 5.92 + insts[count] = (Assembler::dsll_op) | rt_reg | rd_reg | (16 << 6); 5.93 + count += 1; 5.94 + if (Assembler::split_low(value)) { 5.95 + //ori(d, d, split_low(value)); 5.96 + //set_int_at(count << 2, (Assembler::ori_op << 26) | rs_reg | rt_reg | Assembler::split_low(value)); 5.97 + insts[count] = (Assembler::ori_op << 26) | rs_reg | rt_reg | Assembler::split_low(value); 5.98 + count += 1; 5.99 + } 5.100 + } else if ((value> 0) && Assembler::is_simm16(value >> 32)) { 5.101 + //lui(d, value >> 32); 5.102 + //set_int_at(count << 2, (Assembler::lui_op << 26) | rt_reg | Assembler::split_low(value >> 32)); 5.103 + insts[count] = (Assembler::lui_op << 26) | rt_reg | Assembler::split_low(value >> 32); 5.104 + count += 1; 5.105 + //ori(d, d, split_low(value >> 16)); 5.106 + //set_int_at(count << 2, (Assembler::ori_op << 26) | rs_reg | rt_reg | Assembler::split_low(value >> 16)); 5.107 + insts[count] = (Assembler::ori_op << 26) | rs_reg | rt_reg | Assembler::split_low(value >> 16); 5.108 + count += 1; 5.109 + //dsll(d, d, 16); 5.110 + //set_int_at(count << 2, (Assembler::dsll_op) | rt_reg | rd_reg | (16 << 6)); 5.111 + insts[count] = (Assembler::dsll_op) | rt_reg | rd_reg | (16 << 6); 5.112 + count += 1; 5.113 + //ori(d, d, split_low(value)); 5.114 + //set_int_at(count << 2, (Assembler::ori_op << 26) | rs_reg | rt_reg | Assembler::split_low(value)); 5.115 + insts[count] = (Assembler::ori_op << 26) | rs_reg | rt_reg | Assembler::split_low(value); 5.116 + count += 1; 5.117 + } else { 5.118 + tty->print_cr("dest = 0x%x", value); 5.119 + guarantee(false, "Not supported yet !"); 5.120 + } 5.121 + 5.122 + for (count; count < 4; count++) { 5.123 + //nop(); 5.124 + //set_int_at(count << 2, 0); 5.125 + insts[count] = 0; 5.126 + } 5.127 + 5.128 + atomic_store128_ptr func = get_atomic_store128_func(); 5.129 + (*func)((long *)addr_at(0), 0, *(long *)&insts[0], *(long *)&insts[2]); 5.130 + 5.131 + ICache::invalidate_range(addr_at(0), 16); 5.132 +} 5.133 + 5.134 void NativeGeneralJump::patch_set48(address dest) { 5.135 jlong value = (jlong) dest; 5.136 int rt_reg = (int_at(0) & (0x1f << 16)); 5.137 @@ -1191,6 +1280,38 @@ 5.138 //nop(); 5.139 set_int_at(count << 2, 0); 5.140 } 5.141 + 5.142 + ICache::invalidate_range(addr_at(0), 16); 5.143 +} 5.144 + 5.145 + 5.146 +void NativeGeneralJump::patch_on_j_gs(address dst) { 5.147 +#ifdef _LP64 5.148 + long dest = ((long)dst - (((long)addr_at(20)) & 0xfffffffff0000000))>>2; 5.149 +#else 5.150 + long dest = ((long)dst - (((long)addr_at(20)) & 0xf0000000))>>2; 5.151 +#endif 5.152 + if ((dest >= 0) && (dest < (1<<26))) { 5.153 + jint j_inst = (Assembler::j_op << 26) | dest; 5.154 + set_int_at(16, j_inst); 5.155 + ICache::invalidate_range(addr_at(16), 4); 5.156 + } else { 5.157 + ShouldNotReachHere(); 5.158 + } 5.159 +} 5.160 + 5.161 +void NativeGeneralJump::patch_on_j(address dst) { 5.162 + patch_on_j_gs(dst); 5.163 +} 5.164 + 5.165 +void NativeGeneralJump::patch_on_jr_gs(address dst) { 5.166 + patch_set48_gs(dst); 5.167 + ICache::invalidate_range(addr_at(0), 16); 5.168 +} 5.169 + 5.170 +void NativeGeneralJump::patch_on_jr(address dst) { 5.171 + patch_set48(dst); 5.172 + ICache::invalidate_range(addr_at(0), 16); 5.173 } 5.174 5.175 5.176 @@ -1214,8 +1335,20 @@ 5.177 set_int_at(4, (int_at(4) & 0xffff0000) | (Assembler::split_low((intptr_t)dest) & 0xffff)); 5.178 ICache::invalidate_range(addr_at(0), 8); 5.179 #else 5.180 - patch_set48(dest); 5.181 - ICache::invalidate_range(addr_at(0), 24); 5.182 + if (is_op(int_at(16), Assembler::j_op)) { 5.183 + if (UseLoongsonISA) { 5.184 + patch_on_j_gs(dest); 5.185 + } else { 5.186 + patch_on_j(dest); 5.187 + } 5.188 + } else if (is_special_op(int_at(16), Assembler::jr_op)) { 5.189 + if (UseLoongsonISA) { 5.190 + guarantee(!os::is_MP() || (((long)addr_at(0) % 16) == 0), "destination must be aligned for GSSD"); 5.191 + patch_on_jr_gs(dest); 5.192 + } else { 5.193 + patch_on_jr(dest); 5.194 + } 5.195 + } 5.196 #endif 5.197 } 5.198 } 5.199 @@ -1297,6 +1430,24 @@ 5.200 return target; 5.201 } 5.202 5.203 + // nop 5.204 + // nop 5.205 + // nop 5.206 + // nop 5.207 + // j target 5.208 + // nop 5.209 + if ( nativeInstruction_at(addr_at(0))->is_nop() && 5.210 + nativeInstruction_at(addr_at(4))->is_nop() && 5.211 + nativeInstruction_at(addr_at(8))->is_nop() && 5.212 + nativeInstruction_at(addr_at(12))->is_nop() && 5.213 + is_op(int_at(16), Assembler::j_op) && 5.214 + nativeInstruction_at(addr_at(20))->is_nop()) { 5.215 + int instr_index = int_at(16) & 0x3ffffff; 5.216 + intptr_t target_high = ((intptr_t)addr_at(20)) & 0xfffffffff0000000; 5.217 + intptr_t target = target_high | (instr_index << 2); 5.218 + return (address)target; 5.219 + } 5.220 + 5.221 // li64 5.222 if ( is_op(Assembler::lui_op) && 5.223 is_op(int_at(4), Assembler::ori_op) && 5.224 @@ -1494,6 +1645,22 @@ 5.225 return true; 5.226 if (is_op(int_at(12), Assembler::lui_op)) /* original b_far */ 5.227 return true; 5.228 + 5.229 + // nop 5.230 + // nop 5.231 + // nop 5.232 + // nop 5.233 + // j target 5.234 + // nop 5.235 + if ( is_nop() && 5.236 + nativeInstruction_at(addr_at(4))->is_nop() && 5.237 + nativeInstruction_at(addr_at(8))->is_nop() && 5.238 + nativeInstruction_at(addr_at(12))->is_nop() && 5.239 + nativeInstruction_at(addr_at(16))->is_op(Assembler::j_op) && 5.240 + nativeInstruction_at(addr_at(20))->is_nop() ) { 5.241 + return true; 5.242 + } 5.243 + 5.244 if (is_op(int_at(0), Assembler::lui_op) && 5.245 is_op(int_at(4), Assembler::ori_op) && 5.246 is_special_op(int_at(8), Assembler::dsll_op) &&
6.1 --- a/src/cpu/mips/vm/nativeInst_mips.hpp Wed Mar 22 11:43:05 2017 -0400 6.2 +++ b/src/cpu/mips/vm/nativeInst_mips.hpp Tue Mar 28 06:08:41 2017 -0400 6.3 @@ -433,7 +433,15 @@ 6.4 address instruction_address() const { return addr_at(instruction_offset); } 6.5 address jump_destination(); 6.6 6.7 + void patch_set48_gs(address dest); 6.8 void patch_set48(address dest); 6.9 + 6.10 + void patch_on_jr_gs(address dest); 6.11 + void patch_on_jr(address dest); 6.12 + 6.13 + void patch_on_j_gs(address dest); 6.14 + void patch_on_j(address dest); 6.15 + 6.16 void set_jump_destination(address dest); 6.17 6.18 // Creation
7.1 --- a/src/cpu/mips/vm/sharedRuntime_mips_64.cpp Wed Mar 22 11:43:05 2017 -0400 7.2 +++ b/src/cpu/mips/vm/sharedRuntime_mips_64.cpp Tue Mar 28 06:08:41 2017 -0400 7.3 @@ -4079,9 +4079,7 @@ 7.4 __ move(A0, thread); 7.5 // argument already in T0 7.6 __ move(A1, T0); 7.7 - __ patchable_set48(T9, (long)Deoptimization::uncommon_trap); 7.8 - __ jalr(T9); 7.9 - __ delayed()->nop(); 7.10 + __ patchable_call((address)Deoptimization::uncommon_trap); 7.11 7.12 // Set an oopmap for the call site 7.13 OopMapSet *oop_maps = new OopMapSet(); 7.14 @@ -4201,9 +4199,7 @@ 7.15 // restore return values to their stack-slots with the new SP. 7.16 __ move(A0, thread); 7.17 __ move(A1, Deoptimization::Unpack_uncommon_trap); 7.18 - __ patchable_set48(T9, (long)Deoptimization::unpack_frames); 7.19 - __ jalr(T9); 7.20 - __ delayed()->nop(); 7.21 + __ patchable_call((address)Deoptimization::unpack_frames); 7.22 // Set an oopmap for the call site 7.23 //oop_maps->add_gc_map( __ offset(), true, new OopMap( framesize, 0 ) ); 7.24 oop_maps->add_gc_map( __ offset(), new OopMap( framesize, 0 ) );//Fu 7.25 @@ -4323,9 +4319,7 @@ 7.26 __ push(RA); 7.27 //__ lui(T9, Assembler::split_high((int)StubRoutines::forward_exception_entry())); 7.28 //__ addiu(T9, T9, Assembler::split_low((int)StubRoutines::forward_exception_entry())); 7.29 - __ li(T9, StubRoutines::forward_exception_entry()); 7.30 - __ jr(T9); 7.31 - __ delayed()->nop(); 7.32 + __ patchable_jump((address)StubRoutines::forward_exception_entry()); 7.33 7.34 // No exception case 7.35 __ bind(noException);