mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
Merge
This commit is contained in:
commit
6f0a3e4a80
10 changed files with 75 additions and 160 deletions
|
@ -206,7 +206,6 @@ void CppInterpreter::native_entry(methodOop method, intptr_t UNUSED, TRAPS) {
|
||||||
|
|
||||||
// Update the invocation counter
|
// Update the invocation counter
|
||||||
if ((UseCompiler || CountCompiledCalls) && !method->is_synchronized()) {
|
if ((UseCompiler || CountCompiledCalls) && !method->is_synchronized()) {
|
||||||
thread->set_do_not_unlock();
|
|
||||||
InvocationCounter *counter = method->invocation_counter();
|
InvocationCounter *counter = method->invocation_counter();
|
||||||
counter->increment();
|
counter->increment();
|
||||||
if (counter->reached_InvocationLimit()) {
|
if (counter->reached_InvocationLimit()) {
|
||||||
|
@ -215,7 +214,6 @@ void CppInterpreter::native_entry(methodOop method, intptr_t UNUSED, TRAPS) {
|
||||||
if (HAS_PENDING_EXCEPTION)
|
if (HAS_PENDING_EXCEPTION)
|
||||||
goto unwind_and_return;
|
goto unwind_and_return;
|
||||||
}
|
}
|
||||||
thread->clr_do_not_unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lock if necessary
|
// Lock if necessary
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* Copyright 2009 Red Hat, Inc.
|
* Copyright 2009, 2010 Red Hat, Inc.
|
||||||
* 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
|
||||||
|
@ -23,4 +23,10 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// This file is intentionally empty
|
#include "incls/_precompiled.incl"
|
||||||
|
#include "incls/_methodHandles_zero.cpp.incl"
|
||||||
|
|
||||||
|
void MethodHandles::generate_method_handle_stub(MacroAssembler* masm,
|
||||||
|
MethodHandles::EntryKind ek) {
|
||||||
|
ShouldNotCallThis();
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* Copyright 2007, 2008, 2009 Red Hat, Inc.
|
* Copyright 2007, 2008, 2009, 2010 Red Hat, Inc.
|
||||||
* 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
|
||||||
|
@ -41,6 +41,10 @@
|
||||||
code_size2 = 0 // if these are too small. Simply increase
|
code_size2 = 0 // if these are too small. Simply increase
|
||||||
}; // them if that happens.
|
}; // them if that happens.
|
||||||
|
|
||||||
|
enum method_handles_platform_dependent_constants {
|
||||||
|
method_handles_adapters_code_size = 0
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef IA32
|
#ifdef IA32
|
||||||
class x86 {
|
class x86 {
|
||||||
friend class VMStructs;
|
friend class VMStructs;
|
||||||
|
|
|
@ -36,7 +36,7 @@ void ciConstant::print() {
|
||||||
basictype_to_str(basic_type()));
|
basictype_to_str(basic_type()));
|
||||||
switch (basic_type()) {
|
switch (basic_type()) {
|
||||||
case T_BOOLEAN:
|
case T_BOOLEAN:
|
||||||
tty->print("%s", bool_to_str(_value._int == 0));
|
tty->print("%s", bool_to_str(_value._int != 0));
|
||||||
break;
|
break;
|
||||||
case T_CHAR:
|
case T_CHAR:
|
||||||
case T_BYTE:
|
case T_BYTE:
|
||||||
|
|
|
@ -2328,6 +2328,17 @@ run:
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFAULT:
|
DEFAULT:
|
||||||
|
#ifdef ZERO
|
||||||
|
// Some zero configurations use the C++ interpreter as a
|
||||||
|
// fallback interpreter and have support for platform
|
||||||
|
// specific fast bytecodes which aren't supported here, so
|
||||||
|
// redispatch to the equivalent non-fast bytecode when they
|
||||||
|
// are encountered.
|
||||||
|
if (Bytecodes::is_defined((Bytecodes::Code)opcode)) {
|
||||||
|
opcode = (jubyte)Bytecodes::java_code((Bytecodes::Code)opcode);
|
||||||
|
goto opcode_switch;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
fatal2("\t*** Unimplemented opcode: %d = %s\n",
|
fatal2("\t*** Unimplemented opcode: %d = %s\n",
|
||||||
opcode, Bytecodes::name((Bytecodes::Code)opcode));
|
opcode, Bytecodes::name((Bytecodes::Code)opcode));
|
||||||
goto finish;
|
goto finish;
|
||||||
|
|
|
@ -714,8 +714,6 @@ void Parse::catch_inline_exceptions(SafePointNode* ex_map) {
|
||||||
|
|
||||||
// iterate through all entries sequentially
|
// iterate through all entries sequentially
|
||||||
for (;!handlers.is_done(); handlers.next()) {
|
for (;!handlers.is_done(); handlers.next()) {
|
||||||
// Do nothing if turned off
|
|
||||||
if( !DeutschShiffmanExceptions ) break;
|
|
||||||
ciExceptionHandler* handler = handlers.handler();
|
ciExceptionHandler* handler = handlers.handler();
|
||||||
|
|
||||||
if (handler->is_rethrow()) {
|
if (handler->is_rethrow()) {
|
||||||
|
@ -741,46 +739,26 @@ void Parse::catch_inline_exceptions(SafePointNode* ex_map) {
|
||||||
return; // No more handling to be done here!
|
return; // No more handling to be done here!
|
||||||
}
|
}
|
||||||
|
|
||||||
// %%% The following logic replicates make_from_klass_unique.
|
// Get the handler's klass
|
||||||
// TO DO: Replace by a subroutine call. Then generalize
|
|
||||||
// the type check, as noted in the next "%%%" comment.
|
|
||||||
|
|
||||||
ciInstanceKlass* klass = handler->catch_klass();
|
ciInstanceKlass* klass = handler->catch_klass();
|
||||||
if (UseUniqueSubclasses) {
|
|
||||||
// (We use make_from_klass because it respects UseUniqueSubclasses.)
|
if (!klass->is_loaded()) { // klass is not loaded?
|
||||||
const TypeOopPtr* tp = TypeOopPtr::make_from_klass(klass);
|
// fall through into catch_call_exceptions which will emit a
|
||||||
klass = tp->klass()->as_instance_klass();
|
// handler with an uncommon trap.
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the handler's klass
|
|
||||||
if (!klass->is_loaded()) // klass is not loaded?
|
|
||||||
break; // Must call Rethrow!
|
|
||||||
if (klass->is_interface()) // should not happen, but...
|
if (klass->is_interface()) // should not happen, but...
|
||||||
break; // bail out
|
break; // bail out
|
||||||
// See if the loaded exception klass has no subtypes
|
|
||||||
if (klass->has_subklass())
|
|
||||||
break; // Cannot easily do precise test ==> Rethrow
|
|
||||||
|
|
||||||
// %%% Now that subclass checking is very fast, we need to rewrite
|
// Check the type of the exception against the catch type
|
||||||
// this section and remove the option "DeutschShiffmanExceptions".
|
|
||||||
// The exception processing chain should be a normal typecase pattern,
|
|
||||||
// with a bailout to the interpreter only in the case of unloaded
|
|
||||||
// classes. (The bailout should mark the method non-entrant.)
|
|
||||||
// This rewrite should be placed in GraphKit::, not Parse::.
|
|
||||||
|
|
||||||
// Add a dependence; if any subclass added we need to recompile
|
|
||||||
// %%% should use stronger assert_unique_concrete_subtype instead
|
|
||||||
if (!klass->is_final()) {
|
|
||||||
C->dependencies()->assert_leaf_type(klass);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implement precise test
|
|
||||||
const TypeKlassPtr *tk = TypeKlassPtr::make(klass);
|
const TypeKlassPtr *tk = TypeKlassPtr::make(klass);
|
||||||
Node* con = _gvn.makecon(tk);
|
Node* con = _gvn.makecon(tk);
|
||||||
Node* cmp = _gvn.transform( new (C, 3) CmpPNode(ex_klass_node, con) );
|
Node* not_subtype_ctrl = gen_subtype_check(ex_klass_node, con);
|
||||||
Node* bol = _gvn.transform( new (C, 2) BoolNode(cmp, BoolTest::ne) );
|
if (!stopped()) {
|
||||||
{ BuildCutout unless(this, bol, PROB_LIKELY(0.7f));
|
PreserveJVMState pjvms(this);
|
||||||
const TypeInstPtr* tinst = TypeInstPtr::make_exact(TypePtr::NotNull, klass);
|
const TypeInstPtr* tinst = TypeOopPtr::make_from_klass_unique(klass)->cast_to_ptr_type(TypePtr::NotNull)->is_instptr();
|
||||||
|
assert(klass->has_subklass() || tinst->klass_is_exact(), "lost exactness");
|
||||||
Node* ex_oop = _gvn.transform(new (C, 2) CheckCastPPNode(control(), ex_node, tinst));
|
Node* ex_oop = _gvn.transform(new (C, 2) CheckCastPPNode(control(), ex_node, tinst));
|
||||||
push_ex_oop(ex_oop); // Push exception oop for handler
|
push_ex_oop(ex_oop); // Push exception oop for handler
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
|
@ -792,6 +770,7 @@ void Parse::catch_inline_exceptions(SafePointNode* ex_map) {
|
||||||
#endif
|
#endif
|
||||||
merge_exception(handler_bci);
|
merge_exception(handler_bci);
|
||||||
}
|
}
|
||||||
|
set_control(not_subtype_ctrl);
|
||||||
|
|
||||||
// Come here if exception does not match handler.
|
// Come here if exception does not match handler.
|
||||||
// Carry on with more handler checks.
|
// Carry on with more handler checks.
|
||||||
|
@ -800,21 +779,6 @@ void Parse::catch_inline_exceptions(SafePointNode* ex_map) {
|
||||||
|
|
||||||
assert(!stopped(), "you should return if you finish the chain");
|
assert(!stopped(), "you should return if you finish the chain");
|
||||||
|
|
||||||
if (remaining == 1) {
|
|
||||||
// Further checks do not matter.
|
|
||||||
}
|
|
||||||
|
|
||||||
if (can_rerun_bytecode()) {
|
|
||||||
// Do not push_ex_oop here!
|
|
||||||
// Re-executing the bytecode will reproduce the throwing condition.
|
|
||||||
bool must_throw = true;
|
|
||||||
uncommon_trap(Deoptimization::Reason_unhandled,
|
|
||||||
Deoptimization::Action_none,
|
|
||||||
(ciKlass*)NULL, (const char*)NULL, // default args
|
|
||||||
must_throw);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Oops, need to call into the VM to resolve the klasses at runtime.
|
// Oops, need to call into the VM to resolve the klasses at runtime.
|
||||||
// Note: This call must not deoptimize, since it is not a real at this bci!
|
// Note: This call must not deoptimize, since it is not a real at this bci!
|
||||||
kill_dead_locals();
|
kill_dead_locals();
|
||||||
|
|
|
@ -551,9 +551,6 @@ class Parse : public GraphKit {
|
||||||
// Also handles exceptions for individual bytecodes.
|
// Also handles exceptions for individual bytecodes.
|
||||||
void catch_inline_exceptions(SafePointNode* ex_map);
|
void catch_inline_exceptions(SafePointNode* ex_map);
|
||||||
|
|
||||||
// Bytecode classifier, helps decide to use uncommon_trap vs. rethrow_C.
|
|
||||||
bool can_rerun_bytecode();
|
|
||||||
|
|
||||||
// Merge the given map into correct exceptional exit state.
|
// Merge the given map into correct exceptional exit state.
|
||||||
// Assumes that there is no applicable local handler.
|
// Assumes that there is no applicable local handler.
|
||||||
void throw_to_exit(SafePointNode* ex_map);
|
void throw_to_exit(SafePointNode* ex_map);
|
||||||
|
|
|
@ -798,67 +798,6 @@ void Compile::rethrow_exceptions(JVMState* jvms) {
|
||||||
initial_gvn()->transform_no_reclaim(exit);
|
initial_gvn()->transform_no_reclaim(exit);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Parse::can_rerun_bytecode() {
|
|
||||||
switch (bc()) {
|
|
||||||
case Bytecodes::_ldc:
|
|
||||||
case Bytecodes::_ldc_w:
|
|
||||||
case Bytecodes::_ldc2_w:
|
|
||||||
case Bytecodes::_getfield:
|
|
||||||
case Bytecodes::_putfield:
|
|
||||||
case Bytecodes::_getstatic:
|
|
||||||
case Bytecodes::_putstatic:
|
|
||||||
case Bytecodes::_arraylength:
|
|
||||||
case Bytecodes::_baload:
|
|
||||||
case Bytecodes::_caload:
|
|
||||||
case Bytecodes::_iaload:
|
|
||||||
case Bytecodes::_saload:
|
|
||||||
case Bytecodes::_faload:
|
|
||||||
case Bytecodes::_aaload:
|
|
||||||
case Bytecodes::_laload:
|
|
||||||
case Bytecodes::_daload:
|
|
||||||
case Bytecodes::_bastore:
|
|
||||||
case Bytecodes::_castore:
|
|
||||||
case Bytecodes::_iastore:
|
|
||||||
case Bytecodes::_sastore:
|
|
||||||
case Bytecodes::_fastore:
|
|
||||||
case Bytecodes::_aastore:
|
|
||||||
case Bytecodes::_lastore:
|
|
||||||
case Bytecodes::_dastore:
|
|
||||||
case Bytecodes::_irem:
|
|
||||||
case Bytecodes::_idiv:
|
|
||||||
case Bytecodes::_lrem:
|
|
||||||
case Bytecodes::_ldiv:
|
|
||||||
case Bytecodes::_frem:
|
|
||||||
case Bytecodes::_fdiv:
|
|
||||||
case Bytecodes::_drem:
|
|
||||||
case Bytecodes::_ddiv:
|
|
||||||
case Bytecodes::_checkcast:
|
|
||||||
case Bytecodes::_instanceof:
|
|
||||||
case Bytecodes::_anewarray:
|
|
||||||
case Bytecodes::_newarray:
|
|
||||||
case Bytecodes::_multianewarray:
|
|
||||||
case Bytecodes::_new:
|
|
||||||
case Bytecodes::_monitorenter: // can re-run initial null check, only
|
|
||||||
case Bytecodes::_return:
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Don't rerun athrow since it's part of the exception path.
|
|
||||||
case Bytecodes::_athrow:
|
|
||||||
case Bytecodes::_invokestatic:
|
|
||||||
case Bytecodes::_invokedynamic:
|
|
||||||
case Bytecodes::_invokespecial:
|
|
||||||
case Bytecodes::_invokevirtual:
|
|
||||||
case Bytecodes::_invokeinterface:
|
|
||||||
return false;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
assert(false, "unexpected bytecode produced an exception");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------do_exceptions-------------------------------------
|
//---------------------------do_exceptions-------------------------------------
|
||||||
// Process exceptions arising from the current bytecode.
|
// Process exceptions arising from the current bytecode.
|
||||||
// Send caught exceptions to the proper handler within this method.
|
// Send caught exceptions to the proper handler within this method.
|
||||||
|
@ -872,9 +811,6 @@ void Parse::do_exceptions() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure we can classify this bytecode if we need to.
|
|
||||||
debug_only(can_rerun_bytecode());
|
|
||||||
|
|
||||||
PreserveJVMState pjvms(this, false);
|
PreserveJVMState pjvms(this, false);
|
||||||
|
|
||||||
SafePointNode* ex_map;
|
SafePointNode* ex_map;
|
||||||
|
|
|
@ -55,8 +55,7 @@ class vframeStreamForte : public vframeStreamCommon {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static void is_decipherable_compiled_frame(frame* fr, RegisterMap* map,
|
static bool is_decipherable_compiled_frame(JavaThread* thread, frame* fr, nmethod* nm);
|
||||||
bool* is_compiled_p, bool* is_walkable_p);
|
|
||||||
static bool is_decipherable_interpreted_frame(JavaThread* thread,
|
static bool is_decipherable_interpreted_frame(JavaThread* thread,
|
||||||
frame* fr,
|
frame* fr,
|
||||||
methodOop* method_p,
|
methodOop* method_p,
|
||||||
|
@ -122,26 +121,30 @@ void vframeStreamForte::forte_next() {
|
||||||
// Determine if 'fr' is a decipherable compiled frame. We are already
|
// Determine if 'fr' is a decipherable compiled frame. We are already
|
||||||
// assured that fr is for a java nmethod.
|
// assured that fr is for a java nmethod.
|
||||||
|
|
||||||
static bool is_decipherable_compiled_frame(frame* fr) {
|
static bool is_decipherable_compiled_frame(JavaThread* thread, frame* fr, nmethod* nm) {
|
||||||
|
|
||||||
assert(fr->cb() != NULL && fr->cb()->is_nmethod(), "invariant");
|
|
||||||
nmethod* nm = (nmethod*) fr->cb();
|
|
||||||
assert(nm->is_java_method(), "invariant");
|
assert(nm->is_java_method(), "invariant");
|
||||||
|
|
||||||
// First try and find an exact PcDesc
|
if (thread->has_last_Java_frame() && thread->last_Java_pc() == fr->pc()) {
|
||||||
|
// We're stopped at a call into the JVM so look for a PcDesc with
|
||||||
|
// the actual pc reported by the frame.
|
||||||
PcDesc* pc_desc = nm->pc_desc_at(fr->pc());
|
PcDesc* pc_desc = nm->pc_desc_at(fr->pc());
|
||||||
|
|
||||||
// Did we find a useful PcDesc?
|
// Did we find a useful PcDesc?
|
||||||
if (pc_desc != NULL &&
|
if (pc_desc != NULL &&
|
||||||
pc_desc->scope_decode_offset() == DebugInformationRecorder::serialized_null) {
|
pc_desc->scope_decode_offset() != DebugInformationRecorder::serialized_null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
address probe_pc = fr->pc() + 1;
|
// We're at some random pc in the nmethod so search for the PcDesc
|
||||||
pc_desc = nm->pc_desc_near(probe_pc);
|
// whose pc is greater than the current PC. It's done this way
|
||||||
|
// because the extra PcDescs that are recorded for improved debug
|
||||||
|
// info record the end of the region covered by the ScopeDesc
|
||||||
|
// instead of the beginning.
|
||||||
|
PcDesc* pc_desc = nm->pc_desc_near(fr->pc() + 1);
|
||||||
|
|
||||||
// Now do we have a useful PcDesc?
|
// Now do we have a useful PcDesc?
|
||||||
|
if (pc_desc == NULL ||
|
||||||
if (pc_desc != NULL &&
|
|
||||||
pc_desc->scope_decode_offset() == DebugInformationRecorder::serialized_null) {
|
pc_desc->scope_decode_offset() == DebugInformationRecorder::serialized_null) {
|
||||||
// No debug information available for this pc
|
// No debug information available for this pc
|
||||||
// vframeStream would explode if we try and walk the frames.
|
// vframeStream would explode if we try and walk the frames.
|
||||||
|
@ -150,13 +153,11 @@ static bool is_decipherable_compiled_frame(frame* fr) {
|
||||||
|
|
||||||
// This PcDesc is useful however we must adjust the frame's pc
|
// This PcDesc is useful however we must adjust the frame's pc
|
||||||
// so that the vframeStream lookups will use this same pc
|
// so that the vframeStream lookups will use this same pc
|
||||||
|
|
||||||
fr->set_pc(pc_desc->real_pc(nm));
|
fr->set_pc(pc_desc->real_pc(nm));
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Determine if 'fr' is a walkable interpreted frame. Returns false
|
// Determine if 'fr' is a walkable interpreted frame. Returns false
|
||||||
// if it is not. *method_p, and *bci_p are not set when false is
|
// if it is not. *method_p, and *bci_p are not set when false is
|
||||||
// returned. *method_p is non-NULL if frame was executing a Java
|
// returned. *method_p is non-NULL if frame was executing a Java
|
||||||
|
@ -323,13 +324,15 @@ static bool find_initial_Java_frame(JavaThread* thread,
|
||||||
// have a PCDesc that can get us a bci however we did find
|
// have a PCDesc that can get us a bci however we did find
|
||||||
// a method
|
// a method
|
||||||
|
|
||||||
if (!is_decipherable_compiled_frame(&candidate)) {
|
if (!is_decipherable_compiled_frame(thread, &candidate, nm)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// is_decipherable_compiled_frame may modify candidate's pc
|
// is_decipherable_compiled_frame may modify candidate's pc
|
||||||
*initial_frame_p = candidate;
|
*initial_frame_p = candidate;
|
||||||
|
|
||||||
|
assert(nm->pc_desc_at(candidate.pc()) != NULL, "if it's decipherable then pc must be valid");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2502,10 +2502,6 @@ class CommandLineFlags {
|
||||||
notproduct(bool, TraceSpilling, false, \
|
notproduct(bool, TraceSpilling, false, \
|
||||||
"Trace spilling") \
|
"Trace spilling") \
|
||||||
\
|
\
|
||||||
develop(bool, DeutschShiffmanExceptions, true, \
|
|
||||||
"Fast check to find exception handler for precisely typed " \
|
|
||||||
"exceptions") \
|
|
||||||
\
|
|
||||||
product(bool, SplitIfBlocks, true, \
|
product(bool, SplitIfBlocks, true, \
|
||||||
"Clone compares and control flow through merge points to fold " \
|
"Clone compares and control flow through merge points to fold " \
|
||||||
"some branches") \
|
"some branches") \
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue