Mercurial > hg > graal-compiler
diff src/cpu/sparc/vm/assembler_sparc.cpp @ 6266:1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
6984705: JSR 292 method handle creation should not go through JNI
Summary: remove assembly code for JDK 7 chained method handles
Reviewed-by: jrose, twisti, kvn, mhaupt
Contributed-by: John Rose <john.r.rose@oracle.com>, Christian Thalinger <christian.thalinger@oracle.com>, Michael Haupt <michael.haupt@oracle.com>
author | twisti |
---|---|
date | Tue, 24 Jul 2012 10:51:00 -0700 |
parents | 069ab3f976d3 |
children | 957c266d8bc5 da91efe96a93 |
line wrap: on
line diff
--- a/src/cpu/sparc/vm/assembler_sparc.cpp Mon Jul 23 13:04:59 2012 -0700 +++ b/src/cpu/sparc/vm/assembler_sparc.cpp Tue Jul 24 10:51:00 2012 -0700 @@ -44,8 +44,10 @@ #ifdef PRODUCT #define BLOCK_COMMENT(str) /* nothing */ +#define STOP(error) stop(error) #else #define BLOCK_COMMENT(str) block_comment(str) +#define STOP(error) block_comment(error); stop(error) #endif // Convert the raw encoding form into the form expected by the @@ -992,7 +994,7 @@ save_frame(0); // to avoid clobbering O0 ld_ptr(pc_addr, L0); br_null_short(L0, Assembler::pt, PcOk); - stop("last_Java_pc not zeroed before leaving Java"); + STOP("last_Java_pc not zeroed before leaving Java"); bind(PcOk); // Verify that flags was zeroed on return to Java @@ -1001,7 +1003,7 @@ tst(L0); br(Assembler::zero, false, Assembler::pt, FlagsOk); delayed() -> restore(); - stop("flags not zeroed before leaving Java"); + STOP("flags not zeroed before leaving Java"); bind(FlagsOk); #endif /* ASSERT */ // @@ -1021,7 +1023,7 @@ andcc(last_java_sp, 0x01, G0); br(Assembler::notZero, false, Assembler::pt, StackOk); delayed()->nop(); - stop("Stack Not Biased in set_last_Java_frame"); + STOP("Stack Not Biased in set_last_Java_frame"); bind(StackOk); #endif // ASSERT assert( last_java_sp != G4_scratch, "bad register usage in set_last_Java_frame"); @@ -1650,23 +1652,28 @@ void RegistersForDebugging::print(outputStream* s) { + FlagSetting fs(Debugging, true); int j; - for ( j = 0; j < 8; ++j ) - if ( j != 6 ) s->print_cr("i%d = 0x%.16lx", j, i[j]); - else s->print_cr( "fp = 0x%.16lx", i[j]); - s->cr(); - - for ( j = 0; j < 8; ++j ) - s->print_cr("l%d = 0x%.16lx", j, l[j]); + for (j = 0; j < 8; ++j) { + if (j != 6) { s->print("i%d = ", j); os::print_location(s, i[j]); } + else { s->print( "fp = " ); os::print_location(s, i[j]); } + } s->cr(); - for ( j = 0; j < 8; ++j ) - if ( j != 6 ) s->print_cr("o%d = 0x%.16lx", j, o[j]); - else s->print_cr( "sp = 0x%.16lx", o[j]); + for (j = 0; j < 8; ++j) { + s->print("l%d = ", j); os::print_location(s, l[j]); + } s->cr(); - for ( j = 0; j < 8; ++j ) - s->print_cr("g%d = 0x%.16lx", j, g[j]); + for (j = 0; j < 8; ++j) { + if (j != 6) { s->print("o%d = ", j); os::print_location(s, o[j]); } + else { s->print( "sp = " ); os::print_location(s, o[j]); } + } + s->cr(); + + for (j = 0; j < 8; ++j) { + s->print("g%d = ", j); os::print_location(s, g[j]); + } s->cr(); // print out floats with compression @@ -2020,8 +2027,8 @@ char* b = new char[1024]; sprintf(b, "untested: %s", what); - if ( ShowMessageBoxOnError ) stop(b); - else warn(b); + if (ShowMessageBoxOnError) { STOP(b); } + else { warn(b); } } @@ -2998,26 +3005,60 @@ } +// virtual method calling +void MacroAssembler::lookup_virtual_method(Register recv_klass, + RegisterOrConstant vtable_index, + Register method_result) { + assert_different_registers(recv_klass, method_result, vtable_index.register_or_noreg()); + Register sethi_temp = method_result; + const int base = (instanceKlass::vtable_start_offset() * wordSize + + // method pointer offset within the vtable entry: + vtableEntry::method_offset_in_bytes()); + RegisterOrConstant vtable_offset = vtable_index; + // Each of the following three lines potentially generates an instruction. + // But the total number of address formation instructions will always be + // at most two, and will often be zero. In any case, it will be optimal. + // If vtable_index is a register, we will have (sll_ptr N,x; inc_ptr B,x; ld_ptr k,x). + // If vtable_index is a constant, we will have at most (set B+X<<N,t; ld_ptr k,t). + vtable_offset = regcon_sll_ptr(vtable_index, exact_log2(vtableEntry::size() * wordSize), vtable_offset); + vtable_offset = regcon_inc_ptr(vtable_offset, base, vtable_offset, sethi_temp); + Address vtable_entry_addr(recv_klass, ensure_simm13_or_reg(vtable_offset, sethi_temp)); + ld_ptr(vtable_entry_addr, method_result); +} + + void MacroAssembler::check_klass_subtype(Register sub_klass, Register super_klass, Register temp_reg, Register temp2_reg, Label& L_success) { - Label L_failure, L_pop_to_failure; - check_klass_subtype_fast_path(sub_klass, super_klass, - temp_reg, temp2_reg, - &L_success, &L_failure, NULL); Register sub_2 = sub_klass; Register sup_2 = super_klass; if (!sub_2->is_global()) sub_2 = L0; if (!sup_2->is_global()) sup_2 = L1; - - save_frame_and_mov(0, sub_klass, sub_2, super_klass, sup_2); + bool did_save = false; + if (temp_reg == noreg || temp2_reg == noreg) { + temp_reg = L2; + temp2_reg = L3; + save_frame_and_mov(0, sub_klass, sub_2, super_klass, sup_2); + sub_klass = sub_2; + super_klass = sup_2; + did_save = true; + } + Label L_failure, L_pop_to_failure, L_pop_to_success; + check_klass_subtype_fast_path(sub_klass, super_klass, + temp_reg, temp2_reg, + (did_save ? &L_pop_to_success : &L_success), + (did_save ? &L_pop_to_failure : &L_failure), NULL); + + if (!did_save) + save_frame_and_mov(0, sub_klass, sub_2, super_klass, sup_2); check_klass_subtype_slow_path(sub_2, sup_2, L2, L3, L4, L5, NULL, &L_pop_to_failure); // on success: + bind(L_pop_to_success); restore(); ba_short(L_success); @@ -3234,54 +3275,6 @@ } -void MacroAssembler::check_method_handle_type(Register mtype_reg, Register mh_reg, - Register temp_reg, - Label& wrong_method_type) { - assert_different_registers(mtype_reg, mh_reg, temp_reg); - // compare method type against that of the receiver - RegisterOrConstant mhtype_offset = delayed_value(java_lang_invoke_MethodHandle::type_offset_in_bytes, temp_reg); - load_heap_oop(mh_reg, mhtype_offset, temp_reg); - cmp_and_brx_short(temp_reg, mtype_reg, Assembler::notEqual, Assembler::pn, wrong_method_type); -} - - -// A method handle has a "vmslots" field which gives the size of its -// argument list in JVM stack slots. This field is either located directly -// in every method handle, or else is indirectly accessed through the -// method handle's MethodType. This macro hides the distinction. -void MacroAssembler::load_method_handle_vmslots(Register vmslots_reg, Register mh_reg, - Register temp_reg) { - assert_different_registers(vmslots_reg, mh_reg, temp_reg); - // load mh.type.form.vmslots - Register temp2_reg = vmslots_reg; - load_heap_oop(Address(mh_reg, delayed_value(java_lang_invoke_MethodHandle::type_offset_in_bytes, temp_reg)), temp2_reg); - load_heap_oop(Address(temp2_reg, delayed_value(java_lang_invoke_MethodType::form_offset_in_bytes, temp_reg)), temp2_reg); - ld( Address(temp2_reg, delayed_value(java_lang_invoke_MethodTypeForm::vmslots_offset_in_bytes, temp_reg)), vmslots_reg); -} - - -void MacroAssembler::jump_to_method_handle_entry(Register mh_reg, Register temp_reg, bool emit_delayed_nop) { - assert(mh_reg == G3_method_handle, "caller must put MH object in G3"); - assert_different_registers(mh_reg, temp_reg); - - // pick out the interpreted side of the handler - // NOTE: vmentry is not an oop! - ld_ptr(mh_reg, delayed_value(java_lang_invoke_MethodHandle::vmentry_offset_in_bytes, temp_reg), temp_reg); - - // off we go... - ld_ptr(temp_reg, MethodHandleEntry::from_interpreted_entry_offset_in_bytes(), temp_reg); - jmp(temp_reg, 0); - - // for the various stubs which take control at this point, - // see MethodHandles::generate_method_handle_stub - - // Some callers can fill the delay slot. - if (emit_delayed_nop) { - delayed()->nop(); - } -} - - RegisterOrConstant MacroAssembler::argument_offset(RegisterOrConstant arg_slot, Register temp_reg, int extra_slot_offset) { @@ -3914,7 +3907,7 @@ ld_ptr(G2_thread, in_bytes(JavaThread::tlab_start_offset()), t2); or3(t1, t2, t3); cmp_and_br_short(t1, t2, Assembler::greaterEqual, Assembler::pn, next); - stop("assert(top >= start)"); + STOP("assert(top >= start)"); should_not_reach_here(); bind(next); @@ -3922,13 +3915,13 @@ ld_ptr(G2_thread, in_bytes(JavaThread::tlab_end_offset()), t2); or3(t3, t2, t3); cmp_and_br_short(t1, t2, Assembler::lessEqual, Assembler::pn, next2); - stop("assert(top <= end)"); + STOP("assert(top <= end)"); should_not_reach_here(); bind(next2); and3(t3, MinObjAlignmentInBytesMask, t3); cmp_and_br_short(t3, 0, Assembler::lessEqual, Assembler::pn, ok); - stop("assert(aligned)"); + STOP("assert(aligned)"); should_not_reach_here(); bind(ok); @@ -3976,7 +3969,7 @@ btst(MinObjAlignmentInBytesMask, obj); br(Assembler::zero, false, Assembler::pt, L); delayed()->nop(); - stop("eden top is not properly aligned"); + STOP("eden top is not properly aligned"); bind(L); } #endif // ASSERT @@ -4013,7 +4006,7 @@ btst(MinObjAlignmentInBytesMask, top_addr); br(Assembler::zero, false, Assembler::pt, L); delayed()->nop(); - stop("eden top is not properly aligned"); + STOP("eden top is not properly aligned"); bind(L); } #endif // ASSERT @@ -4066,7 +4059,7 @@ btst(MinObjAlignmentInBytesMask, free); br(Assembler::zero, false, Assembler::pt, L); delayed()->nop(); - stop("updated TLAB free is not properly aligned"); + STOP("updated TLAB free is not properly aligned"); bind(L); } #endif // ASSERT @@ -4164,7 +4157,7 @@ ld_ptr(G2_thread, in_bytes(JavaThread::tlab_size_offset()), t2); sll_ptr(t2, LogHeapWordSize, t2); cmp_and_br_short(t1, t2, Assembler::equal, Assembler::pt, ok); - stop("assert(t1 == tlab_size)"); + STOP("assert(t1 == tlab_size)"); should_not_reach_here(); bind(ok);