提交 59f3dfa2 编写于 作者: N never

7045513: JSR 292 inlining causes crashes in methodHandleWalk.cpp

Reviewed-by: jrose
上级 66a7efff
......@@ -1028,7 +1028,12 @@ public class CommandProcessor {
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");
}
......
/*
* 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();
}
}
/*
* 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 class CodeBlob extends VMObject {
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; }
......
/*
* 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 @@ public class CodeCache {
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()) {
......
/*
* 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;
}
}
......@@ -389,7 +389,7 @@ void MethodHandles::load_stack_move(MacroAssembler* _masm,
}
}
#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
......
......@@ -43,7 +43,7 @@ ciMethod* ciMethodHandle::get_adapter_impl(bool is_invokedynamic) const {
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) {
......
......@@ -203,11 +203,14 @@ void print_oop(oop value, outputStream* st) {
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);
}
......
......@@ -615,6 +615,7 @@ void IdealGraphPrinter::visit_node(Node *n, void *param) {
}
}
#ifdef ASSERT
if (node->debug_orig() != NULL) {
stringStream dorigStream;
Node* dorig = node->debug_orig();
......@@ -629,6 +630,7 @@ void IdealGraphPrinter::visit_node(Node *n, void *param) {
}
print_prop("debug_orig", dorigStream.as_string());
}
#endif
if (_chaitin && _chaitin != (PhaseChaitin *)0xdeadbeef) {
buffer[0] = 0;
......
......@@ -265,7 +265,7 @@ MethodHandleWalker::walk(TRAPS) {
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 @@ MethodHandleWalker::walk(TRAPS) {
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 @@ void MethodHandleWalker::retype_raw_conversion(BasicType src, BasicType dst, boo
// -----------------------------------------------------------------------------
// 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 @@ MethodHandleCompiler::MethodHandleCompiler(Handle root, methodHandle callee, int
(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 @@ MethodHandleCompiler::MethodHandleCompiler(Handle root, methodHandle callee, int
_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 @@ methodHandle MethodHandleCompiler::compile(TRAPS) {
}
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 @@ void MethodHandleCompiler::emit_bc(Bytecodes::Code op, int index) {
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 @@ void MethodHandleCompiler::emit_bc(Bytecodes::Code op, int index) {
// 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 @@ void MethodHandleCompiler::emit_bc(Bytecodes::Code op, int index) {
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 @@ void MethodHandleCompiler::emit_bc(Bytecodes::Code op, int index) {
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 @@ void MethodHandleCompiler::emit_bc(Bytecodes::Code op, int index) {
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 @@ MethodHandleCompiler::make_conversion(BasicType type, klassOop tk, Bytecodes::Co
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 @@ MethodHandleCompiler::make_conversion(BasicType type, klassOop tk, Bytecodes::Co
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 @@ MethodHandleCompiler::make_invoke(methodOop m, vmIntrinsics::ID iid,
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 @@ MethodHandleCompiler::make_invoke(methodOop m, vmIntrinsics::ID iid,
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 @@ MethodHandleCompiler::make_invoke(methodOop m, vmIntrinsics::ID iid,
// 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 @@ MethodHandleCompiler::make_invoke(methodOop m, vmIntrinsics::ID iid,
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 @@ MethodHandleCompiler::make_fetch(BasicType type, klassOop tk, Bytecodes::Code op
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 @@ private:
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;
......
......@@ -126,26 +126,34 @@ public:
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; }
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; }
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 { 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 @@ public:
// 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 @@ private:
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 @@ private:
}
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 @@ private:
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);
......
......@@ -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 @@ void MethodHandles::ensure_vmlayout_field(Handle target, TRAPS) {
}
}
#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 @@ JVM_ENTRY(void, MHN_init_DMH(JNIEnv *env, jobject igcls, jobject mh_jh,
}
MethodHandles::init_DirectMethodHandle(mh, m, (do_dispatch != JNI_FALSE), CHECK);
stress_method_handle_walk(mh, CHECK);
}
JVM_END
......@@ -2694,11 +2741,11 @@ JVM_ENTRY(void, MHN_init_BMH(JNIEnv *env, jobject igcls, jobject mh_jh,
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 @@ JVM_ENTRY(void, MHN_init_AMH(JNIEnv *env, jobject igcls, jobject mh_jh,
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
......
......@@ -3724,6 +3724,9 @@ class CommandLineFlags {
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") \
......
......@@ -2861,6 +2861,7 @@ void JavaThread::trace_frames() {
}
#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 @@ void JavaThread::print_frame_layout(int depth, bool validate_only) {
values.print();
}
}
#endif
void JavaThread::trace_stack_from(vframe* start_vf) {
ResourceMark rm;
......
......@@ -783,6 +783,7 @@ static inline uint64_t cast_uint64_t(size_t x)
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 @@ static inline uint64_t cast_uint64_t(size_t x)
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 @@ static inline uint64_t cast_uint64_t(size_t x)
\
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) \
\
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册