mirror of
https://github.com/openjdk/jdk.git
synced 2026-07-12 04:05:26 +00:00
8067247: Crash: assert(method_holder->data() == 0 ...) failed: a) MT-unsafe modification of inline cache
Made invoker LambdaForm instance & its compiled form lifetime tightly coupled. Reviewed-by: vlivanov
This commit is contained in:
parent
fa667c5409
commit
b26b78a4d4
@ -1042,6 +1042,14 @@ void CodeCache::clear_inline_caches() {
|
||||
}
|
||||
}
|
||||
|
||||
void CodeCache::cleanup_inline_caches() {
|
||||
assert_locked_or_safepoint(CodeCache_lock);
|
||||
NMethodIterator iter;
|
||||
while(iter.next_alive()) {
|
||||
iter.method()->cleanup_inline_caches(/*clean_all=*/true);
|
||||
}
|
||||
}
|
||||
|
||||
// Keeps track of time spent for checking dependencies
|
||||
NOT_PRODUCT(static elapsedTimer dependentCheckTime;)
|
||||
|
||||
|
||||
@ -201,6 +201,7 @@ class CodeCache : AllStatic {
|
||||
static bool needs_cache_clean() { return _needs_cache_clean; }
|
||||
static void set_needs_cache_clean(bool v) { _needs_cache_clean = v; }
|
||||
static void clear_inline_caches(); // clear all inline caches
|
||||
static void cleanup_inline_caches();
|
||||
|
||||
// Returns true if an own CodeHeap for the given CodeBlobType is available
|
||||
static bool heap_available(int code_blob_type);
|
||||
|
||||
@ -1138,8 +1138,7 @@ void nmethod::clear_ic_stubs() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void nmethod::cleanup_inline_caches() {
|
||||
void nmethod::cleanup_inline_caches(bool clean_all/*=false*/) {
|
||||
assert_locked_or_safepoint(CompiledIC_lock);
|
||||
|
||||
// If the method is not entrant or zombie then a JMP is plastered over the
|
||||
@ -1169,7 +1168,7 @@ void nmethod::cleanup_inline_caches() {
|
||||
if( cb != NULL && cb->is_nmethod() ) {
|
||||
nmethod* nm = (nmethod*)cb;
|
||||
// Clean inline caches pointing to zombie, non-entrant and unloaded methods
|
||||
if (!nm->is_in_use() || (nm->method()->code() != nm)) ic->set_to_clean(is_alive());
|
||||
if (clean_all || !nm->is_in_use() || (nm->method()->code() != nm)) ic->set_to_clean(is_alive());
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1179,7 +1178,7 @@ void nmethod::cleanup_inline_caches() {
|
||||
if( cb != NULL && cb->is_nmethod() ) {
|
||||
nmethod* nm = (nmethod*)cb;
|
||||
// Clean inline caches pointing to zombie, non-entrant and unloaded methods
|
||||
if (!nm->is_in_use() || (nm->method()->code() != nm)) csc->set_to_clean();
|
||||
if (clean_all || !nm->is_in_use() || (nm->method()->code() != nm)) csc->set_to_clean();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@ -599,7 +599,7 @@ public:
|
||||
// Inline cache support
|
||||
void clear_inline_caches();
|
||||
void clear_ic_stubs();
|
||||
void cleanup_inline_caches();
|
||||
void cleanup_inline_caches(bool clean_all = false);
|
||||
bool inlinecache_check_contains(address addr) const {
|
||||
return (addr >= code_begin() && addr < verified_entry_point());
|
||||
}
|
||||
|
||||
@ -1376,8 +1376,8 @@ WB_ENTRY(jint, WB_ConstantPoolEncodeIndyIndex(JNIEnv* env, jobject wb, jint inde
|
||||
return ConstantPool::encode_invokedynamic_index(index);
|
||||
WB_END
|
||||
|
||||
WB_ENTRY(void, WB_ClearInlineCaches(JNIEnv* env, jobject wb))
|
||||
VM_ClearICs clear_ics;
|
||||
WB_ENTRY(void, WB_ClearInlineCaches(JNIEnv* env, jobject wb, jboolean preserve_static_stubs))
|
||||
VM_ClearICs clear_ics(preserve_static_stubs == JNI_TRUE);
|
||||
VMThread::execute(&clear_ics);
|
||||
WB_END
|
||||
|
||||
@ -1757,7 +1757,7 @@ static JNINativeMethod methods[] = {
|
||||
{CC"isShared", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsShared },
|
||||
{CC"isSharedClass", CC"(Ljava/lang/Class;)Z", (void*)&WB_IsSharedClass },
|
||||
{CC"areSharedStringsIgnored", CC"()Z", (void*)&WB_AreSharedStringsIgnored },
|
||||
{CC"clearInlineCaches", CC"()V", (void*)&WB_ClearInlineCaches },
|
||||
{CC"clearInlineCaches0", CC"(Z)V", (void*)&WB_ClearInlineCaches },
|
||||
{CC"addCompilerDirective", CC"(Ljava/lang/String;)I",
|
||||
(void*)&WB_AddCompilerDirective },
|
||||
{CC"removeCompilerDirective", CC"(I)V", (void*)&WB_RemoveCompilerDirective },
|
||||
|
||||
@ -105,6 +105,14 @@ void VM_ThreadStop::doit() {
|
||||
}
|
||||
}
|
||||
|
||||
void VM_ClearICs::doit() {
|
||||
if (_preserve_static_stubs) {
|
||||
CodeCache::cleanup_inline_caches();
|
||||
} else {
|
||||
CodeCache::clear_inline_caches();
|
||||
}
|
||||
}
|
||||
|
||||
void VM_Deoptimize::doit() {
|
||||
// We do not want any GCs to happen while we are in the middle of this VM operation
|
||||
ResourceMark rm;
|
||||
|
||||
@ -231,9 +231,11 @@ class VM_ThreadStop: public VM_Operation {
|
||||
};
|
||||
|
||||
class VM_ClearICs: public VM_Operation {
|
||||
private:
|
||||
bool _preserve_static_stubs;
|
||||
public:
|
||||
VM_ClearICs() {}
|
||||
void doit() { CodeCache::clear_inline_caches(); }
|
||||
VM_ClearICs(bool preserve_static_stubs) { _preserve_static_stubs = preserve_static_stubs; }
|
||||
void doit();
|
||||
VMOp_Type type() const { return VMOp_ClearICs; }
|
||||
};
|
||||
|
||||
|
||||
75
hotspot/test/compiler/jsr292/InvokerGC.java
Normal file
75
hotspot/test/compiler/jsr292/InvokerGC.java
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8067247
|
||||
* @library /test/lib /compiler/whitebox /
|
||||
* @run main/bootclasspath -Xcomp -Xbatch
|
||||
* -XX:CompileCommand=compileonly,InvokerGC::test
|
||||
* -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
||||
* InvokerGC
|
||||
*/
|
||||
|
||||
import java.lang.invoke.*;
|
||||
import sun.hotspot.WhiteBox;
|
||||
|
||||
public class InvokerGC {
|
||||
static final WhiteBox WB = WhiteBox.getWhiteBox();
|
||||
|
||||
static MethodHandle mh;
|
||||
static {
|
||||
try {
|
||||
mh = MethodHandles.lookup().findStatic(InvokerGC.class, "dummy", MethodType.methodType(void.class));
|
||||
} catch (Exception e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
static void dummy() {}
|
||||
|
||||
static void test() {
|
||||
try {
|
||||
mh.invoke();
|
||||
} catch (Throwable e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
mh.invoke(); // Pre-generate an invoker for ()V signature
|
||||
|
||||
test(); // trigger method compilation
|
||||
test();
|
||||
|
||||
WB.fullGC(); // WB.fullGC has always clear softref policy.
|
||||
|
||||
test();
|
||||
|
||||
WB.clearInlineCaches(true); // Preserve static stubs.
|
||||
|
||||
test(); // Trigger call site re-resolution. Invoker LambdaForm should stay the same.
|
||||
|
||||
System.out.println("TEST PASSED");
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user