src/share/vm/prims/methodHandleWalk.hpp
Index
Unified diffs
Context diffs
Sdiffs
Wdiffs
Patch
New
Old
Previous File
Next File
*** old/src/share/vm/prims/methodHandleWalk.hpp Thu Dec 3 11:54:39 2009
--- new/src/share/vm/prims/methodHandleWalk.hpp Thu Dec 3 11:54:39 2009
*** 66,75 ****
--- 66,76 ----
}
Handle method_handle() { return _method_handle; }
oop method_handle_oop() { return _method_handle(); }
oop method_type_oop() { return MethodHandle_type_oop(); }
+ oop vmtarget_oop() { return MethodHandle_vmtarget_oop(); }
jint adapter_conversion() { assert(is_adapter(), ""); return _conversion; }
int adapter_conversion_op() { return MethodHandles::adapter_conversion_op(adapter_conversion()); }
BasicType adapter_conversion_src_type()
{ return MethodHandles::adapter_conversion_src_type(adapter_conversion()); }
*** 99,110 ****
--- 100,148 ----
// Structure walker for method handles.
// Does abstract interpretation on top of low-level parsing.
// You supply the tokens shuffled by the abstract interpretation.
class MethodHandleWalker : StackObj {
public:
struct _ArgToken { }; // dummy struct
typedef _ArgToken* ArgToken;
+ // Stack values:
+ enum TokenType {
+ tt_void,
+ tt_parameter,
+ tt_temporary,
+ tt_constant,
+ tt_illegal
+ };
+
+ // Argument token:
+ class ArgToken {
+ private:
+ TokenType _tt;
+ BasicType _bt;
+ jvalue _value;
+ Handle _handle;
+
+ public:
+ ArgToken(TokenType tt = tt_illegal) : _tt(tt) {}
+ ArgToken(TokenType tt, BasicType bt, jvalue value) : _tt(tt), _bt(bt), _value(value) {}
+
+ ArgToken(TokenType tt, BasicType bt, int index) : _tt(tt), _bt(bt) {
+ _value.i = index;
+ }
+
+ ArgToken(TokenType tt, BasicType bt, Handle value) : _tt(tt), _bt(bt) {
+ _handle = value;
+ }
+
+ TokenType token_type() const { return _tt; }
+ BasicType basic_type() const { return _bt; }
+ int index() const { return _value.i; }
+ Handle object() const { return _handle; }
+
+ jint get_jint() const { return _value.i; }
+ jlong get_jlong() const { return _value.j; }
+ jfloat get_jfloat() const { return _value.f; }
+ jdouble get_jdouble() const { return _value.d; }
+ };
// Abstract interpretation state:
struct SlotState {
BasicType _type;
ArgToken _arg;
*** 115,133 ****
--- 153,173 ----
return ss;
}
private:
MethodHandleChain _chain;
+ bool _for_invokedynamic;
+ int _local_index;
GrowableArray<SlotState> _outgoing; // current outgoing parameter slots
int _outgoing_argc; // # non-empty outgoing slots
// Replace a value of type old_type at slot (and maybe slot+1) with the new value.
// If old_type != T_VOID, remove the old argument at that point.
// If new_type != T_VOID, insert the new argument at that point.
// Insert or delete a second empty slot as needed.
! void change_argument(BasicType old_type, int slot, BasicType new_type, const ArgToken& new_arg);
SlotState* slot_state(int slot) {
if (slot < 0 || slot >= _outgoing.length())
return NULL;
return _outgoing.adr_at(slot);
*** 150,173 ****
--- 190,227 ----
Bytecodes::Code conversion_code(BasicType src, BasicType dest);
void walk_incoming_state(TRAPS);
public:
! MethodHandleWalker(Handle root, bool for_invokedynamic, TRAPS)
: _chain(root, THREAD),
+ _for_invokedynamic(for_invokedynamic),
_outgoing(THREAD, 10),
_outgoing_argc(0)
{ }
+ {
+ _local_index = for_invokedynamic ? 0 : 1;
+ }
MethodHandleChain& chain() { return _chain; }
+ bool for_invokedynamic() const { return _for_invokedynamic; }
+
+ int new_local_index(BasicType bt) {
+ //int index = _for_invokedynamic ? _local_index : _local_index - 1;
+ int index = _local_index;
+ _local_index += type2size[bt];
+ return index;
+ }
+
+ int max_locals() const { return _local_index; }
+
// plug-in abstract interpretation steps:
virtual ArgToken make_parameter( BasicType type, klassOop tk, int argnum, TRAPS ) = 0;
virtual ArgToken make_prim_constant( BasicType type, jvalue* con, TRAPS ) = 0;
virtual ArgToken make_oop_constant( oop con, TRAPS ) = 0;
! virtual ArgToken make_conversion( BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& src, TRAPS ) = 0;
! virtual ArgToken make_fetch( BasicType type, klassOop tk, Bytecodes::Code op, ArgToken base, ArgToken offset, TRAPS ) = 0;
! virtual ArgToken make_fetch( BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& base, const ArgToken& offset, TRAPS ) = 0;
virtual ArgToken make_invoke( methodOop m, vmIntrinsics::ID iid, Bytecodes::Code op, bool tailcall, int argc, ArgToken* argv, TRAPS ) = 0;
// For make_invoke, the methodOop can be NULL if the intrinsic ID
// is something other than vmIntrinsics::_none.
*** 184,268 ****
--- 238,406 ----
// An abstract interpreter for method handle chains.
// Produces an account of the semantics of a chain, in terms of a static IR.
// The IR happens to be JVM bytecodes.
class MethodHandleCompiler : public MethodHandleWalker {
private:
+ methodHandle _callee;
+ KlassHandle _rklass; // Return type for casting.
+ BasicType _rtype;
+ KlassHandle _target_klass;
Thread* _thread;
struct PrimCon {
BasicType _type;
jvalue _value;
+ // Fake constant pool entry.
+ class ConstantValue {
+ private:
+ int _tag; // Constant pool tag type.
+ JavaValue _value;
+ Handle _handle;
+
+ public:
+ // Constructor for oop types.
+ ConstantValue(int tag, Handle con) : _tag(tag), _handle(con) {
+ assert(tag == JVM_CONSTANT_Utf8 ||
+ tag == JVM_CONSTANT_Class ||
+ tag == JVM_CONSTANT_String ||
+ tag == JVM_CONSTANT_Object, "must be oop type");
+ }
+
+ // Constructor for oop reference types.
+ ConstantValue(int tag, int index) : _tag(tag) {
+ assert(JVM_CONSTANT_Fieldref <= tag && tag <= JVM_CONSTANT_NameAndType, "must be ref type");
+ _value.set_jint(index);
+ }
+ ConstantValue(int tag, int first_index, int second_index) : _tag(tag) {
+ assert(JVM_CONSTANT_Fieldref <= tag && tag <= JVM_CONSTANT_NameAndType, "must be ref type");
+ _value.set_jint(first_index << 16 | second_index);
+ }
+
+ // Constructor for primitive types.
+ ConstantValue(BasicType bt, jvalue con) {
+ _value.set_type(bt);
+ switch (bt) {
+ case T_INT: _tag = JVM_CONSTANT_Integer; _value.set_jint( con.i); break;
+ case T_LONG: _tag = JVM_CONSTANT_Long; _value.set_jlong( con.j); break;
+ case T_FLOAT: _tag = JVM_CONSTANT_Float; _value.set_jfloat( con.f); break;
+ case T_DOUBLE: _tag = JVM_CONSTANT_Double; _value.set_jdouble(con.d); break;
+ default: ShouldNotReachHere();
+ }
+ }
+
+ int tag() const { return _tag; }
+ symbolOop symbol_oop() const { return (symbolOop) _handle(); }
+ klassOop klass_oop() const { return (klassOop) _handle(); }
+ oop object_oop() const { return _handle(); }
+ int index() const { return _value.get_jint(); }
+ int first_index() const { return _value.get_jint() >> 16; }
+ int second_index() const { return _value.get_jint() & 0x0000FFFF; }
+
+ bool is_primitive() const { return is_java_primitive(_value.get_type()); }
+ jint get_jint() const { return _value.get_jint(); }
+ jlong get_jlong() const { return _value.get_jlong(); }
+ jfloat get_jfloat() const { return _value.get_jfloat(); }
+ jdouble get_jdouble() const { return _value.get_jdouble(); }
};
+ // Fake constant pool.
+ GrowableArray<ConstantValue*> _constants;
+
// Accumulated compiler state:
! stringStream _bytes;
GrowableArray<Handle> _constant_oops;
! GrowableArray<PrimCon*> _constant_prims;
! GrowableArray<unsigned char> _bytecode;
+
! int _cur_stack;
int _max_stack;
int _num_params;
int _max_locals;
int _name_index;
int _signature_index;
// Stack values:
enum TokenType {
tt_void,
tt_parameter,
tt_temporary,
tt_constant
! };
+ void stack_push(BasicType bt) {
+ _cur_stack += type2size[bt];
+ if (_cur_stack > _max_stack) _max_stack = _cur_stack;
+ }
+ void stack_pop(BasicType bt) {
+ _cur_stack -= type2size[bt];
! assert(_cur_stack >= 0, "sanity");
+ }
+
+ unsigned char* bytecode() const { return _bytecode.adr_at(0); }
+ int bytecode_length() const { return _bytecode.length(); }
ArgToken make_stack_value(TokenType tt, BasicType type, int id) {
return ArgToken( ((intptr_t)id << 8) | ((intptr_t)type << 4) | (intptr_t)tt );
+ // Fake constant pool.
+ int cpool_oop_put(int tag, Handle con) {
+ if (con.is_null()) return 0;
+ ConstantValue* cv = new ConstantValue(tag, con);
+ return _constants.append(cv);
}
public:
+ int cpool_oop_reference_put(int tag, int first_index, int second_index) {
+ if (first_index == 0 && second_index == 0) return 0;
+ assert(first_index != 0 && second_index != 0, "no zero indexes");
+ ConstantValue* cv = new ConstantValue(tag, first_index, second_index);
+ return _constants.append(cv);
+ }
+
+ int cpool_primitive_put(BasicType type, jvalue* con);
+
+ int cpool_int_put(jint value) {
+ jvalue con; con.i = value;
+ return cpool_primitive_put(T_INT, &con);
+ }
+ int cpool_long_put(jlong value) {
+ jvalue con; con.j = value;
+ return cpool_primitive_put(T_LONG, &con);
+ }
+ int cpool_float_put(jfloat value) {
+ jvalue con; con.f = value;
+ return cpool_primitive_put(T_FLOAT, &con);
+ }
+ int cpool_double_put(jdouble value) {
+ jvalue con; con.d = value;
+ return cpool_primitive_put(T_DOUBLE, &con);
+ }
+
+ int cpool_object_put(Handle obj) {
+ return cpool_oop_put(JVM_CONSTANT_Object, obj);
+ }
+ int cpool_symbol_put(symbolOop sym) {
+ return cpool_oop_put(JVM_CONSTANT_Utf8, sym);
+ }
+ int cpool_klass_put(klassOop klass) {
+ return cpool_oop_put(JVM_CONSTANT_Class, klass);
+ }
+ int cpool_methodref_put(int class_index, int name_and_type_index) {
+ return cpool_oop_reference_put(JVM_CONSTANT_Methodref, class_index, name_and_type_index);
+ }
+ int cpool_name_and_type_put(int name_index, int signature_index) {
+ return cpool_oop_reference_put(JVM_CONSTANT_NameAndType, name_index, signature_index);
+ }
+
+ void emit_bc(Bytecodes::Code op, int index = 0);
+ void emit_load(BasicType bt, int index);
+ void emit_store(BasicType bt, int index);
+ void emit_load_constant(ArgToken arg);
+
virtual ArgToken make_parameter(BasicType type, klassOop tk, int argnum, TRAPS) {
! return make_stack_value(tt_parameter, type, argnum);
! return ArgToken(tt_parameter, type, argnum);
}
virtual ArgToken make_oop_constant(oop con, TRAPS) {
! return make_stack_value(tt_constant, T_OBJECT, find_oop_constant(con));
! Handle h(THREAD, con);
+ return ArgToken(tt_constant, T_OBJECT, h);
}
virtual ArgToken make_prim_constant(BasicType type, jvalue* con, TRAPS) {
! return make_stack_value(tt_constant, type, find_prim_constant(type, con));
! return ArgToken(tt_constant, type, *con);
}
virtual ArgToken make_conversion(BasicType type, klassOop tk, Bytecodes::Code op, ArgToken src, TRAPS);
! virtual ArgToken make_fetch(BasicType type, klassOop tk, Bytecodes::Code op, ArgToken base, ArgToken offset, TRAPS);
+
! virtual ArgToken make_conversion(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& src, TRAPS);
+ virtual ArgToken make_fetch(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& base, const ArgToken& offset, TRAPS);
virtual ArgToken make_invoke(methodOop m, vmIntrinsics::ID iid, Bytecodes::Code op, bool tailcall, int argc, ArgToken* argv, TRAPS);
int find_oop_constant(oop con);
! int find_prim_constant(BasicType type, jvalue* con);
+ // Get a real constant pool.
! constantPoolHandle get_constant_pool(TRAPS) const;
+
+ // Get a real methodOop.
+ methodHandle get_method_oop(TRAPS) const;
public:
! MethodHandleCompiler(Handle root, methodHandle call_method, bool for_invokedynamic, TRAPS);
: MethodHandleWalker(root, THREAD),
_thread(THREAD),
_bytes(50),
_constant_oops(THREAD, 10),
_constant_prims(THREAD, 10),
_max_stack(0), _max_locals(0),
_name_index(0), _signature_index(0)
{ }
const char* bytes() { return _bytes.as_string(); }
int constant_length() { return _constant_oops.length(); }
int max_stack() { return _max_stack; }
int max_locals() { return _max_locals; }
int name_index() { return _name_index; }
int signature_index() { return _signature_index; }
symbolHandle name() { return symbolHandle(_thread, (symbolOop)constant_oop_at(_name_index)()); }
symbolHandle signature() { return symbolHandle(_thread, (symbolOop)constant_oop_at(_signature_index)()); }
bool constant_is_oop_at(int i) {
return (_constant_prims.at(i) == NULL);
}
Handle constant_oop_at(int i) {
assert(constant_is_oop_at(i), "");
return _constant_oops.at(i);
}
PrimCon* constant_prim_at(int i) {
assert(!constant_is_oop_at(i), "");
return _constant_prims.at(i);
}
// Compile the given MH chain into bytecode.
! void compile(TRAPS);
! methodHandle compile(TRAPS);
};
src/share/vm/prims/methodHandleWalk.hpp
Index
Unified diffs
Context diffs
Sdiffs
Wdiffs
Patch
New
Old
Previous File
Next File