From 67aa0ac195b4e42b7f7581d99e3310ab41193290 Mon Sep 17 00:00:00 2001 From: twisti Date: Fri, 21 May 2010 02:59:24 -0700 Subject: 6930772: JSR 292 needs to support SPARC C1 Summary: C1 for SPARC needs to support JSR 292. Reviewed-by: never, jrose --- src/share/vm/c1/c1_FrameMap.hpp | 5 ++++- src/share/vm/c1/c1_IR.cpp | 10 ++++++---- src/share/vm/c1/c1_IR.hpp | 9 +++++++-- src/share/vm/c1/c1_LIR.cpp | 5 ++++- src/share/vm/c1/c1_LIR.hpp | 13 +++++++++---- src/share/vm/c1/c1_LIRAssembler.cpp | 14 ++------------ src/share/vm/c1/c1_LIRAssembler.hpp | 6 +----- src/share/vm/c1/c1_LIRGenerator.cpp | 24 +++++++++++++++++++----- src/share/vm/ci/ciMethod.cpp | 24 ++++++++++++++++++------ src/share/vm/opto/bytecodeInfo.cpp | 6 +++--- src/share/vm/runtime/sharedRuntime.cpp | 2 +- 11 files changed, 74 insertions(+), 44 deletions(-) (limited to 'src/share/vm') diff --git a/src/share/vm/c1/c1_FrameMap.hpp b/src/share/vm/c1/c1_FrameMap.hpp index c8dd5643b..223700291 100644 --- a/src/share/vm/c1/c1_FrameMap.hpp +++ b/src/share/vm/c1/c1_FrameMap.hpp @@ -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 @@ class FrameMap : public CompilationResourceObj { // 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 --git a/src/share/vm/c1/c1_IR.cpp b/src/share/vm/c1/c1_IR.cpp index 176697b66..bc5af0d11 100644 --- a/src/share/vm/c1/c1_IR.cpp +++ b/src/share/vm/c1/c1_IR.cpp @@ -230,7 +230,8 @@ CodeEmitInfo::CodeEmitInfo(int bci, ValueStack* stack, XHandlers* exception_hand , _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 @@ CodeEmitInfo::CodeEmitInfo(CodeEmitInfo* info, bool lock_stack_only) , _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 @@ CodeEmitInfo::CodeEmitInfo(CodeEmitInfo* info, bool lock_stack_only) } -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 --git a/src/share/vm/c1/c1_IR.hpp b/src/share/vm/c1/c1_IR.hpp index 0af76f349..bf8709b82 100644 --- a/src/share/vm/c1/c1_IR.hpp +++ b/src/share/vm/c1/c1_IR.hpp @@ -269,6 +269,7 @@ class CodeEmitInfo: public CompilationResourceObj { 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 @@ class CodeEmitInfo: public CompilationResourceObj { , _stack(NULL) , _exception_handlers(NULL) , _next(NULL) - , _id(-1) { + , _id(-1) + , _is_method_handle_invoke(false) { } // make a copy @@ -302,13 +304,16 @@ class CodeEmitInfo: public CompilationResourceObj { 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 --git a/src/share/vm/c1/c1_LIR.cpp b/src/share/vm/c1/c1_LIR.cpp index e6a3b3147..b60da753a 100644 --- a/src/share/vm/c1/c1_LIR.cpp +++ b/src/share/vm/c1/c1_LIR.cpp @@ -715,7 +715,10 @@ void LIR_OpVisitState::visit(LIR_Op* op) { } 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 --git a/src/share/vm/c1/c1_LIR.hpp b/src/share/vm/c1/c1_LIR.hpp index 8c9194c7b..1f55c259b 100644 --- a/src/share/vm/c1/c1_LIR.hpp +++ b/src/share/vm/c1/c1_LIR.hpp @@ -1033,8 +1033,9 @@ class LIR_OpJavaCall: public LIR_OpCall { 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 @@ class LIR_OpJavaCall: public LIR_OpCall { 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 --git a/src/share/vm/c1/c1_LIRAssembler.cpp b/src/share/vm/c1/c1_LIRAssembler.cpp index ab9c44625..63b40211b 100644 --- a/src/share/vm/c1/c1_LIRAssembler.cpp +++ b/src/share/vm/c1/c1_LIRAssembler.cpp @@ -301,9 +301,9 @@ void LIR_Assembler::add_debug_info_for_branch(CodeEmitInfo* info) { } -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_rtcall(LIR_OpRTCall* op) { 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 @@ void LIR_Assembler::emit_call(LIR_OpJavaCall* op) { 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 --git a/src/share/vm/c1/c1_LIRAssembler.hpp b/src/share/vm/c1/c1_LIRAssembler.hpp index d73a19fdb..fda2d5dd0 100644 --- a/src/share/vm/c1/c1_LIRAssembler.hpp +++ b/src/share/vm/c1/c1_LIRAssembler.hpp @@ -84,7 +84,7 @@ class LIR_Assembler: public CompilationResourceObj { 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 @@ class LIR_Assembler: public CompilationResourceObj { 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 --git a/src/share/vm/c1/c1_LIRGenerator.cpp b/src/share/vm/c1/c1_LIRGenerator.cpp index ea2942d9b..68b4294ea 100644 --- a/src/share/vm/c1/c1_LIRGenerator.cpp +++ b/src/share/vm/c1/c1_LIRGenerator.cpp @@ -2371,9 +2371,17 @@ void LIRGenerator::do_Invoke(Invoke* x) { 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 @@ void LIRGenerator::do_Invoke(Invoke* x) { // 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 @@ void LIRGenerator::do_Invoke(Invoke* x) { // 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 @@ void LIRGenerator::do_Invoke(Invoke* x) { 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 --git a/src/share/vm/ci/ciMethod.cpp b/src/share/vm/ci/ciMethod.cpp index 54a04f8af..67f98b9b1 100644 --- a/src/share/vm/ci/ciMethod.cpp +++ b/src/share/vm/ci/ciMethod.cpp @@ -690,20 +690,32 @@ int ciMethod::scale_count(int count, float prof_factor) { // ------------------------------------------------------------------ // 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 --git a/src/share/vm/opto/bytecodeInfo.cpp b/src/share/vm/opto/bytecodeInfo.cpp index 922b712cd..a0bca50fc 100644 --- a/src/share/vm/opto/bytecodeInfo.cpp +++ b/src/share/vm/opto/bytecodeInfo.cpp @@ -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 @@ const char* InlineTree::shouldNotInline(ciMethod *callee_method, ciMethod* calle 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 --git a/src/share/vm/runtime/sharedRuntime.cpp b/src/share/vm/runtime/sharedRuntime.cpp index 9655de8e2..13a8c9e9c 100644 --- a/src/share/vm/runtime/sharedRuntime.cpp +++ b/src/share/vm/runtime/sharedRuntime.cpp @@ -2055,11 +2055,11 @@ class AdapterHandlerTableIterator : public StackObj { void scan() { while (_index < _table->table_size()) { AdapterHandlerEntry* a = _table->bucket(_index); + _index++; if (a != NULL) { _current = a; return; } - _index++; } } -- cgit v1.2.3