mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 06:45:07 +02:00
8074345: Enable RewriteBytecodes when VM runs with CDS
Enable bytecode rewriting when CDS turned on. Co-authored-by: Ioi Lam <ioi.lam@oracle.com> Reviewed-by: coleenp, iklam
This commit is contained in:
parent
c08ffb03e4
commit
3e6cf09c39
13 changed files with 202 additions and 97 deletions
|
@ -386,7 +386,6 @@ void TemplateTable::fast_aldc(bool wide) {
|
|||
__ verify_oop(Otos_i);
|
||||
}
|
||||
|
||||
|
||||
void TemplateTable::ldc2_w() {
|
||||
transition(vtos, vtos);
|
||||
Label Long, exit;
|
||||
|
@ -431,22 +430,28 @@ void TemplateTable::ldc2_w() {
|
|||
__ bind(exit);
|
||||
}
|
||||
|
||||
|
||||
void TemplateTable::locals_index(Register reg, int offset) {
|
||||
__ ldub( at_bcp(offset), reg );
|
||||
}
|
||||
|
||||
|
||||
void TemplateTable::locals_index_wide(Register reg) {
|
||||
// offset is 2, not 1, because Lbcp points to wide prefix code
|
||||
__ get_2_byte_integer_at_bcp(2, G4_scratch, reg, InterpreterMacroAssembler::Unsigned);
|
||||
}
|
||||
|
||||
void TemplateTable::iload() {
|
||||
iload_internal();
|
||||
}
|
||||
|
||||
void TemplateTable::nofast_iload() {
|
||||
iload_internal(may_not_rewrite);
|
||||
}
|
||||
|
||||
void TemplateTable::iload_internal(RewriteControl rc) {
|
||||
transition(vtos, itos);
|
||||
// Rewrite iload,iload pair into fast_iload2
|
||||
// iload,caload pair into fast_icaload
|
||||
if (RewriteFrequentPairs) {
|
||||
if (RewriteFrequentPairs && rc == may_rewrite) {
|
||||
Label rewrite, done;
|
||||
|
||||
// get next byte
|
||||
|
@ -673,8 +678,15 @@ void TemplateTable::aload(int n) {
|
|||
__ ld_ptr( Llocals, Interpreter::local_offset_in_bytes(n), Otos_i );
|
||||
}
|
||||
|
||||
|
||||
void TemplateTable::aload_0() {
|
||||
aload_0_internal();
|
||||
}
|
||||
|
||||
void TemplateTable::nofast_aload_0() {
|
||||
aload_0_internal(may_not_rewrite);
|
||||
}
|
||||
|
||||
void TemplateTable::aload_0_internal(RewriteControl rc) {
|
||||
transition(vtos, atos);
|
||||
|
||||
// According to bytecode histograms, the pairs:
|
||||
|
@ -688,7 +700,7 @@ void TemplateTable::aload_0() {
|
|||
// bytecode into a pair bytecode; otherwise it rewrites the current
|
||||
// bytecode into _fast_aload_0 that doesn't do the pair check anymore.
|
||||
//
|
||||
if (RewriteFrequentPairs) {
|
||||
if (RewriteFrequentPairs && rc == may_rewrite) {
|
||||
Label rewrite, done;
|
||||
|
||||
// get next byte
|
||||
|
@ -732,7 +744,6 @@ void TemplateTable::aload_0() {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void TemplateTable::istore() {
|
||||
transition(itos, vtos);
|
||||
locals_index(G3_scratch);
|
||||
|
@ -2046,16 +2057,23 @@ void TemplateTable::resolve_cache_and_index(int byte_no,
|
|||
Register index,
|
||||
size_t index_size) {
|
||||
// Depends on cpCacheOop layout!
|
||||
Label resolved;
|
||||
|
||||
assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range");
|
||||
__ get_cache_and_index_and_bytecode_at_bcp(Rcache, index, Lbyte_code, byte_no, 1, index_size);
|
||||
__ cmp(Lbyte_code, (int) bytecode()); // have we resolved this bytecode?
|
||||
__ br(Assembler::equal, false, Assembler::pt, resolved);
|
||||
__ delayed()->set((int)bytecode(), O1);
|
||||
Label resolved;
|
||||
Bytecodes::Code code = bytecode();
|
||||
switch (code) {
|
||||
case Bytecodes::_nofast_getfield: code = Bytecodes::_getfield; break;
|
||||
case Bytecodes::_nofast_putfield: code = Bytecodes::_putfield; break;
|
||||
}
|
||||
|
||||
assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range");
|
||||
__ get_cache_and_index_and_bytecode_at_bcp(Rcache, index, Lbyte_code, byte_no, 1, index_size);
|
||||
__ cmp(Lbyte_code, code); // have we resolved this bytecode?
|
||||
__ br(Assembler::equal, false, Assembler::pt, resolved);
|
||||
__ delayed()->set(code, O1);
|
||||
|
||||
address entry;
|
||||
switch (bytecode()) {
|
||||
|
||||
switch (code) {
|
||||
case Bytecodes::_getstatic : // fall through
|
||||
case Bytecodes::_putstatic : // fall through
|
||||
case Bytecodes::_getfield : // fall through
|
||||
|
@ -2067,7 +2085,7 @@ void TemplateTable::resolve_cache_and_index(int byte_no,
|
|||
case Bytecodes::_invokehandle : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokehandle); break;
|
||||
case Bytecodes::_invokedynamic : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic); break;
|
||||
default:
|
||||
fatal(err_msg("unexpected bytecode: %s", Bytecodes::name(bytecode())));
|
||||
fatal(err_msg("unexpected bytecode: %s", Bytecodes::name(code)));
|
||||
break;
|
||||
}
|
||||
// first time invocation - must resolve first
|
||||
|
@ -2184,7 +2202,7 @@ void TemplateTable::jvmti_post_field_access(Register Rcache,
|
|||
}
|
||||
}
|
||||
|
||||
void TemplateTable::getfield_or_static(int byte_no, bool is_static) {
|
||||
void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteControl rc) {
|
||||
transition(vtos, vtos);
|
||||
|
||||
Register Rcache = G3_scratch;
|
||||
|
@ -2232,7 +2250,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static) {
|
|||
__ load_heap_oop(Rclass, Roffset, Otos_i);
|
||||
__ verify_oop(Otos_i);
|
||||
__ push(atos);
|
||||
if (!is_static) {
|
||||
if (!is_static && rc == may_rewrite) {
|
||||
patch_bytecode(Bytecodes::_fast_agetfield, G3_scratch, G4_scratch);
|
||||
}
|
||||
__ ba(checkVolatile);
|
||||
|
@ -2247,7 +2265,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static) {
|
|||
// itos
|
||||
__ ld(Rclass, Roffset, Otos_i);
|
||||
__ push(itos);
|
||||
if (!is_static) {
|
||||
if (!is_static && rc == may_rewrite) {
|
||||
patch_bytecode(Bytecodes::_fast_igetfield, G3_scratch, G4_scratch);
|
||||
}
|
||||
__ ba(checkVolatile);
|
||||
|
@ -2263,7 +2281,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static) {
|
|||
// load must be atomic
|
||||
__ ld_long(Rclass, Roffset, Otos_l);
|
||||
__ push(ltos);
|
||||
if (!is_static) {
|
||||
if (!is_static && rc == may_rewrite) {
|
||||
patch_bytecode(Bytecodes::_fast_lgetfield, G3_scratch, G4_scratch);
|
||||
}
|
||||
__ ba(checkVolatile);
|
||||
|
@ -2278,7 +2296,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static) {
|
|||
// btos
|
||||
__ ldsb(Rclass, Roffset, Otos_i);
|
||||
__ push(itos);
|
||||
if (!is_static) {
|
||||
if (!is_static && rc == may_rewrite) {
|
||||
patch_bytecode(Bytecodes::_fast_bgetfield, G3_scratch, G4_scratch);
|
||||
}
|
||||
__ ba(checkVolatile);
|
||||
|
@ -2293,7 +2311,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static) {
|
|||
// ctos
|
||||
__ lduh(Rclass, Roffset, Otos_i);
|
||||
__ push(itos);
|
||||
if (!is_static) {
|
||||
if (!is_static && rc == may_rewrite) {
|
||||
patch_bytecode(Bytecodes::_fast_cgetfield, G3_scratch, G4_scratch);
|
||||
}
|
||||
__ ba(checkVolatile);
|
||||
|
@ -2308,7 +2326,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static) {
|
|||
// stos
|
||||
__ ldsh(Rclass, Roffset, Otos_i);
|
||||
__ push(itos);
|
||||
if (!is_static) {
|
||||
if (!is_static && rc == may_rewrite) {
|
||||
patch_bytecode(Bytecodes::_fast_sgetfield, G3_scratch, G4_scratch);
|
||||
}
|
||||
__ ba(checkVolatile);
|
||||
|
@ -2324,7 +2342,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static) {
|
|||
// ftos
|
||||
__ ldf(FloatRegisterImpl::S, Rclass, Roffset, Ftos_f);
|
||||
__ push(ftos);
|
||||
if (!is_static) {
|
||||
if (!is_static && rc == may_rewrite) {
|
||||
patch_bytecode(Bytecodes::_fast_fgetfield, G3_scratch, G4_scratch);
|
||||
}
|
||||
__ ba(checkVolatile);
|
||||
|
@ -2336,7 +2354,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static) {
|
|||
// dtos
|
||||
__ ldf(FloatRegisterImpl::D, Rclass, Roffset, Ftos_d);
|
||||
__ push(dtos);
|
||||
if (!is_static) {
|
||||
if (!is_static && rc == may_rewrite) {
|
||||
patch_bytecode(Bytecodes::_fast_dgetfield, G3_scratch, G4_scratch);
|
||||
}
|
||||
|
||||
|
@ -2351,16 +2369,18 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static) {
|
|||
__ bind(exit);
|
||||
}
|
||||
|
||||
|
||||
void TemplateTable::getfield(int byte_no) {
|
||||
getfield_or_static(byte_no, false);
|
||||
}
|
||||
|
||||
void TemplateTable::nofast_getfield(int byte_no) {
|
||||
getfield_or_static(byte_no, false, may_not_rewrite);
|
||||
}
|
||||
|
||||
void TemplateTable::getstatic(int byte_no) {
|
||||
getfield_or_static(byte_no, true);
|
||||
}
|
||||
|
||||
|
||||
void TemplateTable::fast_accessfield(TosState state) {
|
||||
transition(atos, state);
|
||||
Register Rcache = G3_scratch;
|
||||
|
@ -2545,7 +2565,7 @@ void TemplateTable::pop_and_check_object(Register r) {
|
|||
__ verify_oop(r);
|
||||
}
|
||||
|
||||
void TemplateTable::putfield_or_static(int byte_no, bool is_static) {
|
||||
void TemplateTable::putfield_or_static(int byte_no, bool is_static, RewriteControl rc) {
|
||||
transition(vtos, vtos);
|
||||
Register Rcache = G3_scratch;
|
||||
Register index = G4_scratch;
|
||||
|
@ -2621,7 +2641,7 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static) {
|
|||
__ pop_i();
|
||||
pop_and_check_object(Rclass);
|
||||
__ st(Otos_i, Rclass, Roffset);
|
||||
patch_bytecode(Bytecodes::_fast_iputfield, G3_scratch, G4_scratch, true, byte_no);
|
||||
if (rc == may_rewrite) patch_bytecode(Bytecodes::_fast_iputfield, G3_scratch, G4_scratch, true, byte_no);
|
||||
__ ba(checkVolatile);
|
||||
__ delayed()->tst(Lscratch);
|
||||
}
|
||||
|
@ -2637,7 +2657,7 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static) {
|
|||
pop_and_check_object(Rclass);
|
||||
__ verify_oop(Otos_i);
|
||||
do_oop_store(_masm, Rclass, Roffset, 0, Otos_i, G1_scratch, _bs->kind(), false);
|
||||
patch_bytecode(Bytecodes::_fast_aputfield, G3_scratch, G4_scratch, true, byte_no);
|
||||
if (rc == may_rewrite) patch_bytecode(Bytecodes::_fast_aputfield, G3_scratch, G4_scratch, true, byte_no);
|
||||
__ ba(checkVolatile);
|
||||
__ delayed()->tst(Lscratch);
|
||||
}
|
||||
|
@ -2654,7 +2674,7 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static) {
|
|||
__ pop_i();
|
||||
if (!is_static) pop_and_check_object(Rclass);
|
||||
__ stb(Otos_i, Rclass, Roffset);
|
||||
if (!is_static) {
|
||||
if (!is_static && rc == may_rewrite) {
|
||||
patch_bytecode(Bytecodes::_fast_bputfield, G3_scratch, G4_scratch, true, byte_no);
|
||||
}
|
||||
__ ba(checkVolatile);
|
||||
|
@ -2671,7 +2691,7 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static) {
|
|||
__ pop_l();
|
||||
if (!is_static) pop_and_check_object(Rclass);
|
||||
__ st_long(Otos_l, Rclass, Roffset);
|
||||
if (!is_static) {
|
||||
if (!is_static && rc == may_rewrite) {
|
||||
patch_bytecode(Bytecodes::_fast_lputfield, G3_scratch, G4_scratch, true, byte_no);
|
||||
}
|
||||
__ ba(checkVolatile);
|
||||
|
@ -2688,7 +2708,7 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static) {
|
|||
__ pop_i();
|
||||
if (!is_static) pop_and_check_object(Rclass);
|
||||
__ sth(Otos_i, Rclass, Roffset);
|
||||
if (!is_static) {
|
||||
if (!is_static && rc == may_rewrite) {
|
||||
patch_bytecode(Bytecodes::_fast_cputfield, G3_scratch, G4_scratch, true, byte_no);
|
||||
}
|
||||
__ ba(checkVolatile);
|
||||
|
@ -2705,7 +2725,7 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static) {
|
|||
__ pop_i();
|
||||
if (!is_static) pop_and_check_object(Rclass);
|
||||
__ sth(Otos_i, Rclass, Roffset);
|
||||
if (!is_static) {
|
||||
if (!is_static && rc == may_rewrite) {
|
||||
patch_bytecode(Bytecodes::_fast_sputfield, G3_scratch, G4_scratch, true, byte_no);
|
||||
}
|
||||
__ ba(checkVolatile);
|
||||
|
@ -2722,7 +2742,7 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static) {
|
|||
__ pop_f();
|
||||
if (!is_static) pop_and_check_object(Rclass);
|
||||
__ stf(FloatRegisterImpl::S, Ftos_f, Rclass, Roffset);
|
||||
if (!is_static) {
|
||||
if (!is_static && rc == may_rewrite) {
|
||||
patch_bytecode(Bytecodes::_fast_fputfield, G3_scratch, G4_scratch, true, byte_no);
|
||||
}
|
||||
__ ba(checkVolatile);
|
||||
|
@ -2736,7 +2756,7 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static) {
|
|||
__ pop_d();
|
||||
if (!is_static) pop_and_check_object(Rclass);
|
||||
__ stf(FloatRegisterImpl::D, Ftos_d, Rclass, Roffset);
|
||||
if (!is_static) {
|
||||
if (!is_static && rc == may_rewrite) {
|
||||
patch_bytecode(Bytecodes::_fast_dputfield, G3_scratch, G4_scratch, true, byte_no);
|
||||
}
|
||||
}
|
||||
|
@ -2810,16 +2830,18 @@ void TemplateTable::fast_storefield(TosState state) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void TemplateTable::putfield(int byte_no) {
|
||||
putfield_or_static(byte_no, false);
|
||||
}
|
||||
|
||||
void TemplateTable::nofast_putfield(int byte_no) {
|
||||
putfield_or_static(byte_no, false, may_not_rewrite);
|
||||
}
|
||||
|
||||
void TemplateTable::putstatic(int byte_no) {
|
||||
putfield_or_static(byte_no, true);
|
||||
}
|
||||
|
||||
|
||||
void TemplateTable::fast_xaccess(TosState state) {
|
||||
transition(vtos, state);
|
||||
Register Rcache = G3_scratch;
|
||||
|
@ -2972,7 +2994,9 @@ void TemplateTable::invokevirtual(int byte_no) {
|
|||
__ br(Assembler::zero, false, Assembler::pt, notFinal);
|
||||
__ delayed()->and3(Rret, 0xFF, G4_scratch); // gets number of parameters
|
||||
|
||||
patch_bytecode(Bytecodes::_fast_invokevfinal, Rscratch, Rtemp);
|
||||
if (RewriteBytecodes && !UseSharedSpaces) {
|
||||
patch_bytecode(Bytecodes::_fast_invokevfinal, Rscratch, Rtemp);
|
||||
}
|
||||
|
||||
invokevfinal_helper(Rscratch, Rret);
|
||||
|
||||
|
|
|
@ -544,8 +544,16 @@ void TemplateTable::locals_index(Register reg, int offset) {
|
|||
}
|
||||
|
||||
void TemplateTable::iload() {
|
||||
iload_internal();
|
||||
}
|
||||
|
||||
void TemplateTable::nofast_iload() {
|
||||
iload_internal(may_not_rewrite);
|
||||
}
|
||||
|
||||
void TemplateTable::iload_internal(RewriteControl rc) {
|
||||
transition(vtos, itos);
|
||||
if (RewriteFrequentPairs) {
|
||||
if (RewriteFrequentPairs && rc == may_rewrite) {
|
||||
Label rewrite, done;
|
||||
const Register bc = LP64_ONLY(c_rarg3) NOT_LP64(rcx);
|
||||
LP64_ONLY(assert(rbx != bc, "register damaged"));
|
||||
|
@ -816,6 +824,14 @@ void TemplateTable::aload(int n) {
|
|||
}
|
||||
|
||||
void TemplateTable::aload_0() {
|
||||
aload_0_internal();
|
||||
}
|
||||
|
||||
void TemplateTable::nofast_aload_0() {
|
||||
aload_0_internal(may_not_rewrite);
|
||||
}
|
||||
|
||||
void TemplateTable::aload_0_internal(RewriteControl rc) {
|
||||
transition(vtos, atos);
|
||||
// According to bytecode histograms, the pairs:
|
||||
//
|
||||
|
@ -838,7 +854,7 @@ void TemplateTable::aload_0() {
|
|||
// aload_0, iload_1
|
||||
// These bytecodes with a small amount of code are most profitable
|
||||
// to rewrite
|
||||
if (RewriteFrequentPairs) {
|
||||
if (RewriteFrequentPairs && rc == may_rewrite) {
|
||||
Label rewrite, done;
|
||||
|
||||
const Register bc = LP64_ONLY(c_rarg3) NOT_LP64(rcx);
|
||||
|
@ -2492,14 +2508,21 @@ void TemplateTable::resolve_cache_and_index(int byte_no,
|
|||
assert_different_registers(Rcache, index, temp);
|
||||
|
||||
Label resolved;
|
||||
assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range");
|
||||
__ get_cache_and_index_and_bytecode_at_bcp(Rcache, index, temp, byte_no, 1, index_size);
|
||||
__ cmpl(temp, (int) bytecode()); // have we resolved this bytecode?
|
||||
__ jcc(Assembler::equal, resolved);
|
||||
|
||||
Bytecodes::Code code = bytecode();
|
||||
switch (code) {
|
||||
case Bytecodes::_nofast_getfield: code = Bytecodes::_getfield; break;
|
||||
case Bytecodes::_nofast_putfield: code = Bytecodes::_putfield; break;
|
||||
}
|
||||
|
||||
assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range");
|
||||
__ get_cache_and_index_and_bytecode_at_bcp(Rcache, index, temp, byte_no, 1, index_size);
|
||||
__ cmpl(temp, code); // have we resolved this bytecode?
|
||||
__ jcc(Assembler::equal, resolved);
|
||||
|
||||
// resolve first time through
|
||||
address entry;
|
||||
switch (bytecode()) {
|
||||
switch (code) {
|
||||
case Bytecodes::_getstatic : // fall through
|
||||
case Bytecodes::_putstatic : // fall through
|
||||
case Bytecodes::_getfield : // fall through
|
||||
|
@ -2511,10 +2534,10 @@ void TemplateTable::resolve_cache_and_index(int byte_no,
|
|||
case Bytecodes::_invokehandle : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokehandle); break;
|
||||
case Bytecodes::_invokedynamic : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic); break;
|
||||
default:
|
||||
fatal(err_msg("unexpected bytecode: %s", Bytecodes::name(bytecode())));
|
||||
fatal(err_msg("unexpected bytecode: %s", Bytecodes::name(code)));
|
||||
break;
|
||||
}
|
||||
__ movl(temp, (int)bytecode());
|
||||
__ movl(temp, code);
|
||||
__ call_VM(noreg, entry, temp);
|
||||
// Update registers with resolved info
|
||||
__ get_cache_and_index_at_bcp(Rcache, index, 1, index_size);
|
||||
|
@ -2629,7 +2652,7 @@ void TemplateTable::pop_and_check_object(Register r) {
|
|||
__ verify_oop(r);
|
||||
}
|
||||
|
||||
void TemplateTable::getfield_or_static(int byte_no, bool is_static) {
|
||||
void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteControl rc) {
|
||||
transition(vtos, vtos);
|
||||
|
||||
const Register cache = rcx;
|
||||
|
@ -2661,7 +2684,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static) {
|
|||
__ load_signed_byte(rax, field);
|
||||
__ push(btos);
|
||||
// Rewrite bytecode to be faster
|
||||
if (!is_static) {
|
||||
if (!is_static && rc == may_rewrite) {
|
||||
patch_bytecode(Bytecodes::_fast_bgetfield, bc, rbx);
|
||||
}
|
||||
__ jmp(Done);
|
||||
|
@ -2672,7 +2695,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static) {
|
|||
// atos
|
||||
__ load_heap_oop(rax, field);
|
||||
__ push(atos);
|
||||
if (!is_static) {
|
||||
if (!is_static && rc == may_rewrite) {
|
||||
patch_bytecode(Bytecodes::_fast_agetfield, bc, rbx);
|
||||
}
|
||||
__ jmp(Done);
|
||||
|
@ -2684,7 +2707,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static) {
|
|||
__ movl(rax, field);
|
||||
__ push(itos);
|
||||
// Rewrite bytecode to be faster
|
||||
if (!is_static) {
|
||||
if (!is_static && rc == may_rewrite) {
|
||||
patch_bytecode(Bytecodes::_fast_igetfield, bc, rbx);
|
||||
}
|
||||
__ jmp(Done);
|
||||
|
@ -2696,7 +2719,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static) {
|
|||
__ load_unsigned_short(rax, field);
|
||||
__ push(ctos);
|
||||
// Rewrite bytecode to be faster
|
||||
if (!is_static) {
|
||||
if (!is_static && rc == may_rewrite) {
|
||||
patch_bytecode(Bytecodes::_fast_cgetfield, bc, rbx);
|
||||
}
|
||||
__ jmp(Done);
|
||||
|
@ -2708,7 +2731,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static) {
|
|||
__ load_signed_short(rax, field);
|
||||
__ push(stos);
|
||||
// Rewrite bytecode to be faster
|
||||
if (!is_static) {
|
||||
if (!is_static && rc == may_rewrite) {
|
||||
patch_bytecode(Bytecodes::_fast_sgetfield, bc, rbx);
|
||||
}
|
||||
__ jmp(Done);
|
||||
|
@ -2732,7 +2755,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static) {
|
|||
|
||||
__ push(ltos);
|
||||
// Rewrite bytecode to be faster
|
||||
LP64_ONLY(if (!is_static) patch_bytecode(Bytecodes::_fast_lgetfield, bc, rbx));
|
||||
LP64_ONLY(if (!is_static && rc == may_rewrite) patch_bytecode(Bytecodes::_fast_lgetfield, bc, rbx));
|
||||
__ jmp(Done);
|
||||
|
||||
__ bind(notLong);
|
||||
|
@ -2744,7 +2767,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static) {
|
|||
NOT_LP64(__ fld_s(field));
|
||||
__ push(ftos);
|
||||
// Rewrite bytecode to be faster
|
||||
if (!is_static) {
|
||||
if (!is_static && rc == may_rewrite) {
|
||||
patch_bytecode(Bytecodes::_fast_fgetfield, bc, rbx);
|
||||
}
|
||||
__ jmp(Done);
|
||||
|
@ -2759,7 +2782,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static) {
|
|||
NOT_LP64(__ fld_d(field));
|
||||
__ push(dtos);
|
||||
// Rewrite bytecode to be faster
|
||||
if (!is_static) {
|
||||
if (!is_static && rc == may_rewrite) {
|
||||
patch_bytecode(Bytecodes::_fast_dgetfield, bc, rbx);
|
||||
}
|
||||
#ifdef ASSERT
|
||||
|
@ -2780,6 +2803,10 @@ void TemplateTable::getfield(int byte_no) {
|
|||
getfield_or_static(byte_no, false);
|
||||
}
|
||||
|
||||
void TemplateTable::nofast_getfield(int byte_no) {
|
||||
getfield_or_static(byte_no, false, may_not_rewrite);
|
||||
}
|
||||
|
||||
void TemplateTable::getstatic(int byte_no) {
|
||||
getfield_or_static(byte_no, true);
|
||||
}
|
||||
|
@ -2871,7 +2898,7 @@ void TemplateTable::jvmti_post_field_mod(Register cache, Register index, bool is
|
|||
}
|
||||
}
|
||||
|
||||
void TemplateTable::putfield_or_static(int byte_no, bool is_static) {
|
||||
void TemplateTable::putfield_or_static(int byte_no, bool is_static, RewriteControl rc) {
|
||||
transition(vtos, vtos);
|
||||
|
||||
const Register cache = rcx;
|
||||
|
@ -2912,7 +2939,7 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static) {
|
|||
__ pop(btos);
|
||||
if (!is_static) pop_and_check_object(obj);
|
||||
__ movb(field, rax);
|
||||
if (!is_static) {
|
||||
if (!is_static && rc == may_rewrite) {
|
||||
patch_bytecode(Bytecodes::_fast_bputfield, bc, rbx, true, byte_no);
|
||||
}
|
||||
__ jmp(Done);
|
||||
|
@ -2928,7 +2955,7 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static) {
|
|||
if (!is_static) pop_and_check_object(obj);
|
||||
// Store into the field
|
||||
do_oop_store(_masm, field, rax, _bs->kind(), false);
|
||||
if (!is_static) {
|
||||
if (!is_static && rc == may_rewrite) {
|
||||
patch_bytecode(Bytecodes::_fast_aputfield, bc, rbx, true, byte_no);
|
||||
}
|
||||
__ jmp(Done);
|
||||
|
@ -2943,7 +2970,7 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static) {
|
|||
__ pop(itos);
|
||||
if (!is_static) pop_and_check_object(obj);
|
||||
__ movl(field, rax);
|
||||
if (!is_static) {
|
||||
if (!is_static && rc == may_rewrite) {
|
||||
patch_bytecode(Bytecodes::_fast_iputfield, bc, rbx, true, byte_no);
|
||||
}
|
||||
__ jmp(Done);
|
||||
|
@ -2958,7 +2985,7 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static) {
|
|||
__ pop(ctos);
|
||||
if (!is_static) pop_and_check_object(obj);
|
||||
__ movw(field, rax);
|
||||
if (!is_static) {
|
||||
if (!is_static && rc == may_rewrite) {
|
||||
patch_bytecode(Bytecodes::_fast_cputfield, bc, rbx, true, byte_no);
|
||||
}
|
||||
__ jmp(Done);
|
||||
|
@ -2973,7 +3000,7 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static) {
|
|||
__ pop(stos);
|
||||
if (!is_static) pop_and_check_object(obj);
|
||||
__ movw(field, rax);
|
||||
if (!is_static) {
|
||||
if (!is_static && rc == may_rewrite) {
|
||||
patch_bytecode(Bytecodes::_fast_sputfield, bc, rbx, true, byte_no);
|
||||
}
|
||||
__ jmp(Done);
|
||||
|
@ -2989,7 +3016,7 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static) {
|
|||
__ pop(ltos);
|
||||
if (!is_static) pop_and_check_object(obj);
|
||||
__ movq(field, rax);
|
||||
if (!is_static) {
|
||||
if (!is_static && rc == may_rewrite) {
|
||||
patch_bytecode(Bytecodes::_fast_lputfield, bc, rbx, true, byte_no);
|
||||
}
|
||||
__ jmp(Done);
|
||||
|
@ -3036,7 +3063,7 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static) {
|
|||
if (!is_static) pop_and_check_object(obj);
|
||||
NOT_LP64( __ fstp_s(field);)
|
||||
LP64_ONLY( __ movflt(field, xmm0);)
|
||||
if (!is_static) {
|
||||
if (!is_static && rc == may_rewrite) {
|
||||
patch_bytecode(Bytecodes::_fast_fputfield, bc, rbx, true, byte_no);
|
||||
}
|
||||
__ jmp(Done);
|
||||
|
@ -3054,7 +3081,7 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static) {
|
|||
if (!is_static) pop_and_check_object(obj);
|
||||
NOT_LP64( __ fstp_d(field);)
|
||||
LP64_ONLY( __ movdbl(field, xmm0);)
|
||||
if (!is_static) {
|
||||
if (!is_static && rc == may_rewrite) {
|
||||
patch_bytecode(Bytecodes::_fast_dputfield, bc, rbx, true, byte_no);
|
||||
}
|
||||
}
|
||||
|
@ -3080,6 +3107,10 @@ void TemplateTable::putfield(int byte_no) {
|
|||
putfield_or_static(byte_no, false);
|
||||
}
|
||||
|
||||
void TemplateTable::nofast_putfield(int byte_no) {
|
||||
putfield_or_static(byte_no, false, may_not_rewrite);
|
||||
}
|
||||
|
||||
void TemplateTable::putstatic(int byte_no) {
|
||||
putfield_or_static(byte_no, true);
|
||||
}
|
||||
|
|
|
@ -576,10 +576,10 @@ BytecodeInterpreter::run(interpreterState istate) {
|
|||
/* 0xD8 */ &&opc_default, &&opc_default, &&opc_default, &&opc_default,
|
||||
/* 0xDC */ &&opc_default, &&opc_default, &&opc_default, &&opc_default,
|
||||
|
||||
/* 0xE0 */ &&opc_default, &&opc_default, &&opc_default, &&opc_default,
|
||||
/* 0xE4 */ &&opc_default, &&opc_fast_aldc, &&opc_fast_aldc_w, &&opc_return_register_finalizer,
|
||||
/* 0xE8 */ &&opc_invokehandle,&&opc_default, &&opc_default, &&opc_default,
|
||||
/* 0xEC */ &&opc_default, &&opc_default, &&opc_default, &&opc_default,
|
||||
/* 0xE0 */ &&opc_default, &&opc_default, &&opc_default, &&opc_default,
|
||||
/* 0xE4 */ &&opc_default, &&opc_fast_aldc, &&opc_fast_aldc_w, &&opc_return_register_finalizer,
|
||||
/* 0xE8 */ &&opc_invokehandle,&&opc_nofast_getfield,&&opc_nofast_putfield, &&opc_nofast_aload_0,
|
||||
/* 0xEC */ &&opc_nofast_iload,&&opc_default, &&opc_default, &&opc_default,
|
||||
|
||||
/* 0xF0 */ &&opc_default, &&opc_default, &&opc_default, &&opc_default,
|
||||
/* 0xF4 */ &&opc_default, &&opc_default, &&opc_default, &&opc_default,
|
||||
|
|
|
@ -525,6 +525,12 @@ void Bytecodes::initialize() {
|
|||
def(_fast_aldc , "fast_aldc" , "bj" , NULL , T_OBJECT, 1, true, _ldc );
|
||||
def(_fast_aldc_w , "fast_aldc_w" , "bJJ" , NULL , T_OBJECT, 1, true, _ldc_w );
|
||||
|
||||
def(_nofast_getfield , "nofast_getfield" , "bJJ" , NULL , T_ILLEGAL, 0, true, _getfield );
|
||||
def(_nofast_putfield , "nofast_putfield" , "bJJ" , NULL , T_ILLEGAL, -2, true , _putfield );
|
||||
|
||||
def(_nofast_aload_0 , "nofast_aload_0" , "b" , NULL , T_ILLEGAL, 1, true , _aload_0 );
|
||||
def(_nofast_iload , "nofast_iload" , "bi" , NULL , T_ILLEGAL, 1, false, _iload );
|
||||
|
||||
def(_shouldnotreachhere , "_shouldnotreachhere" , "b" , NULL , T_VOID , 0, false);
|
||||
|
||||
// compare can_trap information for each bytecode with the
|
||||
|
|
|
@ -285,7 +285,20 @@ class Bytecodes: AllStatic {
|
|||
// special handling of signature-polymorphic methods:
|
||||
_invokehandle ,
|
||||
|
||||
_shouldnotreachhere, // For debugging
|
||||
// These bytecodes are rewritten at CDS dump time, so that we can prevent them from being
|
||||
// rewritten at run time. This way, the ConstMethods can be placed in the CDS ReadOnly
|
||||
// section, and RewriteByteCodes/RewriteFrequentPairs can rewrite non-CDS bytecodes
|
||||
// at run time.
|
||||
//
|
||||
// Rewritten at CDS dump time to | Original bytecode
|
||||
// _invoke_virtual rewritten on sparc, will be disabled if UseSharedSpaces turned on.
|
||||
// ------------------------------+------------------
|
||||
_nofast_getfield , // <- _getfield
|
||||
_nofast_putfield , // <- _putfield
|
||||
_nofast_aload_0 , // <- _aload_0
|
||||
_nofast_iload , // <- _iload
|
||||
|
||||
_shouldnotreachhere , // For debugging
|
||||
|
||||
|
||||
number_of_codes
|
||||
|
|
|
@ -541,7 +541,8 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_get_put(JavaThread* thread, Bytecode
|
|||
// resolve field
|
||||
fieldDescriptor info;
|
||||
constantPoolHandle pool(thread, method(thread)->constants());
|
||||
bool is_put = (bytecode == Bytecodes::_putfield || bytecode == Bytecodes::_putstatic);
|
||||
bool is_put = (bytecode == Bytecodes::_putfield || bytecode == Bytecodes::_nofast_putfield ||
|
||||
bytecode == Bytecodes::_putstatic);
|
||||
bool is_static = (bytecode == Bytecodes::_getstatic || bytecode == Bytecodes::_putstatic);
|
||||
|
||||
{
|
||||
|
|
|
@ -777,11 +777,11 @@ void LinkResolver::resolve_field(fieldDescriptor& fd, KlassHandle resolved_klass
|
|||
TRAPS) {
|
||||
assert(byte == Bytecodes::_getstatic || byte == Bytecodes::_putstatic ||
|
||||
byte == Bytecodes::_getfield || byte == Bytecodes::_putfield ||
|
||||
byte == Bytecodes::_nofast_getfield || byte == Bytecodes::_nofast_putfield ||
|
||||
(byte == Bytecodes::_nop && !check_access), "bad field access bytecode");
|
||||
|
||||
bool is_static = (byte == Bytecodes::_getstatic || byte == Bytecodes::_putstatic);
|
||||
bool is_put = (byte == Bytecodes::_putfield || byte == Bytecodes::_putstatic);
|
||||
|
||||
bool is_put = (byte == Bytecodes::_putfield || byte == Bytecodes::_putstatic || byte == Bytecodes::_nofast_putfield);
|
||||
// Check if there's a resolved klass containing the field
|
||||
if (resolved_klass.is_null()) {
|
||||
ResourceMark rm(THREAD);
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "interpreter/bytecodes.hpp"
|
||||
#include "interpreter/interpreter.hpp"
|
||||
#include "interpreter/rewriter.hpp"
|
||||
#include "memory/metaspaceShared.hpp"
|
||||
#include "memory/gcLocker.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "oops/generateOopMap.hpp"
|
||||
|
@ -167,12 +168,12 @@ void Rewriter::rewrite_invokespecial(address bcp, int offset, bool reverse, bool
|
|||
if (!reverse) {
|
||||
int cp_index = Bytes::get_Java_u2(p);
|
||||
if (_pool->tag_at(cp_index).is_interface_method()) {
|
||||
int cache_index = add_invokespecial_cp_cache_entry(cp_index);
|
||||
if (cache_index != (int)(jushort) cache_index) {
|
||||
*invokespecial_error = true;
|
||||
}
|
||||
Bytes::put_native_u2(p, cache_index);
|
||||
} else {
|
||||
int cache_index = add_invokespecial_cp_cache_entry(cp_index);
|
||||
if (cache_index != (int)(jushort) cache_index) {
|
||||
*invokespecial_error = true;
|
||||
}
|
||||
Bytes::put_native_u2(p, cache_index);
|
||||
} else {
|
||||
rewrite_member_reference(bcp, offset, reverse);
|
||||
}
|
||||
} else {
|
||||
|
@ -500,12 +501,14 @@ void Rewriter::rewrite_bytecodes(TRAPS) {
|
|||
}
|
||||
|
||||
void Rewriter::rewrite(instanceKlassHandle klass, TRAPS) {
|
||||
if (!DumpSharedSpaces) {
|
||||
assert(!MetaspaceShared::is_in_shared_space(klass()), "archive methods must not be rewritten at run time");
|
||||
}
|
||||
ResourceMark rm(THREAD);
|
||||
Rewriter rw(klass, klass->constants(), klass->methods(), CHECK);
|
||||
// (That's all, folks.)
|
||||
}
|
||||
|
||||
|
||||
Rewriter::Rewriter(instanceKlassHandle klass, constantPoolHandle cpool, Array<Method*>* methods, TRAPS)
|
||||
: _klass(klass),
|
||||
_pool(cpool),
|
||||
|
|
|
@ -517,6 +517,12 @@ void TemplateTable::initialize() {
|
|||
|
||||
def(Bytecodes::_invokehandle , ubcp|disp|clvm|____, vtos, vtos, invokehandle , f1_byte );
|
||||
|
||||
def(Bytecodes::_nofast_getfield , ubcp|____|clvm|____, vtos, vtos, nofast_getfield , f1_byte );
|
||||
def(Bytecodes::_nofast_putfield , ubcp|____|clvm|____, vtos, vtos, nofast_putfield , f2_byte );
|
||||
|
||||
def(Bytecodes::_nofast_aload_0 , ____|____|clvm|____, vtos, atos, nofast_aload_0 , _ );
|
||||
def(Bytecodes::_nofast_iload , ubcp|____|clvm|____, vtos, itos, nofast_iload , _ );
|
||||
|
||||
def(Bytecodes::_shouldnotreachhere , ____|____|____|____, vtos, vtos, shouldnotreachhere , _ );
|
||||
// platform specific bytecodes
|
||||
pd_initialize();
|
||||
|
|
|
@ -82,6 +82,7 @@ class TemplateTable: AllStatic {
|
|||
enum Operation { add, sub, mul, div, rem, _and, _or, _xor, shl, shr, ushr };
|
||||
enum Condition { equal, not_equal, less, less_equal, greater, greater_equal };
|
||||
enum CacheByte { f1_byte = 1, f2_byte = 2 }; // byte_no codes
|
||||
enum RewriteControl { may_rewrite, may_not_rewrite }; // control for fast code under CDS
|
||||
|
||||
private:
|
||||
static bool _is_initialized; // true if TemplateTable has been initialized
|
||||
|
@ -165,6 +166,10 @@ class TemplateTable: AllStatic {
|
|||
static void dload(int n);
|
||||
static void aload(int n);
|
||||
static void aload_0();
|
||||
static void nofast_aload_0();
|
||||
static void nofast_iload();
|
||||
static void iload_internal(RewriteControl rc = may_rewrite);
|
||||
static void aload_0_internal(RewriteControl rc = may_rewrite);
|
||||
|
||||
static void istore();
|
||||
static void lstore();
|
||||
|
@ -279,10 +284,13 @@ class TemplateTable: AllStatic {
|
|||
static void invokehandle(int byte_no);
|
||||
static void fast_invokevfinal(int byte_no);
|
||||
|
||||
static void getfield_or_static(int byte_no, bool is_static);
|
||||
static void putfield_or_static(int byte_no, bool is_static);
|
||||
static void getfield_or_static(int byte_no, bool is_static, RewriteControl rc = may_rewrite);
|
||||
static void putfield_or_static(int byte_no, bool is_static, RewriteControl rc = may_rewrite);
|
||||
|
||||
static void getfield(int byte_no);
|
||||
static void putfield(int byte_no);
|
||||
static void nofast_getfield(int byte_no);
|
||||
static void nofast_putfield(int byte_no);
|
||||
static void getstatic(int byte_no);
|
||||
static void putstatic(int byte_no);
|
||||
static void pop_and_check_object(Register obj);
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
#include "classfile/symbolTable.hpp"
|
||||
#include "classfile/systemDictionary.hpp"
|
||||
#include "code/codeCache.hpp"
|
||||
#include "interpreter/bytecodes.hpp"
|
||||
#include "interpreter/bytecodeStream.hpp"
|
||||
#include "memory/filemap.hpp"
|
||||
#include "memory/gcLocker.hpp"
|
||||
#include "memory/metaspace.hpp"
|
||||
|
@ -104,15 +106,33 @@ static void remove_unshareable_in_classes() {
|
|||
}
|
||||
}
|
||||
|
||||
// Walk all methods in the class list and assign a fingerprint.
|
||||
// so that this part of the ConstMethod* is read only.
|
||||
static void calculate_fingerprints() {
|
||||
static void rewrite_nofast_bytecode(Method* method) {
|
||||
RawBytecodeStream bcs(method);
|
||||
while (!bcs.is_last_bytecode()) {
|
||||
Bytecodes::Code opcode = bcs.raw_next();
|
||||
switch (opcode) {
|
||||
case Bytecodes::_getfield: *bcs.bcp() = Bytecodes::_nofast_getfield; break;
|
||||
case Bytecodes::_putfield: *bcs.bcp() = Bytecodes::_nofast_putfield; break;
|
||||
case Bytecodes::_aload_0: *bcs.bcp() = Bytecodes::_nofast_aload_0; break;
|
||||
case Bytecodes::_iload: *bcs.bcp() = Bytecodes::_nofast_iload; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Walk all methods in the class list to ensure that they won't be modified at
|
||||
// run time. This includes:
|
||||
// [1] Rewrite all bytecodes as needed, so that the ConstMethod* will not be modified
|
||||
// at run time by RewriteBytecodes/RewriteFrequentPairs
|
||||
// [2] Assign a fingerprint, so one doesn't need to be assigned at run-time.
|
||||
static void rewrite_nofast_bytecodes_and_calculate_fingerprints() {
|
||||
for (int i = 0; i < _global_klass_objects->length(); i++) {
|
||||
Klass* k = _global_klass_objects->at(i);
|
||||
if (k->oop_is_instance()) {
|
||||
InstanceKlass* ik = InstanceKlass::cast(k);
|
||||
for (int i = 0; i < ik->methods()->length(); i++) {
|
||||
Method* m = ik->methods()->at(i);
|
||||
rewrite_nofast_bytecode(m);
|
||||
Fingerprinter fp(m);
|
||||
// The side effect of this call sets method's fingerprint field.
|
||||
fp.fingerprint();
|
||||
|
@ -476,9 +496,10 @@ void VM_PopulateDumpSharedSpace::doit() {
|
|||
tty->print_cr(" type array classes = %5d", num_type_array);
|
||||
}
|
||||
|
||||
// Update all the fingerprints in the shared methods.
|
||||
tty->print("Calculating fingerprints ... ");
|
||||
calculate_fingerprints();
|
||||
|
||||
// Ensure the ConstMethods won't be modified at run-time
|
||||
tty->print("Updating ConstMethods ... ");
|
||||
rewrite_nofast_bytecodes_and_calculate_fingerprints();
|
||||
tty->print_cr("done. ");
|
||||
|
||||
// Remove all references outside the metadata
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
// processes in a read-only section with Class Data Sharing (CDS). It's important
|
||||
// that this class doesn't have virtual functions because the vptr cannot be shared
|
||||
// with CDS.
|
||||
// (*)RewriteByteCodes and RewriteFrequentPairs is an exception but turned off in CDS
|
||||
//
|
||||
// Note that most applications load thousands of methods, so keeping the size of this
|
||||
// structure small has a big impact on footprint.
|
||||
|
|
|
@ -1848,15 +1848,8 @@ void Arguments::set_heap_size() {
|
|||
}
|
||||
}
|
||||
|
||||
// This must be called after ergonomics because we want bytecode rewriting
|
||||
// if the server compiler is used, or if UseSharedSpaces is disabled.
|
||||
// This must be called after ergonomics.
|
||||
void Arguments::set_bytecode_flags() {
|
||||
// Better not attempt to store into a read-only space.
|
||||
if (UseSharedSpaces) {
|
||||
FLAG_SET_DEFAULT(RewriteBytecodes, false);
|
||||
FLAG_SET_DEFAULT(RewriteFrequentPairs, false);
|
||||
}
|
||||
|
||||
if (!RewriteBytecodes) {
|
||||
FLAG_SET_DEFAULT(RewriteFrequentPairs, false);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue