diff options
author | twisti <none@none> | 2011-08-16 04:14:05 -0700 |
---|---|---|
committer | twisti <none@none> | 2011-08-16 04:14:05 -0700 |
commit | 2d574d8661250da83918673dca9c91e133b266b0 (patch) | |
tree | 249fcb8326d4b860056e45227a09b25a6ce5a2f0 /src/share/vm/opto | |
parent | f37c7c47415211e01a95c336a5c4a0ae35300f20 (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.cpp | 29 | ||||
-rw-r--r-- | src/share/vm/opto/callGenerator.hpp | 5 | ||||
-rw-r--r-- | src/share/vm/opto/doCall.cpp | 32 | ||||
-rw-r--r-- | src/share/vm/opto/parse3.cpp | 8 |
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. |