# HG changeset patch # User never # Date 1305684711 25200 # Node ID b3d5b50e2289b16ed5aae94e8786b394dd380ecb # Parent a9aea2b8010ff784298c1527c803ab0d53de3eab 7045513: JSR 292 inlining causes crashes in methodHandleWalk.cpp Reviewed-by: jrose diff -r a9aea2b8010f -r b3d5b50e2289 hotspot/agent/src/share/classes/sun/jvm/hotspot/CommandProcessor.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/CommandProcessor.java Tue May 17 16:50:27 2011 +0200 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/CommandProcessor.java Tue May 17 19:11:51 2011 -0700 @@ -1028,7 +1028,12 @@ if (AddressOps.equal(val, value)) { if (!printed) { printed = true; - blob.printOn(out); + try { + blob.printOn(out); + } catch (Exception e) { + out.println("Exception printing blob at " + base); + e.printStackTrace(); + } } out.println("found at " + base + "\n"); } diff -r a9aea2b8010f -r b3d5b50e2289 hotspot/agent/src/share/classes/sun/jvm/hotspot/code/AdapterBlob.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/AdapterBlob.java Tue May 17 19:11:51 2011 -0700 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot.code; + +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.types.*; + +public class AdapterBlob extends CodeBlob { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static void initialize(TypeDataBase db) { + // Type type = db.lookupType("AdapterBlob"); + + // // FIXME: add any needed fields + } + + public AdapterBlob(Address addr) { + super(addr); + } + + public boolean isAdapterBlob() { + return true; + } + + public String getName() { + return "AdapterBlob: " + super.getName(); + } +} diff -r a9aea2b8010f -r b3d5b50e2289 hotspot/agent/src/share/classes/sun/jvm/hotspot/code/CodeBlob.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/CodeBlob.java Tue May 17 16:50:27 2011 +0200 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/CodeBlob.java Tue May 17 19:11:51 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. 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 @@ -93,6 +93,8 @@ public boolean isUncommonTrapStub() { return false; } public boolean isExceptionStub() { return false; } public boolean isSafepointStub() { return false; } + public boolean isRicochetBlob() { return false; } + public boolean isAdapterBlob() { return false; } // Fine grain nmethod support: isNmethod() == isJavaMethod() || isNativeMethod() || isOSRMethod() public boolean isJavaMethod() { return false; } diff -r a9aea2b8010f -r b3d5b50e2289 hotspot/agent/src/share/classes/sun/jvm/hotspot/code/CodeCache.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/CodeCache.java Tue May 17 16:50:27 2011 +0200 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/CodeCache.java Tue May 17 19:11:51 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. 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 @@ -57,6 +57,8 @@ virtualConstructor.addMapping("BufferBlob", BufferBlob.class); virtualConstructor.addMapping("nmethod", NMethod.class); virtualConstructor.addMapping("RuntimeStub", RuntimeStub.class); + virtualConstructor.addMapping("RicochetBlob", RicochetBlob.class); + virtualConstructor.addMapping("AdapterBlob", AdapterBlob.class); virtualConstructor.addMapping("SafepointBlob", SafepointBlob.class); virtualConstructor.addMapping("DeoptimizationBlob", DeoptimizationBlob.class); if (VM.getVM().isServerCompiler()) { diff -r a9aea2b8010f -r b3d5b50e2289 hotspot/agent/src/share/classes/sun/jvm/hotspot/code/RicochetBlob.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/RicochetBlob.java Tue May 17 19:11:51 2011 -0700 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot.code; + +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.types.*; + +/** RicochetBlob (currently only used by Compiler 2) */ + +public class RicochetBlob extends SingletonBlob { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static void initialize(TypeDataBase db) { + // Type type = db.lookupType("RicochetBlob"); + + // FIXME: add any needed fields + } + + public RicochetBlob(Address addr) { + super(addr); + } + + public boolean isRicochetBlob() { + return true; + } +} diff -r a9aea2b8010f -r b3d5b50e2289 hotspot/src/cpu/x86/vm/methodHandles_x86.cpp --- a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp Tue May 17 16:50:27 2011 +0200 +++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp Tue May 17 19:11:51 2011 -0700 @@ -389,7 +389,7 @@ } } -#ifndef PRODUCT +#ifdef ASSERT void MethodHandles::RicochetFrame::verify_offsets() { // Check compatibility of this struct with the more generally used offsets of class frame: int ebp_off = sender_link_offset_in_bytes(); // offset from struct base to local rbp value diff -r a9aea2b8010f -r b3d5b50e2289 hotspot/src/share/vm/ci/ciMethodHandle.cpp --- a/hotspot/src/share/vm/ci/ciMethodHandle.cpp Tue May 17 16:50:27 2011 +0200 +++ b/hotspot/src/share/vm/ci/ciMethodHandle.cpp Tue May 17 19:11:51 2011 -0700 @@ -43,7 +43,7 @@ methodHandle callee(_callee->get_methodOop()); // We catch all exceptions here that could happen in the method // handle compiler and stop the VM. - MethodHandleCompiler mhc(h, callee, _profile->count(), is_invokedynamic, THREAD); + MethodHandleCompiler mhc(h, callee->name(), callee->signature(), _profile->count(), is_invokedynamic, THREAD); if (!HAS_PENDING_EXCEPTION) { methodHandle m = mhc.compile(THREAD); if (!HAS_PENDING_EXCEPTION) { diff -r a9aea2b8010f -r b3d5b50e2289 hotspot/src/share/vm/interpreter/bytecodeTracer.cpp --- a/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp Tue May 17 16:50:27 2011 +0200 +++ b/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp Tue May 17 19:11:51 2011 -0700 @@ -203,11 +203,14 @@ if (value == NULL) { st->print_cr(" NULL"); } else if (java_lang_String::is_instance(value)) { - EXCEPTION_MARK; - Handle h_value (THREAD, value); - Symbol* sym = java_lang_String::as_symbol(h_value, CATCH); - print_symbol(sym, st); - sym->decrement_refcount(); + char buf[40]; + int len = java_lang_String::utf8_length(value); + java_lang_String::as_utf8_string(value, buf, sizeof(buf)); + if (len >= (int)sizeof(buf)) { + st->print_cr(" %s...[%d]", buf, len); + } else { + st->print_cr(" %s", buf); + } } else { st->print_cr(" " PTR_FORMAT, (intptr_t) value); } diff -r a9aea2b8010f -r b3d5b50e2289 hotspot/src/share/vm/opto/idealGraphPrinter.cpp --- a/hotspot/src/share/vm/opto/idealGraphPrinter.cpp Tue May 17 16:50:27 2011 +0200 +++ b/hotspot/src/share/vm/opto/idealGraphPrinter.cpp Tue May 17 19:11:51 2011 -0700 @@ -615,6 +615,7 @@ } } +#ifdef ASSERT if (node->debug_orig() != NULL) { stringStream dorigStream; Node* dorig = node->debug_orig(); @@ -629,6 +630,7 @@ } print_prop("debug_orig", dorigStream.as_string()); } +#endif if (_chaitin && _chaitin != (PhaseChaitin *)0xdeadbeef) { buffer[0] = 0; diff -r a9aea2b8010f -r b3d5b50e2289 hotspot/src/share/vm/prims/methodHandleWalk.cpp --- a/hotspot/src/share/vm/prims/methodHandleWalk.cpp Tue May 17 16:50:27 2011 +0200 +++ b/hotspot/src/share/vm/prims/methodHandleWalk.cpp Tue May 17 19:11:51 2011 -0700 @@ -265,7 +265,7 @@ assert(dest == arg_state->_type, ""); ArgToken arg = arg_state->_arg; ArgToken new_arg = make_conversion(T_OBJECT, dest_klass, Bytecodes::_checkcast, arg, CHECK_(empty)); - assert(arg.token_type() >= tt_symbolic || arg.index() == new_arg.index(), "should be the same index"); + assert(!arg.has_index() || arg.index() == new_arg.index(), "should be the same index"); debug_only(dest_klass = (klassOop)badOop); break; } @@ -443,8 +443,10 @@ ret = make_conversion(T_OBJECT, rklass, Bytecodes::_checkcast, ret, CHECK_(empty)); } } - int ret_slot = arg_slot + (retain_original_args ? coll_slots : 0); - change_argument(T_VOID, ret_slot, rtype, ret); + if (rtype != T_VOID) { + int ret_slot = arg_slot + (retain_original_args ? coll_slots : 0); + change_argument(T_VOID, ret_slot, rtype, ret); + } break; } @@ -690,9 +692,8 @@ // ----------------------------------------------------------------------------- // MethodHandleCompiler -MethodHandleCompiler::MethodHandleCompiler(Handle root, methodHandle callee, int invoke_count, bool is_invokedynamic, TRAPS) +MethodHandleCompiler::MethodHandleCompiler(Handle root, Symbol* name, Symbol* signature, int invoke_count, bool is_invokedynamic, TRAPS) : MethodHandleWalker(root, is_invokedynamic, THREAD), - _callee(callee), _invoke_count(invoke_count), _thread(THREAD), _bytecode(THREAD, 50), @@ -706,8 +707,8 @@ (void) _constants.append(NULL); // Set name and signature index. - _name_index = cpool_symbol_put(_callee->name()); - _signature_index = cpool_symbol_put(_callee->signature()); + _name_index = cpool_symbol_put(name); + _signature_index = cpool_symbol_put(signature); // Get return type klass. Handle first_mtype(THREAD, chain().method_type_oop()); @@ -715,7 +716,8 @@ _rtype = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::rtype(first_mtype()), &_rklass); if (_rtype == T_ARRAY) _rtype = T_OBJECT; - int params = _callee->size_of_parameters(); // Incoming arguments plus receiver. + ArgumentSizeComputer args(signature); + int params = args.size() + 1; // Incoming arguments plus receiver. _num_params = for_invokedynamic() ? params - 1 : params; // XXX Check if callee is static? } @@ -733,7 +735,7 @@ } -void MethodHandleCompiler::emit_bc(Bytecodes::Code op, int index) { +void MethodHandleCompiler::emit_bc(Bytecodes::Code op, int index, int args_size) { Bytecodes::check(op); // Are we legal? switch (op) { @@ -809,6 +811,14 @@ case Bytecodes::_d2i: case Bytecodes::_d2l: case Bytecodes::_d2f: + case Bytecodes::_iaload: + case Bytecodes::_laload: + case Bytecodes::_faload: + case Bytecodes::_daload: + case Bytecodes::_aaload: + case Bytecodes::_baload: + case Bytecodes::_caload: + case Bytecodes::_saload: case Bytecodes::_ireturn: case Bytecodes::_lreturn: case Bytecodes::_freturn: @@ -822,9 +832,14 @@ // bi case Bytecodes::_ldc: assert(Bytecodes::format_bits(op, false) == (Bytecodes::_fmt_b|Bytecodes::_fmt_has_k), "wrong bytecode format"); - assert((char) index == index, "index does not fit in 8-bit"); - _bytecode.push(op); - _bytecode.push(index); + if (index == (index & 0xff)) { + _bytecode.push(op); + _bytecode.push(index); + } else { + _bytecode.push(Bytecodes::_ldc_w); + _bytecode.push(index >> 8); + _bytecode.push(index); + } break; case Bytecodes::_iload: @@ -838,9 +853,16 @@ case Bytecodes::_dstore: case Bytecodes::_astore: assert(Bytecodes::format_bits(op, false) == Bytecodes::_fmt_bi, "wrong bytecode format"); - assert((char) index == index, "index does not fit in 8-bit"); - _bytecode.push(op); - _bytecode.push(index); + if (index == (index & 0xff)) { + _bytecode.push(op); + _bytecode.push(index); + } else { + // doesn't fit in a u2 + _bytecode.push(Bytecodes::_wide); + _bytecode.push(op); + _bytecode.push(index >> 8); + _bytecode.push(index); + } break; // bkk @@ -848,7 +870,7 @@ case Bytecodes::_ldc2_w: case Bytecodes::_checkcast: assert(Bytecodes::format_bits(op, false) == Bytecodes::_fmt_bkk, "wrong bytecode format"); - assert((short) index == index, "index does not fit in 16-bit"); + assert((unsigned short) index == index, "index does not fit in 16-bit"); _bytecode.push(op); _bytecode.push(index >> 8); _bytecode.push(index); @@ -859,12 +881,23 @@ case Bytecodes::_invokespecial: case Bytecodes::_invokevirtual: assert(Bytecodes::format_bits(op, false) == Bytecodes::_fmt_bJJ, "wrong bytecode format"); - assert((short) index == index, "index does not fit in 16-bit"); + assert((unsigned short) index == index, "index does not fit in 16-bit"); _bytecode.push(op); _bytecode.push(index >> 8); _bytecode.push(index); break; + case Bytecodes::_invokeinterface: + assert(Bytecodes::format_bits(op, false) == Bytecodes::_fmt_bJJ, "wrong bytecode format"); + assert((unsigned short) index == index, "index does not fit in 16-bit"); + assert(args_size > 0, "valid args_size"); + _bytecode.push(op); + _bytecode.push(index >> 8); + _bytecode.push(index); + _bytecode.push(args_size); + _bytecode.push(0); + break; + default: ShouldNotReachHere(); } @@ -983,7 +1016,8 @@ const ArgToken& src, TRAPS) { BasicType srctype = src.basic_type(); - int index = src.index(); + TokenType tt = src.token_type(); + int index = -1; switch (op) { case Bytecodes::_i2l: @@ -1004,18 +1038,31 @@ case Bytecodes::_d2i: case Bytecodes::_d2l: case Bytecodes::_d2f: - emit_load(srctype, index); + if (tt == tt_constant) { + emit_load_constant(src); + } else { + emit_load(srctype, src.index()); + } stack_pop(srctype); // pop the src type emit_bc(op); stack_push(type); // push the dest value - if (srctype != type) + if (tt != tt_constant) + index = src.index(); + if (srctype != type || index == -1) index = new_local_index(type); emit_store(type, index); break; case Bytecodes::_checkcast: - emit_load(srctype, index); + if (tt == tt_constant) { + emit_load_constant(src); + } else { + emit_load(srctype, src.index()); + index = src.index(); + } emit_bc(op, cpool_klass_put(tk)); + if (index == -1) + index = new_local_index(type); emit_store(srctype, index); break; @@ -1058,6 +1105,11 @@ Symbol* name = m->name(); Symbol* signature = m->signature(); + // Count the number of arguments, not the size + ArgumentCount asc(signature); + assert(argc == asc.size() + ((op == Bytecodes::_invokestatic || op == Bytecodes::_invokedynamic) ? 0 : 1), + "argc mismatch"); + if (tailcall) { // Actually, in order to make these methods more recognizable, // let's put them in holder class MethodHandle. That way stack @@ -1106,9 +1158,13 @@ case Bytecodes::_invokevirtual: emit_bc(op, methodref_index); break; - case Bytecodes::_invokeinterface: - Unimplemented(); + + case Bytecodes::_invokeinterface: { + ArgumentSizeComputer asc(signature); + emit_bc(op, methodref_index, asc.size() + 1); break; + } + default: ShouldNotReachHere(); } @@ -1117,6 +1173,7 @@ // Otherwise, make a recursive call to some helper routine. BasicType rbt = m->result_type(); if (rbt == T_ARRAY) rbt = T_OBJECT; + stack_push(rbt); // The return value is already pushed onto the stack. ArgToken ret; if (tailcall) { if (rbt != _rtype) { @@ -1171,7 +1228,6 @@ ret = ArgToken(); // Dummy return value. } else { - stack_push(rbt); // The return value is already pushed onto the stack. int index = new_local_index(rbt); switch (rbt) { case T_BOOLEAN: case T_BYTE: case T_CHAR: case T_SHORT: @@ -1196,8 +1252,32 @@ const MethodHandleWalker::ArgToken& base, const MethodHandleWalker::ArgToken& offset, TRAPS) { - Unimplemented(); - return ArgToken(); + switch (base.token_type()) { + case tt_parameter: + case tt_temporary: + emit_load(base.basic_type(), base.index()); + break; + case tt_constant: + emit_load_constant(base); + break; + default: + ShouldNotReachHere(); + } + switch (offset.token_type()) { + case tt_parameter: + case tt_temporary: + emit_load(offset.basic_type(), offset.index()); + break; + case tt_constant: + emit_load_constant(offset); + break; + default: + ShouldNotReachHere(); + } + emit_bc(op); + int index = new_local_index(type); + emit_store(type, index); + return ArgToken(tt_temporary, type, index); } @@ -1372,12 +1452,10 @@ return s; } ArgToken token(const char* str) { - jvalue string_con; - string_con.j = (intptr_t) str; - return ArgToken(tt_symbolic, T_LONG, string_con); + return ArgToken(str); } const char* string(ArgToken token) { - return (const char*) (intptr_t) token.get_jlong(); + return token.str(); } void start_params() { _param_state <<= 1; diff -r a9aea2b8010f -r b3d5b50e2289 hotspot/src/share/vm/prims/methodHandleWalk.hpp --- a/hotspot/src/share/vm/prims/methodHandleWalk.hpp Tue May 17 16:50:27 2011 +0200 +++ b/hotspot/src/share/vm/prims/methodHandleWalk.hpp Tue May 17 19:11:51 2011 -0700 @@ -126,26 +126,34 @@ 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 = tt_illegal) : _tt(tt) { + assert(tt == tt_illegal || tt == tt_void, "invalid token type"); + } ArgToken(TokenType tt, BasicType bt, int index) : _tt(tt), _bt(bt) { + assert(_tt == tt_parameter || _tt == tt_temporary, "must have index"); _value.i = index; } - ArgToken(TokenType tt, BasicType bt, Handle value) : _tt(tt), _bt(bt) { - _handle = value; + ArgToken(BasicType bt, jvalue value) : _tt(tt_constant), _bt(bt), _value(value) {} + ArgToken(BasicType bt, Handle value) : _tt(tt_constant), _bt(bt), _handle(value) {} + + + ArgToken(const char* str) : _tt(tt_symbolic), _bt(T_LONG) { + _value.j = (intptr_t)str; } TokenType token_type() const { return _tt; } BasicType basic_type() const { return _bt; } - int index() const { return _value.i; } - Handle object() const { return _handle; } + bool has_index() const { return _tt == tt_parameter || _tt == tt_temporary; } + int index() const { assert(has_index(), "must have index");; return _value.i; } + Handle object() const { assert(_tt == tt_constant, "value type"); return _handle; } + const char* str() const { assert(_tt == tt_symbolic, "string type"); return (const char*)_value.j; } - 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; } + jint get_jint() const { assert(_tt == tt_constant, "value types"); return _value.i; } + jlong get_jlong() const { assert(_tt == tt_constant, "value types"); return _value.j; } + jfloat get_jfloat() const { assert(_tt == tt_constant, "value types"); return _value.f; } + jdouble get_jdouble() const { assert(_tt == tt_constant, "value types"); return _value.d; } }; // Abstract interpretation state: @@ -256,7 +264,6 @@ // The IR happens to be JVM bytecodes. class MethodHandleCompiler : public MethodHandleWalker { private: - methodHandle _callee; int _invoke_count; // count the original call site has been executed KlassHandle _rklass; // Return type for casting. BasicType _rtype; @@ -404,7 +411,7 @@ return cpool_oop_reference_put(JVM_CONSTANT_NameAndType, name_index, signature_index); } - void emit_bc(Bytecodes::Code op, int index = 0); + void emit_bc(Bytecodes::Code op, int index = 0, int args_size = -1); void emit_load(BasicType bt, int index); void emit_store(BasicType bt, int index); void emit_load_constant(ArgToken arg); @@ -414,10 +421,10 @@ } virtual ArgToken make_oop_constant(oop con, TRAPS) { Handle h(THREAD, con); - return ArgToken(tt_constant, T_OBJECT, h); + return ArgToken(T_OBJECT, h); } virtual ArgToken make_prim_constant(BasicType type, jvalue* con, TRAPS) { - return ArgToken(tt_constant, type, *con); + return ArgToken(type, *con); } virtual ArgToken make_conversion(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& src, TRAPS); @@ -431,7 +438,7 @@ methodHandle get_method_oop(TRAPS) const; public: - MethodHandleCompiler(Handle root, methodHandle callee, int invoke_count, bool for_invokedynamic, TRAPS); + MethodHandleCompiler(Handle root, Symbol* name, Symbol* signature, int invoke_count, bool for_invokedynamic, TRAPS); // Compile the given MH chain into bytecode. methodHandle compile(TRAPS); diff -r a9aea2b8010f -r b3d5b50e2289 hotspot/src/share/vm/prims/methodHandles.cpp --- a/hotspot/src/share/vm/prims/methodHandles.cpp Tue May 17 16:50:27 2011 +0200 +++ b/hotspot/src/share/vm/prims/methodHandles.cpp Tue May 17 19:11:51 2011 -0700 @@ -25,9 +25,11 @@ #include "precompiled.hpp" #include "classfile/symbolTable.hpp" #include "interpreter/interpreter.hpp" +#include "interpreter/oopMapCache.hpp" #include "memory/allocation.inline.hpp" #include "memory/oopFactory.hpp" #include "prims/methodHandles.hpp" +#include "prims/methodHandleWalk.hpp" #include "runtime/javaCalls.hpp" #include "runtime/reflection.hpp" #include "runtime/signature.hpp" @@ -2599,6 +2601,50 @@ } } +#ifdef ASSERT + +extern "C" +void print_method_handle(oop mh); + +static void stress_method_handle_walk_impl(Handle mh, TRAPS) { + if (StressMethodHandleWalk) { + // Exercise the MethodHandleWalk code in various ways and validate + // the resulting method oop. Some of these produce output so they + // are guarded under Verbose. + ResourceMark rm; + HandleMark hm; + if (Verbose) { + print_method_handle(mh()); + } + TempNewSymbol name = SymbolTable::new_symbol("invoke", CHECK); + Handle mt = java_lang_invoke_MethodHandle::type(mh()); + TempNewSymbol signature = java_lang_invoke_MethodType::as_signature(mt(), true, CHECK); + MethodHandleCompiler mhc(mh, name, signature, 10000, false, CHECK); + methodHandle m = mhc.compile(CHECK); + if (Verbose) { + m->print_codes(); + } + InterpreterOopMap mask; + OopMapCache::compute_one_oop_map(m, m->code_size() - 1, &mask); + } +} + +static void stress_method_handle_walk(Handle mh, TRAPS) { + stress_method_handle_walk_impl(mh, THREAD); + if (HAS_PENDING_EXCEPTION) { + oop ex = PENDING_EXCEPTION; + CLEAR_PENDING_EXCEPTION; + tty->print("StressMethodHandleWalk: "); + java_lang_Throwable::print(ex, tty); + tty->cr(); + } +} +#else + +static void stress_method_handle_walk(Handle mh, TRAPS) {} + +#endif + // // Here are the native methods on sun.invoke.MethodHandleImpl. // They are the private interface between this JVM and the HotSpot-specific @@ -2666,6 +2712,7 @@ } MethodHandles::init_DirectMethodHandle(mh, m, (do_dispatch != JNI_FALSE), CHECK); + stress_method_handle_walk(mh, CHECK); } JVM_END @@ -2694,11 +2741,11 @@ receiver_limit, decode_flags, CHECK); - return; + } else { + // Build a BMH on top of a DMH or another BMH: + MethodHandles::init_BoundMethodHandle(mh, target, argnum, CHECK); } - - // Build a BMH on top of a DMH or another BMH: - MethodHandles::init_BoundMethodHandle(mh, target, argnum, CHECK); + stress_method_handle_walk(mh, CHECK); } JVM_END @@ -2716,6 +2763,7 @@ assert(java_lang_invoke_MethodHandle::vmentry(mh()) == NULL, "must be safely null"); MethodHandles::init_AdapterMethodHandle(mh, target, argnum, CHECK); + stress_method_handle_walk(mh, CHECK); } JVM_END diff -r a9aea2b8010f -r b3d5b50e2289 hotspot/src/share/vm/runtime/globals.hpp --- a/hotspot/src/share/vm/runtime/globals.hpp Tue May 17 16:50:27 2011 +0200 +++ b/hotspot/src/share/vm/runtime/globals.hpp Tue May 17 19:11:51 2011 -0700 @@ -3724,6 +3724,9 @@ diagnostic(bool, OptimizeMethodHandles, true, \ "when constructing method handles, try to improve them") \ \ + develop(bool, StressMethodHandleWalk, false, \ + "Process all method handles with MethodHandleWalk") \ + \ diagnostic(bool, UseRicochetFrames, true, \ "use ricochet stack frames for method handle combination, " \ "if the platform supports them") \ diff -r a9aea2b8010f -r b3d5b50e2289 hotspot/src/share/vm/runtime/thread.cpp --- a/hotspot/src/share/vm/runtime/thread.cpp Tue May 17 16:50:27 2011 +0200 +++ b/hotspot/src/share/vm/runtime/thread.cpp Tue May 17 19:11:51 2011 -0700 @@ -2861,6 +2861,7 @@ } +#ifdef ASSERT // Print or validate the layout of stack frames void JavaThread::print_frame_layout(int depth, bool validate_only) { ResourceMark rm; @@ -2878,7 +2879,7 @@ values.print(); } } - +#endif void JavaThread::trace_stack_from(vframe* start_vf) { ResourceMark rm; diff -r a9aea2b8010f -r b3d5b50e2289 hotspot/src/share/vm/runtime/vmStructs.cpp --- a/hotspot/src/share/vm/runtime/vmStructs.cpp Tue May 17 16:50:27 2011 +0200 +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Tue May 17 19:11:51 2011 -0700 @@ -783,6 +783,7 @@ nonstatic_field(nmethod, _osr_link, nmethod*) \ nonstatic_field(nmethod, _scavenge_root_link, nmethod*) \ nonstatic_field(nmethod, _scavenge_root_state, jbyte) \ + nonstatic_field(nmethod, _state, unsigned char) \ nonstatic_field(nmethod, _exception_offset, int) \ nonstatic_field(nmethod, _deoptimize_offset, int) \ nonstatic_field(nmethod, _orig_pc_offset, int) \ @@ -800,6 +801,8 @@ nonstatic_field(nmethod, _osr_entry_point, address) \ nonstatic_field(nmethod, _lock_count, jint) \ nonstatic_field(nmethod, _stack_traversal_mark, long) \ + nonstatic_field(nmethod, _compile_id, int) \ + nonstatic_field(nmethod, _marked_for_deoptimization, bool) \ \ /********************************/ \ /* JavaCalls (NOTE: incomplete) */ \ @@ -1310,11 +1313,13 @@ \ declare_toplevel_type(CodeBlob) \ declare_type(BufferBlob, CodeBlob) \ - declare_type(nmethod, CodeBlob) \ + declare_type(AdapterBlob, BufferBlob) \ + declare_type(nmethod, CodeBlob) \ declare_type(RuntimeStub, CodeBlob) \ declare_type(SingletonBlob, CodeBlob) \ declare_type(SafepointBlob, SingletonBlob) \ declare_type(DeoptimizationBlob, SingletonBlob) \ + declare_type(RicochetBlob, SingletonBlob) \ declare_c2_type(ExceptionBlob, SingletonBlob) \ declare_c2_type(UncommonTrapBlob, CodeBlob) \ \