# HG changeset patch # User twisti # Date 1274435964 25200 # Node ID b862d1f189bd012c0c20878e834461f95fa038a5 # Parent 5435e77aa3df806763d0c5605c06da99f32fe23e 6930772: JSR 292 needs to support SPARC C1 Summary: C1 for SPARC needs to support JSR 292. Reviewed-by: never, jrose diff -r 5435e77aa3df -r b862d1f189bd hotspot/src/cpu/sparc/vm/assembler_sparc.hpp --- a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp Thu May 20 06:34:23 2010 -0700 +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp Fri May 21 02:59:24 2010 -0700 @@ -87,6 +87,7 @@ // JSR 292 fixed register usages: REGISTER_DECLARATION(Register, G5_method_type , G5); REGISTER_DECLARATION(Register, G3_method_handle , G3); +REGISTER_DECLARATION(Register, L7_mh_SP_save , L7); // The compiler requires that G5_megamorphic_method is G5_inline_cache_klass, // because a single patchable "set" instruction (NativeMovConstReg, diff -r 5435e77aa3df -r b862d1f189bd hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.cpp Thu May 20 06:34:23 2010 -0700 +++ b/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.cpp Fri May 21 02:59:24 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -345,6 +345,13 @@ } +// JSR 292 +LIR_Opr FrameMap::method_handle_invoke_SP_save_opr() { + assert(L7 == L7_mh_SP_save, "must be same register"); + return L7_opr; +} + + bool FrameMap::validate_frame() { int max_offset = in_bytes(framesize_in_bytes()); int java_index = 0; diff -r 5435e77aa3df -r b862d1f189bd hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.hpp --- a/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.hpp Thu May 20 06:34:23 2010 -0700 +++ b/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.hpp Fri May 21 02:59:24 2010 -0700 @@ -143,6 +143,3 @@ static bool is_caller_save_register (LIR_Opr reg); static bool is_caller_save_register (Register r); - - // JSR 292 - static LIR_Opr& method_handle_invoke_SP_save_opr() { return L7_opr; } diff -r 5435e77aa3df -r b862d1f189bd hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Thu May 20 06:34:23 2010 -0700 +++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Fri May 21 02:59:24 2010 -0700 @@ -736,7 +736,8 @@ void LIR_Assembler::call(LIR_OpJavaCall* op, relocInfo::relocType rtype) { __ call(op->addr(), rtype); - // the peephole pass fills the delay slot + // The peephole pass fills the delay slot, add_call_info is done in + // LIR_Assembler::emit_delay. } @@ -745,7 +746,8 @@ __ set_oop((jobject)Universe::non_oop_word(), G5_inline_cache_reg); __ relocate(rspec); __ call(op->addr(), relocInfo::none); - // the peephole pass fills the delay slot + // The peephole pass fills the delay slot, add_call_info is done in + // LIR_Assembler::emit_delay. } @@ -766,16 +768,6 @@ } -void LIR_Assembler::preserve_SP(LIR_OpJavaCall* op) { - Unimplemented(); -} - - -void LIR_Assembler::restore_SP(LIR_OpJavaCall* op) { - Unimplemented(); -} - - // load with 32-bit displacement int LIR_Assembler::load(Register s, int disp, Register d, BasicType ld_type, CodeEmitInfo *info) { int load_offset = code_offset(); @@ -2934,7 +2926,7 @@ // we may also be emitting the call info for the instruction // which we are the delay slot of. - CodeEmitInfo * call_info = op->call_info(); + CodeEmitInfo* call_info = op->call_info(); if (call_info) { add_call_info(code_offset(), call_info); } @@ -3159,6 +3151,7 @@ tty->print_cr("delayed"); inst->at(i - 1)->print(); inst->at(i)->print(); + tty->cr(); } #endif continue; @@ -3174,8 +3167,8 @@ case lir_static_call: case lir_virtual_call: case lir_icvirtual_call: - case lir_optvirtual_call: { - LIR_Op* delay_op = NULL; + case lir_optvirtual_call: + case lir_dynamic_call: { LIR_Op* prev = inst->at(i - 1); if (LIRFillDelaySlots && prev && prev->code() == lir_move && prev->info() == NULL && (op->code() != lir_virtual_call || @@ -3192,15 +3185,14 @@ tty->print_cr("delayed"); inst->at(i - 1)->print(); inst->at(i)->print(); + tty->cr(); } #endif continue; } - if (!delay_op) { - delay_op = new LIR_OpDelay(new LIR_Op0(lir_nop), op->as_OpJavaCall()->info()); - inst->insert_before(i + 1, delay_op); - } + LIR_Op* delay_op = new LIR_OpDelay(new LIR_Op0(lir_nop), op->as_OpJavaCall()->info()); + inst->insert_before(i + 1, delay_op); break; } } diff -r 5435e77aa3df -r b862d1f189bd hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp Thu May 20 06:34:23 2010 -0700 +++ b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp Fri May 21 02:59:24 2010 -0700 @@ -679,8 +679,15 @@ __ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), G2_thread, Oissuing_pc->after_save()); __ verify_not_null_oop(Oexception->after_save()); - __ jmp(O0, 0); - __ delayed()->restore(); + + // Restore SP from L7 if the exception PC is a MethodHandle call site. + __ mov(O0, G5); // Save the target address. + __ lduw(Address(G2_thread, JavaThread::is_method_handle_return_offset()), L0); + __ tst(L0); // Condition codes are preserved over the restore. + __ restore(); + + __ jmp(G5, 0); + __ delayed()->movcc(Assembler::notZero, false, Assembler::icc, L7_mh_SP_save, SP); // Restore SP if required. } break; diff -r 5435e77aa3df -r b862d1f189bd hotspot/src/cpu/sparc/vm/frame_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/frame_sparc.cpp Thu May 20 06:34:23 2010 -0700 +++ b/hotspot/src/cpu/sparc/vm/frame_sparc.cpp Fri May 21 02:59:24 2010 -0700 @@ -336,9 +336,11 @@ #endif // ASSERT } -frame::frame(intptr_t* sp, intptr_t* younger_sp, bool younger_frame_adjusted_stack) { - _sp = sp; - _younger_sp = younger_sp; +frame::frame(intptr_t* sp, intptr_t* younger_sp, bool younger_frame_is_interpreted) : + _sp(sp), + _younger_sp(younger_sp), + _deopt_state(unknown), + _sp_adjustment_by_callee(0) { if (younger_sp == NULL) { // make a deficient frame which doesn't know where its PC is _pc = NULL; @@ -352,20 +354,32 @@ // wrong. (the _last_native_pc will have the right value) // So do not put add any asserts on the _pc here. } - if (younger_frame_adjusted_stack) { - // compute adjustment to this frame's SP made by its interpreted callee - _sp_adjustment_by_callee = (intptr_t*)((intptr_t)younger_sp[I5_savedSP->sp_offset_in_saved_window()] + - STACK_BIAS) - sp; - } else { - _sp_adjustment_by_callee = 0; + + if (_pc != NULL) + _cb = CodeCache::find_blob(_pc); + + // Check for MethodHandle call sites. + if (_cb != NULL) { + nmethod* nm = _cb->as_nmethod_or_null(); + if (nm != NULL) { + if (nm->is_deopt_mh_entry(_pc) || nm->is_method_handle_return(_pc)) { + _sp_adjustment_by_callee = (intptr_t*) ((intptr_t) sp[L7_mh_SP_save->sp_offset_in_saved_window()] + STACK_BIAS) - sp; + // The SP is already adjusted by this MH call site, don't + // overwrite this value with the wrong interpreter value. + younger_frame_is_interpreted = false; + } + } } - _deopt_state = unknown; + if (younger_frame_is_interpreted) { + // compute adjustment to this frame's SP made by its interpreted callee + _sp_adjustment_by_callee = (intptr_t*) ((intptr_t) younger_sp[I5_savedSP->sp_offset_in_saved_window()] + STACK_BIAS) - sp; + } - // It is important that frame be fully construct when we do this lookup - // as get_original_pc() needs correct value for unextended_sp() + // It is important that the frame is fully constructed when we do + // this lookup as get_deopt_original_pc() needs a correct value for + // unextended_sp() which uses _sp_adjustment_by_callee. if (_pc != NULL) { - _cb = CodeCache::find_blob(_pc); address original_pc = nmethod::get_deopt_original_pc(this); if (original_pc != NULL) { _pc = original_pc; @@ -462,9 +476,8 @@ if (is_entry_frame()) return sender_for_entry_frame(map); - intptr_t* younger_sp = sp(); - intptr_t* sp = sender_sp(); - bool adjusted_stack = false; + intptr_t* younger_sp = sp(); + intptr_t* sp = sender_sp(); // Note: The version of this operation on any platform with callee-save // registers must update the register map (if not null). @@ -483,8 +496,8 @@ // interpreted but its pc is in the code cache (for c1 -> osr_frame_return_id stub), so it must be // explicitly recognized. - adjusted_stack = is_interpreted_frame(); - if (adjusted_stack) { + bool frame_is_interpreted = is_interpreted_frame(); + if (frame_is_interpreted) { map->make_integer_regs_unsaved(); map->shift_window(sp, younger_sp); } else if (_cb != NULL) { @@ -503,7 +516,7 @@ } } } - return frame(sp, younger_sp, adjusted_stack); + return frame(sp, younger_sp, frame_is_interpreted); } diff -r 5435e77aa3df -r b862d1f189bd hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp Thu May 20 06:34:23 2010 -0700 +++ b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp Fri May 21 02:59:24 2010 -0700 @@ -375,10 +375,10 @@ Register O0_scratch = O0_argslot; int stackElementSize = Interpreter::stackElementSize; - // Make space on the stack for the arguments. - __ sub(SP, 4*stackElementSize, SP); - __ sub(Gargs, 3*stackElementSize, Gargs); - //__ sub(Lesp, 3*stackElementSize, Lesp); + // Make space on the stack for the arguments and set Gargs + // correctly. + __ sub(SP, 4*stackElementSize, SP); // Keep stack aligned. + __ add(SP, (frame::varargs_offset)*wordSize - 1*Interpreter::stackElementSize + STACK_BIAS + BytesPerWord, Gargs); // void raiseException(int code, Object actual, Object required) __ st( O1_scratch, Address(Gargs, 2*stackElementSize)); // code diff -r 5435e77aa3df -r b862d1f189bd hotspot/src/cpu/sparc/vm/register_definitions_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/register_definitions_sparc.cpp Thu May 20 06:34:23 2010 -0700 +++ b/hotspot/src/cpu/sparc/vm/register_definitions_sparc.cpp Fri May 21 02:59:24 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2002-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -142,9 +142,12 @@ REGISTER_DEFINITION(Register, G3_scratch); REGISTER_DEFINITION(Register, G4_scratch); REGISTER_DEFINITION(Register, Gtemp); +REGISTER_DEFINITION(Register, Lentry_args); + +// JSR 292 REGISTER_DEFINITION(Register, G5_method_type); REGISTER_DEFINITION(Register, G3_method_handle); -REGISTER_DEFINITION(Register, Lentry_args); +REGISTER_DEFINITION(Register, L7_mh_SP_save); #ifdef CC_INTERP REGISTER_DEFINITION(Register, Lstate); diff -r 5435e77aa3df -r b862d1f189bd hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Thu May 20 06:34:23 2010 -0700 +++ b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Fri May 21 02:59:24 2010 -0700 @@ -908,26 +908,13 @@ // O0-O5 - Outgoing args in compiled layout // O6 - Adjusted or restored SP // O7 - Valid return address - // L0-L7, I0-I7 - Caller's temps (no frame pushed yet) + // L0-L7, I0-I7 - Caller's temps (no frame pushed yet) // F0-F7 - more outgoing args // Gargs is the incoming argument base, and also an outgoing argument. __ sub(Gargs, BytesPerWord, Gargs); -#ifdef ASSERT - { - // on entry OsavedSP and SP should be equal - Label ok; - __ cmp(O5_savedSP, SP); - __ br(Assembler::equal, false, Assembler::pt, ok); - __ delayed()->nop(); - __ stop("I5_savedSP not set"); - __ should_not_reach_here(); - __ bind(ok); - } -#endif - // ON ENTRY TO THE CODE WE ARE MAKING, WE HAVE AN INTERPRETED FRAME // WITH O7 HOLDING A VALID RETURN PC // diff -r 5435e77aa3df -r b862d1f189bd hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp Thu May 20 06:34:23 2010 -0700 +++ b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp Fri May 21 02:59:24 2010 -0700 @@ -2911,16 +2911,6 @@ // arraycopy stubs used by compilers generate_arraycopy_stubs(); - // generic method handle stubs - if (EnableMethodHandles && SystemDictionary::MethodHandle_klass() != NULL) { - for (MethodHandles::EntryKind ek = MethodHandles::_EK_FIRST; - ek < MethodHandles::_EK_LIMIT; - ek = MethodHandles::EntryKind(1 + (int)ek)) { - StubCodeMark mark(this, "MethodHandle", MethodHandles::entry_name(ek)); - MethodHandles::generate_method_handle_stub(_masm, ek); - } - } - // Don't initialize the platform math functions since sparc // doesn't have intrinsics for these operations. } diff -r 5435e77aa3df -r b862d1f189bd hotspot/src/cpu/sparc/vm/stubRoutines_sparc.hpp --- a/hotspot/src/cpu/sparc/vm/stubRoutines_sparc.hpp Thu May 20 06:34:23 2010 -0700 +++ b/hotspot/src/cpu/sparc/vm/stubRoutines_sparc.hpp Fri May 21 02:59:24 2010 -0700 @@ -43,7 +43,7 @@ // MethodHandles adapters enum method_handles_platform_dependent_constants { - method_handles_adapters_code_size = 5000 + method_handles_adapters_code_size = 6000 }; class Sparc { diff -r 5435e77aa3df -r b862d1f189bd hotspot/src/cpu/x86/vm/assembler_x86.hpp --- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp Thu May 20 06:34:23 2010 -0700 +++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp Fri May 21 02:59:24 2010 -0700 @@ -135,6 +135,9 @@ #endif // _LP64 +// JSR 292 fixed register usages: +REGISTER_DECLARATION(Register, rbp_mh_SP_save, rbp); + // Address is an abstraction used to represent a memory location // using any of the amd64 addressing modes with one object. // diff -r 5435e77aa3df -r b862d1f189bd hotspot/src/cpu/x86/vm/c1_FrameMap_x86.cpp --- a/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.cpp Thu May 20 06:34:23 2010 -0700 +++ b/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.cpp Fri May 21 02:59:24 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -309,6 +309,13 @@ } +// JSR 292 +LIR_Opr FrameMap::method_handle_invoke_SP_save_opr() { + assert(rbp == rbp_mh_SP_save, "must be same register"); + return rbp_opr; +} + + bool FrameMap::validate_frame() { return true; } diff -r 5435e77aa3df -r b862d1f189bd hotspot/src/cpu/x86/vm/c1_FrameMap_x86.hpp --- a/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.hpp Thu May 20 06:34:23 2010 -0700 +++ b/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.hpp Fri May 21 02:59:24 2010 -0700 @@ -126,6 +126,3 @@ assert(i >= 0 && i < nof_caller_save_xmm_regs, "out of bounds"); return _caller_save_xmm_regs[i]; } - - // JSR 292 - static LIR_Opr& method_handle_invoke_SP_save_opr() { return rbp_opr; } diff -r 5435e77aa3df -r b862d1f189bd hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp --- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Thu May 20 06:34:23 2010 -0700 +++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Fri May 21 02:59:24 2010 -0700 @@ -2784,7 +2784,7 @@ assert(!os::is_MP() || (__ offset() + NativeCall::displacement_offset) % BytesPerWord == 0, "must be aligned"); __ call(AddressLiteral(op->addr(), rtype)); - add_call_info(code_offset(), op->info(), op->is_method_handle_invoke()); + add_call_info(code_offset(), op->info()); } @@ -2795,7 +2795,7 @@ (__ offset() + NativeCall::displacement_offset) % BytesPerWord == 0, "must be aligned"); __ call(AddressLiteral(op->addr(), rh)); - add_call_info(code_offset(), op->info(), op->is_method_handle_invoke()); + add_call_info(code_offset(), op->info()); } @@ -2805,16 +2805,6 @@ } -void LIR_Assembler::preserve_SP(LIR_OpJavaCall* op) { - __ movptr(FrameMap::method_handle_invoke_SP_save_opr()->as_register(), rsp); -} - - -void LIR_Assembler::restore_SP(LIR_OpJavaCall* op) { - __ movptr(rsp, FrameMap::method_handle_invoke_SP_save_opr()->as_register()); -} - - void LIR_Assembler::emit_static_call_stub() { address call_pc = __ pc(); address stub = __ start_a_stub(call_stub_size); diff -r 5435e77aa3df -r b862d1f189bd hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp --- a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp Thu May 20 06:34:23 2010 -0700 +++ b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp Fri May 21 02:59:24 2010 -0700 @@ -782,7 +782,7 @@ // Restore SP from BP if the exception PC is a MethodHandle call site. NOT_LP64(__ get_thread(thread);) __ cmpl(Address(thread, JavaThread::is_method_handle_return_offset()), 0); - __ cmovptr(Assembler::notEqual, rsp, rbp); + __ cmovptr(Assembler::notEqual, rsp, rbp_mh_SP_save); // continue at exception handler (return address removed) // note: do *not* remove arguments when unwinding the diff -r 5435e77aa3df -r b862d1f189bd hotspot/src/cpu/x86/vm/register_definitions_x86.cpp --- a/hotspot/src/cpu/x86/vm/register_definitions_x86.cpp Thu May 20 06:34:23 2010 -0700 +++ b/hotspot/src/cpu/x86/vm/register_definitions_x86.cpp Fri May 21 02:59:24 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2002-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -115,3 +115,6 @@ REGISTER_DEFINITION(MMXRegister, mmx5 ); REGISTER_DEFINITION(MMXRegister, mmx6 ); REGISTER_DEFINITION(MMXRegister, mmx7 ); + +// JSR 292 +REGISTER_DEFINITION(Register, rbp_mh_SP_save); diff -r 5435e77aa3df -r b862d1f189bd hotspot/src/share/vm/c1/c1_FrameMap.hpp --- a/hotspot/src/share/vm/c1/c1_FrameMap.hpp Thu May 20 06:34:23 2010 -0700 +++ b/hotspot/src/share/vm/c1/c1_FrameMap.hpp Fri May 21 02:59:24 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -150,6 +150,9 @@ // Opr representing the stack_pointer on this platform static LIR_Opr stack_pointer(); + // JSR 292 + static LIR_Opr method_handle_invoke_SP_save_opr(); + static BasicTypeArray* signature_type_array_for(const ciMethod* method); static BasicTypeArray* signature_type_array_for(const char * signature); diff -r 5435e77aa3df -r b862d1f189bd hotspot/src/share/vm/c1/c1_IR.cpp --- a/hotspot/src/share/vm/c1/c1_IR.cpp Thu May 20 06:34:23 2010 -0700 +++ b/hotspot/src/share/vm/c1/c1_IR.cpp Fri May 21 02:59:24 2010 -0700 @@ -230,7 +230,8 @@ , _stack(stack) , _exception_handlers(exception_handlers) , _next(NULL) - , _id(-1) { + , _id(-1) + , _is_method_handle_invoke(false) { assert(_stack != NULL, "must be non null"); assert(_bci == SynchronizationEntryBCI || Bytecodes::is_defined(scope()->method()->java_code_at_bci(_bci)), "make sure bci points at a real bytecode"); } @@ -241,7 +242,8 @@ , _exception_handlers(NULL) , _bci(info->_bci) , _scope_debug_info(NULL) - , _oop_map(NULL) { + , _oop_map(NULL) + , _is_method_handle_invoke(info->_is_method_handle_invoke) { if (lock_stack_only) { if (info->_stack != NULL) { _stack = info->_stack->copy_locks(); @@ -259,10 +261,10 @@ } -void CodeEmitInfo::record_debug_info(DebugInformationRecorder* recorder, int pc_offset, bool is_method_handle_invoke) { +void CodeEmitInfo::record_debug_info(DebugInformationRecorder* recorder, int pc_offset) { // record the safepoint before recording the debug info for enclosing scopes recorder->add_safepoint(pc_offset, _oop_map->deep_copy()); - _scope_debug_info->record_debug_info(recorder, pc_offset, true/*topmost*/, is_method_handle_invoke); + _scope_debug_info->record_debug_info(recorder, pc_offset, true/*topmost*/, _is_method_handle_invoke); recorder->end_safepoint(pc_offset); } diff -r 5435e77aa3df -r b862d1f189bd hotspot/src/share/vm/c1/c1_IR.hpp --- a/hotspot/src/share/vm/c1/c1_IR.hpp Thu May 20 06:34:23 2010 -0700 +++ b/hotspot/src/share/vm/c1/c1_IR.hpp Fri May 21 02:59:24 2010 -0700 @@ -269,6 +269,7 @@ int _bci; CodeEmitInfo* _next; int _id; + bool _is_method_handle_invoke; // true if the associated call site is a MethodHandle call site. FrameMap* frame_map() const { return scope()->compilation()->frame_map(); } Compilation* compilation() const { return scope()->compilation(); } @@ -287,7 +288,8 @@ , _stack(NULL) , _exception_handlers(NULL) , _next(NULL) - , _id(-1) { + , _id(-1) + , _is_method_handle_invoke(false) { } // make a copy @@ -302,13 +304,16 @@ int bci() const { return _bci; } void add_register_oop(LIR_Opr opr); - void record_debug_info(DebugInformationRecorder* recorder, int pc_offset, bool is_method_handle_invoke = false); + void record_debug_info(DebugInformationRecorder* recorder, int pc_offset); CodeEmitInfo* next() const { return _next; } void set_next(CodeEmitInfo* next) { _next = next; } int id() const { return _id; } void set_id(int id) { _id = id; } + + bool is_method_handle_invoke() const { return _is_method_handle_invoke; } + void set_is_method_handle_invoke(bool x) { _is_method_handle_invoke = x; } }; diff -r 5435e77aa3df -r b862d1f189bd hotspot/src/share/vm/c1/c1_LIR.cpp --- a/hotspot/src/share/vm/c1/c1_LIR.cpp Thu May 20 06:34:23 2010 -0700 +++ b/hotspot/src/share/vm/c1/c1_LIR.cpp Fri May 21 02:59:24 2010 -0700 @@ -715,7 +715,10 @@ } if (opJavaCall->_info) do_info(opJavaCall->_info); - if (opJavaCall->is_method_handle_invoke()) do_temp(FrameMap::method_handle_invoke_SP_save_opr()); + if (opJavaCall->is_method_handle_invoke()) { + opJavaCall->_method_handle_invoke_SP_save_opr = FrameMap::method_handle_invoke_SP_save_opr(); + do_temp(opJavaCall->_method_handle_invoke_SP_save_opr); + } do_call(); if (opJavaCall->_result->is_valid()) do_output(opJavaCall->_result); diff -r 5435e77aa3df -r b862d1f189bd hotspot/src/share/vm/c1/c1_LIR.hpp --- a/hotspot/src/share/vm/c1/c1_LIR.hpp Thu May 20 06:34:23 2010 -0700 +++ b/hotspot/src/share/vm/c1/c1_LIR.hpp Fri May 21 02:59:24 2010 -0700 @@ -1033,8 +1033,9 @@ friend class LIR_OpVisitState; private: - ciMethod* _method; - LIR_Opr _receiver; + ciMethod* _method; + LIR_Opr _receiver; + LIR_Opr _method_handle_invoke_SP_save_opr; // Used in LIR_OpVisitState::visit to store the reference to FrameMap::method_handle_invoke_SP_save_opr. public: LIR_OpJavaCall(LIR_Code code, ciMethod* method, @@ -1043,14 +1044,18 @@ CodeEmitInfo* info) : LIR_OpCall(code, addr, result, arguments, info) , _receiver(receiver) - , _method(method) { assert(is_in_range(code, begin_opJavaCall, end_opJavaCall), "code check"); } + , _method(method) + , _method_handle_invoke_SP_save_opr(LIR_OprFact::illegalOpr) + { assert(is_in_range(code, begin_opJavaCall, end_opJavaCall), "code check"); } LIR_OpJavaCall(LIR_Code code, ciMethod* method, LIR_Opr receiver, LIR_Opr result, intptr_t vtable_offset, LIR_OprList* arguments, CodeEmitInfo* info) : LIR_OpCall(code, (address)vtable_offset, result, arguments, info) , _receiver(receiver) - , _method(method) { assert(is_in_range(code, begin_opJavaCall, end_opJavaCall), "code check"); } + , _method(method) + , _method_handle_invoke_SP_save_opr(LIR_OprFact::illegalOpr) + { assert(is_in_range(code, begin_opJavaCall, end_opJavaCall), "code check"); } LIR_Opr receiver() const { return _receiver; } ciMethod* method() const { return _method; } diff -r 5435e77aa3df -r b862d1f189bd hotspot/src/share/vm/c1/c1_LIRAssembler.cpp --- a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp Thu May 20 06:34:23 2010 -0700 +++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp Fri May 21 02:59:24 2010 -0700 @@ -301,9 +301,9 @@ } -void LIR_Assembler::add_call_info(int pc_offset, CodeEmitInfo* cinfo, bool is_method_handle_invoke) { +void LIR_Assembler::add_call_info(int pc_offset, CodeEmitInfo* cinfo) { flush_debug_info(pc_offset); - cinfo->record_debug_info(compilation()->debug_info_recorder(), pc_offset, is_method_handle_invoke); + cinfo->record_debug_info(compilation()->debug_info_recorder(), pc_offset); if (cinfo->exception_handlers() != NULL) { compilation()->add_exception_handlers_for_pco(pc_offset, cinfo->exception_handlers()); } @@ -413,12 +413,6 @@ void LIR_Assembler::emit_call(LIR_OpJavaCall* op) { verify_oop_map(op->info()); - // JSR 292 - // Preserve the SP over MethodHandle call sites. - if (op->is_method_handle_invoke()) { - preserve_SP(op); - } - if (os::is_MP()) { // must align calls sites, otherwise they can't be updated atomically on MP hardware align_call(op->code()); @@ -444,10 +438,6 @@ default: ShouldNotReachHere(); } - if (op->is_method_handle_invoke()) { - restore_SP(op); - } - #if defined(X86) && defined(TIERED) // C2 leave fpu stack dirty clean it if (UseSSE < 2) { diff -r 5435e77aa3df -r b862d1f189bd hotspot/src/share/vm/c1/c1_LIRAssembler.hpp --- a/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp Thu May 20 06:34:23 2010 -0700 +++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp Fri May 21 02:59:24 2010 -0700 @@ -84,7 +84,7 @@ Address as_Address_hi(LIR_Address* addr); // debug information - void add_call_info(int pc_offset, CodeEmitInfo* cinfo, bool is_method_handle_invoke = false); + void add_call_info(int pc_offset, CodeEmitInfo* cinfo); void add_debug_info_for_branch(CodeEmitInfo* info); void add_debug_info_for_div0(int pc_offset, CodeEmitInfo* cinfo); void add_debug_info_for_div0_here(CodeEmitInfo* info); @@ -212,10 +212,6 @@ void ic_call( LIR_OpJavaCall* op); void vtable_call( LIR_OpJavaCall* op); - // JSR 292 - void preserve_SP(LIR_OpJavaCall* op); - void restore_SP( LIR_OpJavaCall* op); - void osr_entry(); void build_frame(); diff -r 5435e77aa3df -r b862d1f189bd hotspot/src/share/vm/c1/c1_LIRGenerator.cpp --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Thu May 20 06:34:23 2010 -0700 +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Fri May 21 02:59:24 2010 -0700 @@ -2371,9 +2371,17 @@ bool optimized = x->target_is_loaded() && x->target_is_final(); assert(receiver->is_illegal() || receiver->is_equal(LIR_Assembler::receiverOpr()), "must match"); + // JSR 292 + // Preserve the SP over MethodHandle call sites. + ciMethod* target = x->target(); + if (target->is_method_handle_invoke()) { + info->set_is_method_handle_invoke(true); + __ move(FrameMap::stack_pointer(), FrameMap::method_handle_invoke_SP_save_opr()); + } + switch (x->code()) { case Bytecodes::_invokestatic: - __ call_static(x->target(), result_register, + __ call_static(target, result_register, SharedRuntime::get_resolve_static_call_stub(), arg_list, info); break; @@ -2383,17 +2391,17 @@ // for final target we still produce an inline cache, in order // to be able to call mixed mode if (x->code() == Bytecodes::_invokespecial || optimized) { - __ call_opt_virtual(x->target(), receiver, result_register, + __ call_opt_virtual(target, receiver, result_register, SharedRuntime::get_resolve_opt_virtual_call_stub(), arg_list, info); } else if (x->vtable_index() < 0) { - __ call_icvirtual(x->target(), receiver, result_register, + __ call_icvirtual(target, receiver, result_register, SharedRuntime::get_resolve_virtual_call_stub(), arg_list, info); } else { int entry_offset = instanceKlass::vtable_start_offset() + x->vtable_index() * vtableEntry::size(); int vtable_offset = entry_offset * wordSize + vtableEntry::method_offset_in_bytes(); - __ call_virtual(x->target(), receiver, result_register, vtable_offset, arg_list, info); + __ call_virtual(target, receiver, result_register, vtable_offset, arg_list, info); } break; case Bytecodes::_invokedynamic: { @@ -2432,7 +2440,7 @@ // Load target MethodHandle from CallSite object. __ load(new LIR_Address(tmp, java_dyn_CallSite::target_offset_in_bytes(), T_OBJECT), receiver); - __ call_dynamic(x->target(), receiver, result_register, + __ call_dynamic(target, receiver, result_register, SharedRuntime::get_resolve_opt_virtual_call_stub(), arg_list, info); break; @@ -2442,6 +2450,12 @@ break; } + // JSR 292 + // Restore the SP after MethodHandle call sites. + if (target->is_method_handle_invoke()) { + __ move(FrameMap::method_handle_invoke_SP_save_opr(), FrameMap::stack_pointer()); + } + if (x->type()->is_float() || x->type()->is_double()) { // Force rounding of results from non-strictfp when in strictfp // scope (or when we don't know the strictness of the callee, to diff -r 5435e77aa3df -r b862d1f189bd hotspot/src/share/vm/ci/ciMethod.cpp --- a/hotspot/src/share/vm/ci/ciMethod.cpp Thu May 20 06:34:23 2010 -0700 +++ b/hotspot/src/share/vm/ci/ciMethod.cpp Fri May 21 02:59:24 2010 -0700 @@ -690,20 +690,32 @@ // ------------------------------------------------------------------ // invokedynamic support + +// ------------------------------------------------------------------ +// ciMethod::is_method_handle_invoke // +// Return true if the method is a MethodHandle target. bool ciMethod::is_method_handle_invoke() const { - check_is_loaded(); - bool flag = ((flags().as_int() & JVM_MH_INVOKE_BITS) == JVM_MH_INVOKE_BITS); + bool flag = (holder()->name() == ciSymbol::java_dyn_MethodHandle() && + methodOopDesc::is_method_handle_invoke_name(name()->sid())); #ifdef ASSERT - { - VM_ENTRY_MARK; - bool flag2 = get_methodOop()->is_method_handle_invoke(); - assert(flag == flag2, "consistent"); + if (is_loaded()) { + bool flag2 = ((flags().as_int() & JVM_MH_INVOKE_BITS) == JVM_MH_INVOKE_BITS); + { + VM_ENTRY_MARK; + bool flag3 = get_methodOop()->is_method_handle_invoke(); + assert(flag2 == flag3, "consistent"); + assert(flag == flag3, "consistent"); + } } #endif //ASSERT return flag; } +// ------------------------------------------------------------------ +// ciMethod::is_method_handle_adapter +// +// Return true if the method is a generated MethodHandle adapter. bool ciMethod::is_method_handle_adapter() const { check_is_loaded(); VM_ENTRY_MARK; diff -r 5435e77aa3df -r b862d1f189bd hotspot/src/share/vm/opto/bytecodeInfo.cpp --- a/hotspot/src/share/vm/opto/bytecodeInfo.cpp Thu May 20 06:34:23 2010 -0700 +++ b/hotspot/src/share/vm/opto/bytecodeInfo.cpp Fri May 21 02:59:24 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 1998-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1998-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -188,8 +188,8 @@ return NULL; } - // Always inline MethodHandle methods. - if (callee_method->is_method_handle_invoke()) + // Always inline MethodHandle methods and generated MethodHandle adapters. + if (callee_method->is_method_handle_invoke() || callee_method->is_method_handle_adapter()) return NULL; // First check all inlining restrictions which are required for correctness diff -r 5435e77aa3df -r b862d1f189bd hotspot/src/share/vm/runtime/sharedRuntime.cpp --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp Thu May 20 06:34:23 2010 -0700 +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp Fri May 21 02:59:24 2010 -0700 @@ -2055,11 +2055,11 @@ void scan() { while (_index < _table->table_size()) { AdapterHandlerEntry* a = _table->bucket(_index); + _index++; if (a != NULL) { _current = a; return; } - _index++; } }