# HG changeset patch # User Bernhard Urban # Date 1366048498 -7200 # Node ID bc26f978b0ce2268d6bacd774cefe3067b0a59e3 # Parent 5b25562f8bd704d0db22155ca76a9ceb5172460c HotSpotResolvedObjectType: implement hasFinalizeSubclass() correctly don't use the (wrong) cached value, but ask the runtime on each request. Fixes regression on xml.* benchmarks @ specjvm2008. The problem was: After the constructor of Object was deoptimized due to an assumption violation, it was recompiled again after some time. However, on recompilation, the value of hasFinalizeSubclass for the class was not updated and it was compiled again with a, now wrong, assumption, which then triggers deoptimization again. This was repeated until it hit the recompilation limit (defined by PerMethodRecompilationCutoff), and therefore only executed by the interpreter from now on, causing the performance regression. diff -r 5b25562f8bd7 -r bc26f978b0ce graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Fri Apr 12 11:06:19 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Mon Apr 15 19:54:58 2013 +0200 @@ -169,6 +169,8 @@ HotSpotResolvedJavaField[] getInstanceFields(HotSpotResolvedObjectType klass); + boolean hasFinalizableSubclass(HotSpotResolvedObjectType klass); + /** * Gets the compiled code size for a method. * diff -r 5b25562f8bd7 -r bc26f978b0ce graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Fri Apr 12 11:06:19 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Mon Apr 15 19:54:58 2013 +0200 @@ -106,6 +106,9 @@ public native boolean isTypeInitialized(HotSpotResolvedObjectType klass); @Override + public native boolean hasFinalizableSubclass(HotSpotResolvedObjectType klass); + + @Override public native void initializeType(HotSpotResolvedObjectType klass); @Override diff -r 5b25562f8bd7 -r bc26f978b0ce graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java Fri Apr 12 11:06:19 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java Mon Apr 15 19:54:58 2013 +0200 @@ -76,7 +76,6 @@ * @param name the {@linkplain JavaType#getName() name} of the type * @param simpleName a simple, unqualified name for the type * @param javaMirror the {@link Class} mirror - * @param hasFinalizableSubclass specifies if the type has a finalizable subtype * @param sizeOrSpecies the size of an instance of the type, or * {@link HotSpotResolvedObjectType#INTERFACE_SPECIES_VALUE} or * {@link HotSpotResolvedObjectType#ARRAY_SPECIES_VALUE} @@ -84,7 +83,7 @@ * instantiated by this call in the case of another thread racing to create the same * type */ - ResolvedJavaType createResolvedJavaType(long metaspaceKlass, String name, String simpleName, Class javaMirror, boolean hasFinalizableSubclass, int sizeOrSpecies); + ResolvedJavaType createResolvedJavaType(long metaspaceKlass, String name, String simpleName, Class javaMirror, int sizeOrSpecies); Constant createConstant(Kind kind, long value); diff -r 5b25562f8bd7 -r bc26f978b0ce graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Fri Apr 12 11:06:19 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Mon Apr 15 19:54:58 2013 +0200 @@ -683,8 +683,8 @@ } @Override - public HotSpotResolvedObjectType createResolvedJavaType(long metaspaceKlass, String name, String simpleName, Class javaMirror, boolean hasFinalizableSubclass, int sizeOrSpecies) { - HotSpotResolvedObjectType type = new HotSpotResolvedObjectType(metaspaceKlass, name, simpleName, javaMirror, hasFinalizableSubclass, sizeOrSpecies); + public HotSpotResolvedObjectType createResolvedJavaType(long metaspaceKlass, String name, String simpleName, Class javaMirror, int sizeOrSpecies) { + HotSpotResolvedObjectType type = new HotSpotResolvedObjectType(metaspaceKlass, name, simpleName, javaMirror, sizeOrSpecies); long offset = HotSpotGraalRuntime.getInstance().getConfig().graalMirrorInClassOffset; if (!unsafe.compareAndSwapObject(javaMirror, offset, null, type)) { diff -r 5b25562f8bd7 -r bc26f978b0ce graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Fri Apr 12 11:06:19 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Mon Apr 15 19:54:58 2013 +0200 @@ -23,7 +23,7 @@ package com.oracle.graal.hotspot.meta; import static com.oracle.graal.api.meta.MetaUtil.*; -import static com.oracle.graal.graph.FieldIntrospection.*; +import static com.oracle.graal.graph.UnsafeAccess.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import static java.lang.reflect.Modifier.*; @@ -63,7 +63,6 @@ private final Class javaMirror; // this could be read directly from 'metaspaceKlass'... private final String simpleName; - private final boolean hasFinalizableSubclass; /** * The instance size (in bytes) for an instance type, @@ -120,17 +119,15 @@ } /** - * @param hasFinalizableSubclass * @param sizeOrSpecies the size of an instance of the type, or * {@link HotSpotResolvedObjectType#INTERFACE_SPECIES_VALUE} or * {@link HotSpotResolvedObjectType#ARRAY_SPECIES_VALUE} */ - public HotSpotResolvedObjectType(long metaspaceKlass, String name, String simpleName, Class javaMirror, boolean hasFinalizableSubclass, int sizeOrSpecies) { + public HotSpotResolvedObjectType(long metaspaceKlass, String name, String simpleName, Class javaMirror, int sizeOrSpecies) { super(name); this.metaspaceKlass = metaspaceKlass; this.javaMirror = javaMirror; this.simpleName = simpleName; - this.hasFinalizableSubclass = hasFinalizableSubclass; this.sizeOrSpecies = sizeOrSpecies; assert name.charAt(0) != '[' || sizeOrSpecies == ARRAY_SPECIES_VALUE : name + " " + Long.toHexString(sizeOrSpecies); assert javaMirror.isArray() == isArray(); @@ -260,7 +257,8 @@ @Override public boolean hasFinalizableSubclass() { - return hasFinalizableSubclass; + assert !isArray(); + return HotSpotGraalRuntime.getInstance().getCompilerToVM().hasFinalizableSubclass(this); } @Override diff -r 5b25562f8bd7 -r bc26f978b0ce src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Fri Apr 12 11:06:19 2013 +0200 +++ b/src/share/vm/classfile/vmSymbols.hpp Mon Apr 15 19:54:58 2013 +0200 @@ -360,7 +360,7 @@ template(createUnresolvedJavaType_name, "createUnresolvedJavaType") \ template(createUnresolvedJavaType_signature, "(Ljava/lang/String;)Lcom/oracle/graal/api/meta/JavaType;") \ template(createResolvedJavaType_name, "createResolvedJavaType") \ - template(createResolvedJavaType_signature, "(JLjava/lang/String;Ljava/lang/String;Ljava/lang/Class;ZI)Lcom/oracle/graal/api/meta/ResolvedJavaType;") \ + template(createResolvedJavaType_signature, "(JLjava/lang/String;Ljava/lang/String;Ljava/lang/Class;I)Lcom/oracle/graal/api/meta/ResolvedJavaType;") \ template(createPrimitiveJavaType_name, "createPrimitiveJavaType") \ template(createPrimitiveJavaType_signature, "(I)Lcom/oracle/graal/api/meta/JavaType;") \ template(createLocalImpl_name, "createLocalImpl") \ diff -r 5b25562f8bd7 -r bc26f978b0ce src/share/vm/graal/graalCompiler.cpp --- a/src/share/vm/graal/graalCompiler.cpp Fri Apr 12 11:06:19 2013 +0200 +++ b/src/share/vm/graal/graalCompiler.cpp Mon Apr 15 19:54:58 2013 +0200 @@ -293,9 +293,6 @@ name = java_lang_String::create_from_str(ik->signature_name(), CHECK_NULL); } - // TODO replace this with the correct value - bool hasFinalizableSubclass = false; - int sizeOrSpecies; if (klass->is_interface()) { sizeOrSpecies = (int) 0x80000000; // see HotSpotResolvedObjectType.INTERFACE_SPECIES_VALUE @@ -308,7 +305,7 @@ } } - return VMToCompiler::createResolvedJavaType(klass(), name, simpleName, java_class, hasFinalizableSubclass, sizeOrSpecies, CHECK_NULL); + return VMToCompiler::createResolvedJavaType(klass(), name, simpleName, java_class, sizeOrSpecies, CHECK_NULL); } BasicType GraalCompiler::kindToBasicType(jchar ch) { diff -r 5b25562f8bd7 -r bc26f978b0ce src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Fri Apr 12 11:06:19 2013 +0200 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Mon Apr 15 19:54:58 2013 +0200 @@ -550,6 +550,12 @@ return InstanceKlass::cast(klass)->is_initialized(); C2V_END +C2V_VMENTRY(jboolean, hasFinalizableSubclass,(JNIEnv *, jobject, jobject hotspot_klass)) + Klass* klass = java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(hotspot_klass)); + assert(klass != NULL, "method must not be called for primitive types"); + return Dependencies::find_finalizable_subclass(klass) != NULL; +C2V_END + C2V_VMENTRY(void, initializeType, (JNIEnv *, jobject, jobject hotspot_klass)) Klass* klass = java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(hotspot_klass)); assert(klass != NULL, "method must not be called for primitive types"); @@ -1131,6 +1137,7 @@ {CC"resolveMethod", CC"("HS_RESOLVED_TYPE STRING STRING")"METHOD, FN_PTR(resolveMethod)}, {CC"getInstanceFields", CC"("HS_RESOLVED_TYPE")["HS_RESOLVED_FIELD, FN_PTR(getInstanceFields)}, {CC"isTypeInitialized", CC"("HS_RESOLVED_TYPE")Z", FN_PTR(isTypeInitialized)}, + {CC"hasFinalizableSubclass", CC"("HS_RESOLVED_TYPE")Z", FN_PTR(hasFinalizableSubclass)}, {CC"initializeType", CC"("HS_RESOLVED_TYPE")V", FN_PTR(initializeType)}, {CC"getMaxCallTargetOffset", CC"(J)J", FN_PTR(getMaxCallTargetOffset)}, {CC"getResolvedType", CC"("CLASS")"RESOLVED_TYPE, FN_PTR(getResolvedType)}, diff -r 5b25562f8bd7 -r bc26f978b0ce src/share/vm/graal/graalVMToCompiler.cpp --- a/src/share/vm/graal/graalVMToCompiler.cpp Fri Apr 12 11:06:19 2013 +0200 +++ b/src/share/vm/graal/graalVMToCompiler.cpp Mon Apr 15 19:54:58 2013 +0200 @@ -208,7 +208,7 @@ return (oop) result.get_jobject(); } -oop VMToCompiler::createResolvedJavaType(Klass* klass, Handle name, Handle simpleName, Handle java_mirror, jboolean hasFinalizableSubclass, jint sizeOrSpecies, TRAPS) { +oop VMToCompiler::createResolvedJavaType(Klass* klass, Handle name, Handle simpleName, Handle java_mirror, jint sizeOrSpecies, TRAPS) { assert(!name.is_null(), "just checking"); assert(!simpleName.is_null(), "just checking"); JavaValue result(T_OBJECT); @@ -218,7 +218,6 @@ args.push_oop(name); args.push_oop(simpleName); args.push_oop(java_mirror); - args.push_int(hasFinalizableSubclass); args.push_int(sizeOrSpecies); JavaCalls::call_interface(&result, vmToCompilerKlass(), vmSymbols::createResolvedJavaType_name(), vmSymbols::createResolvedJavaType_signature(), &args, THREAD); check_pending_exception("Error while calling createResolvedJavaType"); diff -r 5b25562f8bd7 -r bc26f978b0ce src/share/vm/graal/graalVMToCompiler.hpp --- a/src/share/vm/graal/graalVMToCompiler.hpp Fri Apr 12 11:06:19 2013 +0200 +++ b/src/share/vm/graal/graalVMToCompiler.hpp Mon Apr 15 19:54:58 2013 +0200 @@ -77,8 +77,8 @@ // public abstract JavaType createUnresolvedJavaType(String name); static oop createUnresolvedJavaType(Handle name, TRAPS); - // public abstract ResolvedJavaType createResolvedJavaType(long metaspaceKlass, String name, String simpleName, Class javaMirror, boolean hasFinalizableSubclass, int sizeOrSpecies); - static oop createResolvedJavaType(Klass* klass, Handle name, Handle simpleName, Handle java_mirror, jboolean hasFinalizableSubclass, jint sizeOrSpecies, TRAPS); + // public abstract ResolvedJavaType createResolvedJavaType(long metaspaceKlass, String name, String simpleName, Class javaMirror, int sizeOrSpecies); + static oop createResolvedJavaType(Klass* klass, Handle name, Handle simpleName, Handle java_mirror, jint sizeOrSpecies, TRAPS); // public abstract JavaType createPrimitiveJavaType(int basicType); static oop createPrimitiveJavaType(int basicType, TRAPS);