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