aboutsummaryrefslogtreecommitdiff
path: root/src/share/vm/opto
diff options
context:
space:
mode:
authortwisti <none@none>2011-08-16 04:14:05 -0700
committertwisti <none@none>2011-08-16 04:14:05 -0700
commit2d574d8661250da83918673dca9c91e133b266b0 (patch)
tree249fcb8326d4b860056e45227a09b25a6ce5a2f0 /src/share/vm/opto
parentf37c7c47415211e01a95c336a5c4a0ae35300f20 (diff)
7071653: JSR 292: call site change notification should be pushed not pulled
Reviewed-by: kvn, never, bdelsart
Diffstat (limited to 'src/share/vm/opto')
-rw-r--r--src/share/vm/opto/callGenerator.cpp29
-rw-r--r--src/share/vm/opto/callGenerator.hpp5
-rw-r--r--src/share/vm/opto/doCall.cpp32
-rw-r--r--src/share/vm/opto/parse3.cpp8
4 files changed, 52 insertions, 22 deletions
diff --git a/src/share/vm/opto/callGenerator.cpp b/src/share/vm/opto/callGenerator.cpp
index fb91f57af..58426ddee 100644
--- a/src/share/vm/opto/callGenerator.cpp
+++ b/src/share/vm/opto/callGenerator.cpp
@@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "ci/bcEscapeAnalyzer.hpp"
+#include "ci/ciCallSite.hpp"
#include "ci/ciCPCache.hpp"
#include "ci/ciMethodHandle.hpp"
#include "classfile/javaClasses.hpp"
@@ -738,6 +739,34 @@ CallGenerator* CallGenerator::for_method_handle_inline(Node* method_handle, JVMS
}
+CallGenerator* CallGenerator::for_invokedynamic_inline(ciCallSite* call_site, JVMState* jvms,
+ ciMethod* caller, ciMethod* callee, ciCallProfile profile) {
+ assert(call_site->is_constant_call_site() || call_site->is_mutable_call_site(), "must be");
+ 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* hit_cg = C->call_generator(target_method, -1, false, jvms, true, PROB_ALWAYS);
+ if (hit_cg != NULL && hit_cg->is_inline()) {
+ // Add a dependence for invalidation of the optimization.
+ if (call_site->is_mutable_call_site()) {
+ C->dependencies()->assert_call_site_target_value(C->env()->CallSite_klass(), call_site, method_handle);
+ }
+ return hit_cg;
+ }
+ }
+ return NULL;
+}
+
+
JVMState* PredictedDynamicCallGenerator::generate(JVMState* jvms) {
GraphKit kit(jvms);
PhaseGVN& gvn = kit.gvn();
diff --git a/src/share/vm/opto/callGenerator.hpp b/src/share/vm/opto/callGenerator.hpp
index cdefb592c..d95ba2b1c 100644
--- a/src/share/vm/opto/callGenerator.hpp
+++ b/src/share/vm/opto/callGenerator.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -111,7 +111,8 @@ class CallGenerator : public ResourceObj {
static CallGenerator* for_dynamic_call(ciMethod* m); // invokedynamic
static CallGenerator* for_virtual_call(ciMethod* m, int vtable_index); // virtual, interface
- static CallGenerator* for_method_handle_inline(Node* method_handle, 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);
// How to generate a replace a direct call with an inline version
static CallGenerator* for_late_inline(ciMethod* m, CallGenerator* inline_cg);
diff --git a/src/share/vm/opto/doCall.cpp b/src/share/vm/opto/doCall.cpp
index c1b25d88e..de51329e8 100644
--- a/src/share/vm/opto/doCall.cpp
+++ b/src/share/vm/opto/doCall.cpp
@@ -114,7 +114,7 @@ CallGenerator* Compile::call_generator(ciMethod* call_method, int vtable_index,
if (cg != NULL) return cg;
}
- // Do MethodHandle calls.
+ // Do method handle calls.
// 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.
@@ -127,33 +127,25 @@ CallGenerator* Compile::call_generator(ciMethod* call_method, int vtable_index,
if (cg != NULL) {
return cg;
}
-
return CallGenerator::for_direct_call(call_method);
}
else {
- // Get the MethodHandle from the CallSite.
+ // Get the CallSite object.
ciMethod* caller_method = jvms->method();
ciBytecodeStream str(caller_method);
str.force_bci(jvms->bci()); // Set the stream to the invokedynamic bci.
- ciCallSite* call_site = str.get_call_site();
- 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(call_method);
- 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) {
- CallGenerator* hit_cg = this->call_generator(target_method, vtable_index, false, jvms, true, prof_factor);
- if (hit_cg != NULL && hit_cg->is_inline()) {
- CallGenerator* miss_cg = CallGenerator::for_dynamic_call(call_method);
- return CallGenerator::for_predicted_dynamic_call(method_handle, miss_cg, hit_cg, prof_factor);
+ ciCallSite* call_site = str.get_call_site();
+
+ // Inline constant and mutable call sites. We don't inline
+ // volatile call sites optimistically since they are specified
+ // to change their value often and that would result in a lot of
+ // deoptimizations and recompiles.
+ if (call_site->is_constant_call_site() || call_site->is_mutable_call_site()) {
+ CallGenerator* cg = CallGenerator::for_invokedynamic_inline(call_site, jvms, caller, call_method, profile);
+ if (cg != NULL) {
+ return cg;
}
}
-
// If something failed, generate a normal dynamic call.
return CallGenerator::for_dynamic_call(call_method);
}
diff --git a/src/share/vm/opto/parse3.cpp b/src/share/vm/opto/parse3.cpp
index e1a319fad..1f0335cfe 100644
--- a/src/share/vm/opto/parse3.cpp
+++ b/src/share/vm/opto/parse3.cpp
@@ -100,6 +100,14 @@ void Parse::do_field_access(bool is_get, bool is_field) {
}
}
+ // Deoptimize on putfield writes to CallSite.target
+ if (!is_get && field->is_call_site_target()) {
+ uncommon_trap(Deoptimization::Reason_unhandled,
+ Deoptimization::Action_reinterpret,
+ NULL, "put to CallSite.target field");
+ return;
+ }
+
assert(field->will_link(method()->holder(), bc()), "getfield: typeflow responsibility");
// Note: We do not check for an unloaded field type here any more.