6655638: dynamic languages need method handles
Initial implementation, with known omissions (x86/64, sparc, compiler optim., c-oops, C++ interp.) Reviewed-by: kvn, twisti, never
This commit is contained in:
parent
318da3f68c
commit
ce0c084720
@ -3029,6 +3029,58 @@ void MacroAssembler::check_klass_subtype_slow_path(Register sub_klass,
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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_dyn_MethodHandle::type_offset_in_bytes, temp_reg);
|
||||||
|
ld_ptr(mh_reg, mhtype_offset, temp_reg);
|
||||||
|
cmp(temp_reg, mtype_reg);
|
||||||
|
br(Assembler::notEqual, false, Assembler::pn, wrong_method_type);
|
||||||
|
delayed()->nop();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MacroAssembler::jump_to_method_handle_entry(Register mh_reg, Register temp_reg) {
|
||||||
|
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
|
||||||
|
ld_ptr(mh_reg, delayed_value(java_dyn_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
|
||||||
|
|
||||||
|
// (Can any caller use this delay slot? If so, add an option for supression.)
|
||||||
|
delayed()->nop();
|
||||||
|
}
|
||||||
|
|
||||||
|
RegisterOrConstant MacroAssembler::argument_offset(RegisterOrConstant arg_slot,
|
||||||
|
int extra_slot_offset) {
|
||||||
|
// cf. TemplateTable::prepare_invoke(), if (load_receiver).
|
||||||
|
int stackElementSize = Interpreter::stackElementWords() * wordSize;
|
||||||
|
int offset = Interpreter::expr_offset_in_bytes(extra_slot_offset+0);
|
||||||
|
int offset1 = Interpreter::expr_offset_in_bytes(extra_slot_offset+1);
|
||||||
|
assert(offset1 - offset == stackElementSize, "correct arithmetic");
|
||||||
|
if (arg_slot.is_constant()) {
|
||||||
|
offset += arg_slot.as_constant() * stackElementSize;
|
||||||
|
return offset;
|
||||||
|
} else {
|
||||||
|
Register temp = arg_slot.as_register();
|
||||||
|
sll_ptr(temp, exact_log2(stackElementSize), temp);
|
||||||
|
if (offset != 0)
|
||||||
|
add(temp, offset, temp);
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void MacroAssembler::biased_locking_enter(Register obj_reg, Register mark_reg,
|
void MacroAssembler::biased_locking_enter(Register obj_reg, Register mark_reg,
|
||||||
Register temp_reg,
|
Register temp_reg,
|
||||||
Label& done, Label* slow_case,
|
Label& done, Label* slow_case,
|
||||||
|
@ -84,6 +84,10 @@ REGISTER_DECLARATION(Register, G4_scratch , G4);
|
|||||||
|
|
||||||
REGISTER_DECLARATION(Register, Gtemp , G5);
|
REGISTER_DECLARATION(Register, Gtemp , G5);
|
||||||
|
|
||||||
|
// JSR 292 fixed register usages:
|
||||||
|
REGISTER_DECLARATION(Register, G5_method_type , G5);
|
||||||
|
REGISTER_DECLARATION(Register, G3_method_handle , G3);
|
||||||
|
|
||||||
// The compiler requires that G5_megamorphic_method is G5_inline_cache_klass,
|
// The compiler requires that G5_megamorphic_method is G5_inline_cache_klass,
|
||||||
// because a single patchable "set" instruction (NativeMovConstReg,
|
// because a single patchable "set" instruction (NativeMovConstReg,
|
||||||
// or NativeMovConstPatching for compiler1) instruction
|
// or NativeMovConstPatching for compiler1) instruction
|
||||||
@ -91,9 +95,13 @@ REGISTER_DECLARATION(Register, Gtemp , G5);
|
|||||||
// call site is an inline cache or is megamorphic. See the function
|
// call site is an inline cache or is megamorphic. See the function
|
||||||
// CompiledIC::set_to_megamorphic.
|
// CompiledIC::set_to_megamorphic.
|
||||||
//
|
//
|
||||||
// On the other hand, G5_inline_cache_klass must differ from G5_method,
|
// If a inline cache targets an interpreted method, then the
|
||||||
// because both registers are needed for an inline cache that calls
|
// G5 register will be used twice during the call. First,
|
||||||
// an interpreted method.
|
// the call site will be patched to load a compiledICHolder
|
||||||
|
// into G5. (This is an ordered pair of ic_klass, method.)
|
||||||
|
// The c2i adapter will first check the ic_klass, then load
|
||||||
|
// G5_method with the method part of the pair just before
|
||||||
|
// jumping into the interpreter.
|
||||||
//
|
//
|
||||||
// Note that G5_method is only the method-self for the interpreter,
|
// Note that G5_method is only the method-self for the interpreter,
|
||||||
// and is logically unrelated to G5_megamorphic_method.
|
// and is logically unrelated to G5_megamorphic_method.
|
||||||
@ -1931,6 +1939,7 @@ class MacroAssembler: public Assembler {
|
|||||||
inline void store_ptr_contents( Register s, Address& a, int offset = 0 );
|
inline void store_ptr_contents( Register s, Address& a, int offset = 0 );
|
||||||
inline void jumpl_to( Address& a, Register d, int offset = 0 );
|
inline void jumpl_to( Address& a, Register d, int offset = 0 );
|
||||||
inline void jump_to( Address& a, int offset = 0 );
|
inline void jump_to( Address& a, int offset = 0 );
|
||||||
|
inline void jump_indirect_to( Address& a, Register temp, int ld_offset = 0, int jmp_offset = 0 );
|
||||||
|
|
||||||
// ring buffer traceable jumps
|
// ring buffer traceable jumps
|
||||||
|
|
||||||
@ -2366,6 +2375,16 @@ class MacroAssembler: public Assembler {
|
|||||||
Register temp2_reg,
|
Register temp2_reg,
|
||||||
Label& L_success);
|
Label& L_success);
|
||||||
|
|
||||||
|
// method handles (JSR 292)
|
||||||
|
void check_method_handle_type(Register mtype_reg, Register mh_reg,
|
||||||
|
Register temp_reg,
|
||||||
|
Label& wrong_method_type);
|
||||||
|
void jump_to_method_handle_entry(Register mh_reg, Register temp_reg);
|
||||||
|
// offset relative to Gargs of argument at tos[arg_slot].
|
||||||
|
// (arg_slot == 0 means the last argument, not the first).
|
||||||
|
RegisterOrConstant argument_offset(RegisterOrConstant arg_slot,
|
||||||
|
int extra_slot_offset = 0);
|
||||||
|
|
||||||
|
|
||||||
// Stack overflow checking
|
// Stack overflow checking
|
||||||
|
|
||||||
|
@ -671,6 +671,15 @@ inline void MacroAssembler::jump_to( Address& a, int offset ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void MacroAssembler::jump_indirect_to( Address& a, Register temp,
|
||||||
|
int ld_offset, int jmp_offset ) {
|
||||||
|
assert_not_delayed();
|
||||||
|
//sethi(a); // sethi is caller responsibility for this one
|
||||||
|
ld_ptr(a, temp, ld_offset);
|
||||||
|
jmp(temp, jmp_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline void MacroAssembler::set_oop( jobject obj, Register d ) {
|
inline void MacroAssembler::set_oop( jobject obj, Register d ) {
|
||||||
set_oop(allocate_oop_address(obj, d));
|
set_oop(allocate_oop_address(obj, d));
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2007-2009 Sun Microsystems, Inc. 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
|
||||||
@ -1017,6 +1017,7 @@ void CppInterpreterGenerator::generate_compute_interpreter_state(const Register
|
|||||||
const int slop_factor = 2*wordSize;
|
const int slop_factor = 2*wordSize;
|
||||||
|
|
||||||
const int fixed_size = ((sizeof(BytecodeInterpreter) + slop_factor) >> LogBytesPerWord) + // what is the slop factor?
|
const int fixed_size = ((sizeof(BytecodeInterpreter) + slop_factor) >> LogBytesPerWord) + // what is the slop factor?
|
||||||
|
//6815692//methodOopDesc::extra_stack_words() + // extra push slots for MH adapters
|
||||||
frame::memory_parameter_word_sp_offset + // register save area + param window
|
frame::memory_parameter_word_sp_offset + // register save area + param window
|
||||||
(native ? frame::interpreter_frame_extra_outgoing_argument_words : 0); // JNI, class
|
(native ? frame::interpreter_frame_extra_outgoing_argument_words : 0); // JNI, class
|
||||||
|
|
||||||
@ -1163,6 +1164,9 @@ void CppInterpreterGenerator::generate_compute_interpreter_state(const Register
|
|||||||
__ st_ptr(O2, XXX_STATE(_stack)); // PREPUSH
|
__ st_ptr(O2, XXX_STATE(_stack)); // PREPUSH
|
||||||
|
|
||||||
__ lduh(max_stack, O3); // Full size expression stack
|
__ lduh(max_stack, O3); // Full size expression stack
|
||||||
|
guarantee(!EnableMethodHandles, "no support yet for java.dyn.MethodHandle"); //6815692
|
||||||
|
//6815692//if (EnableMethodHandles)
|
||||||
|
//6815692// __ inc(O3, methodOopDesc::extra_stack_entries());
|
||||||
__ sll(O3, LogBytesPerWord, O3);
|
__ sll(O3, LogBytesPerWord, O3);
|
||||||
__ sub(O2, O3, O3);
|
__ sub(O2, O3, O3);
|
||||||
// __ sub(O3, wordSize, O3); // so prepush doesn't look out of bounds
|
// __ sub(O3, wordSize, O3); // so prepush doesn't look out of bounds
|
||||||
@ -2017,7 +2021,9 @@ static int size_activation_helper(int callee_extra_locals, int max_stack, int mo
|
|||||||
|
|
||||||
const int fixed_size = sizeof(BytecodeInterpreter)/wordSize + // interpreter state object
|
const int fixed_size = sizeof(BytecodeInterpreter)/wordSize + // interpreter state object
|
||||||
frame::memory_parameter_word_sp_offset; // register save area + param window
|
frame::memory_parameter_word_sp_offset; // register save area + param window
|
||||||
|
const int extra_stack = 0; //6815692//methodOopDesc::extra_stack_entries();
|
||||||
return (round_to(max_stack +
|
return (round_to(max_stack +
|
||||||
|
extra_stack +
|
||||||
slop_factor +
|
slop_factor +
|
||||||
fixed_size +
|
fixed_size +
|
||||||
monitor_size +
|
monitor_size +
|
||||||
@ -2104,7 +2110,8 @@ void BytecodeInterpreter::layout_interpreterState(interpreterState to_fill,
|
|||||||
// Need +1 here because stack_base points to the word just above the first expr stack entry
|
// Need +1 here because stack_base points to the word just above the first expr stack entry
|
||||||
// and stack_limit is supposed to point to the word just below the last expr stack entry.
|
// and stack_limit is supposed to point to the word just below the last expr stack entry.
|
||||||
// See generate_compute_interpreter_state.
|
// See generate_compute_interpreter_state.
|
||||||
to_fill->_stack_limit = stack_base - (method->max_stack() + 1);
|
int extra_stack = 0; //6815692//methodOopDesc::extra_stack_entries();
|
||||||
|
to_fill->_stack_limit = stack_base - (method->max_stack() + 1 + extra_stack);
|
||||||
to_fill->_monitor_base = (BasicObjectLock*) monitor_base;
|
to_fill->_monitor_base = (BasicObjectLock*) monitor_base;
|
||||||
|
|
||||||
// sparc specific
|
// sparc specific
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. 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
|
||||||
@ -29,6 +29,7 @@
|
|||||||
address generate_normal_entry(bool synchronized);
|
address generate_normal_entry(bool synchronized);
|
||||||
address generate_native_entry(bool synchronized);
|
address generate_native_entry(bool synchronized);
|
||||||
address generate_abstract_entry(void);
|
address generate_abstract_entry(void);
|
||||||
|
address generate_method_handle_entry(void);
|
||||||
address generate_math_entry(AbstractInterpreter::MethodKind kind);
|
address generate_math_entry(AbstractInterpreter::MethodKind kind);
|
||||||
address generate_empty_entry(void);
|
address generate_empty_entry(void);
|
||||||
address generate_accessor_entry(void);
|
address generate_accessor_entry(void);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. 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
|
||||||
@ -235,6 +235,19 @@ address InterpreterGenerator::generate_abstract_entry(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Method handle invoker
|
||||||
|
// Dispatch a method of the form java.dyn.MethodHandles::invoke(...)
|
||||||
|
address InterpreterGenerator::generate_method_handle_entry(void) {
|
||||||
|
if (!EnableMethodHandles) {
|
||||||
|
return generate_abstract_entry();
|
||||||
|
}
|
||||||
|
return generate_abstract_entry(); //6815692//
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
// Entry points & stack frame layout
|
// Entry points & stack frame layout
|
||||||
//
|
//
|
||||||
@ -364,6 +377,7 @@ address AbstractInterpreterGenerator::generate_method_entry(AbstractInterpreter:
|
|||||||
case Interpreter::empty : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry(); break;
|
case Interpreter::empty : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry(); break;
|
||||||
case Interpreter::accessor : entry_point = ((InterpreterGenerator*)this)->generate_accessor_entry(); break;
|
case Interpreter::accessor : entry_point = ((InterpreterGenerator*)this)->generate_accessor_entry(); break;
|
||||||
case Interpreter::abstract : entry_point = ((InterpreterGenerator*)this)->generate_abstract_entry(); break;
|
case Interpreter::abstract : entry_point = ((InterpreterGenerator*)this)->generate_abstract_entry(); break;
|
||||||
|
case Interpreter::method_handle : entry_point = ((InterpreterGenerator*)this)->generate_method_handle_entry(); break;
|
||||||
case Interpreter::java_lang_math_sin : break;
|
case Interpreter::java_lang_math_sin : break;
|
||||||
case Interpreter::java_lang_math_cos : break;
|
case Interpreter::java_lang_math_cos : break;
|
||||||
case Interpreter::java_lang_math_tan : break;
|
case Interpreter::java_lang_math_tan : break;
|
||||||
|
70
hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp
Normal file
70
hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1997-2009 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
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||||
|
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||||
|
* have any questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "incls/_precompiled.incl"
|
||||||
|
#include "incls/_methodHandles_sparc.cpp.incl"
|
||||||
|
|
||||||
|
#define __ _masm->
|
||||||
|
|
||||||
|
address MethodHandleEntry::start_compiled_entry(MacroAssembler* _masm,
|
||||||
|
address interpreted_entry) {
|
||||||
|
__ align(wordSize);
|
||||||
|
address target = __ pc() + sizeof(Data);
|
||||||
|
while (__ pc() < target) {
|
||||||
|
__ nop();
|
||||||
|
__ align(wordSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
MethodHandleEntry* me = (MethodHandleEntry*) __ pc();
|
||||||
|
me->set_end_address(__ pc()); // set a temporary end_address
|
||||||
|
me->set_from_interpreted_entry(interpreted_entry);
|
||||||
|
me->set_type_checking_entry(NULL);
|
||||||
|
|
||||||
|
return (address) me;
|
||||||
|
}
|
||||||
|
|
||||||
|
MethodHandleEntry* MethodHandleEntry::finish_compiled_entry(MacroAssembler* _masm,
|
||||||
|
address start_addr) {
|
||||||
|
MethodHandleEntry* me = (MethodHandleEntry*) start_addr;
|
||||||
|
assert(me->end_address() == start_addr, "valid ME");
|
||||||
|
|
||||||
|
// Fill in the real end_address:
|
||||||
|
__ align(wordSize);
|
||||||
|
me->set_end_address(__ pc());
|
||||||
|
|
||||||
|
return me;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Code generation
|
||||||
|
address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* _masm) {
|
||||||
|
ShouldNotReachHere(); //NYI, 6815692
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate an "entry" field for a method handle.
|
||||||
|
// This determines how the method handle will respond to calls.
|
||||||
|
void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek) {
|
||||||
|
ShouldNotReachHere(); //NYI, 6815692
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2002-2009 Sun Microsystems, Inc. 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
|
||||||
@ -142,6 +142,8 @@ REGISTER_DEFINITION(Register, G1_scratch);
|
|||||||
REGISTER_DEFINITION(Register, G3_scratch);
|
REGISTER_DEFINITION(Register, G3_scratch);
|
||||||
REGISTER_DEFINITION(Register, G4_scratch);
|
REGISTER_DEFINITION(Register, G4_scratch);
|
||||||
REGISTER_DEFINITION(Register, Gtemp);
|
REGISTER_DEFINITION(Register, Gtemp);
|
||||||
|
REGISTER_DEFINITION(Register, G5_method_type);
|
||||||
|
REGISTER_DEFINITION(Register, G3_method_handle);
|
||||||
REGISTER_DEFINITION(Register, Lentry_args);
|
REGISTER_DEFINITION(Register, Lentry_args);
|
||||||
|
|
||||||
#ifdef CC_INTERP
|
#ifdef CC_INTERP
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2003-2009 Sun Microsystems, Inc. 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
|
||||||
@ -937,12 +937,12 @@ void AdapterGenerator::gen_i2c_adapter(
|
|||||||
// Inputs:
|
// Inputs:
|
||||||
// G2_thread - TLS
|
// G2_thread - TLS
|
||||||
// G5_method - Method oop
|
// G5_method - Method oop
|
||||||
// O0 - Flag telling us to restore SP from O5
|
// G4 (Gargs) - Pointer to interpreter's args
|
||||||
// O4_args - Pointer to interpreter's args
|
// O0..O4 - free for scratch
|
||||||
// O5 - Caller's saved SP, to be restored if needed
|
// O5_savedSP - Caller's saved SP, to be restored if needed
|
||||||
// O6 - Current SP!
|
// O6 - Current SP!
|
||||||
// O7 - Valid return address
|
// 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)
|
||||||
|
|
||||||
// Outputs:
|
// Outputs:
|
||||||
// G2_thread - TLS
|
// G2_thread - TLS
|
||||||
@ -954,7 +954,7 @@ void AdapterGenerator::gen_i2c_adapter(
|
|||||||
// F0-F7 - more outgoing args
|
// F0-F7 - more outgoing args
|
||||||
|
|
||||||
|
|
||||||
// O4 is about to get loaded up with compiled callee's args
|
// Gargs is the incoming argument base, and also an outgoing argument.
|
||||||
__ sub(Gargs, BytesPerWord, Gargs);
|
__ sub(Gargs, BytesPerWord, Gargs);
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. 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
|
||||||
@ -108,6 +108,24 @@ address TemplateInterpreterGenerator::generate_ClassCastException_handler() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Arguments are: required type in G5_method_type, and
|
||||||
|
// failing object (or NULL) in G3_method_handle.
|
||||||
|
address TemplateInterpreterGenerator::generate_WrongMethodType_handler() {
|
||||||
|
address entry = __ pc();
|
||||||
|
// expression stack must be empty before entering the VM if an exception
|
||||||
|
// happened
|
||||||
|
__ empty_expression_stack();
|
||||||
|
// load exception object
|
||||||
|
__ call_VM(Oexception,
|
||||||
|
CAST_FROM_FN_PTR(address,
|
||||||
|
InterpreterRuntime::throw_WrongMethodTypeException),
|
||||||
|
G5_method_type, // required
|
||||||
|
G3_method_handle); // actual
|
||||||
|
__ should_not_reach_here();
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
address TemplateInterpreterGenerator::generate_ArrayIndexOutOfBounds_handler(const char* name) {
|
address TemplateInterpreterGenerator::generate_ArrayIndexOutOfBounds_handler(const char* name) {
|
||||||
address entry = __ pc();
|
address entry = __ pc();
|
||||||
// expression stack must be empty before entering the VM if an exception happened
|
// expression stack must be empty before entering the VM if an exception happened
|
||||||
@ -448,6 +466,7 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) {
|
|||||||
|
|
||||||
const int extra_space =
|
const int extra_space =
|
||||||
rounded_vm_local_words + // frame local scratch space
|
rounded_vm_local_words + // frame local scratch space
|
||||||
|
//6815692//methodOopDesc::extra_stack_words() + // extra push slots for MH adapters
|
||||||
frame::memory_parameter_word_sp_offset + // register save area
|
frame::memory_parameter_word_sp_offset + // register save area
|
||||||
(native_call ? frame::interpreter_frame_extra_outgoing_argument_words : 0);
|
(native_call ? frame::interpreter_frame_extra_outgoing_argument_words : 0);
|
||||||
|
|
||||||
@ -1447,6 +1466,7 @@ static int size_activation_helper(int callee_extra_locals, int max_stack, int mo
|
|||||||
round_to(callee_extra_locals * Interpreter::stackElementWords(), WordsPerLong);
|
round_to(callee_extra_locals * Interpreter::stackElementWords(), WordsPerLong);
|
||||||
const int max_stack_words = max_stack * Interpreter::stackElementWords();
|
const int max_stack_words = max_stack * Interpreter::stackElementWords();
|
||||||
return (round_to((max_stack_words
|
return (round_to((max_stack_words
|
||||||
|
//6815692//+ methodOopDesc::extra_stack_words()
|
||||||
+ rounded_vm_local_words
|
+ rounded_vm_local_words
|
||||||
+ frame::memory_parameter_word_sp_offset), WordsPerLong)
|
+ frame::memory_parameter_word_sp_offset), WordsPerLong)
|
||||||
// already rounded
|
// already rounded
|
||||||
|
@ -7609,6 +7609,83 @@ RegisterOrConstant MacroAssembler::delayed_value_impl(intptr_t* delayed_value_ad
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// registers on entry:
|
||||||
|
// - rax ('check' register): required MethodType
|
||||||
|
// - rcx: method handle
|
||||||
|
// - rdx, rsi, or ?: killable temp
|
||||||
|
void MacroAssembler::check_method_handle_type(Register mtype_reg, Register mh_reg,
|
||||||
|
Register temp_reg,
|
||||||
|
Label& wrong_method_type) {
|
||||||
|
if (UseCompressedOops) unimplemented(); // field accesses must decode
|
||||||
|
// compare method type against that of the receiver
|
||||||
|
cmpptr(mtype_reg, Address(mh_reg, delayed_value(java_dyn_MethodHandle::type_offset_in_bytes, temp_reg)));
|
||||||
|
jcc(Assembler::notEqual, 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) {
|
||||||
|
if (UseCompressedOops) unimplemented(); // field accesses must decode
|
||||||
|
// load mh.type.form.vmslots
|
||||||
|
if (java_dyn_MethodHandle::vmslots_offset_in_bytes() != 0) {
|
||||||
|
// hoist vmslots into every mh to avoid dependent load chain
|
||||||
|
movl(vmslots_reg, Address(mh_reg, delayed_value(java_dyn_MethodHandle::vmslots_offset_in_bytes, temp_reg)));
|
||||||
|
} else {
|
||||||
|
Register temp2_reg = vmslots_reg;
|
||||||
|
movptr(temp2_reg, Address(mh_reg, delayed_value(java_dyn_MethodHandle::type_offset_in_bytes, temp_reg)));
|
||||||
|
movptr(temp2_reg, Address(temp2_reg, delayed_value(java_dyn_MethodType::form_offset_in_bytes, temp_reg)));
|
||||||
|
movl(vmslots_reg, Address(temp2_reg, delayed_value(java_dyn_MethodTypeForm::vmslots_offset_in_bytes, temp_reg)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// registers on entry:
|
||||||
|
// - rcx: method handle
|
||||||
|
// - rdx: killable temp (interpreted only)
|
||||||
|
// - rax: killable temp (compiled only)
|
||||||
|
void MacroAssembler::jump_to_method_handle_entry(Register mh_reg, Register temp_reg) {
|
||||||
|
assert(mh_reg == rcx, "caller must put MH object in rcx");
|
||||||
|
assert_different_registers(mh_reg, temp_reg);
|
||||||
|
|
||||||
|
if (UseCompressedOops) unimplemented(); // field accesses must decode
|
||||||
|
|
||||||
|
// pick out the interpreted side of the handler
|
||||||
|
movptr(temp_reg, Address(mh_reg, delayed_value(java_dyn_MethodHandle::vmentry_offset_in_bytes, temp_reg)));
|
||||||
|
|
||||||
|
// off we go...
|
||||||
|
jmp(Address(temp_reg, MethodHandleEntry::from_interpreted_entry_offset_in_bytes()));
|
||||||
|
|
||||||
|
// for the various stubs which take control at this point,
|
||||||
|
// see MethodHandles::generate_method_handle_stub
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Address MacroAssembler::argument_address(RegisterOrConstant arg_slot,
|
||||||
|
int extra_slot_offset) {
|
||||||
|
// cf. TemplateTable::prepare_invoke(), if (load_receiver).
|
||||||
|
int stackElementSize = Interpreter::stackElementSize();
|
||||||
|
int offset = Interpreter::expr_offset_in_bytes(extra_slot_offset+0);
|
||||||
|
#ifdef ASSERT
|
||||||
|
int offset1 = Interpreter::expr_offset_in_bytes(extra_slot_offset+1);
|
||||||
|
assert(offset1 - offset == stackElementSize, "correct arithmetic");
|
||||||
|
#endif
|
||||||
|
Register scale_reg = noreg;
|
||||||
|
Address::ScaleFactor scale_factor = Address::no_scale;
|
||||||
|
if (arg_slot.is_constant()) {
|
||||||
|
offset += arg_slot.as_constant() * stackElementSize;
|
||||||
|
} else {
|
||||||
|
scale_reg = arg_slot.as_register();
|
||||||
|
scale_factor = Address::times(stackElementSize);
|
||||||
|
}
|
||||||
|
offset += wordSize; // return PC is on stack
|
||||||
|
return Address(rsp, scale_reg, scale_factor, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void MacroAssembler::verify_oop_addr(Address addr, const char* s) {
|
void MacroAssembler::verify_oop_addr(Address addr, const char* s) {
|
||||||
if (!VerifyOops) return;
|
if (!VerifyOops) return;
|
||||||
|
|
||||||
|
@ -1857,6 +1857,16 @@ class MacroAssembler: public Assembler {
|
|||||||
Register temp_reg,
|
Register temp_reg,
|
||||||
Label& L_success);
|
Label& L_success);
|
||||||
|
|
||||||
|
// method handles (JSR 292)
|
||||||
|
void check_method_handle_type(Register mtype_reg, Register mh_reg,
|
||||||
|
Register temp_reg,
|
||||||
|
Label& wrong_method_type);
|
||||||
|
void load_method_handle_vmslots(Register vmslots_reg, Register mh_reg,
|
||||||
|
Register temp_reg);
|
||||||
|
void jump_to_method_handle_entry(Register mh_reg, Register temp_reg);
|
||||||
|
Address argument_address(RegisterOrConstant arg_slot, int extra_slot_offset = 0);
|
||||||
|
|
||||||
|
|
||||||
//----
|
//----
|
||||||
void set_word_if_not_zero(Register reg); // sets reg to 1 if not zero, otherwise 0
|
void set_word_if_not_zero(Register reg); // sets reg to 1 if not zero, otherwise 0
|
||||||
|
|
||||||
|
@ -513,10 +513,11 @@ void CppInterpreterGenerator::generate_compute_interpreter_state(const Register
|
|||||||
// compute full expression stack limit
|
// compute full expression stack limit
|
||||||
|
|
||||||
const Address size_of_stack (rbx, methodOopDesc::max_stack_offset());
|
const Address size_of_stack (rbx, methodOopDesc::max_stack_offset());
|
||||||
|
const int extra_stack = 0; //6815692//methodOopDesc::extra_stack_words();
|
||||||
__ load_unsigned_short(rdx, size_of_stack); // get size of expression stack in words
|
__ load_unsigned_short(rdx, size_of_stack); // get size of expression stack in words
|
||||||
__ negptr(rdx); // so we can subtract in next step
|
__ negptr(rdx); // so we can subtract in next step
|
||||||
// Allocate expression stack
|
// Allocate expression stack
|
||||||
__ lea(rsp, Address(rsp, rdx, Address::times_ptr));
|
__ lea(rsp, Address(rsp, rdx, Address::times_ptr, -extra_stack));
|
||||||
__ movptr(STATE(_stack_limit), rsp);
|
__ movptr(STATE(_stack_limit), rsp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -659,8 +660,9 @@ void InterpreterGenerator::generate_stack_overflow_check(void) {
|
|||||||
// Always give one monitor to allow us to start interp if sync method.
|
// Always give one monitor to allow us to start interp if sync method.
|
||||||
// Any additional monitors need a check when moving the expression stack
|
// Any additional monitors need a check when moving the expression stack
|
||||||
const int one_monitor = frame::interpreter_frame_monitor_size() * wordSize;
|
const int one_monitor = frame::interpreter_frame_monitor_size() * wordSize;
|
||||||
|
const int extra_stack = 0; //6815692//methodOopDesc::extra_stack_entries();
|
||||||
__ load_unsigned_short(rax, size_of_stack); // get size of expression stack in words
|
__ load_unsigned_short(rax, size_of_stack); // get size of expression stack in words
|
||||||
__ lea(rax, Address(noreg, rax, Interpreter::stackElementScale(), one_monitor));
|
__ lea(rax, Address(noreg, rax, Interpreter::stackElementScale(), extra_stack + one_monitor));
|
||||||
__ lea(rax, Address(rax, rdx, Interpreter::stackElementScale(), overhead_size));
|
__ lea(rax, Address(rax, rdx, Interpreter::stackElementScale(), overhead_size));
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
@ -2185,6 +2187,7 @@ address AbstractInterpreterGenerator::generate_method_entry(AbstractInterpreter:
|
|||||||
case Interpreter::empty : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry(); break;
|
case Interpreter::empty : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry(); break;
|
||||||
case Interpreter::accessor : entry_point = ((InterpreterGenerator*)this)->generate_accessor_entry(); break;
|
case Interpreter::accessor : entry_point = ((InterpreterGenerator*)this)->generate_accessor_entry(); break;
|
||||||
case Interpreter::abstract : entry_point = ((InterpreterGenerator*)this)->generate_abstract_entry(); break;
|
case Interpreter::abstract : entry_point = ((InterpreterGenerator*)this)->generate_abstract_entry(); break;
|
||||||
|
case Interpreter::method_handle : entry_point = ((InterpreterGenerator*)this)->generate_method_handle_entry(); break;
|
||||||
|
|
||||||
case Interpreter::java_lang_math_sin : // fall thru
|
case Interpreter::java_lang_math_sin : // fall thru
|
||||||
case Interpreter::java_lang_math_cos : // fall thru
|
case Interpreter::java_lang_math_cos : // fall thru
|
||||||
@ -2224,7 +2227,8 @@ int AbstractInterpreter::size_top_interpreter_activation(methodOop method) {
|
|||||||
const int overhead_size = sizeof(BytecodeInterpreter)/wordSize +
|
const int overhead_size = sizeof(BytecodeInterpreter)/wordSize +
|
||||||
( frame::sender_sp_offset - frame::link_offset) + 2;
|
( frame::sender_sp_offset - frame::link_offset) + 2;
|
||||||
|
|
||||||
const int method_stack = (method->max_locals() + method->max_stack()) *
|
const int extra_stack = 0; //6815692//methodOopDesc::extra_stack_entries();
|
||||||
|
const int method_stack = (method->max_locals() + method->max_stack() + extra_stack) *
|
||||||
Interpreter::stackElementWords();
|
Interpreter::stackElementWords();
|
||||||
return overhead_size + method_stack + stub_code;
|
return overhead_size + method_stack + stub_code;
|
||||||
}
|
}
|
||||||
@ -2289,7 +2293,8 @@ void BytecodeInterpreter::layout_interpreterState(interpreterState to_fill,
|
|||||||
// Need +1 here because stack_base points to the word just above the first expr stack entry
|
// Need +1 here because stack_base points to the word just above the first expr stack entry
|
||||||
// and stack_limit is supposed to point to the word just below the last expr stack entry.
|
// and stack_limit is supposed to point to the word just below the last expr stack entry.
|
||||||
// See generate_compute_interpreter_state.
|
// See generate_compute_interpreter_state.
|
||||||
to_fill->_stack_limit = stack_base - (method->max_stack() + 1);
|
int extra_stack = 0; //6815692//methodOopDesc::extra_stack_entries();
|
||||||
|
to_fill->_stack_limit = stack_base - (method->max_stack() + extra_stack + 1);
|
||||||
to_fill->_monitor_base = (BasicObjectLock*) monitor_base;
|
to_fill->_monitor_base = (BasicObjectLock*) monitor_base;
|
||||||
|
|
||||||
to_fill->_self_link = to_fill;
|
to_fill->_self_link = to_fill;
|
||||||
@ -2335,7 +2340,8 @@ int AbstractInterpreter::layout_activation(methodOop method,
|
|||||||
monitor_size);
|
monitor_size);
|
||||||
|
|
||||||
// Now with full size expression stack
|
// Now with full size expression stack
|
||||||
int full_frame_size = short_frame_size + method->max_stack() * BytesPerWord;
|
int extra_stack = 0; //6815692//methodOopDesc::extra_stack_entries();
|
||||||
|
int full_frame_size = short_frame_size + (method->max_stack() + extra_stack) * BytesPerWord;
|
||||||
|
|
||||||
// and now with only live portion of the expression stack
|
// and now with only live portion of the expression stack
|
||||||
short_frame_size = short_frame_size + tempcount * BytesPerWord;
|
short_frame_size = short_frame_size + tempcount * BytesPerWord;
|
||||||
|
@ -555,13 +555,18 @@ void InterpreterMacroAssembler::super_call_VM_leaf(address entry_point, Register
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Jump to from_interpreted entry of a call unless single stepping is possible
|
void InterpreterMacroAssembler::prepare_to_jump_from_interpreted() {
|
||||||
// in this thread in which case we must call the i2i entry
|
|
||||||
void InterpreterMacroAssembler::jump_from_interpreted(Register method, Register temp) {
|
|
||||||
// set sender sp
|
// set sender sp
|
||||||
lea(rsi, Address(rsp, wordSize));
|
lea(rsi, Address(rsp, wordSize));
|
||||||
// record last_sp
|
// record last_sp
|
||||||
movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), rsi);
|
movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), rsi);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Jump to from_interpreted entry of a call unless single stepping is possible
|
||||||
|
// in this thread in which case we must call the i2i entry
|
||||||
|
void InterpreterMacroAssembler::jump_from_interpreted(Register method, Register temp) {
|
||||||
|
prepare_to_jump_from_interpreted();
|
||||||
|
|
||||||
if (JvmtiExport::can_post_interpreter_events()) {
|
if (JvmtiExport::can_post_interpreter_events()) {
|
||||||
Label run_compiled_code;
|
Label run_compiled_code;
|
||||||
|
@ -161,6 +161,7 @@ class InterpreterMacroAssembler: public MacroAssembler {
|
|||||||
|
|
||||||
|
|
||||||
// jump to an invoked target
|
// jump to an invoked target
|
||||||
|
void prepare_to_jump_from_interpreted();
|
||||||
void jump_from_interpreted(Register method, Register temp);
|
void jump_from_interpreted(Register method, Register temp);
|
||||||
|
|
||||||
// Returning from interpreted functions
|
// Returning from interpreted functions
|
||||||
|
@ -551,13 +551,18 @@ void InterpreterMacroAssembler::super_call_VM_leaf(address entry_point,
|
|||||||
MacroAssembler::call_VM_leaf_base(entry_point, 3);
|
MacroAssembler::call_VM_leaf_base(entry_point, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Jump to from_interpreted entry of a call unless single stepping is possible
|
void InterpreterMacroAssembler::prepare_to_jump_from_interpreted() {
|
||||||
// in this thread in which case we must call the i2i entry
|
|
||||||
void InterpreterMacroAssembler::jump_from_interpreted(Register method, Register temp) {
|
|
||||||
// set sender sp
|
// set sender sp
|
||||||
lea(r13, Address(rsp, wordSize));
|
lea(r13, Address(rsp, wordSize));
|
||||||
// record last_sp
|
// record last_sp
|
||||||
movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), r13);
|
movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), r13);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Jump to from_interpreted entry of a call unless single stepping is possible
|
||||||
|
// in this thread in which case we must call the i2i entry
|
||||||
|
void InterpreterMacroAssembler::jump_from_interpreted(Register method, Register temp) {
|
||||||
|
prepare_to_jump_from_interpreted();
|
||||||
|
|
||||||
if (JvmtiExport::can_post_interpreter_events()) {
|
if (JvmtiExport::can_post_interpreter_events()) {
|
||||||
Label run_compiled_code;
|
Label run_compiled_code;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2003-2009 Sun Microsystems, Inc. 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
|
||||||
@ -176,6 +176,7 @@ class InterpreterMacroAssembler: public MacroAssembler {
|
|||||||
void dispatch_via (TosState state, address* table);
|
void dispatch_via (TosState state, address* table);
|
||||||
|
|
||||||
// jump to an invoked target
|
// jump to an invoked target
|
||||||
|
void prepare_to_jump_from_interpreted();
|
||||||
void jump_from_interpreted(Register method, Register temp);
|
void jump_from_interpreted(Register method, Register temp);
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. 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
|
||||||
@ -32,6 +32,7 @@
|
|||||||
address generate_normal_entry(bool synchronized);
|
address generate_normal_entry(bool synchronized);
|
||||||
address generate_native_entry(bool synchronized);
|
address generate_native_entry(bool synchronized);
|
||||||
address generate_abstract_entry(void);
|
address generate_abstract_entry(void);
|
||||||
|
address generate_method_handle_entry(void);
|
||||||
address generate_math_entry(AbstractInterpreter::MethodKind kind);
|
address generate_math_entry(AbstractInterpreter::MethodKind kind);
|
||||||
address generate_empty_entry(void);
|
address generate_empty_entry(void);
|
||||||
address generate_accessor_entry(void);
|
address generate_accessor_entry(void);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. 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
|
||||||
@ -201,11 +201,12 @@ address InterpreterGenerator::generate_abstract_entry(void) {
|
|||||||
address entry_point = __ pc();
|
address entry_point = __ pc();
|
||||||
|
|
||||||
// abstract method entry
|
// abstract method entry
|
||||||
// remove return address. Not really needed, since exception handling throws away expression stack
|
|
||||||
__ pop(rbx);
|
|
||||||
|
|
||||||
// adjust stack to what a normal return would do
|
// pop return address, reset last_sp to NULL
|
||||||
__ mov(rsp, rsi);
|
__ empty_expression_stack();
|
||||||
|
__ restore_bcp(); // rsi must be correct for exception handler (was destroyed)
|
||||||
|
__ restore_locals(); // make sure locals pointer is correct as well (was destroyed)
|
||||||
|
|
||||||
// throw exception
|
// throw exception
|
||||||
__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError));
|
__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError));
|
||||||
// the call_VM checks for exception, so we should never return here.
|
// the call_VM checks for exception, so we should never return here.
|
||||||
@ -214,6 +215,20 @@ address InterpreterGenerator::generate_abstract_entry(void) {
|
|||||||
return entry_point;
|
return entry_point;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Method handle invoker
|
||||||
|
// Dispatch a method of the form java.dyn.MethodHandles::invoke(...)
|
||||||
|
address InterpreterGenerator::generate_method_handle_entry(void) {
|
||||||
|
if (!EnableMethodHandles) {
|
||||||
|
return generate_abstract_entry();
|
||||||
|
}
|
||||||
|
|
||||||
|
address entry_point = MethodHandles::generate_method_handle_interpreter_entry(_masm);
|
||||||
|
|
||||||
|
return entry_point;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// This method tells the deoptimizer how big an interpreted frame must be:
|
// This method tells the deoptimizer how big an interpreted frame must be:
|
||||||
int AbstractInterpreter::size_activation(methodOop method,
|
int AbstractInterpreter::size_activation(methodOop method,
|
||||||
int tempcount,
|
int tempcount,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2003-2009 Sun Microsystems, Inc. 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
|
||||||
@ -294,6 +294,16 @@ address InterpreterGenerator::generate_abstract_entry(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Method handle invoker
|
||||||
|
// Dispatch a method of the form java.dyn.MethodHandles::invoke(...)
|
||||||
|
address InterpreterGenerator::generate_method_handle_entry(void) {
|
||||||
|
if (!EnableMethodHandles) {
|
||||||
|
return generate_abstract_entry();
|
||||||
|
}
|
||||||
|
return generate_abstract_entry(); //6815692//
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Empty method, generate a very fast return.
|
// Empty method, generate a very fast return.
|
||||||
|
|
||||||
address InterpreterGenerator::generate_empty_entry(void) {
|
address InterpreterGenerator::generate_empty_entry(void) {
|
||||||
|
1133
hotspot/src/cpu/x86/vm/methodHandles_x86.cpp
Normal file
1133
hotspot/src/cpu/x86/vm/methodHandles_x86.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -2219,6 +2219,16 @@ class StubGenerator: public StubCodeGenerator {
|
|||||||
|
|
||||||
// arraycopy stubs used by compilers
|
// arraycopy stubs used by compilers
|
||||||
generate_arraycopy_stubs();
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -92,6 +92,33 @@ address TemplateInterpreterGenerator::generate_ClassCastException_handler() {
|
|||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Arguments are: required type at TOS+8, failing object (or NULL) at TOS+4.
|
||||||
|
// pc at TOS (just for debugging)
|
||||||
|
address TemplateInterpreterGenerator::generate_WrongMethodType_handler() {
|
||||||
|
address entry = __ pc();
|
||||||
|
|
||||||
|
__ pop(rbx); // actual failing object is at TOS
|
||||||
|
__ pop(rax); // required type is at TOS+4
|
||||||
|
|
||||||
|
__ verify_oop(rbx);
|
||||||
|
__ verify_oop(rax);
|
||||||
|
|
||||||
|
// Various method handle types use interpreter registers as temps.
|
||||||
|
__ restore_bcp();
|
||||||
|
__ restore_locals();
|
||||||
|
|
||||||
|
// Expression stack must be empty before entering the VM for an exception.
|
||||||
|
__ empty_expression_stack();
|
||||||
|
__ empty_FPU_stack();
|
||||||
|
__ call_VM(noreg,
|
||||||
|
CAST_FROM_FN_PTR(address,
|
||||||
|
InterpreterRuntime::throw_WrongMethodTypeException),
|
||||||
|
// pass required type, failing object (or NULL)
|
||||||
|
rax, rbx);
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
address TemplateInterpreterGenerator::generate_exception_handler_common(const char* name, const char* message, bool pass_oop) {
|
address TemplateInterpreterGenerator::generate_exception_handler_common(const char* name, const char* message, bool pass_oop) {
|
||||||
assert(!pass_oop || message == NULL, "either oop or message but not both");
|
assert(!pass_oop || message == NULL, "either oop or message but not both");
|
||||||
address entry = __ pc();
|
address entry = __ pc();
|
||||||
@ -1370,6 +1397,7 @@ address AbstractInterpreterGenerator::generate_method_entry(AbstractInterpreter:
|
|||||||
case Interpreter::empty : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry(); break;
|
case Interpreter::empty : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry(); break;
|
||||||
case Interpreter::accessor : entry_point = ((InterpreterGenerator*)this)->generate_accessor_entry(); break;
|
case Interpreter::accessor : entry_point = ((InterpreterGenerator*)this)->generate_accessor_entry(); break;
|
||||||
case Interpreter::abstract : entry_point = ((InterpreterGenerator*)this)->generate_abstract_entry(); break;
|
case Interpreter::abstract : entry_point = ((InterpreterGenerator*)this)->generate_abstract_entry(); break;
|
||||||
|
case Interpreter::method_handle : entry_point = ((InterpreterGenerator*)this)->generate_method_handle_entry(); break;
|
||||||
|
|
||||||
case Interpreter::java_lang_math_sin : // fall thru
|
case Interpreter::java_lang_math_sin : // fall thru
|
||||||
case Interpreter::java_lang_math_cos : // fall thru
|
case Interpreter::java_lang_math_cos : // fall thru
|
||||||
@ -1400,7 +1428,8 @@ int AbstractInterpreter::size_top_interpreter_activation(methodOop method) {
|
|||||||
// be sure to change this if you add/subtract anything to/from the overhead area
|
// be sure to change this if you add/subtract anything to/from the overhead area
|
||||||
const int overhead_size = -frame::interpreter_frame_initial_sp_offset;
|
const int overhead_size = -frame::interpreter_frame_initial_sp_offset;
|
||||||
|
|
||||||
const int method_stack = (method->max_locals() + method->max_stack()) *
|
const int extra_stack = methodOopDesc::extra_stack_entries();
|
||||||
|
const int method_stack = (method->max_locals() + method->max_stack() + extra_stack) *
|
||||||
Interpreter::stackElementWords();
|
Interpreter::stackElementWords();
|
||||||
return overhead_size + method_stack + stub_code;
|
return overhead_size + method_stack + stub_code;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2003-2009 Sun Microsystems, Inc. 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
|
||||||
@ -100,6 +100,26 @@ address TemplateInterpreterGenerator::generate_ClassCastException_handler() {
|
|||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Arguments are: required type in rarg1, failing object (or NULL) in rarg2
|
||||||
|
address TemplateInterpreterGenerator::generate_WrongMethodType_handler() {
|
||||||
|
address entry = __ pc();
|
||||||
|
|
||||||
|
__ pop(c_rarg2); // failing object is at TOS
|
||||||
|
__ pop(c_rarg1); // required type is at TOS+8
|
||||||
|
|
||||||
|
// expression stack must be empty before entering the VM if an
|
||||||
|
// exception happened
|
||||||
|
__ empty_expression_stack();
|
||||||
|
|
||||||
|
__ call_VM(noreg,
|
||||||
|
CAST_FROM_FN_PTR(address,
|
||||||
|
InterpreterRuntime::
|
||||||
|
throw_WrongMethodTypeException),
|
||||||
|
// pass required type, failing object (or NULL)
|
||||||
|
c_rarg1, c_rarg2);
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
address TemplateInterpreterGenerator::generate_exception_handler_common(
|
address TemplateInterpreterGenerator::generate_exception_handler_common(
|
||||||
const char* name, const char* message, bool pass_oop) {
|
const char* name, const char* message, bool pass_oop) {
|
||||||
assert(!pass_oop || message == NULL, "either oop or message but not both");
|
assert(!pass_oop || message == NULL, "either oop or message but not both");
|
||||||
@ -1393,6 +1413,7 @@ address AbstractInterpreterGenerator::generate_method_entry(
|
|||||||
case Interpreter::empty : entry_point = ((InterpreterGenerator*) this)->generate_empty_entry(); break;
|
case Interpreter::empty : entry_point = ((InterpreterGenerator*) this)->generate_empty_entry(); break;
|
||||||
case Interpreter::accessor : entry_point = ((InterpreterGenerator*) this)->generate_accessor_entry(); break;
|
case Interpreter::accessor : entry_point = ((InterpreterGenerator*) this)->generate_accessor_entry(); break;
|
||||||
case Interpreter::abstract : entry_point = ((InterpreterGenerator*) this)->generate_abstract_entry(); break;
|
case Interpreter::abstract : entry_point = ((InterpreterGenerator*) this)->generate_abstract_entry(); break;
|
||||||
|
case Interpreter::method_handle : entry_point = ((InterpreterGenerator*) this)->generate_method_handle_entry();break;
|
||||||
|
|
||||||
case Interpreter::java_lang_math_sin : // fall thru
|
case Interpreter::java_lang_math_sin : // fall thru
|
||||||
case Interpreter::java_lang_math_cos : // fall thru
|
case Interpreter::java_lang_math_cos : // fall thru
|
||||||
@ -1423,7 +1444,8 @@ int AbstractInterpreter::size_top_interpreter_activation(methodOop method) {
|
|||||||
-(frame::interpreter_frame_initial_sp_offset) + entry_size;
|
-(frame::interpreter_frame_initial_sp_offset) + entry_size;
|
||||||
|
|
||||||
const int stub_code = frame::entry_frame_after_call_words;
|
const int stub_code = frame::entry_frame_after_call_words;
|
||||||
const int method_stack = (method->max_locals() + method->max_stack()) *
|
const int extra_stack = methodOopDesc::extra_stack_entries();
|
||||||
|
const int method_stack = (method->max_locals() + method->max_stack() + extra_stack) *
|
||||||
Interpreter::stackElementWords();
|
Interpreter::stackElementWords();
|
||||||
return (overhead_size + method_stack + stub_code);
|
return (overhead_size + method_stack + stub_code);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1999-2009 Sun Microsystems, Inc. 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
|
||||||
@ -674,6 +674,30 @@ int ciMethod::scale_count(int count, float prof_factor) {
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
// invokedynamic support
|
||||||
|
//
|
||||||
|
bool ciMethod::is_method_handle_invoke() {
|
||||||
|
check_is_loaded();
|
||||||
|
bool flag = ((flags().as_int() & JVM_MH_INVOKE_BITS) == JVM_MH_INVOKE_BITS);
|
||||||
|
#ifdef ASSERT
|
||||||
|
{
|
||||||
|
VM_ENTRY_MARK;
|
||||||
|
bool flag2 = get_methodOop()->is_method_handle_invoke();
|
||||||
|
assert(flag == flag2, "consistent");
|
||||||
|
}
|
||||||
|
#endif //ASSERT
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
ciInstance* ciMethod::method_handle_type() {
|
||||||
|
check_is_loaded();
|
||||||
|
VM_ENTRY_MARK;
|
||||||
|
oop mtype = get_methodOop()->method_handle_type();
|
||||||
|
return CURRENT_THREAD_ENV->get_object(mtype)->as_instance();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// ciMethod::build_method_data
|
// ciMethod::build_method_data
|
||||||
//
|
//
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1999-2009 Sun Microsystems, Inc. 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
|
||||||
@ -207,6 +207,8 @@ class ciMethod : public ciObject {
|
|||||||
bool check_call(int refinfo_index, bool is_static) const;
|
bool check_call(int refinfo_index, bool is_static) const;
|
||||||
void build_method_data(); // make sure it exists in the VM also
|
void build_method_data(); // make sure it exists in the VM also
|
||||||
int scale_count(int count, float prof_factor = 1.); // make MDO count commensurate with IIC
|
int scale_count(int count, float prof_factor = 1.); // make MDO count commensurate with IIC
|
||||||
|
bool is_method_handle_invoke();
|
||||||
|
ciInstance* method_handle_type();
|
||||||
|
|
||||||
// What kind of ciObject is this?
|
// What kind of ciObject is this?
|
||||||
bool is_method() { return true; }
|
bool is_method() { return true; }
|
||||||
|
@ -1842,6 +1842,11 @@ methodHandle ClassFileParser::parse_method(constantPoolHandle cp, bool is_interf
|
|||||||
_has_vanilla_constructor = true;
|
_has_vanilla_constructor = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (EnableMethodHandles && m->is_method_handle_invoke()) {
|
||||||
|
THROW_MSG_(vmSymbols::java_lang_VirtualMachineError(),
|
||||||
|
"Method handle invokers must be defined internally to the VM", nullHandle);
|
||||||
|
}
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2465,9 +2470,84 @@ void ClassFileParser::java_lang_Class_fix_post(int* next_nonstatic_oop_offset_pt
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Force MethodHandle.vmentry to be an unmanaged pointer.
|
||||||
|
// There is no way for a classfile to express this, so we must help it.
|
||||||
|
void ClassFileParser::java_dyn_MethodHandle_fix_pre(constantPoolHandle cp,
|
||||||
|
typeArrayHandle* fields_ptr,
|
||||||
|
FieldAllocationCount *fac_ptr,
|
||||||
|
TRAPS) {
|
||||||
|
// Add fake fields for java.dyn.MethodHandle instances
|
||||||
|
//
|
||||||
|
// This is not particularly nice, but since there is no way to express
|
||||||
|
// a native wordSize field in Java, we must do it at this level.
|
||||||
|
|
||||||
|
if (!EnableMethodHandles) return;
|
||||||
|
|
||||||
|
int word_sig_index = 0;
|
||||||
|
const int cp_size = cp->length();
|
||||||
|
for (int index = 1; index < cp_size; index++) {
|
||||||
|
if (cp->tag_at(index).is_utf8() &&
|
||||||
|
cp->symbol_at(index) == vmSymbols::machine_word_signature()) {
|
||||||
|
word_sig_index = index;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (word_sig_index == 0)
|
||||||
|
THROW_MSG(vmSymbols::java_lang_VirtualMachineError(),
|
||||||
|
"missing I or J signature (for vmentry) in java.dyn.MethodHandle");
|
||||||
|
|
||||||
|
bool found_vmentry = false;
|
||||||
|
|
||||||
|
const int n = (*fields_ptr)()->length();
|
||||||
|
for (int i = 0; i < n; i += instanceKlass::next_offset) {
|
||||||
|
int name_index = (*fields_ptr)->ushort_at(i + instanceKlass::name_index_offset);
|
||||||
|
int sig_index = (*fields_ptr)->ushort_at(i + instanceKlass::signature_index_offset);
|
||||||
|
int acc_flags = (*fields_ptr)->ushort_at(i + instanceKlass::access_flags_offset);
|
||||||
|
symbolOop f_name = cp->symbol_at(name_index);
|
||||||
|
symbolOop f_sig = cp->symbol_at(sig_index);
|
||||||
|
if (f_sig == vmSymbols::byte_signature() &&
|
||||||
|
f_name == vmSymbols::vmentry_name() &&
|
||||||
|
(acc_flags & JVM_ACC_STATIC) == 0) {
|
||||||
|
// Adjust the field type from byte to an unmanaged pointer.
|
||||||
|
assert(fac_ptr->nonstatic_byte_count > 0, "");
|
||||||
|
fac_ptr->nonstatic_byte_count -= 1;
|
||||||
|
(*fields_ptr)->ushort_at_put(i + instanceKlass::signature_index_offset,
|
||||||
|
word_sig_index);
|
||||||
|
if (wordSize == jintSize) {
|
||||||
|
fac_ptr->nonstatic_word_count += 1;
|
||||||
|
} else {
|
||||||
|
fac_ptr->nonstatic_double_count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
FieldAllocationType atype = (FieldAllocationType) (*fields_ptr)->ushort_at(i+4);
|
||||||
|
assert(atype == NONSTATIC_BYTE, "");
|
||||||
|
FieldAllocationType new_atype = NONSTATIC_WORD;
|
||||||
|
if (wordSize > jintSize) {
|
||||||
|
if (Universe::field_type_should_be_aligned(T_LONG)) {
|
||||||
|
atype = NONSTATIC_ALIGNED_DOUBLE;
|
||||||
|
} else {
|
||||||
|
atype = NONSTATIC_DOUBLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(*fields_ptr)->ushort_at_put(i+4, new_atype);
|
||||||
|
|
||||||
|
found_vmentry = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found_vmentry)
|
||||||
|
THROW_MSG(vmSymbols::java_lang_VirtualMachineError(),
|
||||||
|
"missing vmentry byte field in java.dyn.MethodHandle");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name,
|
instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name,
|
||||||
Handle class_loader,
|
Handle class_loader,
|
||||||
Handle protection_domain,
|
Handle protection_domain,
|
||||||
|
KlassHandle host_klass,
|
||||||
GrowableArray<Handle>* cp_patches,
|
GrowableArray<Handle>* cp_patches,
|
||||||
symbolHandle& parsed_name,
|
symbolHandle& parsed_name,
|
||||||
TRAPS) {
|
TRAPS) {
|
||||||
@ -2500,6 +2580,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_host_klass = host_klass;
|
||||||
_cp_patches = cp_patches;
|
_cp_patches = cp_patches;
|
||||||
|
|
||||||
instanceKlassHandle nullHandle;
|
instanceKlassHandle nullHandle;
|
||||||
@ -2808,6 +2889,11 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name,
|
|||||||
java_lang_Class_fix_pre(&methods, &fac, CHECK_(nullHandle));
|
java_lang_Class_fix_pre(&methods, &fac, CHECK_(nullHandle));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// adjust the vmentry field declaration in java.dyn.MethodHandle
|
||||||
|
if (EnableMethodHandles && class_name() == vmSymbols::sun_dyn_MethodHandleImpl() && class_loader.is_null()) {
|
||||||
|
java_dyn_MethodHandle_fix_pre(cp, &fields, &fac, CHECK_(nullHandle));
|
||||||
|
}
|
||||||
|
|
||||||
// Add a fake "discovered" field if it is not present
|
// Add a fake "discovered" field if it is not present
|
||||||
// for compatibility with earlier jdk's.
|
// for compatibility with earlier jdk's.
|
||||||
if (class_name() == vmSymbols::java_lang_ref_Reference()
|
if (class_name() == vmSymbols::java_lang_ref_Reference()
|
||||||
@ -3134,7 +3220,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name,
|
|||||||
this_klass->set_method_ordering(method_ordering());
|
this_klass->set_method_ordering(method_ordering());
|
||||||
this_klass->set_initial_method_idnum(methods->length());
|
this_klass->set_initial_method_idnum(methods->length());
|
||||||
this_klass->set_name(cp->klass_name_at(this_class_index));
|
this_klass->set_name(cp->klass_name_at(this_class_index));
|
||||||
if (LinkWellKnownClasses) // I am well known to myself
|
if (LinkWellKnownClasses || is_anonymous()) // I am well known to myself
|
||||||
cp->klass_at_put(this_class_index, this_klass()); // eagerly resolve
|
cp->klass_at_put(this_class_index, this_klass()); // eagerly resolve
|
||||||
this_klass->set_protection_domain(protection_domain());
|
this_klass->set_protection_domain(protection_domain());
|
||||||
this_klass->set_fields_annotations(fields_annotations());
|
this_klass->set_fields_annotations(fields_annotations());
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. 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
|
||||||
@ -33,6 +33,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
|||||||
u2 _major_version;
|
u2 _major_version;
|
||||||
u2 _minor_version;
|
u2 _minor_version;
|
||||||
symbolHandle _class_name;
|
symbolHandle _class_name;
|
||||||
|
KlassHandle _host_klass;
|
||||||
GrowableArray<Handle>* _cp_patches; // overrides for CP entries
|
GrowableArray<Handle>* _cp_patches; // overrides for CP entries
|
||||||
|
|
||||||
bool _has_finalizer;
|
bool _has_finalizer;
|
||||||
@ -145,6 +146,11 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
|||||||
// Adjust the next_nonstatic_oop_offset to place the fake fields
|
// Adjust the next_nonstatic_oop_offset to place the fake fields
|
||||||
// before any Java fields.
|
// before any Java fields.
|
||||||
void java_lang_Class_fix_post(int* next_nonstatic_oop_offset);
|
void java_lang_Class_fix_post(int* next_nonstatic_oop_offset);
|
||||||
|
// Adjust the field allocation counts for java.dyn.MethodHandle to add
|
||||||
|
// a fake address (void*) field.
|
||||||
|
void java_dyn_MethodHandle_fix_pre(constantPoolHandle cp,
|
||||||
|
typeArrayHandle* fields_ptr,
|
||||||
|
FieldAllocationCount *fac_ptr, TRAPS);
|
||||||
|
|
||||||
// Format checker methods
|
// Format checker methods
|
||||||
void classfile_parse_error(const char* msg, TRAPS);
|
void classfile_parse_error(const char* msg, TRAPS);
|
||||||
@ -204,6 +210,10 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
|||||||
char* skip_over_field_name(char* name, bool slash_ok, unsigned int length);
|
char* skip_over_field_name(char* name, bool slash_ok, unsigned int length);
|
||||||
char* skip_over_field_signature(char* signature, bool void_ok, unsigned int length, TRAPS);
|
char* skip_over_field_signature(char* signature, bool void_ok, unsigned int length, TRAPS);
|
||||||
|
|
||||||
|
bool is_anonymous() {
|
||||||
|
assert(AnonymousClasses || _host_klass.is_null(), "");
|
||||||
|
return _host_klass.not_null();
|
||||||
|
}
|
||||||
bool has_cp_patch_at(int index) {
|
bool has_cp_patch_at(int index) {
|
||||||
assert(AnonymousClasses, "");
|
assert(AnonymousClasses, "");
|
||||||
assert(index >= 0, "oob");
|
assert(index >= 0, "oob");
|
||||||
@ -249,11 +259,13 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
|||||||
Handle protection_domain,
|
Handle protection_domain,
|
||||||
symbolHandle& parsed_name,
|
symbolHandle& parsed_name,
|
||||||
TRAPS) {
|
TRAPS) {
|
||||||
return parseClassFile(name, class_loader, protection_domain, NULL, parsed_name, THREAD);
|
KlassHandle no_host_klass;
|
||||||
|
return parseClassFile(name, class_loader, protection_domain, no_host_klass, NULL, parsed_name, THREAD);
|
||||||
}
|
}
|
||||||
instanceKlassHandle parseClassFile(symbolHandle name,
|
instanceKlassHandle parseClassFile(symbolHandle name,
|
||||||
Handle class_loader,
|
Handle class_loader,
|
||||||
Handle protection_domain,
|
Handle protection_domain,
|
||||||
|
KlassHandle host_klass,
|
||||||
GrowableArray<Handle>* cp_patches,
|
GrowableArray<Handle>* cp_patches,
|
||||||
symbolHandle& parsed_name,
|
symbolHandle& parsed_name,
|
||||||
TRAPS);
|
TRAPS);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2003-2009 Sun Microsystems, Inc. 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
|
||||||
@ -549,6 +549,63 @@ void Dictionary::reorder_dictionary() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SymbolPropertyTable::SymbolPropertyTable(int table_size)
|
||||||
|
: Hashtable(table_size, sizeof(SymbolPropertyEntry))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
SymbolPropertyTable::SymbolPropertyTable(int table_size, HashtableBucket* t,
|
||||||
|
int number_of_entries)
|
||||||
|
: Hashtable(table_size, sizeof(SymbolPropertyEntry), t, number_of_entries)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SymbolPropertyEntry* SymbolPropertyTable::find_entry(int index, unsigned int hash,
|
||||||
|
symbolHandle sym) {
|
||||||
|
assert(index == index_for(sym), "incorrect index?");
|
||||||
|
for (SymbolPropertyEntry* p = bucket(index); p != NULL; p = p->next()) {
|
||||||
|
if (p->hash() == hash && p->symbol() == sym()) {
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SymbolPropertyEntry* SymbolPropertyTable::add_entry(int index, unsigned int hash,
|
||||||
|
symbolHandle sym) {
|
||||||
|
assert_locked_or_safepoint(SystemDictionary_lock);
|
||||||
|
assert(index == index_for(sym), "incorrect index?");
|
||||||
|
assert(find_entry(index, hash, sym) == NULL, "no double entry");
|
||||||
|
|
||||||
|
SymbolPropertyEntry* p = new_entry(hash, sym());
|
||||||
|
Hashtable::add_entry(index, p);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SymbolPropertyTable::oops_do(OopClosure* f) {
|
||||||
|
for (int index = 0; index < table_size(); index++) {
|
||||||
|
for (SymbolPropertyEntry* p = bucket(index); p != NULL; p = p->next()) {
|
||||||
|
f->do_oop((oop*) p->symbol_addr());
|
||||||
|
if (p->property_oop() != NULL) {
|
||||||
|
f->do_oop(p->property_oop_addr());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SymbolPropertyTable::methods_do(void f(methodOop)) {
|
||||||
|
for (int index = 0; index < table_size(); index++) {
|
||||||
|
for (SymbolPropertyEntry* p = bucket(index); p != NULL; p = p->next()) {
|
||||||
|
oop prop = p->property_oop();
|
||||||
|
if (prop != NULL && prop->is_method()) {
|
||||||
|
f((methodOop)prop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2003-2009 Sun Microsystems, Inc. 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
|
||||||
@ -217,3 +217,112 @@ class DictionaryEntry : public HashtableEntry {
|
|||||||
tty->print_cr("pd set = #%d", count);
|
tty->print_cr("pd set = #%d", count);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Entry in a SymbolPropertyTable, mapping a single symbolOop
|
||||||
|
// to a managed and an unmanaged pointer.
|
||||||
|
class SymbolPropertyEntry : public HashtableEntry {
|
||||||
|
friend class VMStructs;
|
||||||
|
private:
|
||||||
|
oop _property_oop;
|
||||||
|
address _property_data;
|
||||||
|
|
||||||
|
public:
|
||||||
|
symbolOop symbol() const { return (symbolOop) literal(); }
|
||||||
|
|
||||||
|
oop property_oop() const { return _property_oop; }
|
||||||
|
void set_property_oop(oop p) { _property_oop = p; }
|
||||||
|
|
||||||
|
address property_data() const { return _property_data; }
|
||||||
|
void set_property_data(address p) { _property_data = p; }
|
||||||
|
|
||||||
|
SymbolPropertyEntry* next() const {
|
||||||
|
return (SymbolPropertyEntry*)HashtableEntry::next();
|
||||||
|
}
|
||||||
|
|
||||||
|
SymbolPropertyEntry** next_addr() {
|
||||||
|
return (SymbolPropertyEntry**)HashtableEntry::next_addr();
|
||||||
|
}
|
||||||
|
|
||||||
|
oop* symbol_addr() { return literal_addr(); }
|
||||||
|
oop* property_oop_addr() { return &_property_oop; }
|
||||||
|
|
||||||
|
void print_on(outputStream* st) const {
|
||||||
|
symbol()->print_value_on(st);
|
||||||
|
st->print(" -> ");
|
||||||
|
bool printed = false;
|
||||||
|
if (property_oop() != NULL) {
|
||||||
|
property_oop()->print_value_on(st);
|
||||||
|
printed = true;
|
||||||
|
}
|
||||||
|
if (property_data() != NULL) {
|
||||||
|
if (printed) st->print(" and ");
|
||||||
|
st->print(INTPTR_FORMAT, property_data());
|
||||||
|
printed = true;
|
||||||
|
}
|
||||||
|
st->print_cr(printed ? "" : "(empty)");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// A system-internal mapping of symbols to pointers, both managed
|
||||||
|
// and unmanaged. Used to record the auto-generation of each method
|
||||||
|
// MethodHandle.invoke(S)T, for all signatures (S)T.
|
||||||
|
class SymbolPropertyTable : public Hashtable {
|
||||||
|
friend class VMStructs;
|
||||||
|
private:
|
||||||
|
SymbolPropertyEntry* bucket(int i) {
|
||||||
|
return (SymbolPropertyEntry*) Hashtable::bucket(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The following method is not MT-safe and must be done under lock.
|
||||||
|
SymbolPropertyEntry** bucket_addr(int i) {
|
||||||
|
return (SymbolPropertyEntry**) Hashtable::bucket_addr(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_entry(int index, SymbolPropertyEntry* new_entry) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
}
|
||||||
|
void set_entry(int index, SymbolPropertyEntry* new_entry) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
}
|
||||||
|
|
||||||
|
SymbolPropertyEntry* new_entry(unsigned int hash, symbolOop symbol) {
|
||||||
|
SymbolPropertyEntry* entry = (SymbolPropertyEntry*) Hashtable::new_entry(hash, symbol);
|
||||||
|
entry->set_property_oop(NULL);
|
||||||
|
entry->set_property_data(NULL);
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
SymbolPropertyTable(int table_size);
|
||||||
|
SymbolPropertyTable(int table_size, HashtableBucket* t, int number_of_entries);
|
||||||
|
|
||||||
|
void free_entry(SymbolPropertyEntry* entry) {
|
||||||
|
Hashtable::free_entry(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int compute_hash(symbolHandle sym) {
|
||||||
|
// Use the regular identity_hash.
|
||||||
|
return Hashtable::compute_hash(sym);
|
||||||
|
}
|
||||||
|
|
||||||
|
// need not be locked; no state change
|
||||||
|
SymbolPropertyEntry* find_entry(int index, unsigned int hash, symbolHandle name);
|
||||||
|
|
||||||
|
// must be done under SystemDictionary_lock
|
||||||
|
SymbolPropertyEntry* add_entry(int index, unsigned int hash, symbolHandle name);
|
||||||
|
|
||||||
|
// GC support
|
||||||
|
void oops_do(OopClosure* f);
|
||||||
|
void methods_do(void f(methodOop));
|
||||||
|
|
||||||
|
// Sharing support
|
||||||
|
void dump(SerializeOopClosure* soc);
|
||||||
|
void restore(SerializeOopClosure* soc);
|
||||||
|
void reorder_dictionary();
|
||||||
|
|
||||||
|
#ifndef PRODUCT
|
||||||
|
void print();
|
||||||
|
#endif
|
||||||
|
void verify();
|
||||||
|
};
|
||||||
|
|
||||||
|
@ -25,13 +25,24 @@
|
|||||||
# include "incls/_precompiled.incl"
|
# include "incls/_precompiled.incl"
|
||||||
# include "incls/_javaClasses.cpp.incl"
|
# include "incls/_javaClasses.cpp.incl"
|
||||||
|
|
||||||
|
static bool find_field(instanceKlass* ik,
|
||||||
|
symbolOop name_symbol, symbolOop signature_symbol,
|
||||||
|
fieldDescriptor* fd,
|
||||||
|
bool allow_super = false) {
|
||||||
|
if (allow_super)
|
||||||
|
return ik->find_field(name_symbol, signature_symbol, fd) != NULL;
|
||||||
|
else
|
||||||
|
return ik->find_local_field(name_symbol, signature_symbol, fd);
|
||||||
|
}
|
||||||
|
|
||||||
// Helpful routine for computing field offsets at run time rather than hardcoding them
|
// Helpful routine for computing field offsets at run time rather than hardcoding them
|
||||||
static void
|
static void
|
||||||
compute_offset(int &dest_offset,
|
compute_offset(int &dest_offset,
|
||||||
klassOop klass_oop, symbolOop name_symbol, symbolOop signature_symbol) {
|
klassOop klass_oop, symbolOop name_symbol, symbolOop signature_symbol,
|
||||||
|
bool allow_super = false) {
|
||||||
fieldDescriptor fd;
|
fieldDescriptor fd;
|
||||||
instanceKlass* ik = instanceKlass::cast(klass_oop);
|
instanceKlass* ik = instanceKlass::cast(klass_oop);
|
||||||
if (!ik->find_local_field(name_symbol, signature_symbol, &fd)) {
|
if (!find_field(ik, name_symbol, signature_symbol, &fd, allow_super)) {
|
||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
tty->print_cr("Invalid layout of %s at %s", ik->external_name(), name_symbol->as_C_string());
|
tty->print_cr("Invalid layout of %s at %s", ik->external_name(), name_symbol->as_C_string());
|
||||||
fatal("Invalid layout of preloaded class");
|
fatal("Invalid layout of preloaded class");
|
||||||
@ -42,14 +53,16 @@ compute_offset(int &dest_offset,
|
|||||||
// Same as above but for "optional" offsets that might not be present in certain JDK versions
|
// Same as above but for "optional" offsets that might not be present in certain JDK versions
|
||||||
static void
|
static void
|
||||||
compute_optional_offset(int& dest_offset,
|
compute_optional_offset(int& dest_offset,
|
||||||
klassOop klass_oop, symbolOop name_symbol, symbolOop signature_symbol) {
|
klassOop klass_oop, symbolOop name_symbol, symbolOop signature_symbol,
|
||||||
|
bool allow_super = false) {
|
||||||
fieldDescriptor fd;
|
fieldDescriptor fd;
|
||||||
instanceKlass* ik = instanceKlass::cast(klass_oop);
|
instanceKlass* ik = instanceKlass::cast(klass_oop);
|
||||||
if (ik->find_local_field(name_symbol, signature_symbol, &fd)) {
|
if (find_field(ik, name_symbol, signature_symbol, &fd, allow_super)) {
|
||||||
dest_offset = fd.offset();
|
dest_offset = fd.offset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Handle java_lang_String::basic_create(int length, bool tenured, TRAPS) {
|
Handle java_lang_String::basic_create(int length, bool tenured, TRAPS) {
|
||||||
// Create the String object first, so there's a chance that the String
|
// Create the String object first, so there's a chance that the String
|
||||||
// and the char array it points to end up in the same cache line.
|
// and the char array it points to end up in the same cache line.
|
||||||
@ -2107,13 +2120,324 @@ void java_lang_ref_SoftReference::set_clock(jlong value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Support for java_dyn_MethodHandle
|
||||||
|
|
||||||
|
int java_dyn_MethodHandle::_type_offset;
|
||||||
|
int java_dyn_MethodHandle::_vmtarget_offset;
|
||||||
|
int java_dyn_MethodHandle::_vmentry_offset;
|
||||||
|
int java_dyn_MethodHandle::_vmslots_offset;
|
||||||
|
|
||||||
|
int sun_dyn_MemberName::_clazz_offset;
|
||||||
|
int sun_dyn_MemberName::_name_offset;
|
||||||
|
int sun_dyn_MemberName::_type_offset;
|
||||||
|
int sun_dyn_MemberName::_flags_offset;
|
||||||
|
int sun_dyn_MemberName::_vmtarget_offset;
|
||||||
|
int sun_dyn_MemberName::_vmindex_offset;
|
||||||
|
|
||||||
|
int sun_dyn_DirectMethodHandle::_vmindex_offset;
|
||||||
|
|
||||||
|
int sun_dyn_BoundMethodHandle::_argument_offset;
|
||||||
|
int sun_dyn_BoundMethodHandle::_vmargslot_offset;
|
||||||
|
|
||||||
|
int sun_dyn_AdapterMethodHandle::_conversion_offset;
|
||||||
|
|
||||||
|
void java_dyn_MethodHandle::compute_offsets() {
|
||||||
|
klassOop k = SystemDictionary::MethodHandle_klass();
|
||||||
|
if (k != NULL && EnableMethodHandles) {
|
||||||
|
compute_offset(_type_offset, k, vmSymbols::type_name(), vmSymbols::java_dyn_MethodType_signature(), true);
|
||||||
|
compute_offset(_vmtarget_offset, k, vmSymbols::vmtarget_name(), vmSymbols::object_signature(), true);
|
||||||
|
compute_offset(_vmentry_offset, k, vmSymbols::vmentry_name(), vmSymbols::machine_word_signature(), true);
|
||||||
|
|
||||||
|
// Note: MH.vmslots (if it is present) is a hoisted copy of MH.type.form.vmslots.
|
||||||
|
// It is optional pending experiments to keep or toss.
|
||||||
|
compute_optional_offset(_vmslots_offset, k, vmSymbols::vmslots_name(), vmSymbols::int_signature(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sun_dyn_MemberName::compute_offsets() {
|
||||||
|
klassOop k = SystemDictionary::MemberName_klass();
|
||||||
|
if (k != NULL && EnableMethodHandles) {
|
||||||
|
compute_offset(_clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature());
|
||||||
|
compute_offset(_name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
|
||||||
|
compute_offset(_type_offset, k, vmSymbols::type_name(), vmSymbols::object_signature());
|
||||||
|
compute_offset(_flags_offset, k, vmSymbols::flags_name(), vmSymbols::int_signature());
|
||||||
|
compute_offset(_vmtarget_offset, k, vmSymbols::vmtarget_name(), vmSymbols::object_signature());
|
||||||
|
compute_offset(_vmindex_offset, k, vmSymbols::vmindex_name(), vmSymbols::int_signature());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sun_dyn_DirectMethodHandle::compute_offsets() {
|
||||||
|
klassOop k = SystemDictionary::DirectMethodHandle_klass();
|
||||||
|
if (k != NULL && EnableMethodHandles) {
|
||||||
|
compute_offset(_vmindex_offset, k, vmSymbols::vmindex_name(), vmSymbols::int_signature(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sun_dyn_BoundMethodHandle::compute_offsets() {
|
||||||
|
klassOop k = SystemDictionary::BoundMethodHandle_klass();
|
||||||
|
if (k != NULL && EnableMethodHandles) {
|
||||||
|
compute_offset(_vmargslot_offset, k, vmSymbols::vmargslot_name(), vmSymbols::int_signature(), true);
|
||||||
|
compute_offset(_argument_offset, k, vmSymbols::argument_name(), vmSymbols::object_signature(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sun_dyn_AdapterMethodHandle::compute_offsets() {
|
||||||
|
klassOop k = SystemDictionary::AdapterMethodHandle_klass();
|
||||||
|
if (k != NULL && EnableMethodHandles) {
|
||||||
|
compute_offset(_conversion_offset, k, vmSymbols::conversion_name(), vmSymbols::int_signature(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
oop java_dyn_MethodHandle::type(oop mh) {
|
||||||
|
return mh->obj_field(_type_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void java_dyn_MethodHandle::set_type(oop mh, oop mtype) {
|
||||||
|
mh->obj_field_put(_type_offset, mtype);
|
||||||
|
}
|
||||||
|
|
||||||
|
int java_dyn_MethodHandle::vmslots(oop mh) {
|
||||||
|
int vmslots_offset = _vmslots_offset;
|
||||||
|
if (vmslots_offset != 0) {
|
||||||
|
#ifdef ASSERT
|
||||||
|
int x = mh->int_field(vmslots_offset);
|
||||||
|
int y = compute_vmslots(mh);
|
||||||
|
assert(x == y, "correct hoisted value");
|
||||||
|
#endif
|
||||||
|
return mh->int_field(vmslots_offset);
|
||||||
|
} else {
|
||||||
|
return compute_vmslots(mh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if MH.vmslots exists, hoist into it the value of type.form.vmslots
|
||||||
|
void java_dyn_MethodHandle::init_vmslots(oop mh) {
|
||||||
|
int vmslots_offset = _vmslots_offset;
|
||||||
|
if (vmslots_offset != 0) {
|
||||||
|
mh->int_field_put(vmslots_offset, compute_vmslots(mh));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fetch type.form.vmslots, which is the number of JVM stack slots
|
||||||
|
// required to carry the arguments of this MH
|
||||||
|
int java_dyn_MethodHandle::compute_vmslots(oop mh) {
|
||||||
|
oop mtype = type(mh);
|
||||||
|
if (mtype == NULL) return 0; // Java code would get NPE
|
||||||
|
oop form = java_dyn_MethodType::form(mtype);
|
||||||
|
if (form == NULL) return 0; // Java code would get NPE
|
||||||
|
return java_dyn_MethodTypeForm::vmslots(form);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fetch the low-level entry point for this mh
|
||||||
|
MethodHandleEntry* java_dyn_MethodHandle::vmentry(oop mh) {
|
||||||
|
return (MethodHandleEntry*) mh->address_field(_vmentry_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void java_dyn_MethodHandle::set_vmentry(oop mh, MethodHandleEntry* me) {
|
||||||
|
assert(_vmentry_offset != 0, "must be present");
|
||||||
|
|
||||||
|
// This is always the final step that initializes a valid method handle:
|
||||||
|
mh->release_address_field_put(_vmentry_offset, (address) me);
|
||||||
|
|
||||||
|
// There should be enough memory barriers on exit from native methods
|
||||||
|
// to ensure that the MH is fully initialized to all threads before
|
||||||
|
// Java code can publish it in global data structures.
|
||||||
|
// But just in case, we use release_address_field_put.
|
||||||
|
}
|
||||||
|
|
||||||
|
/// MemberName accessors
|
||||||
|
|
||||||
|
oop sun_dyn_MemberName::clazz(oop mname) {
|
||||||
|
assert(is_instance(mname), "wrong type");
|
||||||
|
return mname->obj_field(_clazz_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sun_dyn_MemberName::set_clazz(oop mname, oop clazz) {
|
||||||
|
assert(is_instance(mname), "wrong type");
|
||||||
|
mname->obj_field_put(_clazz_offset, clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
oop sun_dyn_MemberName::name(oop mname) {
|
||||||
|
assert(is_instance(mname), "wrong type");
|
||||||
|
return mname->obj_field(_name_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sun_dyn_MemberName::set_name(oop mname, oop name) {
|
||||||
|
assert(is_instance(mname), "wrong type");
|
||||||
|
mname->obj_field_put(_name_offset, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
oop sun_dyn_MemberName::type(oop mname) {
|
||||||
|
assert(is_instance(mname), "wrong type");
|
||||||
|
return mname->obj_field(_type_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sun_dyn_MemberName::set_type(oop mname, oop type) {
|
||||||
|
assert(is_instance(mname), "wrong type");
|
||||||
|
mname->obj_field_put(_type_offset, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sun_dyn_MemberName::flags(oop mname) {
|
||||||
|
assert(is_instance(mname), "wrong type");
|
||||||
|
return mname->int_field(_flags_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sun_dyn_MemberName::set_flags(oop mname, int flags) {
|
||||||
|
assert(is_instance(mname), "wrong type");
|
||||||
|
mname->int_field_put(_flags_offset, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
oop sun_dyn_MemberName::vmtarget(oop mname) {
|
||||||
|
assert(is_instance(mname), "wrong type");
|
||||||
|
return mname->obj_field(_vmtarget_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sun_dyn_MemberName::set_vmtarget(oop mname, oop ref) {
|
||||||
|
assert(is_instance(mname), "wrong type");
|
||||||
|
mname->obj_field_put(_vmtarget_offset, ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sun_dyn_MemberName::vmindex(oop mname) {
|
||||||
|
assert(is_instance(mname), "wrong type");
|
||||||
|
return mname->int_field(_vmindex_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sun_dyn_MemberName::set_vmindex(oop mname, int index) {
|
||||||
|
assert(is_instance(mname), "wrong type");
|
||||||
|
mname->int_field_put(_vmindex_offset, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
oop java_dyn_MethodHandle::vmtarget(oop mh) {
|
||||||
|
assert(is_instance(mh), "MH only");
|
||||||
|
return mh->obj_field(_vmtarget_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void java_dyn_MethodHandle::set_vmtarget(oop mh, oop ref) {
|
||||||
|
assert(is_instance(mh), "MH only");
|
||||||
|
mh->obj_field_put(_vmtarget_offset, ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sun_dyn_DirectMethodHandle::vmindex(oop mh) {
|
||||||
|
assert(is_instance(mh), "DMH only");
|
||||||
|
return mh->int_field(_vmindex_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sun_dyn_DirectMethodHandle::set_vmindex(oop mh, int index) {
|
||||||
|
assert(is_instance(mh), "DMH only");
|
||||||
|
mh->int_field_put(_vmindex_offset, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sun_dyn_BoundMethodHandle::vmargslot(oop mh) {
|
||||||
|
assert(is_instance(mh), "BMH only");
|
||||||
|
return mh->int_field(_vmargslot_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
oop sun_dyn_BoundMethodHandle::argument(oop mh) {
|
||||||
|
assert(is_instance(mh), "BMH only");
|
||||||
|
return mh->obj_field(_argument_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sun_dyn_AdapterMethodHandle::conversion(oop mh) {
|
||||||
|
assert(is_instance(mh), "AMH only");
|
||||||
|
return mh->int_field(_conversion_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sun_dyn_AdapterMethodHandle::set_conversion(oop mh, int conv) {
|
||||||
|
assert(is_instance(mh), "AMH only");
|
||||||
|
mh->int_field_put(_conversion_offset, conv);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Support for java_dyn_MethodType
|
||||||
|
|
||||||
|
int java_dyn_MethodType::_rtype_offset;
|
||||||
|
int java_dyn_MethodType::_ptypes_offset;
|
||||||
|
int java_dyn_MethodType::_form_offset;
|
||||||
|
|
||||||
|
void java_dyn_MethodType::compute_offsets() {
|
||||||
|
klassOop k = SystemDictionary::MethodType_klass();
|
||||||
|
if (k != NULL) {
|
||||||
|
compute_offset(_rtype_offset, k, vmSymbols::rtype_name(), vmSymbols::class_signature());
|
||||||
|
compute_offset(_ptypes_offset, k, vmSymbols::ptypes_name(), vmSymbols::class_array_signature());
|
||||||
|
compute_offset(_form_offset, k, vmSymbols::form_name(), vmSymbols::java_dyn_MethodTypeForm_signature());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void java_dyn_MethodType::print_signature(oop mt, outputStream* st) {
|
||||||
|
st->print("(");
|
||||||
|
objArrayOop pts = ptypes(mt);
|
||||||
|
for (int i = 0, limit = pts->length(); i < limit; i++) {
|
||||||
|
java_lang_Class::print_signature(pts->obj_at(i), st);
|
||||||
|
}
|
||||||
|
st->print(")");
|
||||||
|
java_lang_Class::print_signature(rtype(mt), st);
|
||||||
|
}
|
||||||
|
|
||||||
|
symbolOop java_dyn_MethodType::as_signature(oop mt, bool intern_if_not_found, TRAPS) {
|
||||||
|
ResourceMark rm;
|
||||||
|
stringStream buffer(128);
|
||||||
|
print_signature(mt, &buffer);
|
||||||
|
const char* sigstr = buffer.base();
|
||||||
|
int siglen = (int) buffer.size();
|
||||||
|
if (!intern_if_not_found)
|
||||||
|
return SymbolTable::probe(sigstr, siglen);
|
||||||
|
else
|
||||||
|
return oopFactory::new_symbol(sigstr, siglen, THREAD);
|
||||||
|
}
|
||||||
|
|
||||||
|
oop java_dyn_MethodType::rtype(oop mt) {
|
||||||
|
assert(is_instance(mt), "must be a MethodType");
|
||||||
|
return mt->obj_field(_rtype_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
objArrayOop java_dyn_MethodType::ptypes(oop mt) {
|
||||||
|
assert(is_instance(mt), "must be a MethodType");
|
||||||
|
return (objArrayOop) mt->obj_field(_ptypes_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
oop java_dyn_MethodType::form(oop mt) {
|
||||||
|
assert(is_instance(mt), "must be a MethodType");
|
||||||
|
return mt->obj_field(_form_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
oop java_dyn_MethodType::ptype(oop mt, int idx) {
|
||||||
|
return ptypes(mt)->obj_at(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Support for java_dyn_MethodTypeForm
|
||||||
|
|
||||||
|
int java_dyn_MethodTypeForm::_vmslots_offset;
|
||||||
|
int java_dyn_MethodTypeForm::_erasedType_offset;
|
||||||
|
|
||||||
|
void java_dyn_MethodTypeForm::compute_offsets() {
|
||||||
|
klassOop k = SystemDictionary::MethodTypeForm_klass();
|
||||||
|
if (k != NULL) {
|
||||||
|
compute_optional_offset(_vmslots_offset, k, vmSymbols::vmslots_name(), vmSymbols::int_signature(), true);
|
||||||
|
compute_optional_offset(_erasedType_offset, k, vmSymbols::erasedType_name(), vmSymbols::java_dyn_MethodType_signature(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int java_dyn_MethodTypeForm::vmslots(oop mtform) {
|
||||||
|
assert(mtform->klass() == SystemDictionary::MethodTypeForm_klass(), "MTForm only");
|
||||||
|
return mtform->int_field(_vmslots_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
oop java_dyn_MethodTypeForm::erasedType(oop mtform) {
|
||||||
|
assert(mtform->klass() == SystemDictionary::MethodTypeForm_klass(), "MTForm only");
|
||||||
|
return mtform->obj_field(_erasedType_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Support for java_security_AccessControlContext
|
// Support for java_security_AccessControlContext
|
||||||
|
|
||||||
int java_security_AccessControlContext::_context_offset = 0;
|
int java_security_AccessControlContext::_context_offset = 0;
|
||||||
int java_security_AccessControlContext::_privilegedContext_offset = 0;
|
int java_security_AccessControlContext::_privilegedContext_offset = 0;
|
||||||
int java_security_AccessControlContext::_isPrivileged_offset = 0;
|
int java_security_AccessControlContext::_isPrivileged_offset = 0;
|
||||||
|
|
||||||
|
|
||||||
void java_security_AccessControlContext::compute_offsets() {
|
void java_security_AccessControlContext::compute_offsets() {
|
||||||
assert(_isPrivileged_offset == 0, "offsets should be initialized only once");
|
assert(_isPrivileged_offset == 0, "offsets should be initialized only once");
|
||||||
fieldDescriptor fd;
|
fieldDescriptor fd;
|
||||||
@ -2442,6 +2766,15 @@ void JavaClasses::compute_offsets() {
|
|||||||
java_lang_System::compute_offsets();
|
java_lang_System::compute_offsets();
|
||||||
java_lang_Thread::compute_offsets();
|
java_lang_Thread::compute_offsets();
|
||||||
java_lang_ThreadGroup::compute_offsets();
|
java_lang_ThreadGroup::compute_offsets();
|
||||||
|
if (EnableMethodHandles) {
|
||||||
|
java_dyn_MethodHandle::compute_offsets();
|
||||||
|
sun_dyn_MemberName::compute_offsets();
|
||||||
|
sun_dyn_DirectMethodHandle::compute_offsets();
|
||||||
|
sun_dyn_BoundMethodHandle::compute_offsets();
|
||||||
|
sun_dyn_AdapterMethodHandle::compute_offsets();
|
||||||
|
java_dyn_MethodType::compute_offsets();
|
||||||
|
java_dyn_MethodTypeForm::compute_offsets();
|
||||||
|
}
|
||||||
java_security_AccessControlContext::compute_offsets();
|
java_security_AccessControlContext::compute_offsets();
|
||||||
// Initialize reflection classes. The layouts of these classes
|
// Initialize reflection classes. The layouts of these classes
|
||||||
// changed with the new reflection implementation in JDK 1.4, and
|
// changed with the new reflection implementation in JDK 1.4, and
|
||||||
@ -2459,6 +2792,9 @@ void JavaClasses::compute_offsets() {
|
|||||||
sun_reflect_UnsafeStaticFieldAccessorImpl::compute_offsets();
|
sun_reflect_UnsafeStaticFieldAccessorImpl::compute_offsets();
|
||||||
}
|
}
|
||||||
sun_misc_AtomicLongCSImpl::compute_offsets();
|
sun_misc_AtomicLongCSImpl::compute_offsets();
|
||||||
|
|
||||||
|
// generated interpreter code wants to know about the offsets we just computed:
|
||||||
|
AbstractAssembler::update_delayed_values();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
|
@ -151,6 +151,12 @@ class java_lang_Class : AllStatic {
|
|||||||
// Conversion
|
// Conversion
|
||||||
static klassOop as_klassOop(oop java_class);
|
static klassOop as_klassOop(oop java_class);
|
||||||
static BasicType as_BasicType(oop java_class, klassOop* reference_klass = NULL);
|
static BasicType as_BasicType(oop java_class, klassOop* reference_klass = NULL);
|
||||||
|
static BasicType as_BasicType(oop java_class, KlassHandle* reference_klass) {
|
||||||
|
klassOop refk_oop = NULL;
|
||||||
|
BasicType result = as_BasicType(java_class, &refk_oop);
|
||||||
|
(*reference_klass) = KlassHandle(refk_oop);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
static symbolOop as_signature(oop java_class, bool intern_if_not_found, TRAPS);
|
static symbolOop as_signature(oop java_class, bool intern_if_not_found, TRAPS);
|
||||||
static void print_signature(oop java_class, outputStream *st);
|
static void print_signature(oop java_class, outputStream *st);
|
||||||
// Testing
|
// Testing
|
||||||
@ -778,6 +784,284 @@ class java_lang_ref_SoftReference: public java_lang_ref_Reference {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Interface to java.dyn.MethodHandle objects
|
||||||
|
|
||||||
|
class MethodHandleEntry;
|
||||||
|
|
||||||
|
class java_dyn_MethodHandle: AllStatic {
|
||||||
|
friend class JavaClasses;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static int _vmentry_offset; // assembly code trampoline for MH
|
||||||
|
static int _vmtarget_offset; // class-specific target reference
|
||||||
|
static int _type_offset; // the MethodType of this MH
|
||||||
|
static int _vmslots_offset; // OPTIONAL hoisted type.form.vmslots
|
||||||
|
|
||||||
|
static void compute_offsets();
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Accessors
|
||||||
|
static oop type(oop mh);
|
||||||
|
static void set_type(oop mh, oop mtype);
|
||||||
|
|
||||||
|
static oop vmtarget(oop mh);
|
||||||
|
static void set_vmtarget(oop mh, oop target);
|
||||||
|
|
||||||
|
static MethodHandleEntry* vmentry(oop mh);
|
||||||
|
static void set_vmentry(oop mh, MethodHandleEntry* data);
|
||||||
|
|
||||||
|
static int vmslots(oop mh);
|
||||||
|
static void init_vmslots(oop mh);
|
||||||
|
static int compute_vmslots(oop mh);
|
||||||
|
|
||||||
|
// Testers
|
||||||
|
static bool is_subclass(klassOop klass) {
|
||||||
|
return Klass::cast(klass)->is_subclass_of(SystemDictionary::MethodHandle_klass());
|
||||||
|
}
|
||||||
|
static bool is_instance(oop obj) {
|
||||||
|
return obj != NULL && is_subclass(obj->klass());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accessors for code generation:
|
||||||
|
static int type_offset_in_bytes() { return _type_offset; }
|
||||||
|
static int vmtarget_offset_in_bytes() { return _vmtarget_offset; }
|
||||||
|
static int vmentry_offset_in_bytes() { return _vmentry_offset; }
|
||||||
|
static int vmslots_offset_in_bytes() { return _vmslots_offset; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class sun_dyn_DirectMethodHandle: public java_dyn_MethodHandle {
|
||||||
|
friend class JavaClasses;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// _vmtarget_offset; // method or class or interface
|
||||||
|
static int _vmindex_offset; // negative or vtable idx or itable idx
|
||||||
|
static void compute_offsets();
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Accessors
|
||||||
|
static int vmindex(oop mh);
|
||||||
|
static void set_vmindex(oop mh, int index);
|
||||||
|
|
||||||
|
// Testers
|
||||||
|
static bool is_subclass(klassOop klass) {
|
||||||
|
return Klass::cast(klass)->is_subclass_of(SystemDictionary::DirectMethodHandle_klass());
|
||||||
|
}
|
||||||
|
static bool is_instance(oop obj) {
|
||||||
|
return obj != NULL && is_subclass(obj->klass());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accessors for code generation:
|
||||||
|
static int vmindex_offset_in_bytes() { return _vmindex_offset; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class sun_dyn_BoundMethodHandle: public java_dyn_MethodHandle {
|
||||||
|
friend class JavaClasses;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static int _argument_offset; // argument value bound into this MH
|
||||||
|
static int _vmargslot_offset; // relevant argument slot (<= vmslots)
|
||||||
|
static void compute_offsets();
|
||||||
|
|
||||||
|
public:
|
||||||
|
static oop argument(oop mh);
|
||||||
|
static void set_argument(oop mh, oop ref);
|
||||||
|
|
||||||
|
static jint vmargslot(oop mh);
|
||||||
|
static void set_vmargslot(oop mh, jint slot);
|
||||||
|
|
||||||
|
// Testers
|
||||||
|
static bool is_subclass(klassOop klass) {
|
||||||
|
return Klass::cast(klass)->is_subclass_of(SystemDictionary::BoundMethodHandle_klass());
|
||||||
|
}
|
||||||
|
static bool is_instance(oop obj) {
|
||||||
|
return obj != NULL && is_subclass(obj->klass());
|
||||||
|
}
|
||||||
|
|
||||||
|
static int argument_offset_in_bytes() { return _argument_offset; }
|
||||||
|
static int vmargslot_offset_in_bytes() { return _vmargslot_offset; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class sun_dyn_AdapterMethodHandle: public sun_dyn_BoundMethodHandle {
|
||||||
|
friend class JavaClasses;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static int _conversion_offset; // type of conversion to apply
|
||||||
|
static void compute_offsets();
|
||||||
|
|
||||||
|
public:
|
||||||
|
static int conversion(oop mh);
|
||||||
|
static void set_conversion(oop mh, int conv);
|
||||||
|
|
||||||
|
// Testers
|
||||||
|
static bool is_subclass(klassOop klass) {
|
||||||
|
return Klass::cast(klass)->is_subclass_of(SystemDictionary::AdapterMethodHandle_klass());
|
||||||
|
}
|
||||||
|
static bool is_instance(oop obj) {
|
||||||
|
return obj != NULL && is_subclass(obj->klass());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Relevant integer codes (keep these in synch. with MethodHandleNatives.Constants):
|
||||||
|
enum {
|
||||||
|
OP_RETYPE_ONLY = 0x0, // no argument changes; straight retype
|
||||||
|
OP_CHECK_CAST = 0x1, // ref-to-ref conversion; requires a Class argument
|
||||||
|
OP_PRIM_TO_PRIM = 0x2, // converts from one primitive to another
|
||||||
|
OP_REF_TO_PRIM = 0x3, // unboxes a wrapper to produce a primitive
|
||||||
|
OP_PRIM_TO_REF = 0x4, // boxes a primitive into a wrapper (NYI)
|
||||||
|
OP_SWAP_ARGS = 0x5, // swap arguments (vminfo is 2nd arg)
|
||||||
|
OP_ROT_ARGS = 0x6, // rotate arguments (vminfo is displaced arg)
|
||||||
|
OP_DUP_ARGS = 0x7, // duplicates one or more arguments (at TOS)
|
||||||
|
OP_DROP_ARGS = 0x8, // remove one or more argument slots
|
||||||
|
OP_COLLECT_ARGS = 0x9, // combine one or more arguments into a varargs (NYI)
|
||||||
|
OP_SPREAD_ARGS = 0xA, // expand in place a varargs array (of known size)
|
||||||
|
OP_FLYBY = 0xB, // operate first on reified argument list (NYI)
|
||||||
|
OP_RICOCHET = 0xC, // run an adapter chain on the return value (NYI)
|
||||||
|
CONV_OP_LIMIT = 0xD, // limit of CONV_OP enumeration
|
||||||
|
|
||||||
|
CONV_OP_MASK = 0xF00, // this nybble contains the conversion op field
|
||||||
|
CONV_VMINFO_MASK = 0x0FF, // LSB is reserved for JVM use
|
||||||
|
CONV_VMINFO_SHIFT = 0, // position of bits in CONV_VMINFO_MASK
|
||||||
|
CONV_OP_SHIFT = 8, // position of bits in CONV_OP_MASK
|
||||||
|
CONV_DEST_TYPE_SHIFT = 12, // byte 2 has the adapter BasicType (if needed)
|
||||||
|
CONV_SRC_TYPE_SHIFT = 16, // byte 2 has the source BasicType (if needed)
|
||||||
|
CONV_STACK_MOVE_SHIFT = 20, // high 12 bits give signed SP change
|
||||||
|
CONV_STACK_MOVE_MASK = (1 << (32 - CONV_STACK_MOVE_SHIFT)) - 1
|
||||||
|
};
|
||||||
|
|
||||||
|
static int conversion_offset_in_bytes() { return _conversion_offset; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Interface to sun.dyn.MemberName objects
|
||||||
|
// (These are a private interface for Java code to query the class hierarchy.)
|
||||||
|
|
||||||
|
class sun_dyn_MemberName: AllStatic {
|
||||||
|
friend class JavaClasses;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// From java.dyn.MemberName:
|
||||||
|
// private Class<?> clazz; // class in which the method is defined
|
||||||
|
// private String name; // may be null if not yet materialized
|
||||||
|
// private Object type; // may be null if not yet materialized
|
||||||
|
// private int flags; // modifier bits; see reflect.Modifier
|
||||||
|
// private Object vmtarget; // VM-specific target value
|
||||||
|
// private int vmindex; // method index within class or interface
|
||||||
|
static int _clazz_offset;
|
||||||
|
static int _name_offset;
|
||||||
|
static int _type_offset;
|
||||||
|
static int _flags_offset;
|
||||||
|
static int _vmtarget_offset;
|
||||||
|
static int _vmindex_offset;
|
||||||
|
|
||||||
|
static void compute_offsets();
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Accessors
|
||||||
|
static oop clazz(oop mname);
|
||||||
|
static void set_clazz(oop mname, oop clazz);
|
||||||
|
|
||||||
|
static oop type(oop mname);
|
||||||
|
static void set_type(oop mname, oop type);
|
||||||
|
|
||||||
|
static oop name(oop mname);
|
||||||
|
static void set_name(oop mname, oop name);
|
||||||
|
|
||||||
|
static int flags(oop mname);
|
||||||
|
static void set_flags(oop mname, int flags);
|
||||||
|
|
||||||
|
static int modifiers(oop mname) { return (u2) flags(mname); }
|
||||||
|
static void set_modifiers(oop mname, int mods)
|
||||||
|
{ set_flags(mname, (flags(mname) &~ (u2)-1) | (u2)mods); }
|
||||||
|
|
||||||
|
static oop vmtarget(oop mname);
|
||||||
|
static void set_vmtarget(oop mname, oop target);
|
||||||
|
|
||||||
|
static int vmindex(oop mname);
|
||||||
|
static void set_vmindex(oop mname, int index);
|
||||||
|
|
||||||
|
// Testers
|
||||||
|
static bool is_subclass(klassOop klass) {
|
||||||
|
return Klass::cast(klass)->is_subclass_of(SystemDictionary::MemberName_klass());
|
||||||
|
}
|
||||||
|
static bool is_instance(oop obj) {
|
||||||
|
return obj != NULL && is_subclass(obj->klass());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Relevant integer codes (keep these in synch. with MethodHandleNatives.Constants):
|
||||||
|
enum {
|
||||||
|
MN_IS_METHOD = 0x00010000, // method (not constructor)
|
||||||
|
MN_IS_CONSTRUCTOR = 0x00020000, // constructor
|
||||||
|
MN_IS_FIELD = 0x00040000, // field
|
||||||
|
MN_IS_TYPE = 0x00080000, // nested type
|
||||||
|
MN_SEARCH_SUPERCLASSES = 0x00100000, // for MHN.getMembers
|
||||||
|
MN_SEARCH_INTERFACES = 0x00200000, // for MHN.getMembers
|
||||||
|
VM_INDEX_UNINITIALIZED = -99
|
||||||
|
};
|
||||||
|
|
||||||
|
// Accessors for code generation:
|
||||||
|
static int clazz_offset_in_bytes() { return _clazz_offset; }
|
||||||
|
static int type_offset_in_bytes() { return _type_offset; }
|
||||||
|
static int name_offset_in_bytes() { return _name_offset; }
|
||||||
|
static int flags_offset_in_bytes() { return _flags_offset; }
|
||||||
|
static int vmtarget_offset_in_bytes() { return _vmtarget_offset; }
|
||||||
|
static int vmindex_offset_in_bytes() { return _vmindex_offset; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Interface to java.dyn.MethodType objects
|
||||||
|
|
||||||
|
class java_dyn_MethodType: AllStatic {
|
||||||
|
friend class JavaClasses;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static int _rtype_offset;
|
||||||
|
static int _ptypes_offset;
|
||||||
|
static int _form_offset;
|
||||||
|
|
||||||
|
static void compute_offsets();
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Accessors
|
||||||
|
static oop rtype(oop mt);
|
||||||
|
static objArrayOop ptypes(oop mt);
|
||||||
|
static oop form(oop mt);
|
||||||
|
|
||||||
|
static oop ptype(oop mt, int index);
|
||||||
|
|
||||||
|
static symbolOop as_signature(oop mt, bool intern_if_not_found, TRAPS);
|
||||||
|
static void print_signature(oop mt, outputStream* st);
|
||||||
|
|
||||||
|
static bool is_instance(oop obj) {
|
||||||
|
return obj != NULL && obj->klass() == SystemDictionary::MethodType_klass();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accessors for code generation:
|
||||||
|
static int rtype_offset_in_bytes() { return _rtype_offset; }
|
||||||
|
static int ptypes_offset_in_bytes() { return _ptypes_offset; }
|
||||||
|
static int form_offset_in_bytes() { return _form_offset; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class java_dyn_MethodTypeForm: AllStatic {
|
||||||
|
friend class JavaClasses;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static int _vmslots_offset; // number of argument slots needed
|
||||||
|
static int _erasedType_offset; // erasedType = canonical MethodType
|
||||||
|
|
||||||
|
static void compute_offsets();
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Accessors
|
||||||
|
static int vmslots(oop mtform);
|
||||||
|
static oop erasedType(oop mtform);
|
||||||
|
|
||||||
|
// Accessors for code generation:
|
||||||
|
static int vmslots_offset_in_bytes() { return _vmslots_offset; }
|
||||||
|
static int erasedType_offset_in_bytes() { return _erasedType_offset; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Interface to java.security.AccessControlContext objects
|
// Interface to java.security.AccessControlContext objects
|
||||||
|
|
||||||
class java_security_AccessControlContext: AllStatic {
|
class java_security_AccessControlContext: AllStatic {
|
||||||
|
@ -31,6 +31,7 @@ PlaceholderTable* SystemDictionary::_placeholders = NULL;
|
|||||||
Dictionary* SystemDictionary::_shared_dictionary = NULL;
|
Dictionary* SystemDictionary::_shared_dictionary = NULL;
|
||||||
LoaderConstraintTable* SystemDictionary::_loader_constraints = NULL;
|
LoaderConstraintTable* SystemDictionary::_loader_constraints = NULL;
|
||||||
ResolutionErrorTable* SystemDictionary::_resolution_errors = NULL;
|
ResolutionErrorTable* SystemDictionary::_resolution_errors = NULL;
|
||||||
|
SymbolPropertyTable* SystemDictionary::_invoke_method_table = NULL;
|
||||||
|
|
||||||
|
|
||||||
int SystemDictionary::_number_of_modifications = 0;
|
int SystemDictionary::_number_of_modifications = 0;
|
||||||
@ -966,6 +967,8 @@ klassOop SystemDictionary::parse_stream(symbolHandle class_name,
|
|||||||
instanceKlassHandle k = ClassFileParser(st).parseClassFile(class_name,
|
instanceKlassHandle k = ClassFileParser(st).parseClassFile(class_name,
|
||||||
class_loader,
|
class_loader,
|
||||||
protection_domain,
|
protection_domain,
|
||||||
|
host_klass,
|
||||||
|
cp_patches,
|
||||||
parsed_name,
|
parsed_name,
|
||||||
THREAD);
|
THREAD);
|
||||||
|
|
||||||
@ -1691,6 +1694,10 @@ void SystemDictionary::always_strong_classes_do(OopClosure* blk) {
|
|||||||
// represent classes we're actively loading.
|
// represent classes we're actively loading.
|
||||||
placeholders_do(blk);
|
placeholders_do(blk);
|
||||||
|
|
||||||
|
// Visit extra methods
|
||||||
|
if (invoke_method_table() != NULL)
|
||||||
|
invoke_method_table()->oops_do(blk);
|
||||||
|
|
||||||
// Loader constraints. We must keep the symbolOop used in the name alive.
|
// Loader constraints. We must keep the symbolOop used in the name alive.
|
||||||
constraints()->always_strong_classes_do(blk);
|
constraints()->always_strong_classes_do(blk);
|
||||||
|
|
||||||
@ -1726,6 +1733,10 @@ void SystemDictionary::oops_do(OopClosure* f) {
|
|||||||
// Adjust dictionary
|
// Adjust dictionary
|
||||||
dictionary()->oops_do(f);
|
dictionary()->oops_do(f);
|
||||||
|
|
||||||
|
// Visit extra methods
|
||||||
|
if (invoke_method_table() != NULL)
|
||||||
|
invoke_method_table()->oops_do(f);
|
||||||
|
|
||||||
// Partially loaded classes
|
// Partially loaded classes
|
||||||
placeholders()->oops_do(f);
|
placeholders()->oops_do(f);
|
||||||
|
|
||||||
@ -1798,6 +1809,8 @@ void SystemDictionary::placeholders_do(void f(symbolOop, oop)) {
|
|||||||
|
|
||||||
void SystemDictionary::methods_do(void f(methodOop)) {
|
void SystemDictionary::methods_do(void f(methodOop)) {
|
||||||
dictionary()->methods_do(f);
|
dictionary()->methods_do(f);
|
||||||
|
if (invoke_method_table() != NULL)
|
||||||
|
invoke_method_table()->methods_do(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -1830,6 +1843,7 @@ void SystemDictionary::initialize(TRAPS) {
|
|||||||
_number_of_modifications = 0;
|
_number_of_modifications = 0;
|
||||||
_loader_constraints = new LoaderConstraintTable(_loader_constraint_size);
|
_loader_constraints = new LoaderConstraintTable(_loader_constraint_size);
|
||||||
_resolution_errors = new ResolutionErrorTable(_resolution_error_size);
|
_resolution_errors = new ResolutionErrorTable(_resolution_error_size);
|
||||||
|
// _invoke_method_table is allocated lazily in find_method_handle_invoke()
|
||||||
|
|
||||||
// Allocate private object used as system class loader lock
|
// Allocate private object used as system class loader lock
|
||||||
_system_loader_lock_obj = oopFactory::new_system_objArray(0, CHECK);
|
_system_loader_lock_obj = oopFactory::new_system_objArray(0, CHECK);
|
||||||
@ -1891,6 +1905,9 @@ void SystemDictionary::initialize_wk_klasses_until(WKID limit_id, WKID &start_id
|
|||||||
wk_klass_name_limits[0] = s;
|
wk_klass_name_limits[0] = s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// move the starting value forward to the limit:
|
||||||
|
start_id = limit_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1924,6 +1941,17 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) {
|
|||||||
instanceKlass::cast(WK_KLASS(final_reference_klass))->set_reference_type(REF_FINAL);
|
instanceKlass::cast(WK_KLASS(final_reference_klass))->set_reference_type(REF_FINAL);
|
||||||
instanceKlass::cast(WK_KLASS(phantom_reference_klass))->set_reference_type(REF_PHANTOM);
|
instanceKlass::cast(WK_KLASS(phantom_reference_klass))->set_reference_type(REF_PHANTOM);
|
||||||
|
|
||||||
|
WKID meth_group_start = WK_KLASS_ENUM_NAME(MethodHandle_klass);
|
||||||
|
WKID meth_group_end = WK_KLASS_ENUM_NAME(WrongMethodTypeException_klass);
|
||||||
|
initialize_wk_klasses_until(meth_group_start, scan, CHECK);
|
||||||
|
if (EnableMethodHandles) {
|
||||||
|
initialize_wk_klasses_through(meth_group_start, scan, CHECK);
|
||||||
|
}
|
||||||
|
if (_well_known_klasses[meth_group_start] == NULL) {
|
||||||
|
// Skip the rest of the method handle classes, if MethodHandle is not loaded.
|
||||||
|
scan = WKID(meth_group_end+1);
|
||||||
|
}
|
||||||
|
|
||||||
initialize_wk_klasses_until(WKID_LIMIT, scan, CHECK);
|
initialize_wk_klasses_until(WKID_LIMIT, scan, CHECK);
|
||||||
|
|
||||||
_box_klasses[T_BOOLEAN] = WK_KLASS(boolean_klass);
|
_box_klasses[T_BOOLEAN] = WK_KLASS(boolean_klass);
|
||||||
@ -2254,6 +2282,91 @@ char* SystemDictionary::check_signature_loaders(symbolHandle signature,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
methodOop SystemDictionary::find_method_handle_invoke(symbolHandle signature,
|
||||||
|
Handle class_loader,
|
||||||
|
Handle protection_domain,
|
||||||
|
TRAPS) {
|
||||||
|
if (!EnableMethodHandles) return NULL;
|
||||||
|
assert(class_loader.is_null() && protection_domain.is_null(),
|
||||||
|
"cannot load specialized versions of MethodHandle.invoke");
|
||||||
|
if (invoke_method_table() == NULL) {
|
||||||
|
// create this side table lazily
|
||||||
|
_invoke_method_table = new SymbolPropertyTable(_invoke_method_size);
|
||||||
|
}
|
||||||
|
unsigned int hash = invoke_method_table()->compute_hash(signature);
|
||||||
|
int index = invoke_method_table()->hash_to_index(hash);
|
||||||
|
SymbolPropertyEntry* spe = invoke_method_table()->find_entry(index, hash, signature);
|
||||||
|
if (spe == NULL || spe->property_oop() == NULL) {
|
||||||
|
// Must create lots of stuff here, but outside of the SystemDictionary lock.
|
||||||
|
Handle mt = compute_method_handle_type(signature(),
|
||||||
|
class_loader, protection_domain,
|
||||||
|
CHECK_NULL);
|
||||||
|
KlassHandle mh_klass = SystemDictionaryHandles::MethodHandle_klass();
|
||||||
|
methodHandle m = methodOopDesc::make_invoke_method(mh_klass, signature,
|
||||||
|
mt, CHECK_NULL);
|
||||||
|
// Now grab the lock. We might have to throw away the new method,
|
||||||
|
// if a racing thread has managed to install one at the same time.
|
||||||
|
{
|
||||||
|
MutexLocker ml(SystemDictionary_lock, Thread::current());
|
||||||
|
spe = invoke_method_table()->find_entry(index, hash, signature);
|
||||||
|
if (spe == NULL)
|
||||||
|
spe = invoke_method_table()->add_entry(index, hash, signature);
|
||||||
|
if (spe->property_oop() == NULL)
|
||||||
|
spe->set_property_oop(m());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
methodOop m = (methodOop) spe->property_oop();
|
||||||
|
assert(m->is_method(), "");
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ask Java code to find or construct a java.dyn.MethodType for the given
|
||||||
|
// signature, as interpreted relative to the given class loader.
|
||||||
|
// Because of class loader constraints, all method handle usage must be
|
||||||
|
// consistent with this loader.
|
||||||
|
Handle SystemDictionary::compute_method_handle_type(symbolHandle signature,
|
||||||
|
Handle class_loader,
|
||||||
|
Handle protection_domain,
|
||||||
|
TRAPS) {
|
||||||
|
Handle empty;
|
||||||
|
int npts = ArgumentCount(signature()).size();
|
||||||
|
objArrayHandle pts = oopFactory::new_objArray(SystemDictionary::class_klass(), npts, CHECK_(empty));
|
||||||
|
int arg = 0;
|
||||||
|
Handle rt; // the return type from the signature
|
||||||
|
for (SignatureStream ss(signature()); !ss.is_done(); ss.next()) {
|
||||||
|
oop mirror;
|
||||||
|
if (!ss.is_object()) {
|
||||||
|
mirror = Universe::java_mirror(ss.type());
|
||||||
|
} else {
|
||||||
|
symbolOop name_oop = ss.as_symbol(CHECK_(empty));
|
||||||
|
symbolHandle name(THREAD, name_oop);
|
||||||
|
klassOop klass = resolve_or_fail(name,
|
||||||
|
class_loader, protection_domain,
|
||||||
|
true, CHECK_(empty));
|
||||||
|
mirror = Klass::cast(klass)->java_mirror();
|
||||||
|
}
|
||||||
|
if (ss.at_return_type())
|
||||||
|
rt = Handle(THREAD, mirror);
|
||||||
|
else
|
||||||
|
pts->obj_at_put(arg++, mirror);
|
||||||
|
}
|
||||||
|
assert(arg == npts, "");
|
||||||
|
|
||||||
|
// call MethodType java.dyn.MethodType::makeImpl(Class rt, Class[] pts, false, true)
|
||||||
|
bool varargs = false, trusted = true;
|
||||||
|
JavaCallArguments args(Handle(THREAD, rt()));
|
||||||
|
args.push_oop(pts());
|
||||||
|
args.push_int(false);
|
||||||
|
args.push_int(trusted);
|
||||||
|
JavaValue result(T_OBJECT);
|
||||||
|
JavaCalls::call_static(&result,
|
||||||
|
SystemDictionary::MethodType_klass(),
|
||||||
|
vmSymbols::makeImpl_name(), vmSymbols::makeImpl_signature(),
|
||||||
|
&args, CHECK_(empty));
|
||||||
|
return Handle(THREAD, (oop) result.get_jobject());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Since the identity hash code for symbols changes when the symbols are
|
// Since the identity hash code for symbols changes when the symbols are
|
||||||
// moved from the regular perm gen (hash in the mark word) to the shared
|
// moved from the regular perm gen (hash in the mark word) to the shared
|
||||||
// spaces (hash is the address), the classes loaded into the dictionary
|
// spaces (hash is the address), the classes loaded into the dictionary
|
||||||
|
@ -63,6 +63,7 @@ class PlaceholderTable;
|
|||||||
class LoaderConstraintTable;
|
class LoaderConstraintTable;
|
||||||
class HashtableBucket;
|
class HashtableBucket;
|
||||||
class ResolutionErrorTable;
|
class ResolutionErrorTable;
|
||||||
|
class SymbolPropertyTable;
|
||||||
|
|
||||||
// Certain classes are preloaded, such as java.lang.Object and java.lang.String.
|
// Certain classes are preloaded, such as java.lang.Object and java.lang.String.
|
||||||
// They are all "well-known", in the sense that no class loader is allowed
|
// They are all "well-known", in the sense that no class loader is allowed
|
||||||
@ -131,6 +132,16 @@ class ResolutionErrorTable;
|
|||||||
template(reflect_constant_pool_klass, sun_reflect_ConstantPool, Opt_Only_JDK15) \
|
template(reflect_constant_pool_klass, sun_reflect_ConstantPool, Opt_Only_JDK15) \
|
||||||
template(reflect_unsafe_static_field_accessor_impl_klass, sun_reflect_UnsafeStaticFieldAccessorImpl, Opt_Only_JDK15) \
|
template(reflect_unsafe_static_field_accessor_impl_klass, sun_reflect_UnsafeStaticFieldAccessorImpl, Opt_Only_JDK15) \
|
||||||
\
|
\
|
||||||
|
/* support for dynamic typing; it's OK if these are NULL in earlier JDKs */ \
|
||||||
|
template(MethodHandle_klass, java_dyn_MethodHandle, Opt) \
|
||||||
|
template(MemberName_klass, sun_dyn_MemberName, Opt) \
|
||||||
|
template(MethodHandleImpl_klass, sun_dyn_MethodHandleImpl, Opt) \
|
||||||
|
template(AdapterMethodHandle_klass, sun_dyn_AdapterMethodHandle, Opt) \
|
||||||
|
template(BoundMethodHandle_klass, sun_dyn_BoundMethodHandle, Opt) \
|
||||||
|
template(DirectMethodHandle_klass, sun_dyn_DirectMethodHandle, Opt) \
|
||||||
|
template(MethodType_klass, java_dyn_MethodType, Opt) \
|
||||||
|
template(MethodTypeForm_klass, java_dyn_MethodTypeForm, Opt) \
|
||||||
|
template(WrongMethodTypeException_klass, java_dyn_WrongMethodTypeException, Opt) \
|
||||||
template(vector_klass, java_util_Vector, Pre) \
|
template(vector_klass, java_util_Vector, Pre) \
|
||||||
template(hashtable_klass, java_util_Hashtable, Pre) \
|
template(hashtable_klass, java_util_Hashtable, Pre) \
|
||||||
template(stringBuffer_klass, java_lang_StringBuffer, Pre) \
|
template(stringBuffer_klass, java_lang_StringBuffer, Pre) \
|
||||||
@ -444,6 +455,17 @@ public:
|
|||||||
static char* check_signature_loaders(symbolHandle signature, Handle loader1,
|
static char* check_signature_loaders(symbolHandle signature, Handle loader1,
|
||||||
Handle loader2, bool is_method, TRAPS);
|
Handle loader2, bool is_method, TRAPS);
|
||||||
|
|
||||||
|
// JSR 292
|
||||||
|
// find the java.dyn.MethodHandles::invoke method for a given signature
|
||||||
|
static methodOop find_method_handle_invoke(symbolHandle signature,
|
||||||
|
Handle class_loader,
|
||||||
|
Handle protection_domain,
|
||||||
|
TRAPS);
|
||||||
|
// ask Java to compute the java.dyn.MethodType object for a given signature
|
||||||
|
static Handle compute_method_handle_type(symbolHandle signature,
|
||||||
|
Handle class_loader,
|
||||||
|
Handle protection_domain,
|
||||||
|
TRAPS);
|
||||||
// Utility for printing loader "name" as part of tracing constraints
|
// Utility for printing loader "name" as part of tracing constraints
|
||||||
static const char* loader_name(oop loader) {
|
static const char* loader_name(oop loader) {
|
||||||
return ((loader) == NULL ? "<bootloader>" :
|
return ((loader) == NULL ? "<bootloader>" :
|
||||||
@ -460,6 +482,7 @@ public:
|
|||||||
enum Constants {
|
enum Constants {
|
||||||
_loader_constraint_size = 107, // number of entries in constraint table
|
_loader_constraint_size = 107, // number of entries in constraint table
|
||||||
_resolution_error_size = 107, // number of entries in resolution error table
|
_resolution_error_size = 107, // number of entries in resolution error table
|
||||||
|
_invoke_method_size = 139, // number of entries in invoke method table
|
||||||
_nof_buckets = 1009 // number of buckets in hash table
|
_nof_buckets = 1009 // number of buckets in hash table
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -489,6 +512,9 @@ public:
|
|||||||
// Resolution errors
|
// Resolution errors
|
||||||
static ResolutionErrorTable* _resolution_errors;
|
static ResolutionErrorTable* _resolution_errors;
|
||||||
|
|
||||||
|
// Invoke methods (JSR 292)
|
||||||
|
static SymbolPropertyTable* _invoke_method_table;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// for VM_CounterDecay iteration support
|
// for VM_CounterDecay iteration support
|
||||||
friend class CounterDecay;
|
friend class CounterDecay;
|
||||||
@ -506,6 +532,7 @@ private:
|
|||||||
static PlaceholderTable* placeholders() { return _placeholders; }
|
static PlaceholderTable* placeholders() { return _placeholders; }
|
||||||
static LoaderConstraintTable* constraints() { return _loader_constraints; }
|
static LoaderConstraintTable* constraints() { return _loader_constraints; }
|
||||||
static ResolutionErrorTable* resolution_errors() { return _resolution_errors; }
|
static ResolutionErrorTable* resolution_errors() { return _resolution_errors; }
|
||||||
|
static SymbolPropertyTable* invoke_method_table() { return _invoke_method_table; }
|
||||||
|
|
||||||
// Basic loading operations
|
// Basic loading operations
|
||||||
static klassOop resolve_instance_class_or_null(symbolHandle class_name, Handle class_loader, Handle protection_domain, TRAPS);
|
static klassOop resolve_instance_class_or_null(symbolHandle class_name, Handle class_loader, Handle protection_domain, TRAPS);
|
||||||
|
@ -216,7 +216,26 @@
|
|||||||
template(sun_reflect_UnsafeStaticFieldAccessorImpl, "sun/reflect/UnsafeStaticFieldAccessorImpl")\
|
template(sun_reflect_UnsafeStaticFieldAccessorImpl, "sun/reflect/UnsafeStaticFieldAccessorImpl")\
|
||||||
template(base_name, "base") \
|
template(base_name, "base") \
|
||||||
\
|
\
|
||||||
/* common method names */ \
|
/* Support for JSR 292 & invokedynamic (JDK 1.7 and above) */ \
|
||||||
|
template(java_dyn_MethodHandle, "java/dyn/MethodHandle") \
|
||||||
|
template(java_dyn_MethodType, "java/dyn/MethodType") \
|
||||||
|
template(java_dyn_WrongMethodTypeException, "java/dyn/WrongMethodTypeException") \
|
||||||
|
template(java_dyn_MethodType_signature, "Ljava/dyn/MethodType;") \
|
||||||
|
template(java_dyn_MethodHandle_signature, "Ljava/dyn/MethodHandle;") \
|
||||||
|
/* internal classes known only to the JVM: */ \
|
||||||
|
template(java_dyn_MethodTypeForm, "java/dyn/MethodTypeForm") \
|
||||||
|
template(java_dyn_MethodTypeForm_signature, "Ljava/dyn/MethodTypeForm;") \
|
||||||
|
template(sun_dyn_MemberName, "sun/dyn/MemberName") \
|
||||||
|
template(sun_dyn_MethodHandleImpl, "sun/dyn/MethodHandleImpl") \
|
||||||
|
template(sun_dyn_AdapterMethodHandle, "sun/dyn/AdapterMethodHandle") \
|
||||||
|
template(sun_dyn_BoundMethodHandle, "sun/dyn/BoundMethodHandle") \
|
||||||
|
template(sun_dyn_DirectMethodHandle, "sun/dyn/DirectMethodHandle") \
|
||||||
|
template(makeImpl_name, "makeImpl") /*MethodType::makeImpl*/ \
|
||||||
|
template(makeImpl_signature, "(Ljava/lang/Class;[Ljava/lang/Class;ZZ)Ljava/dyn/MethodType;") \
|
||||||
|
NOT_LP64( do_alias(machine_word_signature, int_signature) ) \
|
||||||
|
LP64_ONLY( do_alias(machine_word_signature, long_signature) ) \
|
||||||
|
\
|
||||||
|
/* common method and field names */ \
|
||||||
template(object_initializer_name, "<init>") \
|
template(object_initializer_name, "<init>") \
|
||||||
template(class_initializer_name, "<clinit>") \
|
template(class_initializer_name, "<clinit>") \
|
||||||
template(println_name, "println") \
|
template(println_name, "println") \
|
||||||
@ -289,6 +308,21 @@
|
|||||||
template(bitCount_name, "bitCount") \
|
template(bitCount_name, "bitCount") \
|
||||||
template(profile_name, "profile") \
|
template(profile_name, "profile") \
|
||||||
template(equals_name, "equals") \
|
template(equals_name, "equals") \
|
||||||
|
template(toString_name, "toString") \
|
||||||
|
template(values_name, "values") \
|
||||||
|
template(receiver_name, "receiver") \
|
||||||
|
template(vmtarget_name, "vmtarget") \
|
||||||
|
template(vmentry_name, "vmentry") \
|
||||||
|
template(vmslots_name, "vmslots") \
|
||||||
|
template(vmindex_name, "vmindex") \
|
||||||
|
template(vmargslot_name, "vmargslot") \
|
||||||
|
template(flags_name, "flags") \
|
||||||
|
template(argument_name, "argument") \
|
||||||
|
template(conversion_name, "conversion") \
|
||||||
|
template(rtype_name, "rtype") \
|
||||||
|
template(ptypes_name, "ptypes") \
|
||||||
|
template(form_name, "form") \
|
||||||
|
template(erasedType_name, "erasedType") \
|
||||||
\
|
\
|
||||||
/* non-intrinsic name/signature pairs: */ \
|
/* non-intrinsic name/signature pairs: */ \
|
||||||
template(register_method_name, "register") \
|
template(register_method_name, "register") \
|
||||||
@ -353,6 +387,7 @@
|
|||||||
template(void_classloader_signature, "()Ljava/lang/ClassLoader;") \
|
template(void_classloader_signature, "()Ljava/lang/ClassLoader;") \
|
||||||
template(void_object_signature, "()Ljava/lang/Object;") \
|
template(void_object_signature, "()Ljava/lang/Object;") \
|
||||||
template(void_class_signature, "()Ljava/lang/Class;") \
|
template(void_class_signature, "()Ljava/lang/Class;") \
|
||||||
|
template(void_string_signature, "()Ljava/lang/String;") \
|
||||||
template(object_array_object_object_signature, "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;")\
|
template(object_array_object_object_signature, "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;")\
|
||||||
template(exception_void_signature, "(Ljava/lang/Exception;)V") \
|
template(exception_void_signature, "(Ljava/lang/Exception;)V") \
|
||||||
template(protectiondomain_signature, "[Ljava/security/ProtectionDomain;") \
|
template(protectiondomain_signature, "[Ljava/security/ProtectionDomain;") \
|
||||||
|
@ -254,6 +254,7 @@ assembler_<arch>.cpp cardTableModRefBS.hpp
|
|||||||
assembler_<arch>.cpp collectedHeap.inline.hpp
|
assembler_<arch>.cpp collectedHeap.inline.hpp
|
||||||
assembler_<arch>.cpp interfaceSupport.hpp
|
assembler_<arch>.cpp interfaceSupport.hpp
|
||||||
assembler_<arch>.cpp interpreter.hpp
|
assembler_<arch>.cpp interpreter.hpp
|
||||||
|
assembler_<arch>.cpp methodHandles.hpp
|
||||||
assembler_<arch>.cpp objectMonitor.hpp
|
assembler_<arch>.cpp objectMonitor.hpp
|
||||||
assembler_<arch>.cpp os.hpp
|
assembler_<arch>.cpp os.hpp
|
||||||
assembler_<arch>.cpp resourceArea.hpp
|
assembler_<arch>.cpp resourceArea.hpp
|
||||||
@ -1274,6 +1275,7 @@ cpCacheKlass.cpp bytecodes.hpp
|
|||||||
cpCacheKlass.cpp collectedHeap.hpp
|
cpCacheKlass.cpp collectedHeap.hpp
|
||||||
cpCacheKlass.cpp constantPoolOop.hpp
|
cpCacheKlass.cpp constantPoolOop.hpp
|
||||||
cpCacheKlass.cpp cpCacheKlass.hpp
|
cpCacheKlass.cpp cpCacheKlass.hpp
|
||||||
|
cpCacheKlass.cpp genOopClosures.inline.hpp
|
||||||
cpCacheKlass.cpp handles.inline.hpp
|
cpCacheKlass.cpp handles.inline.hpp
|
||||||
cpCacheKlass.cpp javaClasses.hpp
|
cpCacheKlass.cpp javaClasses.hpp
|
||||||
cpCacheKlass.cpp markSweep.inline.hpp
|
cpCacheKlass.cpp markSweep.inline.hpp
|
||||||
@ -2202,6 +2204,7 @@ interpreter_<arch_model>.cpp interpreterGenerator.hpp
|
|||||||
interpreter_<arch_model>.cpp jvmtiExport.hpp
|
interpreter_<arch_model>.cpp jvmtiExport.hpp
|
||||||
interpreter_<arch_model>.cpp jvmtiThreadState.hpp
|
interpreter_<arch_model>.cpp jvmtiThreadState.hpp
|
||||||
interpreter_<arch_model>.cpp methodDataOop.hpp
|
interpreter_<arch_model>.cpp methodDataOop.hpp
|
||||||
|
interpreter_<arch_model>.cpp methodHandles.hpp
|
||||||
interpreter_<arch_model>.cpp methodOop.hpp
|
interpreter_<arch_model>.cpp methodOop.hpp
|
||||||
interpreter_<arch_model>.cpp oop.inline.hpp
|
interpreter_<arch_model>.cpp oop.inline.hpp
|
||||||
interpreter_<arch_model>.cpp sharedRuntime.hpp
|
interpreter_<arch_model>.cpp sharedRuntime.hpp
|
||||||
@ -2596,6 +2599,7 @@ linkResolver.cpp handles.inline.hpp
|
|||||||
linkResolver.cpp instanceKlass.hpp
|
linkResolver.cpp instanceKlass.hpp
|
||||||
linkResolver.cpp interpreterRuntime.hpp
|
linkResolver.cpp interpreterRuntime.hpp
|
||||||
linkResolver.cpp linkResolver.hpp
|
linkResolver.cpp linkResolver.hpp
|
||||||
|
linkResolver.cpp methodHandles.hpp
|
||||||
linkResolver.cpp nativeLookup.hpp
|
linkResolver.cpp nativeLookup.hpp
|
||||||
linkResolver.cpp objArrayOop.hpp
|
linkResolver.cpp objArrayOop.hpp
|
||||||
linkResolver.cpp reflection.hpp
|
linkResolver.cpp reflection.hpp
|
||||||
@ -2812,6 +2816,25 @@ methodDataOop.hpp oop.hpp
|
|||||||
methodDataOop.hpp orderAccess.hpp
|
methodDataOop.hpp orderAccess.hpp
|
||||||
methodDataOop.hpp universe.hpp
|
methodDataOop.hpp universe.hpp
|
||||||
|
|
||||||
|
methodHandles.hpp frame.inline.hpp
|
||||||
|
methodHandles.hpp globals.hpp
|
||||||
|
methodHandles.hpp interfaceSupport.hpp
|
||||||
|
methodHandles.hpp javaClasses.hpp
|
||||||
|
methodHandles.hpp vmSymbols.hpp
|
||||||
|
|
||||||
|
methodHandles.cpp allocation.inline.hpp
|
||||||
|
methodHandles.cpp interpreter.hpp
|
||||||
|
methodHandles.cpp javaCalls.hpp
|
||||||
|
methodHandles.cpp methodHandles.hpp
|
||||||
|
methodHandles.cpp oopFactory.hpp
|
||||||
|
methodHandles.cpp reflection.hpp
|
||||||
|
methodHandles.cpp signature.hpp
|
||||||
|
methodHandles.cpp symbolTable.hpp
|
||||||
|
|
||||||
|
methodHandles_<arch>.cpp allocation.inline.hpp
|
||||||
|
methodHandles_<arch>.cpp interpreter.hpp
|
||||||
|
methodHandles_<arch>.cpp methodHandles.hpp
|
||||||
|
|
||||||
methodKlass.cpp collectedHeap.inline.hpp
|
methodKlass.cpp collectedHeap.inline.hpp
|
||||||
methodKlass.cpp constMethodKlass.hpp
|
methodKlass.cpp constMethodKlass.hpp
|
||||||
methodKlass.cpp gcLocker.hpp
|
methodKlass.cpp gcLocker.hpp
|
||||||
@ -3061,6 +3084,7 @@ oop.inline.hpp arrayKlass.hpp
|
|||||||
oop.inline.hpp arrayOop.hpp
|
oop.inline.hpp arrayOop.hpp
|
||||||
oop.inline.hpp atomic.hpp
|
oop.inline.hpp atomic.hpp
|
||||||
oop.inline.hpp barrierSet.inline.hpp
|
oop.inline.hpp barrierSet.inline.hpp
|
||||||
|
oop.inline.hpp bytes_<arch>.hpp
|
||||||
oop.inline.hpp cardTableModRefBS.hpp
|
oop.inline.hpp cardTableModRefBS.hpp
|
||||||
oop.inline.hpp collectedHeap.inline.hpp
|
oop.inline.hpp collectedHeap.inline.hpp
|
||||||
oop.inline.hpp compactingPermGenGen.hpp
|
oop.inline.hpp compactingPermGenGen.hpp
|
||||||
@ -3674,6 +3698,7 @@ sharedRuntime.cpp interpreterRuntime.hpp
|
|||||||
sharedRuntime.cpp interpreter.hpp
|
sharedRuntime.cpp interpreter.hpp
|
||||||
sharedRuntime.cpp javaCalls.hpp
|
sharedRuntime.cpp javaCalls.hpp
|
||||||
sharedRuntime.cpp jvmtiExport.hpp
|
sharedRuntime.cpp jvmtiExport.hpp
|
||||||
|
sharedRuntime.cpp methodHandles.hpp
|
||||||
sharedRuntime.cpp jvmtiRedefineClassesTrace.hpp
|
sharedRuntime.cpp jvmtiRedefineClassesTrace.hpp
|
||||||
sharedRuntime.cpp nativeInst_<arch>.hpp
|
sharedRuntime.cpp nativeInst_<arch>.hpp
|
||||||
sharedRuntime.cpp nativeLookup.hpp
|
sharedRuntime.cpp nativeLookup.hpp
|
||||||
@ -3862,6 +3887,7 @@ stubGenerator_<arch_model>.cpp frame.inline.hpp
|
|||||||
stubGenerator_<arch_model>.cpp handles.inline.hpp
|
stubGenerator_<arch_model>.cpp handles.inline.hpp
|
||||||
stubGenerator_<arch_model>.cpp instanceOop.hpp
|
stubGenerator_<arch_model>.cpp instanceOop.hpp
|
||||||
stubGenerator_<arch_model>.cpp interpreter.hpp
|
stubGenerator_<arch_model>.cpp interpreter.hpp
|
||||||
|
stubGenerator_<arch_model>.cpp methodHandles.hpp
|
||||||
stubGenerator_<arch_model>.cpp methodOop.hpp
|
stubGenerator_<arch_model>.cpp methodOop.hpp
|
||||||
stubGenerator_<arch_model>.cpp nativeInst_<arch>.hpp
|
stubGenerator_<arch_model>.cpp nativeInst_<arch>.hpp
|
||||||
stubGenerator_<arch_model>.cpp objArrayKlass.hpp
|
stubGenerator_<arch_model>.cpp objArrayKlass.hpp
|
||||||
|
@ -36,6 +36,12 @@ constantPoolKlass.cpp psPromotionManager.inline.hpp
|
|||||||
constantPoolKlass.cpp psScavenge.inline.hpp
|
constantPoolKlass.cpp psScavenge.inline.hpp
|
||||||
constantPoolKlass.cpp parOopClosures.inline.hpp
|
constantPoolKlass.cpp parOopClosures.inline.hpp
|
||||||
|
|
||||||
|
constantPoolKlass.cpp cardTableRS.hpp
|
||||||
|
constantPoolKlass.cpp oop.pcgc.inline.hpp
|
||||||
|
constantPoolKlass.cpp psPromotionManager.inline.hpp
|
||||||
|
constantPoolKlass.cpp psScavenge.inline.hpp
|
||||||
|
constantPoolKlass.cpp parOopClosures.inline.hpp
|
||||||
|
|
||||||
genCollectedHeap.cpp concurrentMarkSweepThread.hpp
|
genCollectedHeap.cpp concurrentMarkSweepThread.hpp
|
||||||
genCollectedHeap.cpp vmCMSOperations.hpp
|
genCollectedHeap.cpp vmCMSOperations.hpp
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. 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
|
||||||
@ -61,6 +61,7 @@ class AbstractInterpreter: AllStatic {
|
|||||||
empty, // empty method (code: _return)
|
empty, // empty method (code: _return)
|
||||||
accessor, // accessor method (code: _aload_0, _getfield, _(a|i)return)
|
accessor, // accessor method (code: _aload_0, _getfield, _(a|i)return)
|
||||||
abstract, // abstract method (throws an AbstractMethodException)
|
abstract, // abstract method (throws an AbstractMethodException)
|
||||||
|
method_handle, // java.dyn.MethodHandles::invoke
|
||||||
java_lang_math_sin, // implementation of java.lang.Math.sin (x)
|
java_lang_math_sin, // implementation of java.lang.Math.sin (x)
|
||||||
java_lang_math_cos, // implementation of java.lang.Math.cos (x)
|
java_lang_math_cos, // implementation of java.lang.Math.cos (x)
|
||||||
java_lang_math_tan, // implementation of java.lang.Math.tan (x)
|
java_lang_math_tan, // implementation of java.lang.Math.tan (x)
|
||||||
@ -91,8 +92,6 @@ class AbstractInterpreter: AllStatic {
|
|||||||
|
|
||||||
static address _rethrow_exception_entry; // rethrows an activation in previous frame
|
static address _rethrow_exception_entry; // rethrows an activation in previous frame
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
friend class AbstractInterpreterGenerator;
|
friend class AbstractInterpreterGenerator;
|
||||||
friend class InterpreterGenerator;
|
friend class InterpreterGenerator;
|
||||||
friend class InterpreterMacroAssembler;
|
friend class InterpreterMacroAssembler;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. 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
|
||||||
@ -114,6 +114,7 @@ void CppInterpreterGenerator::generate_all() {
|
|||||||
method_entry(empty);
|
method_entry(empty);
|
||||||
method_entry(accessor);
|
method_entry(accessor);
|
||||||
method_entry(abstract);
|
method_entry(abstract);
|
||||||
|
method_entry(method_handle);
|
||||||
method_entry(java_lang_math_sin );
|
method_entry(java_lang_math_sin );
|
||||||
method_entry(java_lang_math_cos );
|
method_entry(java_lang_math_cos );
|
||||||
method_entry(java_lang_math_tan );
|
method_entry(java_lang_math_tan );
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. 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
|
||||||
@ -168,10 +168,14 @@ AbstractInterpreter::MethodKind AbstractInterpreter::method_kind(methodHandle m)
|
|||||||
// Abstract method?
|
// Abstract method?
|
||||||
if (m->is_abstract()) return abstract;
|
if (m->is_abstract()) return abstract;
|
||||||
|
|
||||||
|
// Invoker for method handles?
|
||||||
|
if (m->is_method_handle_invoke()) return method_handle;
|
||||||
|
|
||||||
// Native method?
|
// Native method?
|
||||||
// Note: This test must come _before_ the test for intrinsic
|
// Note: This test must come _before_ the test for intrinsic
|
||||||
// methods. See also comments below.
|
// methods. See also comments below.
|
||||||
if (m->is_native()) {
|
if (m->is_native()) {
|
||||||
|
assert(!m->is_method_handle_invoke(), "overlapping bits here, watch out");
|
||||||
return m->is_synchronized() ? native_synchronized : native;
|
return m->is_synchronized() ? native_synchronized : native;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,6 +253,7 @@ void AbstractInterpreter::print_method_kind(MethodKind kind) {
|
|||||||
case empty : tty->print("empty" ); break;
|
case empty : tty->print("empty" ); break;
|
||||||
case accessor : tty->print("accessor" ); break;
|
case accessor : tty->print("accessor" ); break;
|
||||||
case abstract : tty->print("abstract" ); break;
|
case abstract : tty->print("abstract" ); break;
|
||||||
|
case method_handle : tty->print("method_handle" ); break;
|
||||||
case java_lang_math_sin : tty->print("java_lang_math_sin" ); break;
|
case java_lang_math_sin : tty->print("java_lang_math_sin" ); break;
|
||||||
case java_lang_math_cos : tty->print("java_lang_math_cos" ); break;
|
case java_lang_math_cos : tty->print("java_lang_math_cos" ); break;
|
||||||
case java_lang_math_tan : tty->print("java_lang_math_tan" ); break;
|
case java_lang_math_tan : tty->print("java_lang_math_tan" ); break;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. 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
|
||||||
@ -293,6 +293,24 @@ IRT_ENTRY(void, InterpreterRuntime::throw_ClassCastException(
|
|||||||
THROW_MSG(vmSymbols::java_lang_ClassCastException(), message);
|
THROW_MSG(vmSymbols::java_lang_ClassCastException(), message);
|
||||||
IRT_END
|
IRT_END
|
||||||
|
|
||||||
|
// required can be either a MethodType, or a Class (for a single argument)
|
||||||
|
// actual (if not null) can be either a MethodHandle, or an arbitrary value (for a single argument)
|
||||||
|
IRT_ENTRY(void, InterpreterRuntime::throw_WrongMethodTypeException(JavaThread* thread,
|
||||||
|
oopDesc* required,
|
||||||
|
oopDesc* actual)) {
|
||||||
|
ResourceMark rm(thread);
|
||||||
|
char* message = SharedRuntime::generate_wrong_method_type_message(thread, required, actual);
|
||||||
|
|
||||||
|
if (ProfileTraps) {
|
||||||
|
note_trap(thread, Deoptimization::Reason_constraint, CHECK);
|
||||||
|
}
|
||||||
|
|
||||||
|
// create exception
|
||||||
|
THROW_MSG(vmSymbols::java_dyn_WrongMethodTypeException(), message);
|
||||||
|
}
|
||||||
|
IRT_END
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// exception_handler_for_exception(...) returns the continuation address,
|
// exception_handler_for_exception(...) returns the continuation address,
|
||||||
// the exception oop (via TLS) and sets the bci/bcp for the continuation.
|
// the exception oop (via TLS) and sets the bci/bcp for the continuation.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. 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
|
||||||
@ -66,6 +66,7 @@ class InterpreterRuntime: AllStatic {
|
|||||||
static void throw_StackOverflowError(JavaThread* thread);
|
static void throw_StackOverflowError(JavaThread* thread);
|
||||||
static void throw_ArrayIndexOutOfBoundsException(JavaThread* thread, char* name, jint index);
|
static void throw_ArrayIndexOutOfBoundsException(JavaThread* thread, char* name, jint index);
|
||||||
static void throw_ClassCastException(JavaThread* thread, oopDesc* obj);
|
static void throw_ClassCastException(JavaThread* thread, oopDesc* obj);
|
||||||
|
static void throw_WrongMethodTypeException(JavaThread* thread, oopDesc* mtype = NULL, oopDesc* mhandle = NULL);
|
||||||
static void create_exception(JavaThread* thread, char* name, char* message);
|
static void create_exception(JavaThread* thread, char* name, char* message);
|
||||||
static void create_klass_exception(JavaThread* thread, char* name, oopDesc* obj);
|
static void create_klass_exception(JavaThread* thread, char* name, oopDesc* obj);
|
||||||
static address exception_handler_for_exception(JavaThread* thread, oopDesc* exception);
|
static address exception_handler_for_exception(JavaThread* thread, oopDesc* exception);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. 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
|
||||||
@ -151,6 +151,20 @@ void LinkResolver::lookup_method_in_interfaces(methodHandle& result, KlassHandle
|
|||||||
result = methodHandle(THREAD, ik->lookup_method_in_all_interfaces(name(), signature()));
|
result = methodHandle(THREAD, ik->lookup_method_in_all_interfaces(name(), signature()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LinkResolver::lookup_implicit_method(methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS) {
|
||||||
|
if (EnableMethodHandles && MethodHandles::enabled() &&
|
||||||
|
name == vmSymbolHandles::invoke_name() && klass() == SystemDictionary::MethodHandle_klass()) {
|
||||||
|
methodOop result_oop = SystemDictionary::find_method_handle_invoke(signature,
|
||||||
|
Handle(),
|
||||||
|
Handle(),
|
||||||
|
CHECK);
|
||||||
|
if (result_oop != NULL) {
|
||||||
|
assert(result_oop->is_method_handle_invoke() && result_oop->signature() == signature(), "consistent");
|
||||||
|
result = methodHandle(THREAD, result_oop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void LinkResolver::check_method_accessability(KlassHandle ref_klass,
|
void LinkResolver::check_method_accessability(KlassHandle ref_klass,
|
||||||
KlassHandle resolved_klass,
|
KlassHandle resolved_klass,
|
||||||
KlassHandle sel_klass,
|
KlassHandle sel_klass,
|
||||||
@ -239,6 +253,11 @@ void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle res
|
|||||||
// 3. lookup method in all the interfaces implemented by the resolved klass
|
// 3. lookup method in all the interfaces implemented by the resolved klass
|
||||||
lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK);
|
lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK);
|
||||||
|
|
||||||
|
if (resolved_method.is_null()) {
|
||||||
|
// JSR 292: see if this is an implicitly generated method MethodHandle.invoke(*...)
|
||||||
|
lookup_implicit_method(resolved_method, resolved_klass, method_name, method_signature, CHECK);
|
||||||
|
}
|
||||||
|
|
||||||
if (resolved_method.is_null()) {
|
if (resolved_method.is_null()) {
|
||||||
// 4. method lookup failed
|
// 4. method lookup failed
|
||||||
ResourceMark rm(THREAD);
|
ResourceMark rm(THREAD);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. 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
|
||||||
@ -103,6 +103,7 @@ class LinkResolver: AllStatic {
|
|||||||
static void lookup_method_in_klasses (methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS);
|
static void lookup_method_in_klasses (methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS);
|
||||||
static void lookup_instance_method_in_klasses (methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS);
|
static void lookup_instance_method_in_klasses (methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS);
|
||||||
static void lookup_method_in_interfaces (methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS);
|
static void lookup_method_in_interfaces (methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS);
|
||||||
|
static void lookup_implicit_method (methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS);
|
||||||
|
|
||||||
static int vtable_index_of_miranda_method(KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS);
|
static int vtable_index_of_miranda_method(KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS);
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. 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
|
||||||
@ -168,6 +168,7 @@ address TemplateInterpreter::_throw_ArrayIndexOutOfBoundsException_entry = NU
|
|||||||
address TemplateInterpreter::_throw_ArrayStoreException_entry = NULL;
|
address TemplateInterpreter::_throw_ArrayStoreException_entry = NULL;
|
||||||
address TemplateInterpreter::_throw_ArithmeticException_entry = NULL;
|
address TemplateInterpreter::_throw_ArithmeticException_entry = NULL;
|
||||||
address TemplateInterpreter::_throw_ClassCastException_entry = NULL;
|
address TemplateInterpreter::_throw_ClassCastException_entry = NULL;
|
||||||
|
address TemplateInterpreter::_throw_WrongMethodType_entry = NULL;
|
||||||
address TemplateInterpreter::_throw_NullPointerException_entry = NULL;
|
address TemplateInterpreter::_throw_NullPointerException_entry = NULL;
|
||||||
address TemplateInterpreter::_throw_StackOverflowError_entry = NULL;
|
address TemplateInterpreter::_throw_StackOverflowError_entry = NULL;
|
||||||
address TemplateInterpreter::_throw_exception_entry = NULL;
|
address TemplateInterpreter::_throw_exception_entry = NULL;
|
||||||
@ -341,6 +342,7 @@ void TemplateInterpreterGenerator::generate_all() {
|
|||||||
Interpreter::_throw_ArrayStoreException_entry = generate_klass_exception_handler("java/lang/ArrayStoreException" );
|
Interpreter::_throw_ArrayStoreException_entry = generate_klass_exception_handler("java/lang/ArrayStoreException" );
|
||||||
Interpreter::_throw_ArithmeticException_entry = generate_exception_handler("java/lang/ArithmeticException" , "/ by zero");
|
Interpreter::_throw_ArithmeticException_entry = generate_exception_handler("java/lang/ArithmeticException" , "/ by zero");
|
||||||
Interpreter::_throw_ClassCastException_entry = generate_ClassCastException_handler();
|
Interpreter::_throw_ClassCastException_entry = generate_ClassCastException_handler();
|
||||||
|
Interpreter::_throw_WrongMethodType_entry = generate_WrongMethodType_handler();
|
||||||
Interpreter::_throw_NullPointerException_entry = generate_exception_handler("java/lang/NullPointerException" , NULL );
|
Interpreter::_throw_NullPointerException_entry = generate_exception_handler("java/lang/NullPointerException" , NULL );
|
||||||
Interpreter::_throw_StackOverflowError_entry = generate_StackOverflowError_handler();
|
Interpreter::_throw_StackOverflowError_entry = generate_StackOverflowError_handler();
|
||||||
}
|
}
|
||||||
@ -358,6 +360,7 @@ void TemplateInterpreterGenerator::generate_all() {
|
|||||||
method_entry(empty)
|
method_entry(empty)
|
||||||
method_entry(accessor)
|
method_entry(accessor)
|
||||||
method_entry(abstract)
|
method_entry(abstract)
|
||||||
|
method_entry(method_handle)
|
||||||
method_entry(java_lang_math_sin )
|
method_entry(java_lang_math_sin )
|
||||||
method_entry(java_lang_math_cos )
|
method_entry(java_lang_math_cos )
|
||||||
method_entry(java_lang_math_tan )
|
method_entry(java_lang_math_tan )
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. 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
|
||||||
@ -77,6 +77,7 @@ class TemplateInterpreter: public AbstractInterpreter {
|
|||||||
friend class VMStructs;
|
friend class VMStructs;
|
||||||
friend class InterpreterMacroAssembler;
|
friend class InterpreterMacroAssembler;
|
||||||
friend class TemplateInterpreterGenerator;
|
friend class TemplateInterpreterGenerator;
|
||||||
|
friend class InterpreterGenerator;
|
||||||
friend class TemplateTable;
|
friend class TemplateTable;
|
||||||
// friend class Interpreter;
|
// friend class Interpreter;
|
||||||
public:
|
public:
|
||||||
@ -93,6 +94,7 @@ class TemplateInterpreter: public AbstractInterpreter {
|
|||||||
static address _throw_ArrayStoreException_entry;
|
static address _throw_ArrayStoreException_entry;
|
||||||
static address _throw_ArithmeticException_entry;
|
static address _throw_ArithmeticException_entry;
|
||||||
static address _throw_ClassCastException_entry;
|
static address _throw_ClassCastException_entry;
|
||||||
|
static address _throw_WrongMethodType_entry;
|
||||||
static address _throw_NullPointerException_entry;
|
static address _throw_NullPointerException_entry;
|
||||||
static address _throw_exception_entry;
|
static address _throw_exception_entry;
|
||||||
|
|
||||||
@ -137,6 +139,7 @@ class TemplateInterpreter: public AbstractInterpreter {
|
|||||||
static address remove_activation_entry() { return _remove_activation_entry; }
|
static address remove_activation_entry() { return _remove_activation_entry; }
|
||||||
static address throw_exception_entry() { return _throw_exception_entry; }
|
static address throw_exception_entry() { return _throw_exception_entry; }
|
||||||
static address throw_ArithmeticException_entry() { return _throw_ArithmeticException_entry; }
|
static address throw_ArithmeticException_entry() { return _throw_ArithmeticException_entry; }
|
||||||
|
static address throw_WrongMethodType_entry() { return _throw_WrongMethodType_entry; }
|
||||||
static address throw_NullPointerException_entry() { return _throw_NullPointerException_entry; }
|
static address throw_NullPointerException_entry() { return _throw_NullPointerException_entry; }
|
||||||
static address throw_StackOverflowError_entry() { return _throw_StackOverflowError_entry; }
|
static address throw_StackOverflowError_entry() { return _throw_StackOverflowError_entry; }
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. 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
|
||||||
@ -48,6 +48,7 @@ class TemplateInterpreterGenerator: public AbstractInterpreterGenerator {
|
|||||||
}
|
}
|
||||||
address generate_exception_handler_common(const char* name, const char* message, bool pass_oop);
|
address generate_exception_handler_common(const char* name, const char* message, bool pass_oop);
|
||||||
address generate_ClassCastException_handler();
|
address generate_ClassCastException_handler();
|
||||||
|
address generate_WrongMethodType_handler();
|
||||||
address generate_ArrayIndexOutOfBounds_handler(const char* name);
|
address generate_ArrayIndexOutOfBounds_handler(const char* name);
|
||||||
address generate_continuation_for(TosState state);
|
address generate_continuation_for(TosState state);
|
||||||
address generate_return_entry_for(TosState state, int step);
|
address generate_return_entry_for(TosState state, int step);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2003-2009 Sun Microsystems, Inc. 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
|
||||||
@ -928,6 +928,9 @@ public:
|
|||||||
// shared classes at runtime, where constraints were previously created.
|
// shared classes at runtime, where constraints were previously created.
|
||||||
guarantee(SystemDictionary::constraints()->number_of_entries() == 0,
|
guarantee(SystemDictionary::constraints()->number_of_entries() == 0,
|
||||||
"loader constraints are not saved");
|
"loader constraints are not saved");
|
||||||
|
// Revisit and implement this if we prelink method handle call sites:
|
||||||
|
guarantee(SystemDictionary::invoke_method_table()->number_of_entries() == 0,
|
||||||
|
"invoke method table is not saved");
|
||||||
GenCollectedHeap* gch = GenCollectedHeap::heap();
|
GenCollectedHeap* gch = GenCollectedHeap::heap();
|
||||||
|
|
||||||
// At this point, many classes have been loaded.
|
// At this point, many classes have been loaded.
|
||||||
|
@ -298,7 +298,11 @@ void methodKlass::oop_print_on(oop obj, outputStream* st) {
|
|||||||
m->code()->print_value_on(st);
|
m->code()->print_value_on(st);
|
||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
if (m->is_native()) {
|
if (m->is_method_handle_invoke()) {
|
||||||
|
st->print_cr(" - invoke method type: " INTPTR_FORMAT, (address) m->method_handle_type());
|
||||||
|
// m is classified as native, but it does not have an interesting
|
||||||
|
// native_function or signature handler
|
||||||
|
} else if (m->is_native()) {
|
||||||
st->print_cr(" - native function: " INTPTR_FORMAT, m->native_function());
|
st->print_cr(" - native function: " INTPTR_FORMAT, m->native_function());
|
||||||
st->print_cr(" - signature handler: " INTPTR_FORMAT, m->signature_handler());
|
st->print_cr(" - signature handler: " INTPTR_FORMAT, m->signature_handler());
|
||||||
}
|
}
|
||||||
|
@ -304,6 +304,12 @@ void methodOopDesc::cleanup_inline_caches() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int methodOopDesc::extra_stack_words() {
|
||||||
|
// not an inline function, to avoid a header dependency on Interpreter
|
||||||
|
return extra_stack_entries() * Interpreter::stackElementSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void methodOopDesc::compute_size_of_parameters(Thread *thread) {
|
void methodOopDesc::compute_size_of_parameters(Thread *thread) {
|
||||||
symbolHandle h_signature(thread, signature());
|
symbolHandle h_signature(thread, signature());
|
||||||
ArgumentSizeComputer asc(h_signature);
|
ArgumentSizeComputer asc(h_signature);
|
||||||
@ -564,6 +570,11 @@ void methodOopDesc::set_signature_handler(address handler) {
|
|||||||
|
|
||||||
|
|
||||||
bool methodOopDesc::is_not_compilable(int comp_level) const {
|
bool methodOopDesc::is_not_compilable(int comp_level) const {
|
||||||
|
if (is_method_handle_invoke()) {
|
||||||
|
// compilers must recognize this method specially, or not at all
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
methodDataOop mdo = method_data();
|
methodDataOop mdo = method_data();
|
||||||
if (mdo != NULL
|
if (mdo != NULL
|
||||||
&& (uint)mdo->decompile_count() > (uint)PerMethodRecompilationCutoff) {
|
&& (uint)mdo->decompile_count() > (uint)PerMethodRecompilationCutoff) {
|
||||||
@ -651,7 +662,7 @@ void methodOopDesc::link_method(methodHandle h_method, TRAPS) {
|
|||||||
assert(entry != NULL, "interpreter entry must be non-null");
|
assert(entry != NULL, "interpreter entry must be non-null");
|
||||||
// Sets both _i2i_entry and _from_interpreted_entry
|
// Sets both _i2i_entry and _from_interpreted_entry
|
||||||
set_interpreter_entry(entry);
|
set_interpreter_entry(entry);
|
||||||
if (is_native()) {
|
if (is_native() && !is_method_handle_invoke()) {
|
||||||
set_native_function(
|
set_native_function(
|
||||||
SharedRuntime::native_method_throw_unsatisfied_link_error_entry(),
|
SharedRuntime::native_method_throw_unsatisfied_link_error_entry(),
|
||||||
!native_bind_event_is_interesting);
|
!native_bind_event_is_interesting);
|
||||||
@ -783,6 +794,100 @@ bool methodOopDesc::should_not_be_cached() const {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Constant pool structure for invoke methods:
|
||||||
|
enum {
|
||||||
|
_imcp_invoke_name = 1, // utf8: 'invoke'
|
||||||
|
_imcp_invoke_signature, // utf8: (variable symbolOop)
|
||||||
|
_imcp_method_type_value, // string: (variable java/dyn/MethodType, sic)
|
||||||
|
_imcp_limit
|
||||||
|
};
|
||||||
|
|
||||||
|
oop methodOopDesc::method_handle_type() const {
|
||||||
|
if (!is_method_handle_invoke()) { assert(false, "caller resp."); return NULL; }
|
||||||
|
oop mt = constants()->resolved_string_at(_imcp_method_type_value);
|
||||||
|
assert(mt->klass() == SystemDictionary::MethodType_klass(), "");
|
||||||
|
return mt;
|
||||||
|
}
|
||||||
|
|
||||||
|
jint* methodOopDesc::method_type_offsets_chain() {
|
||||||
|
static jint pchase[] = { -1, -1, -1 };
|
||||||
|
if (pchase[0] == -1) {
|
||||||
|
jint step0 = in_bytes(constants_offset());
|
||||||
|
jint step1 = (constantPoolOopDesc::header_size() + _imcp_method_type_value) * HeapWordSize;
|
||||||
|
// do this in reverse to avoid races:
|
||||||
|
OrderAccess::release_store(&pchase[1], step1);
|
||||||
|
OrderAccess::release_store(&pchase[0], step0);
|
||||||
|
}
|
||||||
|
return pchase;
|
||||||
|
}
|
||||||
|
|
||||||
|
methodHandle methodOopDesc::make_invoke_method(KlassHandle holder,
|
||||||
|
symbolHandle signature,
|
||||||
|
Handle method_type, TRAPS) {
|
||||||
|
methodHandle empty;
|
||||||
|
|
||||||
|
assert(holder() == SystemDictionary::MethodHandle_klass(),
|
||||||
|
"must be a JSR 292 magic type");
|
||||||
|
|
||||||
|
if (TraceMethodHandles) {
|
||||||
|
tty->print("Creating invoke method for ");
|
||||||
|
signature->print_value();
|
||||||
|
tty->cr();
|
||||||
|
}
|
||||||
|
|
||||||
|
constantPoolHandle cp;
|
||||||
|
{
|
||||||
|
constantPoolOop cp_oop = oopFactory::new_constantPool(_imcp_limit, IsSafeConc, CHECK_(empty));
|
||||||
|
cp = constantPoolHandle(THREAD, cp_oop);
|
||||||
|
}
|
||||||
|
cp->symbol_at_put(_imcp_invoke_name, vmSymbols::invoke_name());
|
||||||
|
cp->symbol_at_put(_imcp_invoke_signature, signature());
|
||||||
|
cp->string_at_put(_imcp_method_type_value, vmSymbols::void_signature());
|
||||||
|
cp->set_pool_holder(holder());
|
||||||
|
|
||||||
|
// set up the fancy stuff:
|
||||||
|
cp->pseudo_string_at_put(_imcp_method_type_value, method_type());
|
||||||
|
methodHandle m;
|
||||||
|
{
|
||||||
|
int flags_bits = (JVM_MH_INVOKE_BITS | JVM_ACC_PUBLIC | JVM_ACC_FINAL);
|
||||||
|
methodOop m_oop = oopFactory::new_method(0, accessFlags_from(flags_bits),
|
||||||
|
0, 0, 0, IsSafeConc, CHECK_(empty));
|
||||||
|
m = methodHandle(THREAD, m_oop);
|
||||||
|
}
|
||||||
|
m->set_constants(cp());
|
||||||
|
m->set_name_index(_imcp_invoke_name);
|
||||||
|
m->set_signature_index(_imcp_invoke_signature);
|
||||||
|
assert(m->name() == vmSymbols::invoke_name(), "");
|
||||||
|
assert(m->signature() == signature(), "");
|
||||||
|
#ifdef CC_INTERP
|
||||||
|
ResultTypeFinder rtf(signature());
|
||||||
|
m->set_result_index(rtf.type());
|
||||||
|
#endif
|
||||||
|
m->compute_size_of_parameters(THREAD);
|
||||||
|
m->set_exception_table(Universe::the_empty_int_array());
|
||||||
|
|
||||||
|
// Finally, set up its entry points.
|
||||||
|
assert(m->method_handle_type() == method_type(), "");
|
||||||
|
assert(m->can_be_statically_bound(), "");
|
||||||
|
m->set_vtable_index(methodOopDesc::nonvirtual_vtable_index);
|
||||||
|
m->link_method(m, CHECK_(empty));
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
// Make sure the pointer chase works.
|
||||||
|
address p = (address) m();
|
||||||
|
for (jint* pchase = method_type_offsets_chain(); (*pchase) != -1; pchase++) {
|
||||||
|
p = *(address*)(p + (*pchase));
|
||||||
|
}
|
||||||
|
assert((oop)p == method_type(), "pointer chase is correct");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (TraceMethodHandles)
|
||||||
|
m->print_on(tty);
|
||||||
|
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
methodHandle methodOopDesc:: clone_with_new_data(methodHandle m, u_char* new_code, int new_code_length,
|
methodHandle methodOopDesc:: clone_with_new_data(methodHandle m, u_char* new_code, int new_code_length,
|
||||||
u_char* new_compressed_linenumber_table, int new_compressed_linenumber_size, TRAPS) {
|
u_char* new_compressed_linenumber_table, int new_compressed_linenumber_size, TRAPS) {
|
||||||
|
@ -320,6 +320,7 @@ class methodOopDesc : public oopDesc {
|
|||||||
enum VtableIndexFlag {
|
enum VtableIndexFlag {
|
||||||
// Valid vtable indexes are non-negative (>= 0).
|
// Valid vtable indexes are non-negative (>= 0).
|
||||||
// These few negative values are used as sentinels.
|
// These few negative values are used as sentinels.
|
||||||
|
highest_unused_vtable_index_value = -5,
|
||||||
invalid_vtable_index = -4, // distinct from any valid vtable index
|
invalid_vtable_index = -4, // distinct from any valid vtable index
|
||||||
garbage_vtable_index = -3, // not yet linked; no vtable layout yet
|
garbage_vtable_index = -3, // not yet linked; no vtable layout yet
|
||||||
nonvirtual_vtable_index = -2 // there is no need for vtable dispatch
|
nonvirtual_vtable_index = -2 // there is no need for vtable dispatch
|
||||||
@ -523,6 +524,18 @@ class methodOopDesc : public oopDesc {
|
|||||||
// Reflection support
|
// Reflection support
|
||||||
bool is_overridden_in(klassOop k) const;
|
bool is_overridden_in(klassOop k) const;
|
||||||
|
|
||||||
|
// JSR 292 support
|
||||||
|
bool is_method_handle_invoke() const { return access_flags().is_method_handle_invoke(); }
|
||||||
|
static methodHandle make_invoke_method(KlassHandle holder,
|
||||||
|
symbolHandle signature,
|
||||||
|
Handle method_type,
|
||||||
|
TRAPS);
|
||||||
|
// these operate only on invoke methods:
|
||||||
|
oop method_handle_type() const;
|
||||||
|
static jint* method_type_offsets_chain(); // series of pointer-offsets, terminated by -1
|
||||||
|
// presize interpreter frames for extra interpreter stack entries, if needed
|
||||||
|
static int extra_stack_entries() { return EnableMethodHandles ? (int)MethodHandlePushLimit : 0; }
|
||||||
|
static int extra_stack_words(); // = extra_stack_entries() * Interpreter::stackElementSize()
|
||||||
// RedefineClasses() support:
|
// RedefineClasses() support:
|
||||||
bool is_old() const { return access_flags().is_old(); }
|
bool is_old() const { return access_flags().is_old(); }
|
||||||
void set_is_old() { _access_flags.set_is_old(); }
|
void set_is_old() { _access_flags.set_is_old(); }
|
||||||
|
@ -263,6 +263,9 @@ class oopDesc {
|
|||||||
jdouble double_field_acquire(int offset) const;
|
jdouble double_field_acquire(int offset) const;
|
||||||
void release_double_field_put(int offset, jdouble contents);
|
void release_double_field_put(int offset, jdouble contents);
|
||||||
|
|
||||||
|
address address_field_acquire(int offset) const;
|
||||||
|
void release_address_field_put(int offset, address contents);
|
||||||
|
|
||||||
// printing functions for VM debugging
|
// printing functions for VM debugging
|
||||||
void print_on(outputStream* st) const; // First level print
|
void print_on(outputStream* st) const; // First level print
|
||||||
void print_value_on(outputStream* st) const; // Second level print.
|
void print_value_on(outputStream* st) const; // Second level print.
|
||||||
|
@ -349,6 +349,9 @@ inline void oopDesc::release_float_field_put(int offset, jfloat contents) { Or
|
|||||||
inline jdouble oopDesc::double_field_acquire(int offset) const { return OrderAccess::load_acquire(double_field_addr(offset)); }
|
inline jdouble oopDesc::double_field_acquire(int offset) const { return OrderAccess::load_acquire(double_field_addr(offset)); }
|
||||||
inline void oopDesc::release_double_field_put(int offset, jdouble contents) { OrderAccess::release_store(double_field_addr(offset), contents); }
|
inline void oopDesc::release_double_field_put(int offset, jdouble contents) { OrderAccess::release_store(double_field_addr(offset), contents); }
|
||||||
|
|
||||||
|
inline address oopDesc::address_field_acquire(int offset) const { return (address) OrderAccess::load_ptr_acquire(address_field_addr(offset)); }
|
||||||
|
inline void oopDesc::release_address_field_put(int offset, address contents) { OrderAccess::release_store_ptr(address_field_addr(offset), contents); }
|
||||||
|
|
||||||
inline int oopDesc::size_given_klass(Klass* klass) {
|
inline int oopDesc::size_given_klass(Klass* klass) {
|
||||||
int lh = klass->layout_helper();
|
int lh = klass->layout_helper();
|
||||||
int s = lh >> LogHeapWordSize; // deliver size scaled by wordSize
|
int s = lh >> LogHeapWordSize; // deliver size scaled by wordSize
|
||||||
|
2347
hotspot/src/share/vm/prims/methodHandles.cpp
Normal file
2347
hotspot/src/share/vm/prims/methodHandles.cpp
Normal file
File diff suppressed because it is too large
Load Diff
435
hotspot/src/share/vm/prims/methodHandles.hpp
Normal file
435
hotspot/src/share/vm/prims/methodHandles.hpp
Normal file
@ -0,0 +1,435 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008-2009 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
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||||
|
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||||
|
* have any questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
class MacroAssembler;
|
||||||
|
class Label;
|
||||||
|
class MethodHandleEntry;
|
||||||
|
|
||||||
|
class MethodHandles: AllStatic {
|
||||||
|
// JVM support for MethodHandle, MethodType, and related types
|
||||||
|
// in java.dyn and java.dyn.hotspot.
|
||||||
|
// See also javaClasses for layouts java_dyn_Method{Handle,Type,Type::Form}.
|
||||||
|
public:
|
||||||
|
enum EntryKind {
|
||||||
|
_check_mtype, // how a caller calls a MH
|
||||||
|
_wrong_method_type, // what happens when there is a type mismatch
|
||||||
|
_invokestatic_mh, // how a MH emulates invokestatic
|
||||||
|
_invokespecial_mh, // ditto for the other invokes...
|
||||||
|
_invokevirtual_mh,
|
||||||
|
_invokeinterface_mh,
|
||||||
|
_bound_ref_mh, // reference argument is bound
|
||||||
|
_bound_int_mh, // int argument is bound (via an Integer or Float)
|
||||||
|
_bound_long_mh, // long argument is bound (via a Long or Double)
|
||||||
|
_bound_ref_direct_mh, // same as above, with direct linkage to methodOop
|
||||||
|
_bound_int_direct_mh,
|
||||||
|
_bound_long_direct_mh,
|
||||||
|
|
||||||
|
_adapter_mh_first, // adapter sequence goes here...
|
||||||
|
_adapter_retype_only = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_RETYPE_ONLY,
|
||||||
|
_adapter_check_cast = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_CHECK_CAST,
|
||||||
|
_adapter_prim_to_prim = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_PRIM_TO_PRIM,
|
||||||
|
_adapter_ref_to_prim = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_REF_TO_PRIM,
|
||||||
|
_adapter_prim_to_ref = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_PRIM_TO_REF,
|
||||||
|
_adapter_swap_args = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_SWAP_ARGS,
|
||||||
|
_adapter_rot_args = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_ROT_ARGS,
|
||||||
|
_adapter_dup_args = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_DUP_ARGS,
|
||||||
|
_adapter_drop_args = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_DROP_ARGS,
|
||||||
|
_adapter_collect_args = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_COLLECT_ARGS,
|
||||||
|
_adapter_spread_args = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_SPREAD_ARGS,
|
||||||
|
_adapter_flyby = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_FLYBY,
|
||||||
|
_adapter_ricochet = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_RICOCHET,
|
||||||
|
_adapter_mh_last = _adapter_mh_first + sun_dyn_AdapterMethodHandle::CONV_OP_LIMIT - 1,
|
||||||
|
|
||||||
|
// Optimized adapter types
|
||||||
|
|
||||||
|
// argument list reordering
|
||||||
|
_adapter_opt_swap_1,
|
||||||
|
_adapter_opt_swap_2,
|
||||||
|
_adapter_opt_rot_1_up,
|
||||||
|
_adapter_opt_rot_1_down,
|
||||||
|
_adapter_opt_rot_2_up,
|
||||||
|
_adapter_opt_rot_2_down,
|
||||||
|
// primitive single to single:
|
||||||
|
_adapter_opt_i2i, // i2c, i2z, i2b, i2s
|
||||||
|
// primitive double to single:
|
||||||
|
_adapter_opt_l2i,
|
||||||
|
_adapter_opt_d2f,
|
||||||
|
// primitive single to double:
|
||||||
|
_adapter_opt_i2l,
|
||||||
|
_adapter_opt_f2d,
|
||||||
|
// conversion between floating point and integer type is handled by Java
|
||||||
|
|
||||||
|
// reference to primitive:
|
||||||
|
_adapter_opt_unboxi,
|
||||||
|
_adapter_opt_unboxl,
|
||||||
|
|
||||||
|
// spreading (array length cases 0, 1, >=2)
|
||||||
|
_adapter_opt_spread_0,
|
||||||
|
_adapter_opt_spread_1,
|
||||||
|
_adapter_opt_spread_more,
|
||||||
|
|
||||||
|
_EK_LIMIT,
|
||||||
|
_EK_FIRST = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
static bool enabled() { return _enabled; }
|
||||||
|
static void set_enabled(bool z);
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum { // import sun_dyn_AdapterMethodHandle::CONV_OP_*
|
||||||
|
CONV_OP_LIMIT = sun_dyn_AdapterMethodHandle::CONV_OP_LIMIT,
|
||||||
|
CONV_OP_MASK = sun_dyn_AdapterMethodHandle::CONV_OP_MASK,
|
||||||
|
CONV_VMINFO_MASK = sun_dyn_AdapterMethodHandle::CONV_VMINFO_MASK,
|
||||||
|
CONV_VMINFO_SHIFT = sun_dyn_AdapterMethodHandle::CONV_VMINFO_SHIFT,
|
||||||
|
CONV_OP_SHIFT = sun_dyn_AdapterMethodHandle::CONV_OP_SHIFT,
|
||||||
|
CONV_DEST_TYPE_SHIFT = sun_dyn_AdapterMethodHandle::CONV_DEST_TYPE_SHIFT,
|
||||||
|
CONV_SRC_TYPE_SHIFT = sun_dyn_AdapterMethodHandle::CONV_SRC_TYPE_SHIFT,
|
||||||
|
CONV_STACK_MOVE_SHIFT = sun_dyn_AdapterMethodHandle::CONV_STACK_MOVE_SHIFT,
|
||||||
|
CONV_STACK_MOVE_MASK = sun_dyn_AdapterMethodHandle::CONV_STACK_MOVE_MASK
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool _enabled;
|
||||||
|
static MethodHandleEntry* _entries[_EK_LIMIT];
|
||||||
|
static const char* _entry_names[_EK_LIMIT+1];
|
||||||
|
static bool ek_valid(EntryKind ek) { return (uint)ek < (uint)_EK_LIMIT; }
|
||||||
|
static bool conv_op_valid(int op) { return (uint)op < (uint)CONV_OP_LIMIT; }
|
||||||
|
|
||||||
|
public:
|
||||||
|
static bool have_entry(EntryKind ek) { return ek_valid(ek) && _entries[ek] != NULL; }
|
||||||
|
static MethodHandleEntry* entry(EntryKind ek) { assert(ek_valid(ek), "initialized");
|
||||||
|
return _entries[ek]; }
|
||||||
|
static const char* entry_name(EntryKind ek) { assert(ek_valid(ek), "oob");
|
||||||
|
return _entry_names[ek]; }
|
||||||
|
static EntryKind adapter_entry_kind(int op) { assert(conv_op_valid(op), "oob");
|
||||||
|
return EntryKind(_adapter_mh_first + op); }
|
||||||
|
|
||||||
|
static void init_entry(EntryKind ek, MethodHandleEntry* me) {
|
||||||
|
assert(ek_valid(ek), "oob");
|
||||||
|
assert(_entries[ek] == NULL, "no double initialization");
|
||||||
|
_entries[ek] = me;
|
||||||
|
}
|
||||||
|
|
||||||
|
static jint adapter_conversion(int conv_op, BasicType src, BasicType dest,
|
||||||
|
int stack_move = 0, int vminfo = 0) {
|
||||||
|
assert(conv_op_valid(conv_op), "oob");
|
||||||
|
jint conv = ((conv_op << CONV_OP_SHIFT)
|
||||||
|
| (src << CONV_SRC_TYPE_SHIFT)
|
||||||
|
| (dest << CONV_DEST_TYPE_SHIFT)
|
||||||
|
| (stack_move << CONV_STACK_MOVE_SHIFT)
|
||||||
|
| (vminfo << CONV_VMINFO_SHIFT)
|
||||||
|
);
|
||||||
|
assert(adapter_conversion_op(conv) == conv_op, "decode conv_op");
|
||||||
|
assert(adapter_conversion_src_type(conv) == src, "decode src");
|
||||||
|
assert(adapter_conversion_dest_type(conv) == dest, "decode dest");
|
||||||
|
assert(adapter_conversion_stack_move(conv) == stack_move, "decode stack_move");
|
||||||
|
assert(adapter_conversion_vminfo(conv) == vminfo, "decode vminfo");
|
||||||
|
return conv;
|
||||||
|
}
|
||||||
|
static int adapter_conversion_op(jint conv) {
|
||||||
|
return ((conv >> CONV_OP_SHIFT) & 0xF);
|
||||||
|
}
|
||||||
|
static BasicType adapter_conversion_src_type(jint conv) {
|
||||||
|
return (BasicType)((conv >> CONV_SRC_TYPE_SHIFT) & 0xF);
|
||||||
|
}
|
||||||
|
static BasicType adapter_conversion_dest_type(jint conv) {
|
||||||
|
return (BasicType)((conv >> CONV_DEST_TYPE_SHIFT) & 0xF);
|
||||||
|
}
|
||||||
|
static int adapter_conversion_stack_move(jint conv) {
|
||||||
|
return (conv >> CONV_STACK_MOVE_SHIFT);
|
||||||
|
}
|
||||||
|
static int adapter_conversion_vminfo(jint conv) {
|
||||||
|
return (conv >> CONV_VMINFO_SHIFT) & CONV_VMINFO_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Offset in words that the interpreter stack pointer moves when an argument is pushed.
|
||||||
|
// The stack_move value must always be a multiple of this.
|
||||||
|
static int stack_move_unit() {
|
||||||
|
return frame::interpreter_frame_expression_stack_direction() * Interpreter::stackElementWords();
|
||||||
|
}
|
||||||
|
|
||||||
|
enum { CONV_VMINFO_SIGN_FLAG = 0x80 };
|
||||||
|
static int adapter_subword_vminfo(BasicType dest) {
|
||||||
|
if (dest == T_BOOLEAN) return (BitsPerInt - 1);
|
||||||
|
if (dest == T_CHAR) return (BitsPerInt - 16);
|
||||||
|
if (dest == T_BYTE) return (BitsPerInt - 8) | CONV_VMINFO_SIGN_FLAG;
|
||||||
|
if (dest == T_SHORT) return (BitsPerInt - 16) | CONV_VMINFO_SIGN_FLAG;
|
||||||
|
return 0; // case T_INT
|
||||||
|
}
|
||||||
|
// Here is the transformation the i2i adapter must perform:
|
||||||
|
static int truncate_subword_from_vminfo(jint value, int vminfo) {
|
||||||
|
jint tem = value << vminfo;
|
||||||
|
if ((vminfo & CONV_VMINFO_SIGN_FLAG) != 0) {
|
||||||
|
return (jint)tem >> vminfo;
|
||||||
|
} else {
|
||||||
|
return (juint)tem >> vminfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline address from_compiled_entry(EntryKind ek);
|
||||||
|
static inline address from_interpreted_entry(EntryKind ek);
|
||||||
|
|
||||||
|
// helpers for decode_method.
|
||||||
|
static methodOop decode_methodOop(methodOop m, int& decode_flags_result);
|
||||||
|
static methodOop decode_vmtarget(oop vmtarget, int vmindex, oop mtype, klassOop& receiver_limit_result, int& decode_flags_result);
|
||||||
|
static methodOop decode_MemberName(oop mname, klassOop& receiver_limit_result, int& decode_flags_result);
|
||||||
|
static methodOop decode_MethodHandle(oop mh, klassOop& receiver_limit_result, int& decode_flags_result);
|
||||||
|
static methodOop decode_DirectMethodHandle(oop mh, klassOop& receiver_limit_result, int& decode_flags_result);
|
||||||
|
static methodOop decode_BoundMethodHandle(oop mh, klassOop& receiver_limit_result, int& decode_flags_result);
|
||||||
|
static methodOop decode_AdapterMethodHandle(oop mh, klassOop& receiver_limit_result, int& decode_flags_result);
|
||||||
|
|
||||||
|
// Find out how many stack slots an mh pushes or pops.
|
||||||
|
// The result is *not* reported as a multiple of stack_move_unit();
|
||||||
|
// It is a signed net number of pushes (a difference in vmslots).
|
||||||
|
// To compare with a stack_move value, first multiply by stack_move_unit().
|
||||||
|
static int decode_MethodHandle_stack_pushes(oop mh);
|
||||||
|
|
||||||
|
public:
|
||||||
|
// working with member names
|
||||||
|
static void resolve_MemberName(Handle mname, TRAPS); // compute vmtarget/vmindex from name/type
|
||||||
|
static void expand_MemberName(Handle mname, int suppress, TRAPS); // expand defc/name/type if missing
|
||||||
|
static void init_MemberName(oop mname_oop, oop target); // compute vmtarget/vmindex from target
|
||||||
|
static void init_MemberName(oop mname_oop, methodOop m, bool do_dispatch);
|
||||||
|
static void init_MemberName(oop mname_oop, klassOop field_holder, AccessFlags mods, int offset);
|
||||||
|
static int find_MemberNames(klassOop k, symbolOop name, symbolOop sig,
|
||||||
|
int mflags, klassOop caller,
|
||||||
|
int skip, objArrayOop results);
|
||||||
|
// bit values for suppress argument to expand_MemberName:
|
||||||
|
enum { _suppress_defc = 1, _suppress_name = 2, _suppress_type = 4 };
|
||||||
|
|
||||||
|
// called from InterpreterGenerator and StubGenerator
|
||||||
|
static address generate_method_handle_interpreter_entry(MacroAssembler* _masm);
|
||||||
|
static void generate_method_handle_stub(MacroAssembler* _masm, EntryKind ek);
|
||||||
|
|
||||||
|
// argument list parsing
|
||||||
|
static int argument_slot(oop method_type, int arg);
|
||||||
|
static int argument_slot_count(oop method_type) { return argument_slot(method_type, -1); }
|
||||||
|
static int argument_slot_to_argnum(oop method_type, int argslot);
|
||||||
|
|
||||||
|
// Runtime support
|
||||||
|
enum { // bit-encoded flags from decode_method or decode_vmref
|
||||||
|
_dmf_has_receiver = 0x01, // target method has leading reference argument
|
||||||
|
_dmf_does_dispatch = 0x02, // method handle performs virtual or interface dispatch
|
||||||
|
_dmf_from_interface = 0x04, // peforms interface dispatch
|
||||||
|
_DMF_DIRECT_MASK = (_dmf_from_interface*2 - _dmf_has_receiver),
|
||||||
|
_dmf_binds_method = 0x08,
|
||||||
|
_dmf_binds_argument = 0x10,
|
||||||
|
_DMF_BOUND_MASK = (_dmf_binds_argument*2 - _dmf_binds_method),
|
||||||
|
_dmf_adapter_lsb = 0x20,
|
||||||
|
_DMF_ADAPTER_MASK = (_dmf_adapter_lsb << CONV_OP_LIMIT) - _dmf_adapter_lsb
|
||||||
|
};
|
||||||
|
static methodOop decode_method(oop x, klassOop& receiver_limit_result, int& decode_flags_result);
|
||||||
|
enum {
|
||||||
|
// format of query to getConstant:
|
||||||
|
GC_JVM_PUSH_LIMIT = 0,
|
||||||
|
GC_JVM_STACK_MOVE_LIMIT = 1,
|
||||||
|
|
||||||
|
// format of result from getTarget / encode_target:
|
||||||
|
ETF_HANDLE_OR_METHOD_NAME = 0, // all available data (immediate MH or method)
|
||||||
|
ETF_DIRECT_HANDLE = 1, // ultimate method handle (will be a DMH, may be self)
|
||||||
|
ETF_METHOD_NAME = 2, // ultimate method as MemberName
|
||||||
|
ETF_REFLECT_METHOD = 3 // ultimate method as java.lang.reflect object (sans refClass)
|
||||||
|
};
|
||||||
|
static int get_named_constant(int which, Handle name_box, TRAPS);
|
||||||
|
static oop encode_target(Handle mh, int format, TRAPS); // report vmtarget (to Java code)
|
||||||
|
static bool class_cast_needed(klassOop src, klassOop dst);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// These checkers operate on a pair of whole MethodTypes:
|
||||||
|
static const char* check_method_type_change(oop src_mtype, int src_beg, int src_end,
|
||||||
|
int insert_argnum, oop insert_type,
|
||||||
|
int change_argnum, oop change_type,
|
||||||
|
int delete_argnum,
|
||||||
|
oop dst_mtype, int dst_beg, int dst_end);
|
||||||
|
static const char* check_method_type_insertion(oop src_mtype,
|
||||||
|
int insert_argnum, oop insert_type,
|
||||||
|
oop dst_mtype) {
|
||||||
|
oop no_ref = NULL;
|
||||||
|
return check_method_type_change(src_mtype, 0, -1,
|
||||||
|
insert_argnum, insert_type,
|
||||||
|
-1, no_ref, -1, dst_mtype, 0, -1);
|
||||||
|
}
|
||||||
|
static const char* check_method_type_conversion(oop src_mtype,
|
||||||
|
int change_argnum, oop change_type,
|
||||||
|
oop dst_mtype) {
|
||||||
|
oop no_ref = NULL;
|
||||||
|
return check_method_type_change(src_mtype, 0, -1, -1, no_ref,
|
||||||
|
change_argnum, change_type,
|
||||||
|
-1, dst_mtype, 0, -1);
|
||||||
|
}
|
||||||
|
static const char* check_method_type_passthrough(oop src_mtype, oop dst_mtype) {
|
||||||
|
oop no_ref = NULL;
|
||||||
|
return check_method_type_change(src_mtype, 0, -1,
|
||||||
|
-1, no_ref, -1, no_ref, -1,
|
||||||
|
dst_mtype, 0, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// These checkers operate on pairs of argument or return types:
|
||||||
|
static const char* check_argument_type_change(BasicType src_type, klassOop src_klass,
|
||||||
|
BasicType dst_type, klassOop dst_klass,
|
||||||
|
int argnum);
|
||||||
|
|
||||||
|
static const char* check_argument_type_change(oop src_type, oop dst_type,
|
||||||
|
int argnum) {
|
||||||
|
klassOop src_klass = NULL, dst_klass = NULL;
|
||||||
|
BasicType src_bt = java_lang_Class::as_BasicType(src_type, &src_klass);
|
||||||
|
BasicType dst_bt = java_lang_Class::as_BasicType(dst_type, &dst_klass);
|
||||||
|
return check_argument_type_change(src_bt, src_klass,
|
||||||
|
dst_bt, dst_klass, argnum);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* check_return_type_change(oop src_type, oop dst_type) {
|
||||||
|
return check_argument_type_change(src_type, dst_type, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* check_return_type_change(BasicType src_type, klassOop src_klass,
|
||||||
|
BasicType dst_type, klassOop dst_klass) {
|
||||||
|
return check_argument_type_change(src_type, src_klass, dst_type, dst_klass, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* check_method_receiver(methodOop m, klassOop passed_recv_type);
|
||||||
|
|
||||||
|
// These verifiers can block, and will throw an error if the checking fails:
|
||||||
|
static void verify_vmslots(Handle mh, TRAPS);
|
||||||
|
static void verify_vmargslot(Handle mh, int argnum, int argslot, TRAPS);
|
||||||
|
|
||||||
|
static void verify_method_type(methodHandle m, Handle mtype,
|
||||||
|
bool has_bound_oop,
|
||||||
|
KlassHandle bound_oop_type,
|
||||||
|
TRAPS);
|
||||||
|
|
||||||
|
static void verify_method_signature(methodHandle m, Handle mtype,
|
||||||
|
int first_ptype_pos,
|
||||||
|
KlassHandle insert_ptype, TRAPS);
|
||||||
|
|
||||||
|
static void verify_DirectMethodHandle(Handle mh, methodHandle m, TRAPS);
|
||||||
|
static void verify_BoundMethodHandle(Handle mh, Handle target, int argnum,
|
||||||
|
bool direct_to_method, TRAPS);
|
||||||
|
static void verify_BoundMethodHandle_with_receiver(Handle mh, methodHandle m, TRAPS);
|
||||||
|
static void verify_AdapterMethodHandle(Handle mh, int argnum, TRAPS);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Fill in the fields of a DirectMethodHandle mh. (MH.type must be pre-filled.)
|
||||||
|
static void init_DirectMethodHandle(Handle mh, methodHandle method, bool do_dispatch, TRAPS);
|
||||||
|
|
||||||
|
// Fill in the fields of a BoundMethodHandle mh. (MH.type, BMH.argument must be pre-filled.)
|
||||||
|
static void init_BoundMethodHandle(Handle mh, Handle target, int argnum, TRAPS);
|
||||||
|
static void init_BoundMethodHandle_with_receiver(Handle mh,
|
||||||
|
methodHandle original_m,
|
||||||
|
KlassHandle receiver_limit,
|
||||||
|
int decode_flags,
|
||||||
|
TRAPS);
|
||||||
|
|
||||||
|
// Fill in the fields of an AdapterMethodHandle mh. (MH.type must be pre-filled.)
|
||||||
|
static void init_AdapterMethodHandle(Handle mh, Handle target, int argnum, TRAPS);
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
static bool spot_check_entry_names();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
static methodHandle dispatch_decoded_method(methodHandle m,
|
||||||
|
KlassHandle receiver_limit,
|
||||||
|
int decode_flags,
|
||||||
|
KlassHandle receiver_klass,
|
||||||
|
TRAPS);
|
||||||
|
|
||||||
|
static bool same_basic_type_for_arguments(BasicType src, BasicType dst,
|
||||||
|
bool for_return = false);
|
||||||
|
static bool same_basic_type_for_returns(BasicType src, BasicType dst) {
|
||||||
|
return same_basic_type_for_arguments(src, dst, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
enum { // arg_mask values
|
||||||
|
_INSERT_NO_MASK = -1,
|
||||||
|
_INSERT_REF_MASK = 0,
|
||||||
|
_INSERT_INT_MASK = 1,
|
||||||
|
_INSERT_LONG_MASK = 3
|
||||||
|
};
|
||||||
|
static void insert_arg_slots(MacroAssembler* _masm,
|
||||||
|
RegisterOrConstant arg_slots,
|
||||||
|
int arg_mask,
|
||||||
|
Register rax_argslot,
|
||||||
|
Register rbx_temp, Register rdx_temp);
|
||||||
|
|
||||||
|
static void remove_arg_slots(MacroAssembler* _masm,
|
||||||
|
RegisterOrConstant arg_slots,
|
||||||
|
Register rax_argslot,
|
||||||
|
Register rbx_temp, Register rdx_temp);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Access methods for the "entry" field of a java.dyn.MethodHandle.
|
||||||
|
// The field is primarily a jump target for compiled calls.
|
||||||
|
// However, we squirrel away some nice pointers for other uses,
|
||||||
|
// just before the jump target.
|
||||||
|
// Aspects of a method handle entry:
|
||||||
|
// - from_compiled_entry - stub used when compiled code calls the MH
|
||||||
|
// - from_interpreted_entry - stub used when the interpreter calls the MH
|
||||||
|
// - type_checking_entry - stub for runtime casting between MHForm siblings (NYI)
|
||||||
|
class MethodHandleEntry {
|
||||||
|
public:
|
||||||
|
class Data {
|
||||||
|
friend class MethodHandleEntry;
|
||||||
|
size_t _total_size; // size including Data and code stub
|
||||||
|
MethodHandleEntry* _type_checking_entry;
|
||||||
|
address _from_interpreted_entry;
|
||||||
|
MethodHandleEntry* method_entry() { return (MethodHandleEntry*)(this + 1); }
|
||||||
|
};
|
||||||
|
|
||||||
|
Data* data() { return (Data*)this - 1; }
|
||||||
|
|
||||||
|
address start_address() { return (address) data(); }
|
||||||
|
address end_address() { return start_address() + data()->_total_size; }
|
||||||
|
|
||||||
|
address from_compiled_entry() { return (address) this; }
|
||||||
|
|
||||||
|
address from_interpreted_entry() { return data()->_from_interpreted_entry; }
|
||||||
|
void set_from_interpreted_entry(address e) { data()->_from_interpreted_entry = e; }
|
||||||
|
|
||||||
|
MethodHandleEntry* type_checking_entry() { return data()->_type_checking_entry; }
|
||||||
|
void set_type_checking_entry(MethodHandleEntry* e) { data()->_type_checking_entry = e; }
|
||||||
|
|
||||||
|
void set_end_address(address end_addr) {
|
||||||
|
size_t total_size = end_addr - start_address();
|
||||||
|
assert(total_size > 0 && total_size < 0x1000, "reasonable end address");
|
||||||
|
data()->_total_size = total_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compiler support:
|
||||||
|
static int from_interpreted_entry_offset_in_bytes() {
|
||||||
|
return (int)( offset_of(Data, _from_interpreted_entry) - sizeof(Data) );
|
||||||
|
}
|
||||||
|
static int type_checking_entry_offset_in_bytes() {
|
||||||
|
return (int)( offset_of(Data, _from_interpreted_entry) - sizeof(Data) );
|
||||||
|
}
|
||||||
|
|
||||||
|
static address start_compiled_entry(MacroAssembler* _masm,
|
||||||
|
address interpreted_entry = NULL);
|
||||||
|
static MethodHandleEntry* finish_compiled_entry(MacroAssembler* masm, address start_addr);
|
||||||
|
};
|
||||||
|
|
||||||
|
address MethodHandles::from_compiled_entry(EntryKind ek) { return entry(ek)->from_compiled_entry(); }
|
||||||
|
address MethodHandles::from_interpreted_entry(EntryKind ek) { return entry(ek)->from_interpreted_entry(); }
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. 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
|
||||||
@ -78,6 +78,7 @@ char* NativeLookup::long_jni_name(methodHandle method) {
|
|||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
void JNICALL JVM_RegisterUnsafeMethods(JNIEnv *env, jclass unsafecls);
|
void JNICALL JVM_RegisterUnsafeMethods(JNIEnv *env, jclass unsafecls);
|
||||||
|
void JNICALL JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass unsafecls);
|
||||||
void JNICALL JVM_RegisterPerfMethods(JNIEnv *env, jclass perfclass);
|
void JNICALL JVM_RegisterPerfMethods(JNIEnv *env, jclass perfclass);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,6 +98,9 @@ static address lookup_special_native(char* jni_name) {
|
|||||||
if (strstr(jni_name, "Java_sun_misc_Unsafe_registerNatives") != NULL) {
|
if (strstr(jni_name, "Java_sun_misc_Unsafe_registerNatives") != NULL) {
|
||||||
return CAST_FROM_FN_PTR(address, JVM_RegisterUnsafeMethods);
|
return CAST_FROM_FN_PTR(address, JVM_RegisterUnsafeMethods);
|
||||||
}
|
}
|
||||||
|
if (strstr(jni_name, "Java_sun_dyn_MethodHandleNatives_registerNatives") != NULL) {
|
||||||
|
return CAST_FROM_FN_PTR(address, JVM_RegisterMethodHandleMethods);
|
||||||
|
}
|
||||||
if (strstr(jni_name, "Java_sun_misc_Perf_registerNatives") != NULL) {
|
if (strstr(jni_name, "Java_sun_misc_Perf_registerNatives") != NULL) {
|
||||||
return CAST_FROM_FN_PTR(address, JVM_RegisterPerfMethods);
|
return CAST_FROM_FN_PTR(address, JVM_RegisterPerfMethods);
|
||||||
}
|
}
|
||||||
|
@ -2619,6 +2619,13 @@ jint Arguments::parse(const JavaVMInitArgs* args) {
|
|||||||
}
|
}
|
||||||
#endif // PRODUCT
|
#endif // PRODUCT
|
||||||
|
|
||||||
|
if (EnableMethodHandles && !AnonymousClasses) {
|
||||||
|
if (!FLAG_IS_DEFAULT(AnonymousClasses)) {
|
||||||
|
warning("forcing AnonymousClasses true to enable EnableMethodHandles");
|
||||||
|
}
|
||||||
|
AnonymousClasses = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (PrintGCDetails) {
|
if (PrintGCDetails) {
|
||||||
// Turn on -verbose:gc options as well
|
// Turn on -verbose:gc options as well
|
||||||
PrintGC = true;
|
PrintGC = true;
|
||||||
|
@ -3298,6 +3298,21 @@ class CommandLineFlags {
|
|||||||
product(bool, AnonymousClasses, false, \
|
product(bool, AnonymousClasses, false, \
|
||||||
"support sun.misc.Unsafe.defineAnonymousClass") \
|
"support sun.misc.Unsafe.defineAnonymousClass") \
|
||||||
\
|
\
|
||||||
|
product(bool, EnableMethodHandles, false, \
|
||||||
|
"support method handles (true by default under JSR 292)") \
|
||||||
|
\
|
||||||
|
diagnostic(intx, MethodHandlePushLimit, 3, \
|
||||||
|
"number of additional stack slots a method handle may push") \
|
||||||
|
\
|
||||||
|
develop(bool, TraceMethodHandles, false, \
|
||||||
|
"trace internal method handle operations") \
|
||||||
|
\
|
||||||
|
diagnostic(bool, VerifyMethodHandles, trueInDebug, \
|
||||||
|
"perform extra checks when constructing method handles") \
|
||||||
|
\
|
||||||
|
diagnostic(bool, OptimizeMethodHandles, true, \
|
||||||
|
"when constructing method handles, try to improve them") \
|
||||||
|
\
|
||||||
product(bool, TaggedStackInterpreter, false, \
|
product(bool, TaggedStackInterpreter, false, \
|
||||||
"Insert tags in interpreter execution stack for oopmap generaion")\
|
"Insert tags in interpreter execution stack for oopmap generaion")\
|
||||||
\
|
\
|
||||||
|
@ -1471,9 +1471,73 @@ char* SharedRuntime::generate_class_cast_message(
|
|||||||
return generate_class_cast_message(objName, targetKlass->external_name());
|
return generate_class_cast_message(objName, targetKlass->external_name());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char* SharedRuntime::generate_wrong_method_type_message(JavaThread* thread,
|
||||||
|
oopDesc* required,
|
||||||
|
oopDesc* actual) {
|
||||||
|
assert(EnableMethodHandles, "");
|
||||||
|
oop singleKlass = wrong_method_type_is_for_single_argument(thread, required);
|
||||||
|
if (singleKlass != NULL) {
|
||||||
|
const char* objName = "argument or return value";
|
||||||
|
if (actual != NULL) {
|
||||||
|
// be flexible about the junk passed in:
|
||||||
|
klassOop ak = (actual->is_klass()
|
||||||
|
? (klassOop)actual
|
||||||
|
: actual->klass());
|
||||||
|
objName = Klass::cast(ak)->external_name();
|
||||||
|
}
|
||||||
|
Klass* targetKlass = Klass::cast(required->is_klass()
|
||||||
|
? (klassOop)required
|
||||||
|
: java_lang_Class::as_klassOop(required));
|
||||||
|
return generate_class_cast_message(objName, targetKlass->external_name());
|
||||||
|
} else {
|
||||||
|
// %%% need to get the MethodType string, without messing around too much
|
||||||
|
// Get a signature from the invoke instruction
|
||||||
|
const char* mhName = "method handle";
|
||||||
|
const char* targetType = "the required signature";
|
||||||
|
vframeStream vfst(thread, true);
|
||||||
|
if (!vfst.at_end()) {
|
||||||
|
Bytecode_invoke* call = Bytecode_invoke_at(vfst.method(), vfst.bci());
|
||||||
|
methodHandle target;
|
||||||
|
{
|
||||||
|
EXCEPTION_MARK;
|
||||||
|
target = call->static_target(THREAD);
|
||||||
|
if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; }
|
||||||
|
}
|
||||||
|
if (target.not_null()
|
||||||
|
&& target->is_method_handle_invoke()
|
||||||
|
&& required == target->method_handle_type()) {
|
||||||
|
targetType = target->signature()->as_C_string();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
klassOop kignore; int fignore;
|
||||||
|
methodOop actual_method = MethodHandles::decode_method(actual,
|
||||||
|
kignore, fignore);
|
||||||
|
if (actual_method != NULL) {
|
||||||
|
if (actual_method->name() == vmSymbols::invoke_name())
|
||||||
|
mhName = "$";
|
||||||
|
else
|
||||||
|
mhName = actual_method->signature()->as_C_string();
|
||||||
|
if (mhName[0] == '$')
|
||||||
|
mhName = actual_method->signature()->as_C_string();
|
||||||
|
}
|
||||||
|
return generate_class_cast_message(mhName, targetType,
|
||||||
|
" cannot be called as ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
oop SharedRuntime::wrong_method_type_is_for_single_argument(JavaThread* thr,
|
||||||
|
oopDesc* required) {
|
||||||
|
if (required == NULL) return NULL;
|
||||||
|
if (required->klass() == SystemDictionary::class_klass())
|
||||||
|
return required;
|
||||||
|
if (required->is_klass())
|
||||||
|
return Klass::cast(klassOop(required))->java_mirror();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
char* SharedRuntime::generate_class_cast_message(
|
char* SharedRuntime::generate_class_cast_message(
|
||||||
const char* objName, const char* targetKlassName) {
|
const char* objName, const char* targetKlassName, const char* desc) {
|
||||||
const char* desc = " cannot be cast to ";
|
|
||||||
size_t msglen = strlen(objName) + strlen(desc) + strlen(targetKlassName) + 1;
|
size_t msglen = strlen(objName) + strlen(desc) + strlen(targetKlassName) + 1;
|
||||||
|
|
||||||
char* message = NEW_RESOURCE_ARRAY(char, msglen);
|
char* message = NEW_RESOURCE_ARRAY(char, msglen);
|
||||||
|
@ -211,11 +211,33 @@ class SharedRuntime: AllStatic {
|
|||||||
*/
|
*/
|
||||||
static char* generate_class_cast_message(JavaThread* thr, const char* name);
|
static char* generate_class_cast_message(JavaThread* thr, const char* name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fill in the message for a WrongMethodTypeException
|
||||||
|
*
|
||||||
|
* @param thr the current thread
|
||||||
|
* @param mtype (optional) expected method type (or argument class)
|
||||||
|
* @param mhandle (optional) actual method handle (or argument)
|
||||||
|
* @return the dynamically allocated exception message
|
||||||
|
*
|
||||||
|
* BCP for the frame on top of the stack must refer to an
|
||||||
|
* 'invokevirtual' op for a method handle, or an 'invokedyamic' op.
|
||||||
|
* The caller (or one of its callers) must use a ResourceMark
|
||||||
|
* in order to correctly free the result.
|
||||||
|
*/
|
||||||
|
static char* generate_wrong_method_type_message(JavaThread* thr,
|
||||||
|
oopDesc* mtype = NULL,
|
||||||
|
oopDesc* mhandle = NULL);
|
||||||
|
|
||||||
|
/** Return non-null if the mtype is a klass or Class, not a MethodType. */
|
||||||
|
static oop wrong_method_type_is_for_single_argument(JavaThread* thr,
|
||||||
|
oopDesc* mtype);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fill in the "X cannot be cast to a Y" message for ClassCastException
|
* Fill in the "X cannot be cast to a Y" message for ClassCastException
|
||||||
*
|
*
|
||||||
* @param name the name of the class of the object attempted to be cast
|
* @param name the name of the class of the object attempted to be cast
|
||||||
* @param klass the name of the target klass attempt
|
* @param klass the name of the target klass attempt
|
||||||
|
* @param gripe the specific kind of problem being reported
|
||||||
* @return the dynamically allocated exception message (must be freed
|
* @return the dynamically allocated exception message (must be freed
|
||||||
* by the caller using a resource mark)
|
* by the caller using a resource mark)
|
||||||
*
|
*
|
||||||
@ -224,7 +246,8 @@ class SharedRuntime: AllStatic {
|
|||||||
* The caller (or one of it's callers) must use a ResourceMark
|
* The caller (or one of it's callers) must use a ResourceMark
|
||||||
* in order to correctly free the result.
|
* in order to correctly free the result.
|
||||||
*/
|
*/
|
||||||
static char* generate_class_cast_message(const char* name, const char* klass);
|
static char* generate_class_cast_message(const char* name, const char* klass,
|
||||||
|
const char* gripe = " cannot be cast to ");
|
||||||
|
|
||||||
// Resolves a call site- may patch in the destination of the call into the
|
// Resolves a call site- may patch in the destination of the call into the
|
||||||
// compiled code.
|
// compiled code.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. 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
|
||||||
@ -47,6 +47,8 @@ enum {
|
|||||||
JVM_ACC_IS_OLD = 0x00010000, // RedefineClasses() has replaced this method
|
JVM_ACC_IS_OLD = 0x00010000, // RedefineClasses() has replaced this method
|
||||||
JVM_ACC_IS_OBSOLETE = 0x00020000, // RedefineClasses() has made method obsolete
|
JVM_ACC_IS_OBSOLETE = 0x00020000, // RedefineClasses() has made method obsolete
|
||||||
JVM_ACC_IS_PREFIXED_NATIVE = 0x00040000, // JVMTI has prefixed this native method
|
JVM_ACC_IS_PREFIXED_NATIVE = 0x00040000, // JVMTI has prefixed this native method
|
||||||
|
JVM_MH_INVOKE_BITS // = 0x10001100 // MethodHandle.invoke quasi-native
|
||||||
|
= (JVM_ACC_NATIVE | JVM_ACC_SYNTHETIC | JVM_ACC_MONITOR_MATCH),
|
||||||
|
|
||||||
// klassOop flags
|
// klassOop flags
|
||||||
JVM_ACC_HAS_MIRANDA_METHODS = 0x10000000, // True if this class has miranda methods in it's vtable
|
JVM_ACC_HAS_MIRANDA_METHODS = 0x10000000, // True if this class has miranda methods in it's vtable
|
||||||
@ -72,6 +74,7 @@ enum {
|
|||||||
|
|
||||||
// flags accepted by set_field_flags()
|
// flags accepted by set_field_flags()
|
||||||
JVM_ACC_FIELD_FLAGS = 0x00008000 | JVM_ACC_WRITTEN_FLAGS
|
JVM_ACC_FIELD_FLAGS = 0x00008000 | JVM_ACC_WRITTEN_FLAGS
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -114,6 +117,15 @@ class AccessFlags VALUE_OBJ_CLASS_SPEC {
|
|||||||
bool is_obsolete () const { return (_flags & JVM_ACC_IS_OBSOLETE ) != 0; }
|
bool is_obsolete () const { return (_flags & JVM_ACC_IS_OBSOLETE ) != 0; }
|
||||||
bool is_prefixed_native () const { return (_flags & JVM_ACC_IS_PREFIXED_NATIVE ) != 0; }
|
bool is_prefixed_native () const { return (_flags & JVM_ACC_IS_PREFIXED_NATIVE ) != 0; }
|
||||||
|
|
||||||
|
// JSR 292: A method of the form MethodHandle.invoke(A...)R method is
|
||||||
|
// neither bytecoded nor a JNI native, but rather a fast call through
|
||||||
|
// a lightweight method handle object. Because it is not bytecoded,
|
||||||
|
// it has the native bit set, but the monitor-match bit is also set
|
||||||
|
// to distinguish it from a JNI native (which never has the match bit set).
|
||||||
|
// The synthetic bit is also present, because such a method is never
|
||||||
|
// explicitly defined in Java code.
|
||||||
|
bool is_method_handle_invoke () const { return (_flags & JVM_MH_INVOKE_BITS) == JVM_MH_INVOKE_BITS; }
|
||||||
|
|
||||||
// klassOop flags
|
// klassOop flags
|
||||||
bool has_miranda_methods () const { return (_flags & JVM_ACC_HAS_MIRANDA_METHODS ) != 0; }
|
bool has_miranda_methods () const { return (_flags & JVM_ACC_HAS_MIRANDA_METHODS ) != 0; }
|
||||||
bool has_vanilla_constructor () const { return (_flags & JVM_ACC_HAS_VANILLA_CONSTRUCTOR) != 0; }
|
bool has_vanilla_constructor () const { return (_flags & JVM_ACC_HAS_VANILLA_CONSTRUCTOR) != 0; }
|
||||||
@ -199,6 +211,14 @@ class AccessFlags VALUE_OBJ_CLASS_SPEC {
|
|||||||
jshort as_short() { return (jshort)_flags; }
|
jshort as_short() { return (jshort)_flags; }
|
||||||
jint as_int() { return _flags; }
|
jint as_int() { return _flags; }
|
||||||
|
|
||||||
|
inline friend AccessFlags accessFlags_from(jint flags);
|
||||||
|
|
||||||
// Printing/debugging
|
// Printing/debugging
|
||||||
void print_on(outputStream* st) const PRODUCT_RETURN;
|
void print_on(outputStream* st) const PRODUCT_RETURN;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline AccessFlags accessFlags_from(jint flags) {
|
||||||
|
AccessFlags af;
|
||||||
|
af._flags = flags;
|
||||||
|
return af;
|
||||||
|
}
|
||||||
|
@ -237,6 +237,9 @@ class Exceptions {
|
|||||||
#define THROW_ARG_0(name, signature, arg) THROW_ARG_(name, signature, arg, 0)
|
#define THROW_ARG_0(name, signature, arg) THROW_ARG_(name, signature, arg, 0)
|
||||||
#define THROW_MSG_CAUSE_0(name, message, cause) THROW_MSG_CAUSE_(name, message, cause, 0)
|
#define THROW_MSG_CAUSE_0(name, message, cause) THROW_MSG_CAUSE_(name, message, cause, 0)
|
||||||
|
|
||||||
|
#define THROW_NULL(name) THROW_(name, NULL)
|
||||||
|
#define THROW_MSG_NULL(name, message) THROW_MSG_(name, message, NULL)
|
||||||
|
|
||||||
// The CATCH macro checks that no exception has been thrown by a function; it is used at
|
// The CATCH macro checks that no exception has been thrown by a function; it is used at
|
||||||
// call sites about which is statically known that the callee cannot throw an exception
|
// call sites about which is statically known that the callee cannot throw an exception
|
||||||
// even though it is declared with TRAPS.
|
// even though it is declared with TRAPS.
|
||||||
|
@ -408,6 +408,15 @@ inline bool is_java_primitive(BasicType t) {
|
|||||||
return T_BOOLEAN <= t && t <= T_LONG;
|
return T_BOOLEAN <= t && t <= T_LONG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool is_subword_type(BasicType t) {
|
||||||
|
// these guys are processed exactly like T_INT in calling sequences:
|
||||||
|
return (t == T_BOOLEAN || t == T_CHAR || t == T_BYTE || t == T_SHORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool is_signed_subword_type(BasicType t) {
|
||||||
|
return (t == T_BYTE || t == T_SHORT);
|
||||||
|
}
|
||||||
|
|
||||||
// Convert a char from a classfile signature to a BasicType
|
// Convert a char from a classfile signature to a BasicType
|
||||||
inline BasicType char2type(char c) {
|
inline BasicType char2type(char c) {
|
||||||
switch( c ) {
|
switch( c ) {
|
||||||
|
Loading…
Reference in New Issue
Block a user