7045513: JSR 292 inlining causes crashes in methodHandleWalk.cpp
Reviewed-by: jrose
--- 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");
}
--- /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();
+ }
+}
--- 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; }
--- 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()) {
--- /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;
+ }
+}
--- 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
--- 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) {
--- 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);
}
--- 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;
--- 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;
--- 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);
--- 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
--- 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") \
--- 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;
--- 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) \
\