aboutsummaryrefslogtreecommitdiff
path: root/src/share/vm/opto
diff options
context:
space:
mode:
authortwisti <none@none>2012-08-10 15:50:49 -0700
committertwisti <none@none>2012-08-10 15:50:49 -0700
commit5c203aa613f00c52384025a50048327a368f3b19 (patch)
tree2952a5512ed57bdbd58140cbee748814025816c9 /src/share/vm/opto
parent011c3dc7a80e4a281d3eab0a0b6ba79dd844a5c6 (diff)
parent10ff9a44239d87a6f26de90d5900f4bbd97cd6be (diff)
Merge
Diffstat (limited to 'src/share/vm/opto')
-rw-r--r--src/share/vm/opto/bytecodeInfo.cpp91
-rw-r--r--src/share/vm/opto/callGenerator.cpp342
-rw-r--r--src/share/vm/opto/callGenerator.hpp24
-rw-r--r--src/share/vm/opto/callnode.cpp12
-rw-r--r--src/share/vm/opto/callnode.hpp21
-rw-r--r--src/share/vm/opto/chaitin.cpp2
-rw-r--r--src/share/vm/opto/compile.cpp6
-rw-r--r--src/share/vm/opto/doCall.cpp164
-rw-r--r--src/share/vm/opto/escape.cpp22
-rw-r--r--src/share/vm/opto/escape.hpp10
-rw-r--r--src/share/vm/opto/graphKit.cpp18
-rw-r--r--src/share/vm/opto/graphKit.hpp9
-rw-r--r--src/share/vm/opto/idealGraphPrinter.cpp4
-rw-r--r--src/share/vm/opto/library_call.cpp6
-rw-r--r--src/share/vm/opto/matcher.cpp3
-rw-r--r--src/share/vm/opto/node.hpp4
-rw-r--r--src/share/vm/opto/parse.hpp2
-rw-r--r--src/share/vm/opto/parse1.cpp6
-rw-r--r--src/share/vm/opto/phaseX.hpp1
19 files changed, 317 insertions, 430 deletions
diff --git a/src/share/vm/opto/bytecodeInfo.cpp b/src/share/vm/opto/bytecodeInfo.cpp
index a8e95fcec..00632a239 100644
--- a/src/share/vm/opto/bytecodeInfo.cpp
+++ b/src/share/vm/opto/bytecodeInfo.cpp
@@ -93,7 +93,7 @@ static bool is_init_with_ea(ciMethod* callee_method,
);
}
-// positive filter: should send be inlined? returns NULL, if yes, or rejection msg
+// positive filter: should callee be inlined? returns NULL, if yes, or rejection msg
const char* InlineTree::should_inline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result) const {
// Allows targeted inlining
if(callee_method->should_inline()) {
@@ -131,33 +131,6 @@ const char* InlineTree::should_inline(ciMethod* callee_method, ciMethod* caller_
int call_site_count = method()->scale_count(profile.count());
int invoke_count = method()->interpreter_invocation_count();
- // Bytecoded method handle adapters do not have interpreter
- // profiling data but only made up MDO data. Get the counter from
- // there.
- if (caller_method->is_method_handle_adapter()) {
- assert(method()->method_data_or_null(), "must have an MDO");
- ciMethodData* mdo = method()->method_data();
- ciProfileData* mha_profile = mdo->bci_to_data(caller_bci);
- assert(mha_profile, "must exist");
- CounterData* cd = mha_profile->as_CounterData();
- invoke_count = cd->count();
- if (invoke_count == 0) {
- return "method handle not reached";
- }
-
- if (_caller_jvms != NULL && _caller_jvms->method() != NULL &&
- _caller_jvms->method()->method_data() != NULL &&
- !_caller_jvms->method()->method_data()->is_empty()) {
- ciMethodData* mdo = _caller_jvms->method()->method_data();
- ciProfileData* mha_profile = mdo->bci_to_data(_caller_jvms->bci());
- assert(mha_profile, "must exist");
- CounterData* cd = mha_profile->as_CounterData();
- call_site_count = cd->count();
- } else {
- call_site_count = invoke_count; // use the same value
- }
- }
-
assert(invoke_count != 0, "require invocation count greater than zero");
int freq = call_site_count / invoke_count;
@@ -189,15 +162,16 @@ const char* InlineTree::should_inline(ciMethod* callee_method, ciMethod* caller_
}
-// negative filter: should send NOT be inlined? returns NULL, ok to inline, or rejection msg
+// negative filter: should callee NOT be inlined? returns NULL, ok to inline, or rejection msg
const char* InlineTree::should_not_inline(ciMethod *callee_method, ciMethod* caller_method, WarmCallInfo* wci_result) const {
// negative filter: should send NOT be inlined? returns NULL (--> inline) or rejection msg
if (!UseOldInlining) {
const char* fail = NULL;
- if (callee_method->is_abstract()) fail = "abstract method";
+ if ( callee_method->is_abstract()) fail = "abstract method";
// note: we allow ik->is_abstract()
- if (!callee_method->holder()->is_initialized()) fail = "method holder not initialized";
- if (callee_method->is_native()) fail = "native method";
+ if (!callee_method->holder()->is_initialized()) fail = "method holder not initialized";
+ if ( callee_method->is_native()) fail = "native method";
+ if ( callee_method->dont_inline()) fail = "don't inline by annotation";
if (fail) {
*wci_result = *(WarmCallInfo::always_cold());
@@ -217,7 +191,8 @@ const char* InlineTree::should_not_inline(ciMethod *callee_method, ciMethod* cal
}
}
- if (callee_method->has_compiled_code() && callee_method->instructions_size(CompLevel_full_optimization) > InlineSmallCode) {
+ if (callee_method->has_compiled_code() &&
+ callee_method->instructions_size(CompLevel_full_optimization) > InlineSmallCode) {
wci_result->set_profit(wci_result->profit() * 0.1);
// %%% adjust wci_result->size()?
}
@@ -225,26 +200,25 @@ const char* InlineTree::should_not_inline(ciMethod *callee_method, ciMethod* cal
return NULL;
}
- // Always inline MethodHandle methods and generated MethodHandle adapters.
- if (callee_method->is_method_handle_invoke() || callee_method->is_method_handle_adapter())
- return NULL;
-
// First check all inlining restrictions which are required for correctness
- if (callee_method->is_abstract()) return "abstract method";
+ if ( callee_method->is_abstract()) return "abstract method";
// note: we allow ik->is_abstract()
- if (!callee_method->holder()->is_initialized()) return "method holder not initialized";
- if (callee_method->is_native()) return "native method";
- if (callee_method->has_unloaded_classes_in_signature()) return "unloaded signature classes";
+ if (!callee_method->holder()->is_initialized()) return "method holder not initialized";
+ if ( callee_method->is_native()) return "native method";
+ if ( callee_method->dont_inline()) return "don't inline by annotation";
+ if ( callee_method->has_unloaded_classes_in_signature()) return "unloaded signature classes";
- if (callee_method->should_inline()) {
+ if (callee_method->force_inline() || callee_method->should_inline()) {
// ignore heuristic controls on inlining
return NULL;
}
// Now perform checks which are heuristic
- if( callee_method->has_compiled_code() && callee_method->instructions_size(CompLevel_full_optimization) > InlineSmallCode )
+ if (callee_method->has_compiled_code() &&
+ callee_method->instructions_size(CompLevel_full_optimization) > InlineSmallCode) {
return "already compiled into a big method";
+ }
// don't inline exception code unless the top method belongs to an
// exception class
@@ -270,7 +244,7 @@ const char* InlineTree::should_not_inline(ciMethod *callee_method, ciMethod* cal
}
// use frequency-based objections only for non-trivial methods
- if (callee_method->code_size_for_inlining() <= MaxTrivialSize) return NULL;
+ if (callee_method->code_size() <= MaxTrivialSize) return NULL;
// don't use counts with -Xcomp or CTW
if (UseInterpreter && !CompileTheWorld) {
@@ -319,7 +293,7 @@ const char* InlineTree::try_to_inline(ciMethod* callee_method, ciMethod* caller_
}
// suppress a few checks for accessors and trivial methods
- if (callee_method->code_size_for_inlining() > MaxTrivialSize) {
+ if (callee_method->code_size() > MaxTrivialSize) {
// don't inline into giant methods
if (C->unique() > (uint)NodeCountInliningCutoff) {
@@ -346,7 +320,7 @@ const char* InlineTree::try_to_inline(ciMethod* callee_method, ciMethod* caller_
}
// detect direct and indirect recursive inlining
- {
+ if (!callee_method->is_compiled_lambda_form()) {
// count the current method and the callee
int inline_level = (method() == callee_method) ? 1 : 0;
if (inline_level > MaxRecursiveInlineLevel)
@@ -412,6 +386,7 @@ bool pass_initial_checks(ciMethod* caller_method, int caller_bci, ciMethod* call
const char* InlineTree::check_can_parse(ciMethod* callee) {
// Certain methods cannot be parsed at all:
if ( callee->is_native()) return "native method";
+ if ( callee->is_abstract()) return "abstract method";
if (!callee->can_be_compiled()) return "not compilable (disabled)";
if (!callee->has_balanced_monitors()) return "not compilable (unbalanced monitors)";
if ( callee->get_flow_analysis()->failing()) return "not compilable (flow analysis failed)";
@@ -426,7 +401,7 @@ void InlineTree::print_inlining(ciMethod* callee_method, int caller_bci, const c
if (Verbose && callee_method) {
const InlineTree *top = this;
while( top->caller_tree() != NULL ) { top = top->caller_tree(); }
- tty->print(" bcs: %d+%d invoked: %d", top->count_inline_bcs(), callee_method->code_size(), callee_method->interpreter_invocation_count());
+ //tty->print(" bcs: %d+%d invoked: %d", top->count_inline_bcs(), callee_method->code_size(), callee_method->interpreter_invocation_count());
}
}
@@ -449,10 +424,7 @@ WarmCallInfo* InlineTree::ok_to_inline(ciMethod* callee_method, JVMState* jvms,
// Do some initial checks.
if (!pass_initial_checks(caller_method, caller_bci, callee_method)) {
- if (PrintInlining) {
- failure_msg = "failed_initial_checks";
- print_inlining(callee_method, caller_bci, failure_msg);
- }
+ if (PrintInlining) print_inlining(callee_method, caller_bci, "failed initial checks");
return NULL;
}
@@ -539,9 +511,10 @@ InlineTree *InlineTree::build_inline_tree_for_callee( ciMethod* callee_method, J
}
int max_inline_level_adjust = 0;
if (caller_jvms->method() != NULL) {
- if (caller_jvms->method()->is_method_handle_adapter())
+ if (caller_jvms->method()->is_compiled_lambda_form())
max_inline_level_adjust += 1; // don't count actions in MH or indy adapter frames
- else if (callee_method->is_method_handle_invoke()) {
+ else if (callee_method->is_method_handle_intrinsic() ||
+ callee_method->is_compiled_lambda_form()) {
max_inline_level_adjust += 1; // don't count method handle calls from java.lang.invoke implem
}
if (max_inline_level_adjust != 0 && PrintInlining && (Verbose || WizardMode)) {
@@ -590,7 +563,7 @@ InlineTree *InlineTree::build_inline_tree_root() {
// Given a jvms, which determines a call chain from the root method,
// find the corresponding inline tree.
// Note: This method will be removed or replaced as InlineTree goes away.
-InlineTree* InlineTree::find_subtree_from_root(InlineTree* root, JVMState* jvms, ciMethod* callee, bool create_if_not_found) {
+InlineTree* InlineTree::find_subtree_from_root(InlineTree* root, JVMState* jvms, ciMethod* callee) {
InlineTree* iltp = root;
uint depth = jvms && jvms->has_method() ? jvms->depth() : 0;
for (uint d = 1; d <= depth; d++) {
@@ -599,12 +572,12 @@ InlineTree* InlineTree::find_subtree_from_root(InlineTree* root, JVMState* jvms,
assert(jvmsp->method() == iltp->method(), "tree still in sync");
ciMethod* d_callee = (d == depth) ? callee : jvms->of_depth(d+1)->method();
InlineTree* sub = iltp->callee_at(jvmsp->bci(), d_callee);
- if (!sub) {
- if (create_if_not_found && d == depth) {
- return iltp->build_inline_tree_for_callee(d_callee, jvmsp, jvmsp->bci());
+ if (sub == NULL) {
+ if (d == depth) {
+ sub = iltp->build_inline_tree_for_callee(d_callee, jvmsp, jvmsp->bci());
}
- assert(sub != NULL, "should be a sub-ilt here");
- return NULL;
+ guarantee(sub != NULL, "should be a sub-ilt here");
+ return sub;
}
iltp = sub;
}
diff --git a/src/share/vm/opto/callGenerator.cpp b/src/share/vm/opto/callGenerator.cpp
index 1fef941d9..cb4be976a 100644
--- a/src/share/vm/opto/callGenerator.cpp
+++ b/src/share/vm/opto/callGenerator.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -26,6 +26,7 @@
#include "ci/bcEscapeAnalyzer.hpp"
#include "ci/ciCallSite.hpp"
#include "ci/ciCPCache.hpp"
+#include "ci/ciMemberName.hpp"
#include "ci/ciMethodHandle.hpp"
#include "classfile/javaClasses.hpp"
#include "compiler/compileLog.hpp"
@@ -39,9 +40,6 @@
#include "opto/runtime.hpp"
#include "opto/subnode.hpp"
-CallGenerator::CallGenerator(ciMethod* method) {
- _method = method;
-}
// Utility function.
const TypeFunc* CallGenerator::tf() const {
@@ -148,7 +146,8 @@ JVMState* DirectCallGenerator::generate(JVMState* jvms) {
}
// Mark the call node as virtual, sort of:
call->set_optimized_virtual(true);
- if (method()->is_method_handle_invoke()) {
+ if (method()->is_method_handle_intrinsic() ||
+ method()->is_compiled_lambda_form()) {
call->set_method_handle_invoke(true);
}
}
@@ -325,12 +324,13 @@ CallGenerator* CallGenerator::for_direct_call(ciMethod* m, bool separate_io_proj
CallGenerator* CallGenerator::for_virtual_call(ciMethod* m, int vtable_index) {
assert(!m->is_static(), "for_virtual_call mismatch");
- assert(!m->is_method_handle_invoke(), "should be a direct call");
+ assert(!m->is_method_handle_intrinsic(), "should be a direct call");
return new VirtualCallGenerator(m, vtable_index);
}
CallGenerator* CallGenerator::for_dynamic_call(ciMethod* m) {
- assert(m->is_method_handle_invoke() || m->is_method_handle_adapter(), "for_dynamic_call mismatch");
+ assert(m->is_compiled_lambda_form(), "for_dynamic_call mismatch");
+ //@@ FIXME: this should be done via a direct call
return new DynamicCallGenerator(m);
}
@@ -654,269 +654,93 @@ JVMState* PredictedCallGenerator::generate(JVMState* jvms) {
}
-//------------------------PredictedDynamicCallGenerator-----------------------
-// Internal class which handles all out-of-line calls checking receiver type.
-class PredictedDynamicCallGenerator : public CallGenerator {
- ciMethodHandle* _predicted_method_handle;
- CallGenerator* _if_missed;
- CallGenerator* _if_hit;
- float _hit_prob;
-
-public:
- PredictedDynamicCallGenerator(ciMethodHandle* predicted_method_handle,
- CallGenerator* if_missed,
- CallGenerator* if_hit,
- float hit_prob)
- : CallGenerator(if_missed->method()),
- _predicted_method_handle(predicted_method_handle),
- _if_missed(if_missed),
- _if_hit(if_hit),
- _hit_prob(hit_prob)
- {}
-
- virtual bool is_inline() const { return _if_hit->is_inline(); }
- virtual bool is_deferred() const { return _if_hit->is_deferred(); }
-
- virtual JVMState* generate(JVMState* jvms);
-};
-
-
-CallGenerator* CallGenerator::for_predicted_dynamic_call(ciMethodHandle* predicted_method_handle,
- CallGenerator* if_missed,
- CallGenerator* if_hit,
- float hit_prob) {
- return new PredictedDynamicCallGenerator(predicted_method_handle, if_missed, if_hit, hit_prob);
-}
-
-
-CallGenerator* CallGenerator::for_method_handle_call(Node* method_handle, JVMState* jvms,
- ciMethod* caller, ciMethod* callee, ciCallProfile profile) {
- assert(callee->is_method_handle_invoke() || callee->is_method_handle_adapter(), "for_method_handle_call mismatch");
- CallGenerator* cg = CallGenerator::for_method_handle_inline(method_handle, jvms, caller, callee, profile);
+CallGenerator* CallGenerator::for_method_handle_call(JVMState* jvms, ciMethod* caller, ciMethod* callee) {
+ assert(callee->is_method_handle_intrinsic() ||
+ callee->is_compiled_lambda_form(), "for_method_handle_call mismatch");
+ CallGenerator* cg = CallGenerator::for_method_handle_inline(jvms, caller, callee);
if (cg != NULL)
return cg;
return CallGenerator::for_direct_call(callee);
}
-CallGenerator* CallGenerator::for_method_handle_inline(Node* method_handle, JVMState* jvms,
- ciMethod* caller, ciMethod* callee, ciCallProfile profile) {
- if (method_handle->Opcode() == Op_ConP) {
- const TypeOopPtr* oop_ptr = method_handle->bottom_type()->is_oopptr();
- ciObject* const_oop = oop_ptr->const_oop();
- ciMethodHandle* method_handle = const_oop->as_method_handle();
-
- // Set the callee to have access to the class and signature in
- // the MethodHandleCompiler.
- method_handle->set_callee(callee);
- method_handle->set_caller(caller);
- method_handle->set_call_profile(profile);
-
- // Get an adapter for the MethodHandle.
- ciMethod* target_method = method_handle->get_method_handle_adapter();
- if (target_method != NULL) {
- CallGenerator* cg = Compile::current()->call_generator(target_method, -1, false, jvms, true, PROB_ALWAYS);
- if (cg != NULL && cg->is_inline())
- return cg;
- }
- } else if (method_handle->Opcode() == Op_Phi && method_handle->req() == 3 &&
- method_handle->in(1)->Opcode() == Op_ConP && method_handle->in(2)->Opcode() == Op_ConP) {
- float prob = PROB_FAIR;
- Node* meth_region = method_handle->in(0);
- if (meth_region->is_Region() &&
- meth_region->in(1)->is_Proj() && meth_region->in(2)->is_Proj() &&
- meth_region->in(1)->in(0) == meth_region->in(2)->in(0) &&
- meth_region->in(1)->in(0)->is_If()) {
- // If diamond, so grab the probability of the test to drive the inlining below
- prob = meth_region->in(1)->in(0)->as_If()->_prob;
- if (meth_region->in(1)->is_IfTrue()) {
- prob = 1 - prob;
+CallGenerator* CallGenerator::for_method_handle_inline(JVMState* jvms, ciMethod* caller, ciMethod* callee) {
+ GraphKit kit(jvms);
+ PhaseGVN& gvn = kit.gvn();
+ Compile* C = kit.C;
+ vmIntrinsics::ID iid = callee->intrinsic_id();
+ switch (iid) {
+ case vmIntrinsics::_invokeBasic:
+ {
+ // get MethodHandle receiver
+ Node* receiver = kit.argument(0);
+ if (receiver->Opcode() == Op_ConP) {
+ const TypeOopPtr* oop_ptr = receiver->bottom_type()->is_oopptr();
+ ciMethod* target = oop_ptr->const_oop()->as_method_handle()->get_vmtarget();
+ guarantee(!target->is_method_handle_intrinsic(), "should not happen"); // XXX remove
+ const int vtable_index = methodOopDesc::invalid_vtable_index;
+ CallGenerator* cg = C->call_generator(target, vtable_index, false, jvms, true, PROB_ALWAYS);
+ if (cg != NULL && cg->is_inline())
+ return cg;
+ } else {
+ if (PrintInlining) CompileTask::print_inlining(callee, jvms->depth() - 1, jvms->bci(), "receiver not constant");
}
}
-
- // selectAlternative idiom merging two constant MethodHandles.
- // Generate a guard so that each can be inlined. We might want to
- // do more inputs at later point but this gets the most common
- // case.
- CallGenerator* cg1 = for_method_handle_call(method_handle->in(1), jvms, caller, callee, profile.rescale(1.0 - prob));
- CallGenerator* cg2 = for_method_handle_call(method_handle->in(2), jvms, caller, callee, profile.rescale(prob));
- if (cg1 != NULL && cg2 != NULL) {
- const TypeOopPtr* oop_ptr = method_handle->in(1)->bottom_type()->is_oopptr();
- ciObject* const_oop = oop_ptr->const_oop();
- ciMethodHandle* mh = const_oop->as_method_handle();
- return new PredictedDynamicCallGenerator(mh, cg2, cg1, prob);
- }
- }
- return NULL;
-}
-
-CallGenerator* CallGenerator::for_invokedynamic_call(JVMState* jvms, ciMethod* caller, ciMethod* callee, ciCallProfile profile) {
- assert(callee->is_method_handle_invoke() || callee->is_method_handle_adapter(), "for_invokedynamic_call mismatch");
- // Get the CallSite object.
- ciBytecodeStream str(caller);
- str.force_bci(jvms->bci()); // Set the stream to the invokedynamic bci.
- ciCallSite* call_site = str.get_call_site();
- CallGenerator* cg = CallGenerator::for_invokedynamic_inline(call_site, jvms, caller, callee, profile);
- if (cg != NULL)
- return cg;
- return CallGenerator::for_dynamic_call(callee);
-}
-
-CallGenerator* CallGenerator::for_invokedynamic_inline(ciCallSite* call_site, JVMState* jvms,
- ciMethod* caller, ciMethod* callee, ciCallProfile profile) {
- ciMethodHandle* method_handle = call_site->get_target();
-
- // Set the callee to have access to the class and signature in the
- // MethodHandleCompiler.
- method_handle->set_callee(callee);
- method_handle->set_caller(caller);
- method_handle->set_call_profile(profile);
-
- // Get an adapter for the MethodHandle.
- ciMethod* target_method = method_handle->get_invokedynamic_adapter();
- if (target_method != NULL) {
- Compile *C = Compile::current();
- CallGenerator* cg = C->call_generator(target_method, -1, false, jvms, true, PROB_ALWAYS);
- if (cg != NULL && cg->is_inline()) {
- // Add a dependence for invalidation of the optimization.
- if (!call_site->is_constant_call_site()) {
- C->dependencies()->assert_call_site_target_value(call_site, method_handle);
+ break;
+
+ case vmIntrinsics::_linkToVirtual:
+ case vmIntrinsics::_linkToStatic:
+ case vmIntrinsics::_linkToSpecial:
+ case vmIntrinsics::_linkToInterface:
+ {
+ // pop MemberName argument
+ Node* member_name = kit.argument(callee->arg_size() - 1);
+ if (member_name->Opcode() == Op_ConP) {
+ const TypeOopPtr* oop_ptr = member_name->bottom_type()->is_oopptr();
+ ciMethod* target = oop_ptr->const_oop()->as_member_name()->get_vmtarget();
+
+ // In lamda forms we erase signature types to avoid resolving issues
+ // involving class loaders. When we optimize a method handle invoke
+ // to a direct call we must cast the receiver and arguments to its
+ // actual types.
+ ciSignature* signature = target->signature();
+ const int receiver_skip = target->is_static() ? 0 : 1;
+ // Cast receiver to its type.
+ if (!target->is_static()) {
+ Node* arg = kit.argument(0);
+ const TypeOopPtr* arg_type = arg->bottom_type()->isa_oopptr();
+ const Type* sig_type = TypeOopPtr::make_from_klass(signature->accessing_klass());
+ if (arg_type != NULL && !arg_type->higher_equal(sig_type)) {
+ Node* cast_obj = gvn.transform(new (C, 2) CheckCastPPNode(kit.control(), arg, sig_type));
+ kit.set_argument(0, cast_obj);
+ }
+ }
+ // Cast reference arguments to its type.
+ for (int i = 0; i < signature->count(); i++) {
+ ciType* t = signature->type_at(i);
+ if (t->is_klass()) {
+ Node* arg = kit.argument(receiver_skip + i);
+ const TypeOopPtr* arg_type = arg->bottom_type()->isa_oopptr();
+ const Type* sig_type = TypeOopPtr::make_from_klass(t->as_klass());
+ if (arg_type != NULL && !arg_type->higher_equal(sig_type)) {
+ Node* cast_obj = gvn.transform(new (C, 2) CheckCastPPNode(kit.control(), arg, sig_type));
+ kit.set_argument(receiver_skip + i, cast_obj);
+ }
+ }
+ }
+ const int vtable_index = methodOopDesc::invalid_vtable_index;
+ const bool call_is_virtual = target->is_abstract(); // FIXME workaround
+ CallGenerator* cg = C->call_generator(target, vtable_index, call_is_virtual, jvms, true, PROB_ALWAYS);
+ if (cg != NULL && cg->is_inline())
+ return cg;
}
- return cg;
- }
- }
- return NULL;
-}
-
-
-JVMState* PredictedDynamicCallGenerator::generate(JVMState* jvms) {
- GraphKit kit(jvms);
- Compile* C = kit.C;
- PhaseGVN& gvn = kit.gvn();
-
- CompileLog* log = C->log();
- if (log != NULL) {
- log->elem("predicted_dynamic_call bci='%d'", jvms->bci());
- }
-
- const TypeOopPtr* predicted_mh_ptr = TypeOopPtr::make_from_constant(_predicted_method_handle, true);
- Node* predicted_mh = kit.makecon(predicted_mh_ptr);
-
- Node* bol = NULL;
- int bc = jvms->method()->java_code_at_bci(jvms->bci());
- if (bc != Bytecodes::_invokedynamic) {
- // This is the selectAlternative idiom for guardWithTest or
- // similar idioms.
- Node* receiver = kit.argument(0);
-
- // Check if the MethodHandle is the expected one
- Node* cmp = gvn.transform(new (C, 3) CmpPNode(receiver, predicted_mh));
- bol = gvn.transform(new (C, 2) BoolNode(cmp, BoolTest::eq) );
- } else {
- // Get the constant pool cache from the caller class.
- ciMethod* caller_method = jvms->method();
- ciBytecodeStream str(caller_method);
- str.force_bci(jvms->bci()); // Set the stream to the invokedynamic bci.
- ciCPCache* cpcache = str.get_cpcache();
-
- // Get the offset of the CallSite from the constant pool cache
- // pointer.
- int index = str.get_method_index();
- size_t call_site_offset = cpcache->get_f1_offset(index);
-
- // Load the CallSite object from the constant pool cache.
- const TypeOopPtr* cpcache_type = TypeOopPtr::make_from_constant(cpcache); // returns TypeAryPtr of type T_OBJECT
- const TypeOopPtr* call_site_type = TypeOopPtr::make_from_klass(C->env()->CallSite_klass());
- Node* cpcache_adr = kit.makecon(cpcache_type);
- Node* call_site_adr = kit.basic_plus_adr(cpcache_adr, call_site_offset);
- // The oops in the constant pool cache are not compressed; load then as raw pointers.
- Node* call_site = kit.make_load(kit.control(), call_site_adr, call_site_type, T_ADDRESS, Compile::AliasIdxRaw);
-
- // Load the target MethodHandle from the CallSite object.
- const TypeOopPtr* target_type = TypeOopPtr::make_from_klass(C->env()->MethodHandle_klass());
- Node* target_adr = kit.basic_plus_adr(call_site, call_site, java_lang_invoke_CallSite::target_offset_in_bytes());
- Node* target_mh = kit.make_load(kit.control(), target_adr, target_type, T_OBJECT);
-
- // Check if the MethodHandle is still the same.
- Node* cmp = gvn.transform(new (C, 3) CmpPNode(target_mh, predicted_mh));
- bol = gvn.transform(new (C, 2) BoolNode(cmp, BoolTest::eq) );
- }
- IfNode* iff = kit.create_and_xform_if(kit.control(), bol, _hit_prob, COUNT_UNKNOWN);
- kit.set_control( gvn.transform(new (C, 1) IfTrueNode (iff)));
- Node* slow_ctl = gvn.transform(new (C, 1) IfFalseNode(iff));
-
- SafePointNode* slow_map = NULL;
- JVMState* slow_jvms;
- { PreserveJVMState pjvms(&kit);
- kit.set_control(slow_ctl);
- if (!kit.stopped()) {
- slow_jvms = _if_missed->generate(kit.sync_jvms());
- if (kit.failing())
- return NULL; // might happen because of NodeCountInliningCutoff
- assert(slow_jvms != NULL, "must be");
- kit.add_exception_states_from(slow_jvms);
- kit.set_map(slow_jvms->map());
- if (!kit.stopped())
- slow_map = kit.stop();
}
- }
-
- if (kit.stopped()) {
- // Instance exactly does not matches the desired type.
- kit.set_jvms(slow_jvms);
- return kit.transfer_exceptions_into_jvms();
- }
-
- // Make the hot call:
- JVMState* new_jvms = _if_hit->generate(kit.sync_jvms());
- if (new_jvms == NULL) {
- // Inline failed, so make a direct call.
- assert(_if_hit->is_inline(), "must have been a failed inline");
- CallGenerator* cg = CallGenerator::for_direct_call(_if_hit->method());
- new_jvms = cg->generate(kit.sync_jvms());
- }
- kit.add_exception_states_from(new_jvms);
- kit.set_jvms(new_jvms);
-
- // Need to merge slow and fast?
- if (slow_map == NULL) {
- // The fast path is the only path remaining.
- return kit.transfer_exceptions_into_jvms();
- }
-
- if (kit.stopped()) {
- // Inlined method threw an exception, so it's just the slow path after all.
- kit.set_jvms(slow_jvms);
- return kit.transfer_exceptions_into_jvms();
- }
+ break;
- // Finish the diamond.
- kit.C->set_has_split_ifs(true); // Has chance for split-if optimization
- RegionNode* region = new (C, 3) RegionNode(3);
- region->init_req(1, kit.control());
- region->init_req(2, slow_map->control());
- kit.set_control(gvn.transform(region));
- Node* iophi = PhiNode::make(region, kit.i_o(), Type::ABIO);
- iophi->set_req(2, slow_map->i_o());
- kit.set_i_o(gvn.transform(iophi));
- kit.merge_memory(slow_map->merged_memory(), region, 2);
- uint tos = kit.jvms()->stkoff() + kit.sp();
- uint limit = slow_map->req();
- for (uint i = TypeFunc::Parms; i < limit; i++) {
- // Skip unused stack slots; fast forward to monoff();
- if (i == tos) {
- i = kit.jvms()->monoff();
- if( i >= limit ) break;
- }
- Node* m = kit.map()->in(i);
- Node* n = slow_map->in(i);
- if (m != n) {
- const Type* t = gvn.type(m)->meet(gvn.type(n));
- Node* phi = PhiNode::make(region, m, t);
- phi->set_req(2, n);
- kit.map()->set_req(i, gvn.transform(phi));
- }
+ default:
+ fatal(err_msg_res("unexpected intrinsic %d: %s", iid, vmIntrinsics::name_at(iid)));
+ break;
}
- return kit.transfer_exceptions_into_jvms();
+ return NULL;
}
diff --git a/src/share/vm/opto/callGenerator.hpp b/src/share/vm/opto/callGenerator.hpp
index 6247f7a7f..a578a4258 100644
--- a/src/share/vm/opto/callGenerator.hpp
+++ b/src/share/vm/opto/callGenerator.hpp
@@ -25,6 +25,7 @@
#ifndef SHARE_VM_OPTO_CALLGENERATOR_HPP
#define SHARE_VM_OPTO_CALLGENERATOR_HPP
+#include "compiler/compileBroker.hpp"
#include "opto/callnode.hpp"
#include "opto/compile.hpp"
#include "opto/type.hpp"
@@ -44,7 +45,7 @@ class CallGenerator : public ResourceObj {
ciMethod* _method; // The method being called.
protected:
- CallGenerator(ciMethod* method);
+ CallGenerator(ciMethod* method) : _method(method) {}
public:
// Accessors
@@ -111,11 +112,8 @@ class CallGenerator : public ResourceObj {
static CallGenerator* for_virtual_call(ciMethod* m, int vtable_index); // virtual, interface
static CallGenerator* for_dynamic_call(ciMethod* m); // invokedynamic
- static CallGenerator* for_method_handle_call(Node* method_handle, JVMState* jvms, ciMethod* caller, ciMethod* callee, ciCallProfile profile);
- static CallGenerator* for_invokedynamic_call( JVMState* jvms, ciMethod* caller, ciMethod* callee, ciCallProfile profile);
-
- static CallGenerator* for_method_handle_inline(Node* method_handle, JVMState* jvms, ciMethod* caller, ciMethod* callee, ciCallProfile profile);
- static CallGenerator* for_invokedynamic_inline(ciCallSite* call_site, JVMState* jvms, ciMethod* caller, ciMethod* callee, ciCallProfile profile);
+ static CallGenerator* for_method_handle_call( JVMState* jvms, ciMethod* caller, ciMethod* callee);
+ static CallGenerator* for_method_handle_inline(JVMState* jvms, ciMethod* caller, ciMethod* callee);
// How to generate a replace a direct call with an inline version
static CallGenerator* for_late_inline(ciMethod* m, CallGenerator* inline_cg);
@@ -145,13 +143,21 @@ class CallGenerator : public ResourceObj {
// Registry for intrinsics:
static CallGenerator* for_intrinsic(ciMethod* m);
static void register_intrinsic(ciMethod* m, CallGenerator* cg);
+
+ static void print_inlining(ciMethod* callee, int inline_level, int bci, const char* msg) {
+ if (PrintInlining)
+ CompileTask::print_inlining(callee, inline_level, bci, msg);
+ }
};
-class InlineCallGenerator : public CallGenerator {
- virtual bool is_inline() const { return true; }
+//------------------------InlineCallGenerator----------------------------------
+class InlineCallGenerator : public CallGenerator {
protected:
- InlineCallGenerator(ciMethod* method) : CallGenerator(method) { }
+ InlineCallGenerator(ciMethod* method) : CallGenerator(method) {}
+
+ public:
+ virtual bool is_inline() const { return true; }
};
diff --git a/src/share/vm/opto/callnode.cpp b/src/share/vm/opto/callnode.cpp
index 154cc1a0d..2fdacf9f5 100644
--- a/src/share/vm/opto/callnode.cpp
+++ b/src/share/vm/opto/callnode.cpp
@@ -231,9 +231,9 @@ uint TailJumpNode::match_edge(uint idx) const {
}
//=============================================================================
-JVMState::JVMState(ciMethod* method, JVMState* caller) {
+JVMState::JVMState(ciMethod* method, JVMState* caller) :
+ _method(method) {
assert(method != NULL, "must be valid call site");
- _method = method;
_reexecute = Reexecute_Undefined;
debug_only(_bci = -99); // random garbage value
debug_only(_map = (SafePointNode*)-1);
@@ -246,8 +246,8 @@ JVMState::JVMState(ciMethod* method, JVMState* caller) {
_endoff = _monoff;
_sp = 0;
}
-JVMState::JVMState(int stack_size) {
- _method = NULL;
+JVMState::JVMState(int stack_size) :
+ _method(NULL) {
_bci = InvocationEntryBci;
_reexecute = Reexecute_Undefined;
debug_only(_map = (SafePointNode*)-1);
@@ -526,8 +526,8 @@ void JVMState::dump_on(outputStream* st) const {
}
_map->dump(2);
}
- st->print("JVMS depth=%d loc=%d stk=%d mon=%d scalar=%d end=%d mondepth=%d sp=%d bci=%d reexecute=%s method=",
- depth(), locoff(), stkoff(), monoff(), scloff(), endoff(), monitor_depth(), sp(), bci(), should_reexecute()?"true":"false");
+ st->print("JVMS depth=%d loc=%d stk=%d arg=%d mon=%d scalar=%d end=%d mondepth=%d sp=%d bci=%d reexecute=%s method=",
+ depth(), locoff(), stkoff(), argoff(), monoff(), scloff(), endoff(), monitor_depth(), sp(), bci(), should_reexecute()?"true":"false");
if (_method == NULL) {
st->print_cr("(none)");
} else {
diff --git a/src/share/vm/opto/callnode.hpp b/src/share/vm/opto/callnode.hpp
index d9108ce87..a412e2b0d 100644
--- a/src/share/vm/opto/callnode.hpp
+++ b/src/share/vm/opto/callnode.hpp
@@ -197,7 +197,7 @@ public:
private:
JVMState* _caller; // List pointer for forming scope chains
- uint _depth; // One mroe than caller depth, or one.
+ uint _depth; // One more than caller depth, or one.
uint _locoff; // Offset to locals in input edge mapping
uint _stkoff; // Offset to stack in input edge mapping
uint _monoff; // Offset to monitors in input edge mapping
@@ -223,6 +223,8 @@ public:
JVMState(int stack_size); // root state; has a null method
// Access functions for the JVM
+ // ... --|--- loc ---|--- stk ---|--- arg ---|--- mon ---|--- scl ---|
+ // \ locoff \ stkoff \ argoff \ monoff \ scloff \ endoff
uint locoff() const { return _locoff; }
uint stkoff() const { return _stkoff; }
uint argoff() const { return _stkoff + _sp; }
@@ -231,15 +233,16 @@ public:
uint endoff() const { return _endoff; }
uint oopoff() const { return debug_end(); }
- int loc_size() const { return _stkoff - _locoff; }
- int stk_size() const { return _monoff - _stkoff; }
- int mon_size() const { return _scloff - _monoff; }
- int scl_size() const { return _endoff - _scloff; }
+ int loc_size() const { return stkoff() - locoff(); }
+ int stk_size() const { return monoff() - stkoff(); }
+ int arg_size() const { return monoff() - argoff(); }
+ int mon_size() const { return scloff() - monoff(); }
+ int scl_size() const { return endoff() - scloff(); }
- bool is_loc(uint i) const { return i >= _locoff && i < _stkoff; }
- bool is_stk(uint i) const { return i >= _stkoff && i < _monoff; }
- bool is_mon(uint i) const { return i >= _monoff && i < _scloff; }
- bool is_scl(uint i) const { return i >= _scloff && i < _endoff; }
+ bool is_loc(uint i) const { return locoff() <= i && i < stkoff(); }
+ bool is_stk(uint i) const { return stkoff() <= i && i < monoff(); }
+ bool is_mon(uint i) const { return monoff() <= i && i < scloff(); }
+ bool is_scl(uint i) const { return scloff() <= i && i < endoff(); }
uint sp() const { return _sp; }
int bci() const { return _bci; }
diff --git a/src/share/vm/opto/chaitin.cpp b/src/share/vm/opto/chaitin.cpp
index 00cabcf23..6ee1393a8 100644
--- a/src/share/vm/opto/chaitin.cpp
+++ b/src/share/vm/opto/chaitin.cpp
@@ -1536,7 +1536,7 @@ Node *PhaseChaitin::find_base_for_derived( Node **derived_base_map, Node *derive
// Check for AddP-related opcodes
if( !derived->is_Phi() ) {
- assert(derived->as_Mach()->ideal_Opcode() == Op_AddP, err_msg("but is: %s", derived->Name()));
+ assert(derived->as_Mach()->ideal_Opcode() == Op_AddP, err_msg_res("but is: %s", derived->Name()));
Node *base = derived->in(AddPNode::Base);
derived_base_map[derived->_idx] = base;
return base;
diff --git a/src/share/vm/opto/compile.cpp b/src/share/vm/opto/compile.cpp
index 5331d033f..0836fc205 100644
--- a/src/share/vm/opto/compile.cpp
+++ b/src/share/vm/opto/compile.cpp
@@ -3138,7 +3138,7 @@ void Compile::ConstantTable::emit(CodeBuffer& cb) {
default: ShouldNotReachHere();
}
assert(constant_addr, "consts section too small");
- assert((constant_addr - _masm.code()->consts()->start()) == con.offset(), err_msg("must be: %d == %d", constant_addr - _masm.code()->consts()->start(), con.offset()));
+ assert((constant_addr - _masm.code()->consts()->start()) == con.offset(), err_msg_res("must be: %d == %d", constant_addr - _masm.code()->consts()->start(), con.offset()));
}
}
@@ -3199,7 +3199,7 @@ void Compile::ConstantTable::fill_jump_table(CodeBuffer& cb, MachConstantNode* n
if (Compile::current()->in_scratch_emit_size()) return;
assert(labels.is_nonempty(), "must be");
- assert((uint) labels.length() == n->outcnt(), err_msg("must be equal: %d == %d", labels.length(), n->outcnt()));
+ assert((uint) labels.length() == n->outcnt(), err_msg_res("must be equal: %d == %d", labels.length(), n->outcnt()));
// Since MachConstantNode::constant_offset() also contains
// table_base_offset() we need to subtract the table_base_offset()
@@ -3211,7 +3211,7 @@ void Compile::ConstantTable::fill_jump_table(CodeBuffer& cb, MachConstantNode* n
for (uint i = 0; i < n->outcnt(); i++) {
address* constant_addr = &jump_table_base[i];
- assert(*constant_addr == (((address) n) + i), err_msg("all jump-table entries must contain adjusted node pointer: " INTPTR_FORMAT " == " INTPTR_FORMAT, *constant_addr, (((address) n) + i)));
+ assert(*constant_addr == (((address) n) + i), err_msg_res("all jump-table entries must contain adjusted node pointer: " INTPTR_FORMAT " == " INTPTR_FORMAT, *constant_addr, (((address) n) + i)));
*constant_addr = cb.consts()->target(*labels.at(i), (address) constant_addr);
cb.consts()->relocate((address) constant_addr, relocInfo::internal_word_type);
}
diff --git a/src/share/vm/opto/doCall.cpp b/src/share/vm/opto/doCall.cpp
index f90f1eac0..580740b9f 100644
--- a/src/share/vm/opto/doCall.cpp
+++ b/src/share/vm/opto/doCall.cpp
@@ -59,13 +59,13 @@ void trace_type_profile(ciMethod *method, int depth, int bci, ciMethod *prof_met
}
#endif
-CallGenerator* Compile::call_generator(ciMethod* call_method, int vtable_index, bool call_is_virtual,
+CallGenerator* Compile::call_generator(ciMethod* callee, int vtable_index, bool call_is_virtual,
JVMState* jvms, bool allow_inline,
float prof_factor, bool allow_intrinsics) {
ciMethod* caller = jvms->method();
int bci = jvms->bci();
Bytecodes::Code bytecode = caller->java_code_at_bci(bci);
- guarantee(call_method != NULL, "failed method resolution");
+ guarantee(callee != NULL, "failed method resolution");
// Dtrace currently doesn't work unless all calls are vanilla
if (env()->dtrace_method_probes()) {
@@ -91,7 +91,7 @@ CallGenerator* Compile::call_generator(ciMethod* call_method, int vtable_index,
int rid = (receiver_count >= 0)? log->identify(profile.receiver(0)): -1;
int r2id = (rid != -1 && profile.has_receiver(1))? log->identify(profile.receiver(1)):-1;
log->begin_elem("call method='%d' count='%d' prof_factor='%g'",
- log->identify(call_method), site_count, prof_factor);
+ log->identify(callee), site_count, prof_factor);
if (call_is_virtual) log->print(" virtual='1'");
if (allow_inline) log->print(" inline='1'");
if (receiver_count >= 0) {
@@ -109,7 +109,7 @@ CallGenerator* Compile::call_generator(ciMethod* call_method, int vtable_index,
// We do this before the strict f.p. check below because the
// intrinsics handle strict f.p. correctly.
if (allow_inline && allow_intrinsics) {
- CallGenerator* cg = find_intrinsic(call_method, call_is_virtual);
+ CallGenerator* cg = find_intrinsic(callee, call_is_virtual);
if (cg != NULL) return cg;
}
@@ -117,19 +117,12 @@ CallGenerator* Compile::call_generator(ciMethod* call_method, int vtable_index,
// NOTE: This must happen before normal inlining logic below since
// MethodHandle.invoke* are native methods which obviously don't
// have bytecodes and so normal inlining fails.
- if (call_method->is_method_handle_invoke()) {
- if (bytecode != Bytecodes::_invokedynamic) {
- GraphKit kit(jvms);
- Node* method_handle = kit.argument(0);
- return CallGenerator::for_method_handle_call(method_handle, jvms, caller, call_method, profile);
- }
- else {
- return CallGenerator::for_invokedynamic_call(jvms, caller, call_method, profile);
- }
+ if (callee->is_method_handle_intrinsic()) {
+ return CallGenerator::for_method_handle_call(jvms, caller, callee);
}
// Do not inline strict fp into non-strict code, or the reverse
- if (caller->is_strict() ^ call_method->is_strict()) {
+ if (caller->is_strict() ^ callee->is_strict()) {
allow_inline = false;
}
@@ -155,26 +148,26 @@ CallGenerator* Compile::call_generator(ciMethod* call_method, int vtable_index,
}
WarmCallInfo scratch_ci;
if (!UseOldInlining)
- scratch_ci.init(jvms, call_method, profile, prof_factor);
- WarmCallInfo* ci = ilt->ok_to_inline(call_method, jvms, profile, &scratch_ci);
+ scratch_ci.init(jvms, callee, profile, prof_factor);
+ WarmCallInfo* ci = ilt->ok_to_inline(callee, jvms, profile, &scratch_ci);
assert(ci != &scratch_ci, "do not let this pointer escape");
bool allow_inline = (ci != NULL && !ci->is_cold());
bool require_inline = (allow_inline && ci->is_hot());
if (allow_inline) {
- CallGenerator* cg = CallGenerator::for_inline(call_method, expected_uses);
- if (require_inline && cg != NULL && should_delay_inlining(call_method, jvms)) {
+ CallGenerator* cg = CallGenerator::for_inline(callee, expected_uses);
+ if (require_inline && cg != NULL && should_delay_inlining(callee, jvms)) {
// Delay the inlining of this method to give us the
// opportunity to perform some high level optimizations
// first.
- return CallGenerator::for_late_inline(call_method, cg);
+ return CallGenerator::for_late_inline(callee, cg);
}
if (cg == NULL) {
// Fall through.
} else if (require_inline || !InlineWarmCalls) {
return cg;
} else {
- CallGenerator* cold_cg = call_generator(call_method, vtable_index, call_is_virtual, jvms, false, prof_factor);
+ CallGenerator* cold_cg = call_generator(callee, vtable_index, call_is_virtual, jvms, false, prof_factor);
return CallGenerator::for_warm_call(ci, cold_cg, cg);
}
}
@@ -189,7 +182,7 @@ CallGenerator* Compile::call_generator(ciMethod* call_method, int vtable_index,
(profile.morphism() == 2 && UseBimorphicInlining)) {
// receiver_method = profile.method();
// Profiles do not suggest methods now. Look it up in the major receiver.
- receiver_method = call_method->resolve_invoke(jvms->method()->holder(),
+ receiver_method = callee->resolve_invoke(jvms->method()->holder(),
profile.receiver(0));
}
if (receiver_method != NULL) {
@@ -201,7 +194,7 @@ CallGenerator* Compile::call_generator(ciMethod* call_method, int vtable_index,
CallGenerator* next_hit_cg = NULL;
ciMethod* next_receiver_method = NULL;
if (profile.morphism() == 2 && UseBimorphicInlining) {
- next_receiver_method = call_method->resolve_invoke(jvms->method()->holder(),
+ next_receiver_method = callee->resolve_invoke(jvms->method()->holder(),
profile.receiver(1));
if (next_receiver_method != NULL) {
next_hit_cg = this->call_generator(next_receiver_method,
@@ -224,12 +217,12 @@ CallGenerator* Compile::call_generator(ciMethod* call_method, int vtable_index,
) {
// Generate uncommon trap for class check failure path
// in case of monomorphic or bimorphic virtual call site.
- miss_cg = CallGenerator::for_uncommon_trap(call_method, reason,
+ miss_cg = CallGenerator::for_uncommon_trap(callee, reason,
Deoptimization::Action_maybe_recompile);
} else {
// Generate virtual call for class check failure path
// in case of polymorphic virtual call site.
- miss_cg = CallGenerator::for_virtual_call(call_method, vtable_index);
+ miss_cg = CallGenerator::for_virtual_call(callee, vtable_index);
}
if (miss_cg != NULL) {
if (next_hit_cg != NULL) {
@@ -252,11 +245,11 @@ CallGenerator* Compile::call_generator(ciMethod* call_method, int vtable_index,
// There was no special inlining tactic, or it bailed out.
// Use a more generic tactic, like a simple call.
if (call_is_virtual) {
- return CallGenerator::for_virtual_call(call_method, vtable_index);
+ return CallGenerator::for_virtual_call(callee, vtable_index);
} else {
// Class Hierarchy Analysis or Type Profile reveals a unique target,
// or it is a static or special call.
- return CallGenerator::for_direct_call(call_method, should_delay_inlining(call_method, jvms));
+ return CallGenerator::for_direct_call(callee, should_delay_inlining(callee, jvms));
}
}
@@ -355,33 +348,40 @@ void Parse::do_call() {
// Find target being called
bool will_link;
- ciMethod* dest_method = iter().get_method(will_link);
- ciInstanceKlass* holder_klass = dest_method->holder();
+ ciMethod* bc_callee = iter().get_method(will_link); // actual callee from bytecode
+ ciInstanceKlass* holder_klass = bc_callee->holder();
ciKlass* holder = iter().get_declared_method_holder();
ciInstanceKlass* klass = ciEnv::get_instance_klass_for_declared_method_holder(holder);
- int nargs = dest_method->arg_size();
- if (is_invokedynamic) nargs -= 1;
-
// uncommon-trap when callee is unloaded, uninitialized or will not link
// bailout when too many arguments for register representation
- if (!will_link || can_not_compile_call_site(dest_method, klass)) {
+ if (!will_link || can_not_compile_call_site(bc_callee, klass)) {
#ifndef PRODUCT
if (PrintOpto && (Verbose || WizardMode)) {
method()->print_name(); tty->print_cr(" can not compile call at bci %d to:", bci());
- dest_method->print_name(); tty->cr();
+ bc_callee->print_name(); tty->cr();
}
#endif
return;
}
assert(holder_klass->is_loaded(), "");
- assert((dest_method->is_static() || is_invokedynamic) == !has_receiver , "must match bc");
+ //assert((bc_callee->is_static() || is_invokedynamic) == !has_receiver , "must match bc"); // XXX invokehandle (cur_bc_raw)
// Note: this takes into account invokeinterface of methods declared in java/lang/Object,
// which should be invokevirtuals but according to the VM spec may be invokeinterfaces
assert(holder_klass->is_interface() || holder_klass->super() == NULL || (bc() != Bytecodes::_invokeinterface), "must match bc");
// Note: In the absence of miranda methods, an abstract class K can perform
// an invokevirtual directly on an interface method I.m if K implements I.
+ const int nargs = bc_callee->arg_size();
+
+ // Push appendix argument (MethodType, CallSite, etc.), if one.
+ if (iter().has_appendix()) {
+ ciObject* appendix_arg = iter().get_appendix();
+ const TypeOopPtr* appendix_arg_type = TypeOopPtr::make_from_constant(appendix_arg);
+ Node* appendix_arg_node = _gvn.makecon(appendix_arg_type);
+ push(appendix_arg_node);
+ }
+
// ---------------------
// Does Class Hierarchy Analysis reveal only a single target of a v-call?
// Then we may inline or make a static call, but become dependent on there being only 1 target.
@@ -392,21 +392,21 @@ void Parse::do_call() {
// Choose call strategy.
bool call_is_virtual = is_virtual_or_interface;
int vtable_index = methodOopDesc::invalid_vtable_index;
- ciMethod* call_method = dest_method;
+ ciMethod* callee = bc_callee;
// Try to get the most accurate receiver type
if (is_virtual_or_interface) {
Node* receiver_node = stack(sp() - nargs);
const TypeOopPtr* receiver_type = _gvn.type(receiver_node)->isa_oopptr();
- ciMethod* optimized_virtual_method = optimize_inlining(method(), bci(), klass, dest_method, receiver_type);
+ ciMethod* optimized_virtual_method = optimize_inlining(method(), bci(), klass, bc_callee, receiver_type);
// Have the call been sufficiently improved such that it is no longer a virtual?
if (optimized_virtual_method != NULL) {
- call_method = optimized_virtual_method;
+ callee = optimized_virtual_method;
call_is_virtual = false;
- } else if (!UseInlineCaches && is_virtual && call_method->is_loaded()) {
+ } else if (!UseInlineCaches && is_virtual && callee->is_loaded()) {
// We can make a vtable call at this site
- vtable_index = call_method->resolve_vtable_index(method()->holder(), klass);
+ vtable_index = callee->resolve_vtable_index(method()->holder(), klass);
}
}
@@ -416,22 +416,24 @@ void Parse::do_call() {
bool try_inline = (C->do_inlining() || InlineAccessors);
// ---------------------
- inc_sp(- nargs); // Temporarily pop args for JVM state of call
+ dec_sp(nargs); // Temporarily pop args for JVM state of call
JVMState* jvms = sync_jvms();
// ---------------------
// Decide call tactic.
// This call checks with CHA, the interpreter profile, intrinsics table, etc.
// It decides whether inlining is desirable or not.
- CallGenerator* cg = C->call_generator(call_method, vtable_index, call_is_virtual, jvms, try_inline, prof_factor());
+ CallGenerator* cg = C->call_generator(callee, vtable_index, call_is_virtual, jvms, try_inline, prof_factor());
+
+ bc_callee = callee = NULL; // don't use bc_callee and callee after this point
// ---------------------
// Round double arguments before call
- round_double_arguments(dest_method);
+ round_double_arguments(cg->method());
#ifndef PRODUCT
// bump global counters for calls
- count_compiled_calls(false/*at_method_entry*/, cg->is_inline());
+ count_compiled_calls(/*at_method_entry*/ false, cg->is_inline());
// Record first part of parsing work for this call
parse_histogram()->record_change();
@@ -447,8 +449,8 @@ void Parse::do_call() {
// because exceptions don't return to the call site.)
profile_call(receiver);
- JVMState* new_jvms;
- if ((new_jvms = cg->generate(jvms)) == NULL) {
+ JVMState* new_jvms = cg->generate(jvms);
+ if (new_jvms == NULL) {
// When inlining attempt fails (e.g., too many arguments),
// it may contaminate the current compile state, making it
// impossible to pull back and try again. Once we call
@@ -460,7 +462,7 @@ void Parse::do_call() {
// the call site, perhaps because it did not match a pattern the
// intrinsic was expecting to optimize. Should always be possible to
// get a normal java call that may inline in that case
- cg = C->call_generator(call_method, vtable_index, call_is_virtual, jvms, try_inline, prof_factor(), /* allow_intrinsics= */ false);
+ cg = C->call_generator(cg->method(), vtable_index, call_is_virtual, jvms, try_inline, prof_factor(), /* allow_intrinsics= */ false);
if ((new_jvms = cg->generate(jvms)) == NULL) {
guarantee(failing(), "call failed to generate: calls should work");
return;
@@ -469,8 +471,8 @@ void Parse::do_call() {
if (cg->is_inline()) {
// Accumulate has_loops estimate
- C->set_has_loops(C->has_loops() || call_method->has_loops());
- C->env()->notice_inlined_method(call_method);
+ C->set_has_loops(C->has_loops() || cg->method()->has_loops());
+ C->env()->notice_inlined_method(cg->method());
}
// Reset parser state from [new_]jvms, which now carries results of the call.
@@ -492,20 +494,74 @@ void Parse::do_call() {
}
// Round double result after a call from strict to non-strict code
- round_double_result(dest_method);
+ round_double_result(cg->method());
+
+ ciType* rtype = cg->method()->return_type();
+ if (iter().cur_bc_raw() == Bytecodes::_invokehandle || is_invokedynamic) {
+ // Be careful here with return types.
+ ciType* ctype = iter().get_declared_method_signature()->return_type();
+ if (ctype != rtype) {
+ BasicType rt = rtype->basic_type();
+ BasicType ct = ctype->basic_type();
+ Node* retnode = peek();
+ if (ct == T_VOID) {
+ // It's OK for a method to return a value that is discarded.
+ // The discarding does not require any special action from the caller.
+ // The Java code knows this, at VerifyType.isNullConversion.
+ pop_node(rt); // whatever it was, pop it
+ retnode = top();
+ } else if (rt == T_INT || is_subword_type(rt)) {
+ // FIXME: This logic should be factored out.
+ if (ct == T_BOOLEAN) {
+ retnode = _gvn.transform( new (C, 3) AndINode(retnode, intcon(0x1)) );
+ } else if (ct == T_CHAR) {
+ retnode = _gvn.transform( new (C, 3) AndINode(retnode, intcon(0xFFFF)) );
+ } else if (ct == T_BYTE) {
+ retnode = _gvn.transform( new (C, 3) LShiftINode(retnode, intcon(24)) );
+ retnode = _gvn.transform( new (C, 3) RShiftINode(retnode, intcon(24)) );
+ } else if (ct == T_SHORT) {
+ retnode = _gvn.transform( new (C, 3) LShiftINode(retnode, intcon(16)) );
+ retnode = _gvn.transform( new (C, 3) RShiftINode(retnode, intcon(16)) );
+ } else {
+ assert(ct == T_INT, err_msg_res("rt=%s, ct=%s", type2name(rt), type2name(ct)));
+ }
+ } else if (rt == T_OBJECT || rt == T_ARRAY) {
+ assert(ct == T_OBJECT || ct == T_ARRAY, err_msg_res("rt=%s, ct=%s", type2name(rt), type2name(ct)));
+ if (ctype->is_loaded()) {
+ Node* if_fail = top();
+ retnode = gen_checkcast(retnode, makecon(TypeKlassPtr::make(ctype->as_klass())), &if_fail);
+ if (if_fail != top()) {
+ PreserveJVMState pjvms(this);
+ set_control(if_fail);
+ builtin_throw(Deoptimization::Reason_class_check);
+ }
+ pop();
+ push(retnode);
+ }
+ } else {
+ assert(ct == rt, err_msg_res("unexpected mismatch rt=%d, ct=%d", rt, ct));
+ // push a zero; it's better than getting an oop/int mismatch
+ retnode = pop_node(rt);
+ retnode = zerocon(ct);
+ push_node(ct, retnode);
+ }
+ // Now that the value is well-behaved, continue with the call-site type.
+ rtype = ctype;
+ }
+ }
// If the return type of the method is not loaded, assert that the
// value we got is a null. Otherwise, we need to recompile.
- if (!dest_method->return_type()->is_loaded()) {
+ if (!rtype->is_loaded()) {
#ifndef PRODUCT
if (PrintOpto && (Verbose || WizardMode)) {
method()->print_name(); tty->print_cr(" asserting nullness of result at bci: %d", bci());
- dest_method->print_name(); tty->cr();
+ cg->method()->print_name(); tty->cr();
}
#endif
if (C->log() != NULL) {
C->log()->elem("assert_null reason='return' klass='%d'",
- C->log()->identify(dest_method->return_type()));
+ C->log()->identify(rtype));
}
// If there is going to be a trap, put it at the next bytecode:
set_bci(iter().next_bci());
@@ -585,8 +641,8 @@ void Parse::catch_call_exceptions(ciExceptionHandlerStream& handlers) {
#ifndef PRODUCT
// We do not expect the same handler bci to take both cold unloaded
// and hot loaded exceptions. But, watch for it.
- if (extype->is_loaded()) {
- tty->print_cr("Warning: Handler @%d takes mixed loaded/unloaded exceptions in ");
+ if ((Verbose || WizardMode) && extype->is_loaded()) {
+ tty->print("Warning: Handler @%d takes mixed loaded/unloaded exceptions in ", bci());
method()->print_name(); tty->cr();
} else if (PrintOpto && (Verbose || WizardMode)) {
tty->print("Bailing out on unloaded exception type ");
diff --git a/src/share/vm/opto/escape.cpp b/src/share/vm/opto/escape.cpp
index faf463cbd..49206f7ab 100644
--- a/src/share/vm/opto/escape.cpp
+++ b/src/share/vm/opto/escape.cpp
@@ -1055,7 +1055,7 @@ bool ConnectionGraph::complete_connection_graph(
C->log()->text("%s", (iterations >= CG_BUILD_ITER_LIMIT) ? "iterations" : "time");
C->log()->end_elem(" limit'");
}
- assert(false, err_msg("infinite EA connection graph build (%f sec, %d iterations) with %d nodes and worklist size %d",
+ assert(false, err_msg_res("infinite EA connection graph build (%f sec, %d iterations) with %d nodes and worklist size %d",
time.seconds(), iterations, nodes_size(), ptnodes_worklist.length()));
// Possible infinite build_connection_graph loop,
// bailout (no changes to ideal graph were made).
@@ -1768,8 +1768,12 @@ void ConnectionGraph::add_field(Node *n, PointsToNode::EscapeState es, int offse
assert(ptadr->is_Field() && ptadr->ideal_node() == n, "sanity");
return;
}
+ bool unsafe = false;
+ bool is_oop = is_oop_field(n, offset, &unsafe);
+ if (unsafe) {
+ es = PointsToNode::GlobalEscape;
+ }
Compile* C = _compile;
- bool is_oop = is_oop_field(n, offset);
FieldNode* field = new (C->comp_arena()) FieldNode(C, n, es, offset, is_oop);
_nodes.at_put(n->_idx, field);
}
@@ -1794,7 +1798,7 @@ void ConnectionGraph::add_arraycopy(Node *n, PointsToNode::EscapeState es,
dst->set_arraycopy_dst();
}
-bool ConnectionGraph::is_oop_field(Node* n, int offset) {
+bool ConnectionGraph::is_oop_field(Node* n, int offset, bool* unsafe) {
const Type* adr_type = n->as_AddP()->bottom_type();
BasicType bt = T_INT;
if (offset == Type::OffsetBot) {
@@ -1813,7 +1817,16 @@ bool ConnectionGraph::is_oop_field(Node* n, int offset) {
if (field != NULL) {
bt = field->layout_type();
} else {
- // Ignore non field load (for example, klass load)
+ // Check for unsafe oop field access
+ for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
+ int opcode = n->fast_out(i)->Opcode();
+ if (opcode == Op_StoreP || opcode == Op_LoadP ||
+ opcode == Op_StoreN || opcode == Op_LoadN) {
+ bt = T_OBJECT;
+ (*unsafe) = true;
+ break;
+ }
+ }
}
} else if (adr_type->isa_aryptr()) {
if (offset == arrayOopDesc::length_offset_in_bytes()) {
@@ -1831,6 +1844,7 @@ bool ConnectionGraph::is_oop_field(Node* n, int offset) {
if (opcode == Op_StoreP || opcode == Op_LoadP ||
opcode == Op_StoreN || opcode == Op_LoadN) {
bt = T_OBJECT;
+ break;
}
}
}
diff --git a/src/share/vm/opto/escape.hpp b/src/share/vm/opto/escape.hpp
index 218dbf46c..54e5f5853 100644
--- a/src/share/vm/opto/escape.hpp
+++ b/src/share/vm/opto/escape.hpp
@@ -512,13 +512,11 @@ private:
assert(ptn != NULL, "node should be registered");
}
add_edge(ptnode_adr(n->_idx), ptn);
- }
-
+ }
// Helper functions
- bool is_oop_field(Node* n, int offset);
- static Node* get_addp_base(Node *addp);
- static Node* find_second_addp(Node* addp, Node* n);
-
+ bool is_oop_field(Node* n, int offset, bool* unsafe);
+ static Node* get_addp_base(Node *addp);
+ static Node* find_second_addp(Node* addp, Node* n);
// offset of a field reference
int address_offset(Node* adr, PhaseTransform *phase);
diff --git a/src/share/vm/opto/graphKit.cpp b/src/share/vm/opto/graphKit.cpp
index b3dca9531..da24dc369 100644
--- a/src/share/vm/opto/graphKit.cpp
+++ b/src/share/vm/opto/graphKit.cpp
@@ -965,7 +965,7 @@ void GraphKit::add_safepoint_edges(SafePointNode* call, bool must_throw) {
assert(call->jvms()->debug_depth() == call->req() - non_debug_edges, "");
}
-bool GraphKit::compute_stack_effects(int& inputs, int& depth) {
+bool GraphKit::compute_stack_effects(int& inputs, int& depth, bool for_parse) {
Bytecodes::Code code = java_bc();
if (code == Bytecodes::_wide) {
code = method()->java_code_at_bci(bci() + 1);
@@ -1032,12 +1032,21 @@ bool GraphKit::compute_stack_effects(int& inputs, int& depth) {
ciBytecodeStream iter(method());
iter.reset_to_bci(bci());
iter.next();
- ciMethod* method = iter.get_method(ignore);
+ ciMethod* callee = iter.get_method(ignore);
// (Do not use ciMethod::arg_size(), because
// it might be an unloaded method, which doesn't
// know whether it is static or not.)
- inputs = method->invoke_arg_size(code);
- int size = method->return_type()->size();
+ if (for_parse) {
+ // Case 1: When called from parse we are *before* the invoke (in the
+ // caller) and need to to adjust the inputs by an appendix
+ // argument that will be pushed implicitly.
+ inputs = callee->invoke_arg_size(code) - (iter.has_appendix() ? 1 : 0);
+ } else {
+ // Case 2: Here we are *after* the invoke (in the callee) and need to
+ // remove any appendix arguments that were popped.
+ inputs = callee->invoke_arg_size(code) - (callee->has_member_arg() ? 1 : 0);
+ }
+ int size = callee->return_type()->size();
depth = size - inputs;
}
break;
@@ -1373,7 +1382,6 @@ void GraphKit::replace_in_map(Node* old, Node* neww) {
}
-
//=============================================================================
//--------------------------------memory---------------------------------------
Node* GraphKit::memory(uint alias_idx) {
diff --git a/src/share/vm/opto/graphKit.hpp b/src/share/vm/opto/graphKit.hpp
index 723e65e3b..c32575d07 100644
--- a/src/share/vm/opto/graphKit.hpp
+++ b/src/share/vm/opto/graphKit.hpp
@@ -145,6 +145,7 @@ class GraphKit : public Phase {
void clean_stack(int from_sp); // clear garbage beyond from_sp to top
void inc_sp(int i) { set_sp(sp() + i); }
+ void dec_sp(int i) { set_sp(sp() - i); }
void set_bci(int bci) { _bci = bci; }
// Make sure jvms has current bci & sp.
@@ -285,7 +286,7 @@ class GraphKit : public Phase {
// How many stack inputs does the current BC consume?
// And, how does the stack change after the bytecode?
// Returns false if unknown.
- bool compute_stack_effects(int& inputs, int& depth);
+ bool compute_stack_effects(int& inputs, int& depth, bool for_parse = false);
// Add a fixed offset to a pointer
Node* basic_plus_adr(Node* base, Node* ptr, intptr_t offset) {
@@ -370,9 +371,9 @@ class GraphKit : public Phase {
// Replace all occurrences of one node by another.
void replace_in_map(Node* old, Node* neww);
- void push(Node* n) { map_not_null(); _map->set_stack(_map->_jvms,_sp++,n); }
- Node* pop() { map_not_null(); return _map->stack(_map->_jvms,--_sp); }
- Node* peek(int off=0) { map_not_null(); return _map->stack(_map->_jvms, _sp - off - 1); }
+ void push(Node* n) { map_not_null(); _map->set_stack(_map->_jvms, _sp++, n); }
+ Node* pop() { map_not_null(); return _map->stack( _map->_jvms, --_sp); }
+ Node* peek(int off = 0) { map_not_null(); return _map->stack( _map->_jvms, _sp - off - 1); }
void push_pair(Node* ldval) {
push(ldval);
diff --git a/src/share/vm/opto/idealGraphPrinter.cpp b/src/share/vm/opto/idealGraphPrinter.cpp
index 3344ce29c..b3919a654 100644
--- a/src/share/vm/opto/idealGraphPrinter.cpp
+++ b/src/share/vm/opto/idealGraphPrinter.cpp
@@ -155,8 +155,8 @@ IdealGraphPrinter::IdealGraphPrinter() {
} else {
// It would be nice if we could shut down cleanly but it should
// be an error if we can't connect to the visualizer.
- fatal(err_msg("Couldn't connect to visualizer at %s:%d",
- PrintIdealGraphAddress, PrintIdealGraphPort));
+ fatal(err_msg_res("Couldn't connect to visualizer at %s:%d",
+ PrintIdealGraphAddress, PrintIdealGraphPort));
}
}
diff --git a/src/share/vm/opto/library_call.cpp b/src/share/vm/opto/library_call.cpp
index 981a241a4..cb8dcbb65 100644
--- a/src/share/vm/opto/library_call.cpp
+++ b/src/share/vm/opto/library_call.cpp
@@ -2171,7 +2171,7 @@ bool LibraryCallKit::inline_reverseBytes(vmIntrinsics::ID id) {
if (id == vmIntrinsics::_reverseBytes_l && !Matcher::has_match_rule(Op_ReverseBytesL)) return false;
if (id == vmIntrinsics::_reverseBytes_c && !Matcher::has_match_rule(Op_ReverseBytesUS)) return false;
if (id == vmIntrinsics::_reverseBytes_s && !Matcher::has_match_rule(Op_ReverseBytesS)) return false;
- _sp += arg_size(); // restore stack pointer
+ _sp += arg_size(); // restore stack pointer
switch (id) {
case vmIntrinsics::_reverseBytes_i:
push(_gvn.transform(new (C, 2) ReverseBytesINode(0, pop())));
@@ -2344,6 +2344,7 @@ bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, Bas
// Argument words: "this" plus (oop/offset) or (lo/hi) args plus maybe 1 or 2 value words
int nargs = 1 + (is_native_ptr ? 2 : 3) + (is_store ? type_words : 0);
+ assert(callee()->arg_size() == nargs, "must be");
debug_only(int saved_sp = _sp);
_sp += nargs;
@@ -4047,7 +4048,8 @@ bool LibraryCallKit::is_method_invoke_or_aux_frame(JVMState* jvms) {
}
}
}
- else if (method->is_method_handle_adapter()) {
+ else if (method->is_method_handle_intrinsic() ||
+ method->is_compiled_lambda_form()) {
// This is an internal adapter frame from the MethodHandleCompiler -- skip it
return true;
}
diff --git a/src/share/vm/opto/matcher.cpp b/src/share/vm/opto/matcher.cpp
index f6bb30769..d5f14f4f6 100644
--- a/src/share/vm/opto/matcher.cpp
+++ b/src/share/vm/opto/matcher.cpp
@@ -1283,8 +1283,9 @@ MachNode *Matcher::match_sfpt( SafePointNode *sfpt ) {
if (is_method_handle_invoke) {
// Kill some extra stack space in case method handles want to do
// a little in-place argument insertion.
+ // FIXME: Is this still necessary?
int regs_per_word = NOT_LP64(1) LP64_ONLY(2); // %%% make a global const!
- out_arg_limit_per_call += MethodHandlePushLimit * regs_per_word;
+ out_arg_limit_per_call += methodOopDesc::extra_stack_entries() * regs_per_word;
// Do not update mcall->_argsize because (a) the extra space is not
// pushed as arguments and (b) _argsize is dead (not used anywhere).
}
diff --git a/src/share/vm/opto/node.hpp b/src/share/vm/opto/node.hpp
index f63a967b6..759c0bcd6 100644
--- a/src/share/vm/opto/node.hpp
+++ b/src/share/vm/opto/node.hpp
@@ -363,7 +363,7 @@ protected:
#endif
// Reference to the i'th input Node. Error if out of bounds.
- Node* in(uint i) const { assert(i < _max,"oob"); return _in[i]; }
+ Node* in(uint i) const { assert(i < _max, err_msg_res("oob: i=%d, _max=%d", i, _max)); return _in[i]; }
// Reference to the i'th output Node. Error if out of bounds.
// Use this accessor sparingly. We are going trying to use iterators instead.
Node* raw_out(uint i) const { assert(i < _outcnt,"oob"); return _out[i]; }
@@ -394,7 +394,7 @@ protected:
void ins_req( uint i, Node *n ); // Insert a NEW required input
void set_req( uint i, Node *n ) {
assert( is_not_dead(n), "can not use dead node");
- assert( i < _cnt, "oob");
+ assert( i < _cnt, err_msg_res("oob: i=%d, _cnt=%d", i, _cnt));
assert( !VerifyHashTableKeys || _hash_lock == 0,
"remove node from hash table before modifying it");
Node** p = &_in[i]; // cache this._in, across the del_out call
diff --git a/src/share/vm/opto/parse.hpp b/src/share/vm/opto/parse.hpp
index d05ed9b9b..620c8370d 100644
--- a/src/share/vm/opto/parse.hpp
+++ b/src/share/vm/opto/parse.hpp
@@ -84,7 +84,7 @@ public:
static const char* check_can_parse(ciMethod* callee);
static InlineTree* build_inline_tree_root();
- static InlineTree* find_subtree_from_root(InlineTree* root, JVMState* jvms, ciMethod* callee, bool create_if_not_found = false);
+ static InlineTree* find_subtree_from_root(InlineTree* root, JVMState* jvms, ciMethod* callee);
// For temporary (stack-allocated, stateless) ilts:
InlineTree(Compile* c, ciMethod* callee_method, JVMState* caller_jvms, float site_invoke_ratio, int max_inline_level);
diff --git a/src/share/vm/opto/parse1.cpp b/src/share/vm/opto/parse1.cpp
index 99bdf93b9..79fab69c1 100644
--- a/src/share/vm/opto/parse1.cpp
+++ b/src/share/vm/opto/parse1.cpp
@@ -398,7 +398,7 @@ Parse::Parse(JVMState* caller, ciMethod* parse_method, float expected_uses)
if (PrintCompilation || PrintOpto) {
// Make sure I have an inline tree, so I can print messages about it.
JVMState* ilt_caller = is_osr_parse() ? caller->caller() : caller;
- InlineTree::find_subtree_from_root(C->ilt(), ilt_caller, parse_method, true);
+ InlineTree::find_subtree_from_root(C->ilt(), ilt_caller, parse_method);
}
_max_switch_depth = 0;
_est_switch_depth = 0;
@@ -1398,8 +1398,8 @@ void Parse::do_one_block() {
#ifdef ASSERT
int pre_bc_sp = sp();
int inputs, depth;
- bool have_se = !stopped() && compute_stack_effects(inputs, depth);
- assert(!have_se || pre_bc_sp >= inputs, "have enough stack to execute this BC");
+ bool have_se = !stopped() && compute_stack_effects(inputs, depth, /*for_parse*/ true);
+ assert(!have_se || pre_bc_sp >= inputs, err_msg_res("have enough stack to execute this BC: pre_bc_sp=%d, inputs=%d", pre_bc_sp, inputs));
#endif //ASSERT
do_one_bytecode();
diff --git a/src/share/vm/opto/phaseX.hpp b/src/share/vm/opto/phaseX.hpp
index 8a58a9d89..8068e6d54 100644
--- a/src/share/vm/opto/phaseX.hpp
+++ b/src/share/vm/opto/phaseX.hpp
@@ -193,6 +193,7 @@ public:
// If you want the type of a very new (untransformed) node,
// you must use type_or_null, and test the result for NULL.
const Type* type(const Node* n) const {
+ assert(n != NULL, "must not be null");
const Type* t = _types.fast_lookup(n->_idx);
assert(t != NULL, "must set before get");
return t;