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

7045513: JSR 292 inlining causes crashes in methodHandleWalk.cpp

Reviewed-by: jrose
上级 66a7efff
...@@ -1028,7 +1028,12 @@ public class CommandProcessor { ...@@ -1028,7 +1028,12 @@ public class CommandProcessor {
if (AddressOps.equal(val, value)) { if (AddressOps.equal(val, value)) {
if (!printed) { if (!printed) {
printed = true; 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"); 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -93,6 +93,8 @@ public class CodeBlob extends VMObject { ...@@ -93,6 +93,8 @@ public class CodeBlob extends VMObject {
public boolean isUncommonTrapStub() { return false; } public boolean isUncommonTrapStub() { return false; }
public boolean isExceptionStub() { return false; } public boolean isExceptionStub() { return false; }
public boolean isSafepointStub() { 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() // Fine grain nmethod support: isNmethod() == isJavaMethod() || isNativeMethod() || isOSRMethod()
public boolean isJavaMethod() { return false; } 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -57,6 +57,8 @@ public class CodeCache { ...@@ -57,6 +57,8 @@ public class CodeCache {
virtualConstructor.addMapping("BufferBlob", BufferBlob.class); virtualConstructor.addMapping("BufferBlob", BufferBlob.class);
virtualConstructor.addMapping("nmethod", NMethod.class); virtualConstructor.addMapping("nmethod", NMethod.class);
virtualConstructor.addMapping("RuntimeStub", RuntimeStub.class); virtualConstructor.addMapping("RuntimeStub", RuntimeStub.class);
virtualConstructor.addMapping("RicochetBlob", RicochetBlob.class);
virtualConstructor.addMapping("AdapterBlob", AdapterBlob.class);
virtualConstructor.addMapping("SafepointBlob", SafepointBlob.class); virtualConstructor.addMapping("SafepointBlob", SafepointBlob.class);
virtualConstructor.addMapping("DeoptimizationBlob", DeoptimizationBlob.class); virtualConstructor.addMapping("DeoptimizationBlob", DeoptimizationBlob.class);
if (VM.getVM().isServerCompiler()) { 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, ...@@ -389,7 +389,7 @@ void MethodHandles::load_stack_move(MacroAssembler* _masm,
} }
} }
#ifndef PRODUCT #ifdef ASSERT
void MethodHandles::RicochetFrame::verify_offsets() { void MethodHandles::RicochetFrame::verify_offsets() {
// Check compatibility of this struct with the more generally used offsets of class frame: // 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 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 { ...@@ -43,7 +43,7 @@ ciMethod* ciMethodHandle::get_adapter_impl(bool is_invokedynamic) const {
methodHandle callee(_callee->get_methodOop()); methodHandle callee(_callee->get_methodOop());
// We catch all exceptions here that could happen in the method // We catch all exceptions here that could happen in the method
// handle compiler and stop the VM. // 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) { if (!HAS_PENDING_EXCEPTION) {
methodHandle m = mhc.compile(THREAD); methodHandle m = mhc.compile(THREAD);
if (!HAS_PENDING_EXCEPTION) { if (!HAS_PENDING_EXCEPTION) {
......
...@@ -203,11 +203,14 @@ void print_oop(oop value, outputStream* st) { ...@@ -203,11 +203,14 @@ void print_oop(oop value, outputStream* st) {
if (value == NULL) { if (value == NULL) {
st->print_cr(" NULL"); st->print_cr(" NULL");
} else if (java_lang_String::is_instance(value)) { } else if (java_lang_String::is_instance(value)) {
EXCEPTION_MARK; char buf[40];
Handle h_value (THREAD, value); int len = java_lang_String::utf8_length(value);
Symbol* sym = java_lang_String::as_symbol(h_value, CATCH); java_lang_String::as_utf8_string(value, buf, sizeof(buf));
print_symbol(sym, st); if (len >= (int)sizeof(buf)) {
sym->decrement_refcount(); st->print_cr(" %s...[%d]", buf, len);
} else {
st->print_cr(" %s", buf);
}
} else { } else {
st->print_cr(" " PTR_FORMAT, (intptr_t) value); st->print_cr(" " PTR_FORMAT, (intptr_t) value);
} }
......
...@@ -615,6 +615,7 @@ void IdealGraphPrinter::visit_node(Node *n, void *param) { ...@@ -615,6 +615,7 @@ void IdealGraphPrinter::visit_node(Node *n, void *param) {
} }
} }
#ifdef ASSERT
if (node->debug_orig() != NULL) { if (node->debug_orig() != NULL) {
stringStream dorigStream; stringStream dorigStream;
Node* dorig = node->debug_orig(); Node* dorig = node->debug_orig();
...@@ -629,6 +630,7 @@ void IdealGraphPrinter::visit_node(Node *n, void *param) { ...@@ -629,6 +630,7 @@ void IdealGraphPrinter::visit_node(Node *n, void *param) {
} }
print_prop("debug_orig", dorigStream.as_string()); print_prop("debug_orig", dorigStream.as_string());
} }
#endif
if (_chaitin && _chaitin != (PhaseChaitin *)0xdeadbeef) { if (_chaitin && _chaitin != (PhaseChaitin *)0xdeadbeef) {
buffer[0] = 0; buffer[0] = 0;
......
...@@ -265,7 +265,7 @@ MethodHandleWalker::walk(TRAPS) { ...@@ -265,7 +265,7 @@ MethodHandleWalker::walk(TRAPS) {
assert(dest == arg_state->_type, ""); assert(dest == arg_state->_type, "");
ArgToken arg = arg_state->_arg; ArgToken arg = arg_state->_arg;
ArgToken new_arg = make_conversion(T_OBJECT, dest_klass, Bytecodes::_checkcast, arg, CHECK_(empty)); 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); debug_only(dest_klass = (klassOop)badOop);
break; break;
} }
...@@ -443,8 +443,10 @@ MethodHandleWalker::walk(TRAPS) { ...@@ -443,8 +443,10 @@ MethodHandleWalker::walk(TRAPS) {
ret = make_conversion(T_OBJECT, rklass, Bytecodes::_checkcast, ret, CHECK_(empty)); ret = make_conversion(T_OBJECT, rklass, Bytecodes::_checkcast, ret, CHECK_(empty));
} }
} }
int ret_slot = arg_slot + (retain_original_args ? coll_slots : 0); if (rtype != T_VOID) {
change_argument(T_VOID, ret_slot, rtype, ret); int ret_slot = arg_slot + (retain_original_args ? coll_slots : 0);
change_argument(T_VOID, ret_slot, rtype, ret);
}
break; break;
} }
...@@ -690,9 +692,8 @@ void MethodHandleWalker::retype_raw_conversion(BasicType src, BasicType dst, boo ...@@ -690,9 +692,8 @@ void MethodHandleWalker::retype_raw_conversion(BasicType src, BasicType dst, boo
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// MethodHandleCompiler // 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), : MethodHandleWalker(root, is_invokedynamic, THREAD),
_callee(callee),
_invoke_count(invoke_count), _invoke_count(invoke_count),
_thread(THREAD), _thread(THREAD),
_bytecode(THREAD, 50), _bytecode(THREAD, 50),
...@@ -706,8 +707,8 @@ MethodHandleCompiler::MethodHandleCompiler(Handle root, methodHandle callee, int ...@@ -706,8 +707,8 @@ MethodHandleCompiler::MethodHandleCompiler(Handle root, methodHandle callee, int
(void) _constants.append(NULL); (void) _constants.append(NULL);
// Set name and signature index. // Set name and signature index.
_name_index = cpool_symbol_put(_callee->name()); _name_index = cpool_symbol_put(name);
_signature_index = cpool_symbol_put(_callee->signature()); _signature_index = cpool_symbol_put(signature);
// Get return type klass. // Get return type klass.
Handle first_mtype(THREAD, chain().method_type_oop()); Handle first_mtype(THREAD, chain().method_type_oop());
...@@ -715,7 +716,8 @@ MethodHandleCompiler::MethodHandleCompiler(Handle root, methodHandle callee, int ...@@ -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); _rtype = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::rtype(first_mtype()), &_rklass);
if (_rtype == T_ARRAY) _rtype = T_OBJECT; 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? _num_params = for_invokedynamic() ? params - 1 : params; // XXX Check if callee is static?
} }
...@@ -733,7 +735,7 @@ methodHandle MethodHandleCompiler::compile(TRAPS) { ...@@ -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? Bytecodes::check(op); // Are we legal?
switch (op) { switch (op) {
...@@ -809,6 +811,14 @@ void MethodHandleCompiler::emit_bc(Bytecodes::Code op, int index) { ...@@ -809,6 +811,14 @@ void MethodHandleCompiler::emit_bc(Bytecodes::Code op, int index) {
case Bytecodes::_d2i: case Bytecodes::_d2i:
case Bytecodes::_d2l: case Bytecodes::_d2l:
case Bytecodes::_d2f: 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::_ireturn:
case Bytecodes::_lreturn: case Bytecodes::_lreturn:
case Bytecodes::_freturn: case Bytecodes::_freturn:
...@@ -822,9 +832,14 @@ void MethodHandleCompiler::emit_bc(Bytecodes::Code op, int index) { ...@@ -822,9 +832,14 @@ void MethodHandleCompiler::emit_bc(Bytecodes::Code op, int index) {
// bi // bi
case Bytecodes::_ldc: case Bytecodes::_ldc:
assert(Bytecodes::format_bits(op, false) == (Bytecodes::_fmt_b|Bytecodes::_fmt_has_k), "wrong bytecode format"); 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"); if (index == (index & 0xff)) {
_bytecode.push(op); _bytecode.push(op);
_bytecode.push(index); _bytecode.push(index);
} else {
_bytecode.push(Bytecodes::_ldc_w);
_bytecode.push(index >> 8);
_bytecode.push(index);
}
break; break;
case Bytecodes::_iload: case Bytecodes::_iload:
...@@ -838,9 +853,16 @@ void MethodHandleCompiler::emit_bc(Bytecodes::Code op, int index) { ...@@ -838,9 +853,16 @@ void MethodHandleCompiler::emit_bc(Bytecodes::Code op, int index) {
case Bytecodes::_dstore: case Bytecodes::_dstore:
case Bytecodes::_astore: case Bytecodes::_astore:
assert(Bytecodes::format_bits(op, false) == Bytecodes::_fmt_bi, "wrong bytecode format"); assert(Bytecodes::format_bits(op, false) == Bytecodes::_fmt_bi, "wrong bytecode format");
assert((char) index == index, "index does not fit in 8-bit"); if (index == (index & 0xff)) {
_bytecode.push(op); _bytecode.push(op);
_bytecode.push(index); _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; break;
// bkk // bkk
...@@ -848,7 +870,7 @@ void MethodHandleCompiler::emit_bc(Bytecodes::Code op, int index) { ...@@ -848,7 +870,7 @@ void MethodHandleCompiler::emit_bc(Bytecodes::Code op, int index) {
case Bytecodes::_ldc2_w: case Bytecodes::_ldc2_w:
case Bytecodes::_checkcast: case Bytecodes::_checkcast:
assert(Bytecodes::format_bits(op, false) == Bytecodes::_fmt_bkk, "wrong bytecode format"); 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(op);
_bytecode.push(index >> 8); _bytecode.push(index >> 8);
_bytecode.push(index); _bytecode.push(index);
...@@ -859,12 +881,23 @@ void MethodHandleCompiler::emit_bc(Bytecodes::Code op, int index) { ...@@ -859,12 +881,23 @@ void MethodHandleCompiler::emit_bc(Bytecodes::Code op, int index) {
case Bytecodes::_invokespecial: case Bytecodes::_invokespecial:
case Bytecodes::_invokevirtual: case Bytecodes::_invokevirtual:
assert(Bytecodes::format_bits(op, false) == Bytecodes::_fmt_bJJ, "wrong bytecode format"); 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(op);
_bytecode.push(index >> 8); _bytecode.push(index >> 8);
_bytecode.push(index); _bytecode.push(index);
break; 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: default:
ShouldNotReachHere(); ShouldNotReachHere();
} }
...@@ -983,7 +1016,8 @@ MethodHandleCompiler::make_conversion(BasicType type, klassOop tk, Bytecodes::Co ...@@ -983,7 +1016,8 @@ MethodHandleCompiler::make_conversion(BasicType type, klassOop tk, Bytecodes::Co
const ArgToken& src, TRAPS) { const ArgToken& src, TRAPS) {
BasicType srctype = src.basic_type(); BasicType srctype = src.basic_type();
int index = src.index(); TokenType tt = src.token_type();
int index = -1;
switch (op) { switch (op) {
case Bytecodes::_i2l: case Bytecodes::_i2l:
...@@ -1004,18 +1038,31 @@ MethodHandleCompiler::make_conversion(BasicType type, klassOop tk, Bytecodes::Co ...@@ -1004,18 +1038,31 @@ MethodHandleCompiler::make_conversion(BasicType type, klassOop tk, Bytecodes::Co
case Bytecodes::_d2i: case Bytecodes::_d2i:
case Bytecodes::_d2l: case Bytecodes::_d2l:
case Bytecodes::_d2f: 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 stack_pop(srctype); // pop the src type
emit_bc(op); emit_bc(op);
stack_push(type); // push the dest value 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); index = new_local_index(type);
emit_store(type, index); emit_store(type, index);
break; break;
case Bytecodes::_checkcast: 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)); emit_bc(op, cpool_klass_put(tk));
if (index == -1)
index = new_local_index(type);
emit_store(srctype, index); emit_store(srctype, index);
break; break;
...@@ -1058,6 +1105,11 @@ MethodHandleCompiler::make_invoke(methodOop m, vmIntrinsics::ID iid, ...@@ -1058,6 +1105,11 @@ MethodHandleCompiler::make_invoke(methodOop m, vmIntrinsics::ID iid,
Symbol* name = m->name(); Symbol* name = m->name();
Symbol* signature = m->signature(); 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) { if (tailcall) {
// Actually, in order to make these methods more recognizable, // Actually, in order to make these methods more recognizable,
// let's put them in holder class MethodHandle. That way stack // let's put them in holder class MethodHandle. That way stack
...@@ -1106,9 +1158,13 @@ MethodHandleCompiler::make_invoke(methodOop m, vmIntrinsics::ID iid, ...@@ -1106,9 +1158,13 @@ MethodHandleCompiler::make_invoke(methodOop m, vmIntrinsics::ID iid,
case Bytecodes::_invokevirtual: case Bytecodes::_invokevirtual:
emit_bc(op, methodref_index); emit_bc(op, methodref_index);
break; break;
case Bytecodes::_invokeinterface:
Unimplemented(); case Bytecodes::_invokeinterface: {
ArgumentSizeComputer asc(signature);
emit_bc(op, methodref_index, asc.size() + 1);
break; break;
}
default: default:
ShouldNotReachHere(); ShouldNotReachHere();
} }
...@@ -1117,6 +1173,7 @@ MethodHandleCompiler::make_invoke(methodOop m, vmIntrinsics::ID iid, ...@@ -1117,6 +1173,7 @@ MethodHandleCompiler::make_invoke(methodOop m, vmIntrinsics::ID iid,
// Otherwise, make a recursive call to some helper routine. // Otherwise, make a recursive call to some helper routine.
BasicType rbt = m->result_type(); BasicType rbt = m->result_type();
if (rbt == T_ARRAY) rbt = T_OBJECT; if (rbt == T_ARRAY) rbt = T_OBJECT;
stack_push(rbt); // The return value is already pushed onto the stack.
ArgToken ret; ArgToken ret;
if (tailcall) { if (tailcall) {
if (rbt != _rtype) { if (rbt != _rtype) {
...@@ -1171,7 +1228,6 @@ MethodHandleCompiler::make_invoke(methodOop m, vmIntrinsics::ID iid, ...@@ -1171,7 +1228,6 @@ MethodHandleCompiler::make_invoke(methodOop m, vmIntrinsics::ID iid,
ret = ArgToken(); // Dummy return value. ret = ArgToken(); // Dummy return value.
} }
else { else {
stack_push(rbt); // The return value is already pushed onto the stack.
int index = new_local_index(rbt); int index = new_local_index(rbt);
switch (rbt) { switch (rbt) {
case T_BOOLEAN: case T_BYTE: case T_CHAR: case T_SHORT: 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 ...@@ -1196,8 +1252,32 @@ MethodHandleCompiler::make_fetch(BasicType type, klassOop tk, Bytecodes::Code op
const MethodHandleWalker::ArgToken& base, const MethodHandleWalker::ArgToken& base,
const MethodHandleWalker::ArgToken& offset, const MethodHandleWalker::ArgToken& offset,
TRAPS) { TRAPS) {
Unimplemented(); switch (base.token_type()) {
return ArgToken(); 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: ...@@ -1372,12 +1452,10 @@ private:
return s; return s;
} }
ArgToken token(const char* str) { ArgToken token(const char* str) {
jvalue string_con; return ArgToken(str);
string_con.j = (intptr_t) str;
return ArgToken(tt_symbolic, T_LONG, string_con);
} }
const char* string(ArgToken token) { const char* string(ArgToken token) {
return (const char*) (intptr_t) token.get_jlong(); return token.str();
} }
void start_params() { void start_params() {
_param_state <<= 1; _param_state <<= 1;
......
...@@ -126,26 +126,34 @@ public: ...@@ -126,26 +126,34 @@ public:
Handle _handle; Handle _handle;
public: public:
ArgToken(TokenType tt = tt_illegal) : _tt(tt) {} ArgToken(TokenType tt = tt_illegal) : _tt(tt) {
ArgToken(TokenType tt, BasicType bt, jvalue value) : _tt(tt), _bt(bt), _value(value) {} assert(tt == tt_illegal || tt == tt_void, "invalid token type");
}
ArgToken(TokenType tt, BasicType bt, int index) : _tt(tt), _bt(bt) { ArgToken(TokenType tt, BasicType bt, int index) : _tt(tt), _bt(bt) {
assert(_tt == tt_parameter || _tt == tt_temporary, "must have index");
_value.i = index; _value.i = index;
} }
ArgToken(TokenType tt, BasicType bt, Handle value) : _tt(tt), _bt(bt) { ArgToken(BasicType bt, jvalue value) : _tt(tt_constant), _bt(bt), _value(value) {}
_handle = 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; } TokenType token_type() const { return _tt; }
BasicType basic_type() const { return _bt; } BasicType basic_type() const { return _bt; }
int index() const { return _value.i; } bool has_index() const { return _tt == tt_parameter || _tt == tt_temporary; }
Handle object() const { return _handle; } int index() const { assert(has_index(), "must have index");; return _value.i; }
Handle object() const { assert(_tt == tt_constant, "value type"); return _handle; }
jint get_jint() const { return _value.i; } const char* str() const { assert(_tt == tt_symbolic, "string type"); return (const char*)_value.j; }
jlong get_jlong() const { return _value.j; }
jfloat get_jfloat() const { return _value.f; } jint get_jint() const { assert(_tt == tt_constant, "value types"); return _value.i; }
jdouble get_jdouble() const { return _value.d; } 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: // Abstract interpretation state:
...@@ -256,7 +264,6 @@ public: ...@@ -256,7 +264,6 @@ public:
// The IR happens to be JVM bytecodes. // The IR happens to be JVM bytecodes.
class MethodHandleCompiler : public MethodHandleWalker { class MethodHandleCompiler : public MethodHandleWalker {
private: private:
methodHandle _callee;
int _invoke_count; // count the original call site has been executed int _invoke_count; // count the original call site has been executed
KlassHandle _rklass; // Return type for casting. KlassHandle _rklass; // Return type for casting.
BasicType _rtype; BasicType _rtype;
...@@ -404,7 +411,7 @@ private: ...@@ -404,7 +411,7 @@ private:
return cpool_oop_reference_put(JVM_CONSTANT_NameAndType, name_index, 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_bc(Bytecodes::Code op, int index = 0, int args_size = -1);
void emit_load(BasicType bt, int index); void emit_load(BasicType bt, int index);
void emit_store(BasicType bt, int index); void emit_store(BasicType bt, int index);
void emit_load_constant(ArgToken arg); void emit_load_constant(ArgToken arg);
...@@ -414,10 +421,10 @@ private: ...@@ -414,10 +421,10 @@ private:
} }
virtual ArgToken make_oop_constant(oop con, TRAPS) { virtual ArgToken make_oop_constant(oop con, TRAPS) {
Handle h(THREAD, con); 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) { 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); virtual ArgToken make_conversion(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& src, TRAPS);
...@@ -431,7 +438,7 @@ private: ...@@ -431,7 +438,7 @@ private:
methodHandle get_method_oop(TRAPS) const; methodHandle get_method_oop(TRAPS) const;
public: 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. // Compile the given MH chain into bytecode.
methodHandle compile(TRAPS); methodHandle compile(TRAPS);
......
...@@ -25,9 +25,11 @@ ...@@ -25,9 +25,11 @@
#include "precompiled.hpp" #include "precompiled.hpp"
#include "classfile/symbolTable.hpp" #include "classfile/symbolTable.hpp"
#include "interpreter/interpreter.hpp" #include "interpreter/interpreter.hpp"
#include "interpreter/oopMapCache.hpp"
#include "memory/allocation.inline.hpp" #include "memory/allocation.inline.hpp"
#include "memory/oopFactory.hpp" #include "memory/oopFactory.hpp"
#include "prims/methodHandles.hpp" #include "prims/methodHandles.hpp"
#include "prims/methodHandleWalk.hpp"
#include "runtime/javaCalls.hpp" #include "runtime/javaCalls.hpp"
#include "runtime/reflection.hpp" #include "runtime/reflection.hpp"
#include "runtime/signature.hpp" #include "runtime/signature.hpp"
...@@ -2599,6 +2601,50 @@ void MethodHandles::ensure_vmlayout_field(Handle target, TRAPS) { ...@@ -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. // Here are the native methods on sun.invoke.MethodHandleImpl.
// They are the private interface between this JVM and the HotSpot-specific // 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, ...@@ -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); MethodHandles::init_DirectMethodHandle(mh, m, (do_dispatch != JNI_FALSE), CHECK);
stress_method_handle_walk(mh, CHECK);
} }
JVM_END JVM_END
...@@ -2694,11 +2741,11 @@ JVM_ENTRY(void, MHN_init_BMH(JNIEnv *env, jobject igcls, jobject mh_jh, ...@@ -2694,11 +2741,11 @@ JVM_ENTRY(void, MHN_init_BMH(JNIEnv *env, jobject igcls, jobject mh_jh,
receiver_limit, receiver_limit,
decode_flags, decode_flags,
CHECK); CHECK);
return; } else {
// Build a BMH on top of a DMH or another BMH:
MethodHandles::init_BoundMethodHandle(mh, target, argnum, CHECK);
} }
stress_method_handle_walk(mh, CHECK);
// Build a BMH on top of a DMH or another BMH:
MethodHandles::init_BoundMethodHandle(mh, target, argnum, CHECK);
} }
JVM_END JVM_END
...@@ -2716,6 +2763,7 @@ JVM_ENTRY(void, MHN_init_AMH(JNIEnv *env, jobject igcls, jobject mh_jh, ...@@ -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"); assert(java_lang_invoke_MethodHandle::vmentry(mh()) == NULL, "must be safely null");
MethodHandles::init_AdapterMethodHandle(mh, target, argnum, CHECK); MethodHandles::init_AdapterMethodHandle(mh, target, argnum, CHECK);
stress_method_handle_walk(mh, CHECK);
} }
JVM_END JVM_END
......
...@@ -3724,6 +3724,9 @@ class CommandLineFlags { ...@@ -3724,6 +3724,9 @@ class CommandLineFlags {
diagnostic(bool, OptimizeMethodHandles, true, \ diagnostic(bool, OptimizeMethodHandles, true, \
"when constructing method handles, try to improve them") \ "when constructing method handles, try to improve them") \
\ \
develop(bool, StressMethodHandleWalk, false, \
"Process all method handles with MethodHandleWalk") \
\
diagnostic(bool, UseRicochetFrames, true, \ diagnostic(bool, UseRicochetFrames, true, \
"use ricochet stack frames for method handle combination, " \ "use ricochet stack frames for method handle combination, " \
"if the platform supports them") \ "if the platform supports them") \
......
...@@ -2861,6 +2861,7 @@ void JavaThread::trace_frames() { ...@@ -2861,6 +2861,7 @@ void JavaThread::trace_frames() {
} }
#ifdef ASSERT
// Print or validate the layout of stack frames // Print or validate the layout of stack frames
void JavaThread::print_frame_layout(int depth, bool validate_only) { void JavaThread::print_frame_layout(int depth, bool validate_only) {
ResourceMark rm; ResourceMark rm;
...@@ -2878,7 +2879,7 @@ void JavaThread::print_frame_layout(int depth, bool validate_only) { ...@@ -2878,7 +2879,7 @@ void JavaThread::print_frame_layout(int depth, bool validate_only) {
values.print(); values.print();
} }
} }
#endif
void JavaThread::trace_stack_from(vframe* start_vf) { void JavaThread::trace_stack_from(vframe* start_vf) {
ResourceMark rm; ResourceMark rm;
......
...@@ -783,6 +783,7 @@ static inline uint64_t cast_uint64_t(size_t x) ...@@ -783,6 +783,7 @@ static inline uint64_t cast_uint64_t(size_t x)
nonstatic_field(nmethod, _osr_link, nmethod*) \ nonstatic_field(nmethod, _osr_link, nmethod*) \
nonstatic_field(nmethod, _scavenge_root_link, nmethod*) \ nonstatic_field(nmethod, _scavenge_root_link, nmethod*) \
nonstatic_field(nmethod, _scavenge_root_state, jbyte) \ nonstatic_field(nmethod, _scavenge_root_state, jbyte) \
nonstatic_field(nmethod, _state, unsigned char) \
nonstatic_field(nmethod, _exception_offset, int) \ nonstatic_field(nmethod, _exception_offset, int) \
nonstatic_field(nmethod, _deoptimize_offset, int) \ nonstatic_field(nmethod, _deoptimize_offset, int) \
nonstatic_field(nmethod, _orig_pc_offset, int) \ nonstatic_field(nmethod, _orig_pc_offset, int) \
...@@ -800,6 +801,8 @@ static inline uint64_t cast_uint64_t(size_t x) ...@@ -800,6 +801,8 @@ static inline uint64_t cast_uint64_t(size_t x)
nonstatic_field(nmethod, _osr_entry_point, address) \ nonstatic_field(nmethod, _osr_entry_point, address) \
nonstatic_field(nmethod, _lock_count, jint) \ nonstatic_field(nmethod, _lock_count, jint) \
nonstatic_field(nmethod, _stack_traversal_mark, long) \ nonstatic_field(nmethod, _stack_traversal_mark, long) \
nonstatic_field(nmethod, _compile_id, int) \
nonstatic_field(nmethod, _marked_for_deoptimization, bool) \
\ \
/********************************/ \ /********************************/ \
/* JavaCalls (NOTE: incomplete) */ \ /* JavaCalls (NOTE: incomplete) */ \
...@@ -1310,11 +1313,13 @@ static inline uint64_t cast_uint64_t(size_t x) ...@@ -1310,11 +1313,13 @@ static inline uint64_t cast_uint64_t(size_t x)
\ \
declare_toplevel_type(CodeBlob) \ declare_toplevel_type(CodeBlob) \
declare_type(BufferBlob, CodeBlob) \ declare_type(BufferBlob, CodeBlob) \
declare_type(nmethod, CodeBlob) \ declare_type(AdapterBlob, BufferBlob) \
declare_type(nmethod, CodeBlob) \
declare_type(RuntimeStub, CodeBlob) \ declare_type(RuntimeStub, CodeBlob) \
declare_type(SingletonBlob, CodeBlob) \ declare_type(SingletonBlob, CodeBlob) \
declare_type(SafepointBlob, SingletonBlob) \ declare_type(SafepointBlob, SingletonBlob) \
declare_type(DeoptimizationBlob, SingletonBlob) \ declare_type(DeoptimizationBlob, SingletonBlob) \
declare_type(RicochetBlob, SingletonBlob) \
declare_c2_type(ExceptionBlob, SingletonBlob) \ declare_c2_type(ExceptionBlob, SingletonBlob) \
declare_c2_type(UncommonTrapBlob, CodeBlob) \ declare_c2_type(UncommonTrapBlob, CodeBlob) \
\ \
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册