src/cpu/x86/vm/x86_64.ad

Print this page
rev 4449 : 8003853: specify offset of IC load in java_to_interp stub

If a compiled static call calls the interpreter, it jumps past a
java_to_interp stub in the compiled code. Patching this call must
find the load of the IC. So far the shared code assumed this is the
first instruction in the stub.
This might not be the case if, for example, the base of the constant
table must be loaded as it happens on PPC.  The position of the IC
load is platform dependent, but used in shared code.

To fix this, this change cleans up the code handling compiled static
Java calls:
 - Methods using native instructions are moved from compiledIC.cpp
   to compiledIC_<cpu>.cpp
   With this the offset can be implemented platform dependent.
 - Methods emitting the stub moved from the ad file to this class.
   As a side effect this reduces redundancies in x86_64.ad and x86_32.ad.
 - We get rid of extern declarations in output.cpp.

Now all code concerning CompiledStaticCalls is collected on one class,
except for emitting the call itself.  The PPC port needs not change
shared code any more to implement them.


1371     emit_opcode(cbuf, 0x8D); // LEA  reg,[SP+offset]
1372     emit_rm(cbuf, 0x2, reg & 7, 0x04);
1373     emit_rm(cbuf, 0x0, 0x04, RSP_enc);
1374     emit_d32(cbuf, offset);
1375   } else {
1376     emit_opcode(cbuf, reg < 8 ? Assembler::REX_W : Assembler::REX_WR);
1377     emit_opcode(cbuf, 0x8D); // LEA  reg,[SP+offset]
1378     emit_rm(cbuf, 0x1, reg & 7, 0x04);
1379     emit_rm(cbuf, 0x0, 0x04, RSP_enc);
1380     emit_d8(cbuf, offset);
1381   }
1382 }
1383 
1384 uint BoxLockNode::size(PhaseRegAlloc *ra_) const
1385 {
1386   int offset = ra_->reg2offset(in_RegMask(0).find_first_elem());
1387   return (offset < 0x80) ? 5 : 8; // REX
1388 }
1389 
1390 //=============================================================================
1391 
1392 // emit call stub, compiled java to interpreter
1393 void emit_java_to_interp(CodeBuffer& cbuf)
1394 {
1395   // Stub is fixed up when the corresponding call is converted from
1396   // calling compiled code to calling interpreted code.
1397   // movq rbx, 0
1398   // jmp -5 # to self
1399 
1400   address mark = cbuf.insts_mark();  // get mark within main instrs section
1401 
1402   // Note that the code buffer's insts_mark is always relative to insts.
1403   // That's why we must use the macroassembler to generate a stub.
1404   MacroAssembler _masm(&cbuf);
1405 
1406   address base =
1407   __ start_a_stub(Compile::MAX_stubs_size);
1408   if (base == NULL)  return;  // CodeBuffer::expand failed
1409   // static stub relocation stores the instruction address of the call
1410   __ relocate(static_stub_Relocation::spec(mark), RELOC_IMM64);
1411   // static stub relocation also tags the Method* in the code-stream.
1412   __ mov_metadata(rbx, (Metadata*) NULL);  // method is zapped till fixup time
1413   // This is recognized as unresolved by relocs/nativeinst/ic code
1414   __ jump(RuntimeAddress(__ pc()));
1415 
1416   // Update current stubs pointer and restore insts_end.
1417   __ end_a_stub();
1418 }
1419 
1420 // size of call stub, compiled java to interpretor
1421 uint size_java_to_interp()
1422 {
1423   return 15;  // movq (1+1+8); jmp (1+4)
1424 }
1425 
1426 // relocation entries for call stub, compiled java to interpretor
1427 uint reloc_java_to_interp()
1428 {
1429   return 4; // 3 in emit_java_to_interp + 1 in Java_Static_Call
1430 }
1431 
1432 //=============================================================================
1433 #ifndef PRODUCT
1434 void MachUEPNode::format(PhaseRegAlloc* ra_, outputStream* st) const
1435 {
1436   if (UseCompressedKlassPointers) {
1437     st->print_cr("movl    rscratch1, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass");
1438     if (Universe::narrow_klass_shift() != 0) {
1439       st->print_cr("\tdecode_klass_not_null rscratch1, rscratch1");
1440     }
1441     st->print_cr("\tcmpq    rax, rscratch1\t # Inline cache check");
1442   } else {
1443     st->print_cr("\tcmpq    rax, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t"
1444                  "# Inline cache check");
1445   }
1446   st->print_cr("\tjne     SharedRuntime::_ic_miss_stub");
1447   st->print_cr("\tnop\t# nops to align entry point");
1448 }
1449 #endif
1450 
1451 void MachUEPNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const
1452 {


2072     cbuf.set_insts_mark();
2073     $$$emit8$primary;
2074 
2075     if (!_method) {
2076       emit_d32_reloc(cbuf,
2077                      (int) ($meth$$method - ((intptr_t) cbuf.insts_end()) - 4),
2078                      runtime_call_Relocation::spec(),
2079                      RELOC_DISP32);
2080     } else if (_optimized_virtual) {
2081       emit_d32_reloc(cbuf,
2082                      (int) ($meth$$method - ((intptr_t) cbuf.insts_end()) - 4),
2083                      opt_virtual_call_Relocation::spec(),
2084                      RELOC_DISP32);
2085     } else {
2086       emit_d32_reloc(cbuf,
2087                      (int) ($meth$$method - ((intptr_t) cbuf.insts_end()) - 4),
2088                      static_call_Relocation::spec(),
2089                      RELOC_DISP32);
2090     }
2091     if (_method) {
2092       // Emit stub for static call
2093       emit_java_to_interp(cbuf);
2094     }
2095   %}
2096 
2097   enc_class Java_Dynamic_Call(method meth) %{
2098     MacroAssembler _masm(&cbuf);
2099     __ ic_call((address)$meth$$method);
2100   %}
2101 
2102   enc_class Java_Compiled_Call(method meth)
2103   %{
2104     // JAVA COMPILED CALL
2105     int disp = in_bytes(Method:: from_compiled_offset());
2106 
2107     // XXX XXX offset is 128 is 1.5 NON-PRODUCT !!!
2108     // assert(-0x80 <= disp && disp < 0x80, "compiled_code_offset isn't small");
2109 
2110     // callq *disp(%rax)
2111     cbuf.set_insts_mark();
2112     $$$emit8$primary;
2113     if (disp < 0x80) {




1371     emit_opcode(cbuf, 0x8D); // LEA  reg,[SP+offset]
1372     emit_rm(cbuf, 0x2, reg & 7, 0x04);
1373     emit_rm(cbuf, 0x0, 0x04, RSP_enc);
1374     emit_d32(cbuf, offset);
1375   } else {
1376     emit_opcode(cbuf, reg < 8 ? Assembler::REX_W : Assembler::REX_WR);
1377     emit_opcode(cbuf, 0x8D); // LEA  reg,[SP+offset]
1378     emit_rm(cbuf, 0x1, reg & 7, 0x04);
1379     emit_rm(cbuf, 0x0, 0x04, RSP_enc);
1380     emit_d8(cbuf, offset);
1381   }
1382 }
1383 
1384 uint BoxLockNode::size(PhaseRegAlloc *ra_) const
1385 {
1386   int offset = ra_->reg2offset(in_RegMask(0).find_first_elem());
1387   return (offset < 0x80) ? 5 : 8; // REX
1388 }
1389 
1390 //=============================================================================










































1391 #ifndef PRODUCT
1392 void MachUEPNode::format(PhaseRegAlloc* ra_, outputStream* st) const
1393 {
1394   if (UseCompressedKlassPointers) {
1395     st->print_cr("movl    rscratch1, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass");
1396     if (Universe::narrow_klass_shift() != 0) {
1397       st->print_cr("\tdecode_klass_not_null rscratch1, rscratch1");
1398     }
1399     st->print_cr("\tcmpq    rax, rscratch1\t # Inline cache check");
1400   } else {
1401     st->print_cr("\tcmpq    rax, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t"
1402                  "# Inline cache check");
1403   }
1404   st->print_cr("\tjne     SharedRuntime::_ic_miss_stub");
1405   st->print_cr("\tnop\t# nops to align entry point");
1406 }
1407 #endif
1408 
1409 void MachUEPNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const
1410 {


2030     cbuf.set_insts_mark();
2031     $$$emit8$primary;
2032 
2033     if (!_method) {
2034       emit_d32_reloc(cbuf,
2035                      (int) ($meth$$method - ((intptr_t) cbuf.insts_end()) - 4),
2036                      runtime_call_Relocation::spec(),
2037                      RELOC_DISP32);
2038     } else if (_optimized_virtual) {
2039       emit_d32_reloc(cbuf,
2040                      (int) ($meth$$method - ((intptr_t) cbuf.insts_end()) - 4),
2041                      opt_virtual_call_Relocation::spec(),
2042                      RELOC_DISP32);
2043     } else {
2044       emit_d32_reloc(cbuf,
2045                      (int) ($meth$$method - ((intptr_t) cbuf.insts_end()) - 4),
2046                      static_call_Relocation::spec(),
2047                      RELOC_DISP32);
2048     }
2049     if (_method) {
2050       // Emit stub for static call.
2051       CompiledStaticCall::emit_to_interp_stub(cbuf);
2052     }
2053   %}
2054 
2055   enc_class Java_Dynamic_Call(method meth) %{
2056     MacroAssembler _masm(&cbuf);
2057     __ ic_call((address)$meth$$method);
2058   %}
2059 
2060   enc_class Java_Compiled_Call(method meth)
2061   %{
2062     // JAVA COMPILED CALL
2063     int disp = in_bytes(Method:: from_compiled_offset());
2064 
2065     // XXX XXX offset is 128 is 1.5 NON-PRODUCT !!!
2066     // assert(-0x80 <= disp && disp < 0x80, "compiled_code_offset isn't small");
2067 
2068     // callq *disp(%rax)
2069     cbuf.set_insts_mark();
2070     $$$emit8$primary;
2071     if (disp < 0x80) {