提交 79bbc02e 编写于 作者: T twisti

6998541: JSR 292 implement missing return-type conversion for OP_RETYPE_RAW

Reviewed-by: jrose, kvn, never
上级 e1b99956
...@@ -142,18 +142,8 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* ...@@ -142,18 +142,8 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler*
Register O2_form = O2_scratch; Register O2_form = O2_scratch;
Register O3_adapter = O3_scratch; Register O3_adapter = O3_scratch;
__ load_heap_oop(Address(O0_mtype, __ delayed_value(java_lang_invoke_MethodType::form_offset_in_bytes, O1_scratch)), O2_form); __ load_heap_oop(Address(O0_mtype, __ delayed_value(java_lang_invoke_MethodType::form_offset_in_bytes, O1_scratch)), O2_form);
// load_heap_oop(Address(O2_form, __ delayed_value(java_lang_invoke_MethodTypeForm::genericInvoker_offset_in_bytes, O1_scratch)), O3_adapter); __ load_heap_oop(Address(O2_form, __ delayed_value(java_lang_invoke_MethodTypeForm::genericInvoker_offset_in_bytes, O1_scratch)), O3_adapter);
// deal with old JDK versions: __ verify_oop(O3_adapter);
__ add( Address(O2_form, __ delayed_value(java_lang_invoke_MethodTypeForm::genericInvoker_offset_in_bytes, O1_scratch)), O3_adapter);
__ cmp(O3_adapter, O2_form);
Label sorry_no_invoke_generic;
__ brx(Assembler::lessUnsigned, false, Assembler::pn, sorry_no_invoke_generic);
__ delayed()->nop();
__ load_heap_oop(Address(O3_adapter, 0), O3_adapter);
__ tst(O3_adapter);
__ brx(Assembler::zero, false, Assembler::pn, sorry_no_invoke_generic);
__ delayed()->nop();
__ st_ptr(O3_adapter, Address(O4_argbase, 1 * Interpreter::stackElementSize)); __ st_ptr(O3_adapter, Address(O4_argbase, 1 * Interpreter::stackElementSize));
// As a trusted first argument, pass the type being called, so the adapter knows // As a trusted first argument, pass the type being called, so the adapter knows
// the actual types of the arguments and return values. // the actual types of the arguments and return values.
...@@ -164,12 +154,6 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* ...@@ -164,12 +154,6 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler*
trace_method_handle(_masm, "invokeGeneric"); trace_method_handle(_masm, "invokeGeneric");
__ jump_to_method_handle_entry(G3_method_handle, O1_scratch); __ jump_to_method_handle_entry(G3_method_handle, O1_scratch);
__ bind(sorry_no_invoke_generic); // no invokeGeneric implementation available!
__ mov(O0_mtype, G5_method_type); // required by throw_WrongMethodType
// mov(G3_method_handle, G3_method_handle); // already in this register
__ jump_to(AddressLiteral(Interpreter::throw_WrongMethodType_entry()), O1_scratch);
__ delayed()->nop();
return entry_point; return entry_point;
} }
......
...@@ -163,7 +163,7 @@ void MethodHandles::RicochetFrame::generate_ricochet_blob(MacroAssembler* _masm, ...@@ -163,7 +163,7 @@ void MethodHandles::RicochetFrame::generate_ricochet_blob(MacroAssembler* _masm,
BLOCK_COMMENT("ricochet_blob.bounce"); BLOCK_COMMENT("ricochet_blob.bounce");
if (VerifyMethodHandles) RicochetFrame::verify_clean(_masm); if (VerifyMethodHandles) RicochetFrame::verify_clean(_masm);
trace_method_handle(_masm, "ricochet_blob.bounce"); trace_method_handle(_masm, "return/ricochet_blob.bounce");
__ jmp(frame_address(continuation_offset_in_bytes())); __ jmp(frame_address(continuation_offset_in_bytes()));
__ hlt(); __ hlt();
...@@ -615,18 +615,10 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* ...@@ -615,18 +615,10 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler*
rcx_argslot, rbx_temp, rdx_temp); rcx_argslot, rbx_temp, rdx_temp);
// load up an adapter from the calling type (Java weaves this) // load up an adapter from the calling type (Java weaves this)
__ load_heap_oop(rdx_temp, Address(rax_mtype, __ delayed_value(java_lang_invoke_MethodType::form_offset_in_bytes, rdi_temp)));
Register rdx_adapter = rdx_temp; Register rdx_adapter = rdx_temp;
// __ load_heap_oop(rdx_adapter, Address(rdx_temp, java_lang_invoke_MethodTypeForm::genericInvoker_offset_in_bytes())); __ load_heap_oop(rdx_temp, Address(rax_mtype, __ delayed_value(java_lang_invoke_MethodType::form_offset_in_bytes, rdi_temp)));
// deal with old JDK versions: __ load_heap_oop(rdx_adapter, Address(rdx_temp, __ delayed_value(java_lang_invoke_MethodTypeForm::genericInvoker_offset_in_bytes, rdi_temp)));
__ lea(rdi_temp, Address(rdx_temp, __ delayed_value(java_lang_invoke_MethodTypeForm::genericInvoker_offset_in_bytes, rdi_temp))); __ verify_oop(rdx_adapter);
__ cmpptr(rdi_temp, rdx_temp);
Label sorry_no_invoke_generic;
__ jcc(Assembler::below, sorry_no_invoke_generic);
__ load_heap_oop(rdx_adapter, Address(rdi_temp, 0));
__ testptr(rdx_adapter, rdx_adapter);
__ jcc(Assembler::zero, sorry_no_invoke_generic);
__ movptr(Address(rcx_argslot, 1 * Interpreter::stackElementSize), rdx_adapter); __ movptr(Address(rcx_argslot, 1 * Interpreter::stackElementSize), rdx_adapter);
// As a trusted first argument, pass the type being called, so the adapter knows // As a trusted first argument, pass the type being called, so the adapter knows
// the actual types of the arguments and return values. // the actual types of the arguments and return values.
...@@ -637,12 +629,6 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* ...@@ -637,12 +629,6 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler*
trace_method_handle(_masm, "invokeGeneric"); trace_method_handle(_masm, "invokeGeneric");
__ jump_to_method_handle_entry(rcx, rdi_temp); __ jump_to_method_handle_entry(rcx, rdi_temp);
__ bind(sorry_no_invoke_generic); // no invokeGeneric implementation available!
__ movptr(rcx_recv, Address(rcx_argslot, -1 * Interpreter::stackElementSize)); // recover original MH
__ push(rax_mtype); // required mtype
__ push(rcx_recv); // bad mh (1st stacked argument)
__ jump(ExternalAddress(Interpreter::throw_WrongMethodType_entry()));
return entry_point; return entry_point;
} }
...@@ -688,7 +674,7 @@ void MethodHandles::insert_arg_slots(MacroAssembler* _masm, ...@@ -688,7 +674,7 @@ void MethodHandles::insert_arg_slots(MacroAssembler* _masm,
__ movptr(Address(rdx_temp, arg_slots, Interpreter::stackElementScale()), rbx_temp); __ movptr(Address(rdx_temp, arg_slots, Interpreter::stackElementScale()), rbx_temp);
__ addptr(rdx_temp, wordSize); __ addptr(rdx_temp, wordSize);
__ cmpptr(rdx_temp, rax_argslot); __ cmpptr(rdx_temp, rax_argslot);
__ jcc(Assembler::less, loop); __ jcc(Assembler::below, loop);
} }
// Now move the argslot down, to point to the opened-up space. // Now move the argslot down, to point to the opened-up space.
...@@ -731,7 +717,7 @@ void MethodHandles::remove_arg_slots(MacroAssembler* _masm, ...@@ -731,7 +717,7 @@ void MethodHandles::remove_arg_slots(MacroAssembler* _masm,
__ movptr(Address(rdx_temp, arg_slots, Interpreter::stackElementScale()), rbx_temp); __ movptr(Address(rdx_temp, arg_slots, Interpreter::stackElementScale()), rbx_temp);
__ addptr(rdx_temp, -wordSize); __ addptr(rdx_temp, -wordSize);
__ cmpptr(rdx_temp, rsp); __ cmpptr(rdx_temp, rsp);
__ jcc(Assembler::greaterEqual, loop); __ jcc(Assembler::aboveEqual, loop);
} }
// Now move the argslot up, to point to the just-copied block. // Now move the argslot up, to point to the just-copied block.
...@@ -980,12 +966,21 @@ void trace_method_handle_stub(const char* adaptername, ...@@ -980,12 +966,21 @@ void trace_method_handle_stub(const char* adaptername,
intptr_t* saved_sp, intptr_t* saved_sp,
intptr_t* saved_bp) { intptr_t* saved_bp) {
// called as a leaf from native code: do not block the JVM! // called as a leaf from native code: do not block the JVM!
bool has_mh = (strstr(adaptername, "return/") == NULL); // return adapters don't have rcx_mh
intptr_t* last_sp = (intptr_t*) saved_bp[frame::interpreter_frame_last_sp_offset]; intptr_t* last_sp = (intptr_t*) saved_bp[frame::interpreter_frame_last_sp_offset];
intptr_t* base_sp = (intptr_t*) saved_bp[frame::interpreter_frame_monitor_block_top_offset]; intptr_t* base_sp = last_sp;
tty->print_cr("MH %s mh="INTPTR_FORMAT" sp=("INTPTR_FORMAT"+"INTX_FORMAT") stack_size="INTX_FORMAT" bp="INTPTR_FORMAT, typedef MethodHandles::RicochetFrame RicochetFrame;
adaptername, (intptr_t)mh, (intptr_t)entry_sp, (intptr_t)(saved_sp - entry_sp), (intptr_t)(base_sp - last_sp), (intptr_t)saved_bp); RicochetFrame* rfp = (RicochetFrame*)((address)saved_bp - RicochetFrame::sender_link_offset_in_bytes());
if (last_sp != saved_sp && last_sp != NULL) if (!UseRicochetFrames || Universe::heap()->is_in((address) rfp->saved_args_base())) {
tty->print_cr("*** last_sp="INTPTR_FORMAT, (intptr_t)last_sp); // Probably an interpreter frame.
base_sp = (intptr_t*) saved_bp[frame::interpreter_frame_monitor_block_top_offset];
}
intptr_t mh_reg = (intptr_t)mh;
const char* mh_reg_name = "rcx_mh";
if (!has_mh) mh_reg_name = "rcx";
tty->print_cr("MH %s %s="PTR_FORMAT" sp=("PTR_FORMAT"+"INTX_FORMAT") stack_size="INTX_FORMAT" bp="PTR_FORMAT,
adaptername, mh_reg_name, mh_reg,
(intptr_t)entry_sp, (intptr_t)(saved_sp - entry_sp), (intptr_t)(base_sp - last_sp), (intptr_t)saved_bp);
if (Verbose) { if (Verbose) {
tty->print(" reg dump: "); tty->print(" reg dump: ");
int saved_regs_count = (entry_sp-1) - saved_regs; int saved_regs_count = (entry_sp-1) - saved_regs;
...@@ -996,18 +991,21 @@ void trace_method_handle_stub(const char* adaptername, ...@@ -996,18 +991,21 @@ void trace_method_handle_stub(const char* adaptername,
tty->cr(); tty->cr();
tty->print(" + dump: "); tty->print(" + dump: ");
} }
tty->print(" %d: "INTPTR_FORMAT, i, saved_regs[i]); tty->print(" %d: "PTR_FORMAT, i, saved_regs[i]);
} }
tty->cr(); tty->cr();
if (last_sp != saved_sp && last_sp != NULL)
tty->print_cr("*** last_sp="PTR_FORMAT, (intptr_t)last_sp);
int stack_dump_count = 16; int stack_dump_count = 16;
if (stack_dump_count < (int)(saved_bp + 2 - saved_sp)) if (stack_dump_count < (int)(saved_bp + 2 - saved_sp))
stack_dump_count = (int)(saved_bp + 2 - saved_sp); stack_dump_count = (int)(saved_bp + 2 - saved_sp);
if (stack_dump_count > 64) stack_dump_count = 48; if (stack_dump_count > 64) stack_dump_count = 48;
for (i = 0; i < stack_dump_count; i += 4) { for (i = 0; i < stack_dump_count; i += 4) {
tty->print_cr(" dump at SP[%d] "INTPTR_FORMAT": "INTPTR_FORMAT" "INTPTR_FORMAT" "INTPTR_FORMAT" "INTPTR_FORMAT, tty->print_cr(" dump at SP[%d] "PTR_FORMAT": "PTR_FORMAT" "PTR_FORMAT" "PTR_FORMAT" "PTR_FORMAT,
i, (intptr_t) &entry_sp[i+0], entry_sp[i+0], entry_sp[i+1], entry_sp[i+2], entry_sp[i+3]); i, (intptr_t) &entry_sp[i+0], entry_sp[i+0], entry_sp[i+1], entry_sp[i+2], entry_sp[i+3]);
} }
print_method_handle(mh); if (has_mh)
print_method_handle(mh);
} }
} }
...@@ -1073,7 +1071,6 @@ int MethodHandles::adapter_conversion_ops_supported_mask() { ...@@ -1073,7 +1071,6 @@ int MethodHandles::adapter_conversion_ops_supported_mask() {
//OP_COLLECT_ARGS is below... //OP_COLLECT_ARGS is below...
|(1<<java_lang_invoke_AdapterMethodHandle::OP_SPREAD_ARGS) |(1<<java_lang_invoke_AdapterMethodHandle::OP_SPREAD_ARGS)
|(!UseRicochetFrames ? 0 : |(!UseRicochetFrames ? 0 :
LP64_ONLY(FLAG_IS_DEFAULT(UseRicochetFrames) ? 0 :)
java_lang_invoke_MethodTypeForm::vmlayout_offset_in_bytes() <= 0 ? 0 : java_lang_invoke_MethodTypeForm::vmlayout_offset_in_bytes() <= 0 ? 0 :
((1<<java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_REF) ((1<<java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_REF)
|(1<<java_lang_invoke_AdapterMethodHandle::OP_COLLECT_ARGS) |(1<<java_lang_invoke_AdapterMethodHandle::OP_COLLECT_ARGS)
...@@ -1546,7 +1543,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan ...@@ -1546,7 +1543,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
#else //_LP64 #else //_LP64
if (ek == _adapter_opt_f2d) { if (ek == _adapter_opt_f2d) {
__ fld_s(vmarg); // load float to ST0 __ fld_s(vmarg); // load float to ST0
__ fstp_s(vmarg); // store single __ fstp_d(vmarg); // store double
} else { } else {
__ fld_d(vmarg); // load double to ST0 __ fld_d(vmarg); // load double to ST0
__ fstp_s(vmarg); // store single __ fstp_s(vmarg); // store single
...@@ -2353,7 +2350,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan ...@@ -2353,7 +2350,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
rbx_temp, rdi_temp); rbx_temp, rdi_temp);
__ addptr(rsi_source, type2aelembytes(elem_type)); __ addptr(rsi_source, type2aelembytes(elem_type));
__ cmpptr(rdx_fill_ptr, rax_argslot); __ cmpptr(rdx_fill_ptr, rax_argslot);
__ jcc(Assembler::greater, loop); __ jcc(Assembler::above, loop);
} else if (length_constant == 0) { } else if (length_constant == 0) {
// nothing to copy // nothing to copy
} else { } else {
......
/* /*
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -233,7 +233,10 @@ private: ...@@ -233,7 +233,10 @@ private:
public: public:
bool is_method_data() { return true; } bool is_method_data() { return true; }
bool is_empty() { return _state == empty_state; }
void set_mature() { _state = mature_state; }
bool is_empty() { return _state == empty_state; }
bool is_mature() { return _state == mature_state; } bool is_mature() { return _state == mature_state; }
int creation_mileage() { return _orig.creation_mileage(); } int creation_mileage() { return _orig.creation_mileage(); }
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "precompiled.hpp" #include "precompiled.hpp"
#include "ci/ciClassList.hpp" #include "ci/ciClassList.hpp"
#include "ci/ciInstance.hpp" #include "ci/ciInstance.hpp"
#include "ci/ciMethodData.hpp"
#include "ci/ciMethodHandle.hpp" #include "ci/ciMethodHandle.hpp"
#include "ci/ciUtilities.hpp" #include "ci/ciUtilities.hpp"
#include "prims/methodHandleWalk.hpp" #include "prims/methodHandleWalk.hpp"
...@@ -36,13 +37,13 @@ ...@@ -36,13 +37,13 @@
// ciMethodHandle::get_adapter // ciMethodHandle::get_adapter
// //
// Return an adapter for this MethodHandle. // Return an adapter for this MethodHandle.
ciMethod* ciMethodHandle::get_adapter(bool is_invokedynamic) const { ciMethod* ciMethodHandle::get_adapter_impl(bool is_invokedynamic) const {
VM_ENTRY_MARK; VM_ENTRY_MARK;
Handle h(get_oop()); Handle h(get_oop());
methodHandle callee(_callee->get_methodOop()); methodHandle callee(_callee->get_methodOop());
// We catch all exceptions here that could happen in the method // We catch all exceptions here that could happen in the method
// handle compiler and stop the VM. // handle compiler and stop the VM.
MethodHandleCompiler mhc(h, callee, call_profile()->count(), is_invokedynamic, THREAD); MethodHandleCompiler mhc(h, callee, _profile->count(), is_invokedynamic, THREAD);
if (!HAS_PENDING_EXCEPTION) { if (!HAS_PENDING_EXCEPTION) {
methodHandle m = mhc.compile(THREAD); methodHandle m = mhc.compile(THREAD);
if (!HAS_PENDING_EXCEPTION) { if (!HAS_PENDING_EXCEPTION) {
...@@ -58,6 +59,22 @@ ciMethod* ciMethodHandle::get_adapter(bool is_invokedynamic) const { ...@@ -58,6 +59,22 @@ ciMethod* ciMethodHandle::get_adapter(bool is_invokedynamic) const {
return NULL; return NULL;
} }
// ------------------------------------------------------------------
// ciMethodHandle::get_adapter
//
// Return an adapter for this MethodHandle.
ciMethod* ciMethodHandle::get_adapter(bool is_invokedynamic) const {
ciMethod* result = get_adapter_impl(is_invokedynamic);
if (result) {
// Fake up the MDO maturity.
ciMethodData* mdo = result->method_data();
if (mdo != NULL && _caller->method_data() != NULL && _caller->method_data()->is_mature()) {
mdo->set_mature();
}
}
return result;
}
// ------------------------------------------------------------------ // ------------------------------------------------------------------
// ciMethodHandle::print_impl // ciMethodHandle::print_impl
......
...@@ -35,35 +35,36 @@ ...@@ -35,35 +35,36 @@
class ciMethodHandle : public ciInstance { class ciMethodHandle : public ciInstance {
private: private:
ciMethod* _callee; ciMethod* _callee;
ciMethod* _caller;
ciCallProfile* _profile; ciCallProfile* _profile;
// Return an adapter for this MethodHandle. // Return an adapter for this MethodHandle.
ciMethod* get_adapter(bool is_invokedynamic) const; ciMethod* get_adapter_impl(bool is_invokedynamic) const;
ciMethod* get_adapter( bool is_invokedynamic) const;
protected: protected:
void print_impl(outputStream* st); void print_impl(outputStream* st);
public: public:
ciMethodHandle(instanceHandle h_i) : ciInstance(h_i) {}; ciMethodHandle(instanceHandle h_i) :
ciInstance(h_i),
_callee(NULL),
_caller(NULL),
_profile(NULL)
{}
// What kind of ciObject is this? // What kind of ciObject is this?
bool is_method_handle() const { return true; } bool is_method_handle() const { return true; }
ciMethod* callee() const { return _callee; } void set_callee(ciMethod* m) { _callee = m; }
void set_callee(ciMethod* m) { _callee = m; } void set_caller(ciMethod* m) { _caller = m; }
void set_call_profile(ciCallProfile* profile) { _profile = profile; }
ciCallProfile* call_profile() const { return _profile; }
void set_call_profile(ciCallProfile* profile) { _profile = profile; }
// Return an adapter for a MethodHandle call. // Return an adapter for a MethodHandle call.
ciMethod* get_method_handle_adapter() const { ciMethod* get_method_handle_adapter() const { return get_adapter(false); }
return get_adapter(false);
}
// Return an adapter for an invokedynamic call. // Return an adapter for an invokedynamic call.
ciMethod* get_invokedynamic_adapter() const { ciMethod* get_invokedynamic_adapter() const { return get_adapter(true); }
return get_adapter(true);
}
}; };
#endif // SHARE_VM_CI_CIMETHODHANDLE_HPP #endif // SHARE_VM_CI_CIMETHODHANDLE_HPP
...@@ -62,7 +62,10 @@ void trace_type_profile(ciMethod *method, int depth, int bci, ciMethod *prof_met ...@@ -62,7 +62,10 @@ void trace_type_profile(ciMethod *method, int depth, int bci, ciMethod *prof_met
CallGenerator* Compile::call_generator(ciMethod* call_method, int vtable_index, bool call_is_virtual, CallGenerator* Compile::call_generator(ciMethod* call_method, int vtable_index, bool call_is_virtual,
JVMState* jvms, bool allow_inline, JVMState* jvms, bool allow_inline,
float prof_factor) { float prof_factor) {
CallGenerator* cg; CallGenerator* cg;
ciMethod* caller = jvms->method();
int bci = jvms->bci();
Bytecodes::Code bytecode = caller->java_code_at_bci(bci);
guarantee(call_method != NULL, "failed method resolution"); guarantee(call_method != NULL, "failed method resolution");
// Dtrace currently doesn't work unless all calls are vanilla // Dtrace currently doesn't work unless all calls are vanilla
...@@ -73,8 +76,7 @@ CallGenerator* Compile::call_generator(ciMethod* call_method, int vtable_index, ...@@ -73,8 +76,7 @@ CallGenerator* Compile::call_generator(ciMethod* call_method, int vtable_index,
// Note: When we get profiling during stage-1 compiles, we want to pull // Note: When we get profiling during stage-1 compiles, we want to pull
// from more specific profile data which pertains to this inlining. // from more specific profile data which pertains to this inlining.
// Right now, ignore the information in jvms->caller(), and do method[bci]. // Right now, ignore the information in jvms->caller(), and do method[bci].
ciCallProfile profile = jvms->method()->call_profile_at_bci(jvms->bci()); ciCallProfile profile = caller->call_profile_at_bci(bci);
Bytecodes::Code bytecode = jvms->method()->java_code_at_bci(jvms->bci());
// See how many times this site has been invoked. // See how many times this site has been invoked.
int site_count = profile.count(); int site_count = profile.count();
...@@ -126,9 +128,10 @@ CallGenerator* Compile::call_generator(ciMethod* call_method, int vtable_index, ...@@ -126,9 +128,10 @@ CallGenerator* Compile::call_generator(ciMethod* call_method, int vtable_index,
ciObject* const_oop = oop_ptr->const_oop(); ciObject* const_oop = oop_ptr->const_oop();
ciMethodHandle* method_handle = const_oop->as_method_handle(); ciMethodHandle* method_handle = const_oop->as_method_handle();
// Set the actually called method to have access to the class // Set the callee to have access to the class and signature in
// and signature in the MethodHandleCompiler. // the MethodHandleCompiler.
method_handle->set_callee(call_method); method_handle->set_callee(call_method);
method_handle->set_caller(caller);
method_handle->set_call_profile(&profile); method_handle->set_call_profile(&profile);
// Get an adapter for the MethodHandle. // Get an adapter for the MethodHandle.
...@@ -150,9 +153,10 @@ CallGenerator* Compile::call_generator(ciMethod* call_method, int vtable_index, ...@@ -150,9 +153,10 @@ CallGenerator* Compile::call_generator(ciMethod* call_method, int vtable_index,
ciCallSite* call_site = str.get_call_site(); ciCallSite* call_site = str.get_call_site();
ciMethodHandle* method_handle = call_site->get_target(); ciMethodHandle* method_handle = call_site->get_target();
// Set the actually called method to have access to the class // Set the callee to have access to the class and signature in
// and signature in the MethodHandleCompiler. // the MethodHandleCompiler.
method_handle->set_callee(call_method); method_handle->set_callee(call_method);
method_handle->set_caller(caller);
method_handle->set_call_profile(&profile); method_handle->set_call_profile(&profile);
// Get an adapter for the MethodHandle. // Get an adapter for the MethodHandle.
......
...@@ -113,6 +113,7 @@ public: ...@@ -113,6 +113,7 @@ public:
tt_parameter, tt_parameter,
tt_temporary, tt_temporary,
tt_constant, tt_constant,
tt_symbolic,
tt_illegal tt_illegal
}; };
...@@ -164,6 +165,10 @@ private: ...@@ -164,6 +165,10 @@ private:
bool _for_invokedynamic; bool _for_invokedynamic;
int _local_index; int _local_index;
// This array is kept in an unusual order, indexed by low-level "slot number".
// TOS is always _outgoing.at(0), so simple pushes and pops shift the whole _outgoing array.
// If there is a receiver in the current argument list, it is at _outgoing.at(_outgoing.length()-1).
// If a value at _outgoing.at(n) is T_LONG or T_DOUBLE, the value at _outgoing.at(n+1) is T_VOID.
GrowableArray<SlotState> _outgoing; // current outgoing parameter slots GrowableArray<SlotState> _outgoing; // current outgoing parameter slots
int _outgoing_argc; // # non-empty outgoing slots int _outgoing_argc; // # non-empty outgoing slots
...@@ -173,6 +178,11 @@ private: ...@@ -173,6 +178,11 @@ private:
// Insert or delete a second empty slot as needed. // Insert or delete a second empty slot as needed.
void change_argument(BasicType old_type, int slot, BasicType new_type, const ArgToken& new_arg); void change_argument(BasicType old_type, int slot, BasicType new_type, const ArgToken& new_arg);
// Raw retype conversions for OP_RAW_RETYPE.
void retype_raw_conversion(BasicType src, BasicType dst, bool for_return, int slot, TRAPS);
void retype_raw_argument_type(BasicType src, BasicType dst, int slot, TRAPS) { retype_raw_conversion(src, dst, false, slot, CHECK); }
void retype_raw_return_type( BasicType src, BasicType dst, TRAPS) { retype_raw_conversion(src, dst, true, -1, CHECK); }
SlotState* slot_state(int slot) { SlotState* slot_state(int slot) {
if (slot < 0 || slot >= _outgoing.length()) if (slot < 0 || slot >= _outgoing.length())
return NULL; return NULL;
...@@ -221,12 +231,12 @@ public: ...@@ -221,12 +231,12 @@ public:
int max_locals() const { return _local_index; } int max_locals() const { return _local_index; }
// plug-in abstract interpretation steps: // plug-in abstract interpretation steps:
virtual ArgToken make_parameter( BasicType type, klassOop tk, int argnum, TRAPS ) = 0; virtual ArgToken make_parameter(BasicType type, klassOop tk, int argnum, TRAPS) = 0;
virtual ArgToken make_prim_constant( BasicType type, jvalue* con, TRAPS ) = 0; virtual ArgToken make_prim_constant(BasicType type, jvalue* con, TRAPS) = 0;
virtual ArgToken make_oop_constant( oop con, TRAPS ) = 0; virtual ArgToken make_oop_constant(oop con, TRAPS) = 0;
virtual ArgToken make_conversion( BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& src, TRAPS ) = 0; virtual ArgToken make_conversion(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& src, TRAPS) = 0;
virtual ArgToken make_fetch( BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& base, const ArgToken& offset, TRAPS ) = 0; virtual ArgToken make_fetch(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& base, const ArgToken& offset, TRAPS) = 0;
virtual ArgToken make_invoke( methodOop m, vmIntrinsics::ID iid, Bytecodes::Code op, bool tailcall, int argc, ArgToken* argv, TRAPS ) = 0; virtual ArgToken make_invoke(methodOop m, vmIntrinsics::ID iid, Bytecodes::Code op, bool tailcall, int argc, ArgToken* argv, TRAPS) = 0;
// For make_invoke, the methodOop can be NULL if the intrinsic ID // For make_invoke, the methodOop can be NULL if the intrinsic ID
// is something other than vmIntrinsics::_none. // is something other than vmIntrinsics::_none.
...@@ -253,6 +263,10 @@ private: ...@@ -253,6 +263,10 @@ private:
KlassHandle _target_klass; KlassHandle _target_klass;
Thread* _thread; Thread* _thread;
// Values used by the compiler.
static jvalue zero_jvalue;
static jvalue one_jvalue;
// Fake constant pool entry. // Fake constant pool entry.
class ConstantValue { class ConstantValue {
private: private:
...@@ -417,7 +431,7 @@ private: ...@@ -417,7 +431,7 @@ private:
methodHandle get_method_oop(TRAPS) const; methodHandle get_method_oop(TRAPS) const;
public: public:
MethodHandleCompiler(Handle root, methodHandle call_method, int invoke_count, bool for_invokedynamic, TRAPS); MethodHandleCompiler(Handle root, methodHandle callee, int invoke_count, bool for_invokedynamic, TRAPS);
// Compile the given MH chain into bytecode. // Compile the given MH chain into bytecode.
methodHandle compile(TRAPS); methodHandle compile(TRAPS);
......
...@@ -1099,6 +1099,14 @@ static oop object_java_mirror() { ...@@ -1099,6 +1099,14 @@ static oop object_java_mirror() {
return Klass::cast(SystemDictionary::Object_klass())->java_mirror(); return Klass::cast(SystemDictionary::Object_klass())->java_mirror();
} }
bool MethodHandles::is_float_fixed_reinterpretation_cast(BasicType src, BasicType dst) {
if (src == T_FLOAT) return dst == T_INT;
if (src == T_INT) return dst == T_FLOAT;
if (src == T_DOUBLE) return dst == T_LONG;
if (src == T_LONG) return dst == T_DOUBLE;
return false;
}
bool MethodHandles::same_basic_type_for_arguments(BasicType src, bool MethodHandles::same_basic_type_for_arguments(BasicType src,
BasicType dst, BasicType dst,
bool raw, bool raw,
...@@ -1125,10 +1133,8 @@ bool MethodHandles::same_basic_type_for_arguments(BasicType src, ...@@ -1125,10 +1133,8 @@ bool MethodHandles::same_basic_type_for_arguments(BasicType src,
return true; // remaining case: byte fits in short return true; // remaining case: byte fits in short
} }
// allow float/fixed reinterpretation casts // allow float/fixed reinterpretation casts
if (src == T_FLOAT) return dst == T_INT; if (is_float_fixed_reinterpretation_cast(src, dst))
if (src == T_INT) return dst == T_FLOAT; return true;
if (src == T_DOUBLE) return dst == T_LONG;
if (src == T_LONG) return dst == T_DOUBLE;
return false; return false;
} }
...@@ -1399,7 +1405,7 @@ const char* MethodHandles::check_argument_type_change(BasicType src_type, ...@@ -1399,7 +1405,7 @@ const char* MethodHandles::check_argument_type_change(BasicType src_type,
int argnum, int argnum,
bool raw) { bool raw) {
const char* err = NULL; const char* err = NULL;
bool for_return = (argnum < 0); const bool for_return = (argnum < 0);
// just in case: // just in case:
if (src_type == T_ARRAY) src_type = T_OBJECT; if (src_type == T_ARRAY) src_type = T_OBJECT;
...@@ -1408,17 +1414,17 @@ const char* MethodHandles::check_argument_type_change(BasicType src_type, ...@@ -1408,17 +1414,17 @@ const char* MethodHandles::check_argument_type_change(BasicType src_type,
// Produce some nice messages if VerifyMethodHandles is turned on: // Produce some nice messages if VerifyMethodHandles is turned on:
if (!same_basic_type_for_arguments(src_type, dst_type, raw, for_return)) { if (!same_basic_type_for_arguments(src_type, dst_type, raw, for_return)) {
if (src_type == T_OBJECT) { if (src_type == T_OBJECT) {
if (raw && dst_type == T_INT && is_always_null_type(src_klass)) if (raw && is_java_primitive(dst_type))
return NULL; // OK to convert a null pointer to a garbage int return NULL; // ref-to-prim discards ref and returns zero
err = ((argnum >= 0) err = (!for_return
? "type mismatch: passing a %s for method argument #%d, which expects primitive %s" ? "type mismatch: passing a %s for method argument #%d, which expects primitive %s"
: "type mismatch: returning a %s, but caller expects primitive %s"); : "type mismatch: returning a %s, but caller expects primitive %s");
} else if (dst_type == T_OBJECT) { } else if (dst_type == T_OBJECT) {
err = ((argnum >= 0) err = (!for_return
? "type mismatch: passing a primitive %s for method argument #%d, which expects %s" ? "type mismatch: passing a primitive %s for method argument #%d, which expects %s"
: "type mismatch: returning a primitive %s, but caller expects %s"); : "type mismatch: returning a primitive %s, but caller expects %s");
} else { } else {
err = ((argnum >= 0) err = (!for_return
? "type mismatch: passing a %s for method argument #%d, which expects %s" ? "type mismatch: passing a %s for method argument #%d, which expects %s"
: "type mismatch: returning a %s, but caller expects %s"); : "type mismatch: returning a %s, but caller expects %s");
} }
...@@ -1427,11 +1433,11 @@ const char* MethodHandles::check_argument_type_change(BasicType src_type, ...@@ -1427,11 +1433,11 @@ const char* MethodHandles::check_argument_type_change(BasicType src_type,
if (!class_cast_needed(dst_klass, src_klass)) { if (!class_cast_needed(dst_klass, src_klass)) {
if (raw) if (raw)
return NULL; // reverse cast is OK; the MH target is trusted to enforce it return NULL; // reverse cast is OK; the MH target is trusted to enforce it
err = ((argnum >= 0) err = (!for_return
? "cast required: passing a %s for method argument #%d, which expects %s" ? "cast required: passing a %s for method argument #%d, which expects %s"
: "cast required: returning a %s, but caller expects %s"); : "cast required: returning a %s, but caller expects %s");
} else { } else {
err = ((argnum >= 0) err = (!for_return
? "reference mismatch: passing a %s for method argument #%d, which expects %s" ? "reference mismatch: passing a %s for method argument #%d, which expects %s"
: "reference mismatch: returning a %s, but caller expects %s"); : "reference mismatch: returning a %s, but caller expects %s");
} }
...@@ -1452,7 +1458,7 @@ const char* MethodHandles::check_argument_type_change(BasicType src_type, ...@@ -1452,7 +1458,7 @@ const char* MethodHandles::check_argument_type_change(BasicType src_type,
size_t msglen = strlen(err) + strlen(src_name) + strlen(dst_name) + (argnum < 10 ? 1 : 11); size_t msglen = strlen(err) + strlen(src_name) + strlen(dst_name) + (argnum < 10 ? 1 : 11);
char* msg = NEW_RESOURCE_ARRAY(char, msglen + 1); char* msg = NEW_RESOURCE_ARRAY(char, msglen + 1);
if (argnum >= 0) { if (!for_return) {
assert(strstr(err, "%d") != NULL, ""); assert(strstr(err, "%d") != NULL, "");
jio_snprintf(msg, msglen, err, src_name, argnum, dst_name); jio_snprintf(msg, msglen, err, src_name, argnum, dst_name);
} else { } else {
...@@ -2180,9 +2186,10 @@ void MethodHandles::verify_AdapterMethodHandle(Handle mh, int argnum, TRAPS) { ...@@ -2180,9 +2186,10 @@ void MethodHandles::verify_AdapterMethodHandle(Handle mh, int argnum, TRAPS) {
} }
void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnum, TRAPS) { void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnum, TRAPS) {
int argslot = java_lang_invoke_AdapterMethodHandle::vmargslot(mh()); Handle argument = java_lang_invoke_AdapterMethodHandle::argument(mh());
jint conversion = java_lang_invoke_AdapterMethodHandle::conversion(mh()); int argslot = java_lang_invoke_AdapterMethodHandle::vmargslot(mh());
jint conv_op = adapter_conversion_op(conversion); jint conversion = java_lang_invoke_AdapterMethodHandle::conversion(mh());
jint conv_op = adapter_conversion_op(conversion);
// adjust the adapter code to the internal EntryKind enumeration: // adjust the adapter code to the internal EntryKind enumeration:
EntryKind ek_orig = adapter_entry_kind(conv_op); EntryKind ek_orig = adapter_entry_kind(conv_op);
...@@ -2241,7 +2248,7 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu ...@@ -2241,7 +2248,7 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu
} else if (src == T_DOUBLE && dest == T_FLOAT) { } else if (src == T_DOUBLE && dest == T_FLOAT) {
ek_opt = _adapter_opt_d2f; ek_opt = _adapter_opt_d2f;
} else { } else {
assert(false, ""); goto throw_not_impl; // runs user code, hence could block
} }
break; break;
case 1 *4+ 2: case 1 *4+ 2:
...@@ -2250,11 +2257,11 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu ...@@ -2250,11 +2257,11 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu
} else if (src == T_FLOAT && dest == T_DOUBLE) { } else if (src == T_FLOAT && dest == T_DOUBLE) {
ek_opt = _adapter_opt_f2d; ek_opt = _adapter_opt_f2d;
} else { } else {
assert(false, ""); goto throw_not_impl; // runs user code, hence could block
} }
break; break;
default: default:
assert(false, ""); goto throw_not_impl; // runs user code, hence could block
break; break;
} }
} }
...@@ -2271,7 +2278,7 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu ...@@ -2271,7 +2278,7 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu
ek_opt = _adapter_opt_unboxl; ek_opt = _adapter_opt_unboxl;
break; break;
default: default:
assert(false, ""); goto throw_not_impl;
break; break;
} }
} }
...@@ -2284,6 +2291,9 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu ...@@ -2284,6 +2291,9 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu
vminfo = argslot; vminfo = argslot;
ek_opt = _adapter_opt_collect_ref; ek_opt = _adapter_opt_collect_ref;
ensure_vmlayout_field(target, CHECK); ensure_vmlayout_field(target, CHECK);
// for MethodHandleWalk:
if (java_lang_invoke_AdapterMethodHandle::is_instance(argument()))
ensure_vmlayout_field(argument, CHECK);
if (!OptimizeMethodHandles) break; if (!OptimizeMethodHandles) break;
switch (type2size[src]) { switch (type2size[src]) {
case 1: case 1:
...@@ -2311,7 +2321,7 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu ...@@ -2311,7 +2321,7 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu
ek_opt = _adapter_opt_collect_2_ref; ek_opt = _adapter_opt_collect_2_ref;
break; break;
default: default:
assert(false, ""); goto throw_not_impl;
break; break;
} }
} }
...@@ -2335,7 +2345,7 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu ...@@ -2335,7 +2345,7 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu
rotate > 0 ? _adapter_opt_rot_2_up : _adapter_opt_rot_2_down); rotate > 0 ? _adapter_opt_rot_2_up : _adapter_opt_rot_2_down);
break; break;
default: default:
assert(false, ""); goto throw_not_impl;
break; break;
} }
} }
...@@ -2402,12 +2412,11 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu ...@@ -2402,12 +2412,11 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu
case _adapter_collect_args: case _adapter_collect_args:
{ {
assert(UseRicochetFrames, "else don't come here"); assert(UseRicochetFrames, "else don't come here");
int elem_slots = argument_slot_count( int elem_slots = argument_slot_count(java_lang_invoke_MethodHandle::type(argument()));
java_lang_invoke_MethodHandle::type(
java_lang_invoke_AdapterMethodHandle::argument(mh()) ) );
// vminfo will be the location to insert the return value // vminfo will be the location to insert the return value
vminfo = argslot; vminfo = argslot;
ensure_vmlayout_field(target, CHECK); ensure_vmlayout_field(target, CHECK);
ensure_vmlayout_field(argument, CHECK);
// general case: // general case:
switch (dest) { switch (dest) {
...@@ -2472,12 +2481,11 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu ...@@ -2472,12 +2481,11 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu
case _adapter_fold_args: case _adapter_fold_args:
{ {
assert(UseRicochetFrames, "else don't come here"); assert(UseRicochetFrames, "else don't come here");
int elem_slots = argument_slot_count( int elem_slots = argument_slot_count(java_lang_invoke_MethodHandle::type(argument()));
java_lang_invoke_MethodHandle::type(
java_lang_invoke_AdapterMethodHandle::argument(mh()) ) );
// vminfo will be the location to insert the return value // vminfo will be the location to insert the return value
vminfo = argslot + elem_slots; vminfo = argslot + elem_slots;
ensure_vmlayout_field(target, CHECK); ensure_vmlayout_field(target, CHECK);
ensure_vmlayout_field(argument, CHECK);
switch (dest) { switch (dest) {
default : if (!is_subword_type(dest)) goto throw_not_impl; default : if (!is_subword_type(dest)) goto throw_not_impl;
...@@ -2527,15 +2535,31 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu ...@@ -2527,15 +2535,31 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu
break; break;
} }
if (err != NULL && (vminfo & CONV_VMINFO_MASK) != vminfo) { if (err == NULL && (vminfo & CONV_VMINFO_MASK) != vminfo) {
// should not happen, since vminfo is used to encode arg/slot indexes < 255 // should not happen, since vminfo is used to encode arg/slot indexes < 255
err = "vminfo overflow"; err = "vminfo overflow";
} }
if (err != NULL && !have_entry(ek_opt)) { if (err == NULL && !have_entry(ek_opt)) {
err = "adapter stub for this kind of method handle is missing"; err = "adapter stub for this kind of method handle is missing";
} }
if (err == NULL && ek_opt == ek_orig) {
switch (ek_opt) {
case _adapter_prim_to_prim:
case _adapter_ref_to_prim:
case _adapter_prim_to_ref:
case _adapter_swap_args:
case _adapter_rot_args:
case _adapter_collect_args:
case _adapter_fold_args:
case _adapter_spread_args:
// should be handled completely by optimized cases; see above
err = "init_AdapterMethodHandle should not issue this";
break;
}
}
if (err != NULL) { if (err != NULL) {
throw_InternalError_for_bad_conversion(conversion, err, THREAD); throw_InternalError_for_bad_conversion(conversion, err, THREAD);
return; return;
......
...@@ -698,6 +698,8 @@ class MethodHandles: AllStatic { ...@@ -698,6 +698,8 @@ class MethodHandles: AllStatic {
KlassHandle receiver_klass, KlassHandle receiver_klass,
TRAPS); TRAPS);
public:
static bool is_float_fixed_reinterpretation_cast(BasicType src, BasicType dst);
static bool same_basic_type_for_arguments(BasicType src, BasicType dst, static bool same_basic_type_for_arguments(BasicType src, BasicType dst,
bool raw = false, bool raw = false,
bool for_return = false); bool for_return = false);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册