From b521dcfc79cdc2a72377c0be7d93e65ead9e85dd Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Tue, 8 Nov 2022 21:22:58 +0100 Subject: [PATCH 1/6] tmp: test GR-41977 --- common.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common.json b/common.json index 64959793851a..fcafc6b63130 100644 --- a/common.json +++ b/common.json @@ -23,8 +23,8 @@ "labsjdk-ce-19": {"name": "labsjdk", "version": "ce-19+36-jvmci-23.0-b01", "platformspecific": true }, "labsjdk-ce-19Debug": {"name": "labsjdk", "version": "ce-19+36-jvmci-23.0-b01-debug", "platformspecific": true }, "labsjdk-ce-19-llvm": {"name": "labsjdk", "version": "ce-19+36-jvmci-23.0-b01-sulong", "platformspecific": true }, - "labsjdk-ee-19": {"name": "labsjdk", "version": "ee-19.0.1+10-jvmci-23.0-b01", "platformspecific": true }, - "labsjdk-ee-19Debug": {"name": "labsjdk", "version": "ee-19.0.1+10-jvmci-23.0-b01-debug", "platformspecific": true }, + "labsjdk-ee-19": {"name": "labsjdk", "version": "ee-19.0.1+10-jvmci-41977.1-b01-20221107143847-ds_GR_41977-master-798a7efecb+697030422a", "platformspecific": true }, + "labsjdk-ee-19Debug": {"name": "labsjdk", "version": "ee-19.0.1+10-jvmci-41977.1-b01-20221107143847-ds_GR_41977-master-798a7efecb+697030422a-debug", "platformspecific": true }, "labsjdk-ee-19-llvm": {"name": "labsjdk", "version": "ee-19.0.1+10-jvmci-23.0-b01-sulong", "platformspecific": true } }, From 3491c522bf5f81dc62782963f5f8a5cf49f24e18 Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Wed, 2 Nov 2022 10:10:50 +0100 Subject: [PATCH 2/6] removed JVMCI test --- .../test/HotSpotResolvedJavaFieldTest.java | 138 ------------------ 1 file changed, 138 deletions(-) delete mode 100644 compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotResolvedJavaFieldTest.java diff --git a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotResolvedJavaFieldTest.java b/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotResolvedJavaFieldTest.java deleted file mode 100644 index bd64c70f30e6..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotResolvedJavaFieldTest.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) 2013, 2020, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ -package org.graalvm.compiler.hotspot.test; - -import static java.lang.reflect.Modifier.FINAL; -import static java.lang.reflect.Modifier.PRIVATE; -import static java.lang.reflect.Modifier.PROTECTED; -import static java.lang.reflect.Modifier.PUBLIC; -import static java.lang.reflect.Modifier.STATIC; -import static java.lang.reflect.Modifier.TRANSIENT; -import static java.lang.reflect.Modifier.VOLATILE; - -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -import org.graalvm.compiler.core.common.util.Util; -import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; -import org.junit.Assert; -import org.junit.Test; - -import jdk.vm.ci.hotspot.HotSpotResolvedJavaField; -import jdk.vm.ci.hotspot.HotSpotVMConfigAccess; -import jdk.vm.ci.meta.JavaType; -import jdk.vm.ci.meta.ResolvedJavaField; -import jdk.vm.ci.meta.ResolvedJavaType; - -/** - * Tests {@link HotSpotResolvedJavaField} functionality. - */ -public class HotSpotResolvedJavaFieldTest extends HotSpotGraalCompilerTest { - - private static final Class[] classesWithInternalFields = {Class.class, ClassLoader.class}; - - private static final Method createFieldMethod; - private static final Field indexField; - - static { - Method m = null; - Field f = null; - try { - Class typeImpl = Class.forName("jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl"); - m = typeImpl.getDeclaredMethod("createField", JavaType.class, long.class, int.class, int.class); - Util.setAccessible(m, true); - Class fieldImpl = Class.forName("jdk.vm.ci.hotspot.HotSpotResolvedJavaFieldImpl"); - f = fieldImpl.getDeclaredField("index"); - Util.setAccessible(f, true); - } catch (Exception e) { - throw new AssertionError(e); - } - - createFieldMethod = m; - indexField = f; - } - - /** - * Same as {@code HotSpotModifiers.jvmFieldModifiers()} but works when using a JVMCI version - * prior to the introduction of that method. - */ - private int jvmFieldModifiers() { - GraalHotSpotVMConfig config = runtime().getVMConfig(); - HotSpotVMConfigAccess access = new HotSpotVMConfigAccess(config.getStore()); - int accEnum = access.getConstant("JVM_ACC_ENUM", Integer.class, 0x4000); - int accSynthetic = access.getConstant("JVM_ACC_SYNTHETIC", Integer.class, 0x1000); - return PUBLIC | PRIVATE | PROTECTED | STATIC | FINAL | VOLATILE | TRANSIENT | accEnum | accSynthetic; - } - - /** - * Tests that {@link HotSpotResolvedJavaField#getModifiers()} only includes the modifiers - * returned by {@link Field#getModifiers()}. Namely, it must not include - * {@code HotSpotResolvedJavaField#FIELD_INTERNAL_FLAG}. - */ - @Test - public void testModifiersForInternal() { - for (Class c : classesWithInternalFields) { - ResolvedJavaType type = getMetaAccess().lookupJavaType(c); - for (ResolvedJavaField field : type.getInstanceFields(false)) { - if (field.isInternal()) { - Assert.assertEquals(0, ~jvmFieldModifiers() & field.getModifiers()); - } - } - } - } - - /** - * Tests that {@code HotSpotResolvedObjectTypeImpl#createField(String, JavaType, long, int)} - * always returns an {@linkplain ResolvedJavaField#equals(Object) equivalent} object for an - * internal field. - * - * @throws InvocationTargetException - * @throws IllegalArgumentException - * @throws IllegalAccessException - */ - @Test - public void testEquivalenceForInternalFields() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { - for (Class c : classesWithInternalFields) { - ResolvedJavaType type = getMetaAccess().lookupJavaType(c); - for (ResolvedJavaField field : type.getInstanceFields(false)) { - if (field.isInternal()) { - HotSpotResolvedJavaField expected = (HotSpotResolvedJavaField) field; - int index = indexField.getInt(expected); - ResolvedJavaField actual = (ResolvedJavaField) createFieldMethod.invoke(type, expected.getType(), expected.getOffset(), expected.getModifiers(), index); - Assert.assertEquals(expected, actual); - } - } - } - } - - @Test - public void testIsInObject() { - for (Field f : String.class.getDeclaredFields()) { - HotSpotResolvedJavaField rf = (HotSpotResolvedJavaField) getMetaAccess().lookupJavaField(f); - Assert.assertEquals(rf.toString(), rf.isInObject(getConstantReflection().forString("a string")), !rf.isStatic()); - } - } -} From a721e083dabb22a918c91e838b39275a2b195d5e Mon Sep 17 00:00:00 2001 From: Christian Wimmer Date: Tue, 1 Nov 2022 14:52:53 -0700 Subject: [PATCH 3/6] Use new JVMCI API --- .../HotSpotSnippetReflectionProvider.java | 77 ++--------- .../StandaloneConstantReflectionProvider.java | 4 +- .../infrastructure/WrappedConstantPool.java | 18 +-- .../graal/pointsto/meta/AnalysisField.java | 6 + .../UninitializedStaticFieldValueReader.java | 120 ------------------ .../phases/NoClassInitializationPlugin.java | 3 +- .../AnalysisConstantReflectionProvider.java | 14 +- .../AnnotationSubstitutionField.java | 5 + .../oracle/svm/hosted/meta/HostedField.java | 5 + .../svm/hosted/substitute/AnnotatedField.java | 5 + .../hosted/substitute/ComputedValueField.java | 5 + .../hosted/substitute/SubstitutionField.java | 6 + 12 files changed, 61 insertions(+), 207 deletions(-) delete mode 100644 substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/UninitializedStaticFieldValueReader.java diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSnippetReflectionProvider.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSnippetReflectionProvider.java index a992d69a83c5..8a97cb59073a 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSnippetReflectionProvider.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSnippetReflectionProvider.java @@ -28,7 +28,7 @@ import java.lang.reflect.Executable; import java.lang.reflect.Field; -import java.lang.reflect.Method; +import java.util.Objects; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.debug.GraalError; @@ -39,12 +39,13 @@ import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider; import jdk.vm.ci.hotspot.HotSpotObjectConstant; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaField; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.ResolvedJavaField; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; -import jdk.vm.ci.services.Services; public class HotSpotSnippetReflectionProvider implements SnippetReflectionProvider { @@ -52,39 +53,10 @@ public class HotSpotSnippetReflectionProvider implements SnippetReflectionProvid private final HotSpotConstantReflectionProvider constantReflection; private final WordTypes wordTypes; - /* - * GR-41976: JVMCI currently does not have public API to convert methods and fields back to - * reflection objects. So we do it via reflective invocation of JVMCI internals. - * - * These fields are intentionally not static, because we do not want libgraal to run with the - * state initialized at image build time. - */ - private final Method hotSpotJDKReflectionGetMethod; - private final Method hotSpotJDKReflectionGetField; - public HotSpotSnippetReflectionProvider(HotSpotGraalRuntimeProvider runtime, HotSpotConstantReflectionProvider constantReflection, WordTypes wordTypes) { this.runtime = runtime; this.constantReflection = constantReflection; this.wordTypes = wordTypes; - - if (Services.IS_IN_NATIVE_IMAGE) { - /* No access to method/field mirrors when running in libgraal. */ - hotSpotJDKReflectionGetMethod = null; - hotSpotJDKReflectionGetField = null; - } else { - try { - Class hsJDKReflection = Class.forName("jdk.vm.ci.hotspot.HotSpotJDKReflection"); - hotSpotJDKReflectionGetMethod = lookupMethod(hsJDKReflection, "getMethod", Class.forName("jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl")); - hotSpotJDKReflectionGetField = lookupMethod(hsJDKReflection, "getField", Class.forName("jdk.vm.ci.hotspot.HotSpotResolvedJavaFieldImpl")); - } catch (ReflectiveOperationException ex) { - /* - * Note that older JVMCI versions do not have those methods even when running in JDK - * mode and not in libgraal mode. But that affects only OpenJDK 11, and we no longer - * support JDK 11 at all. OpenJDK 17 already has the necessary methods. - */ - throw GraalError.shouldNotReachHere(ex); - } - } } @Override @@ -150,52 +122,23 @@ public Class originalClass(ResolvedJavaType type) { return runtime().getMirror(type); } - private static Method lookupMethod(Class declaringClass, String methodName, Class... parameterTypes) throws ReflectiveOperationException { - Method result = declaringClass.getDeclaredMethod(methodName, parameterTypes); - result.setAccessible(true); - return result; - } - @Override public Executable originalMethod(ResolvedJavaMethod method) { + Objects.requireNonNull(method); + GraalError.guarantee(method instanceof HotSpotResolvedJavaMethod, "Unexpected implementation class: %s", method.getClass()); + if (method.isClassInitializer()) { /* methods never have a corresponding java.lang.reflect.Method. */ return null; } - - if (hotSpotJDKReflectionGetMethod == null) { - return null; - } - try { - return (Executable) hotSpotJDKReflectionGetMethod.invoke(null, method); - } catch (ReflectiveOperationException ex) { - throw rethrow(ex.getCause()); - } + return runtime().getMirror(method); } @Override public Field originalField(ResolvedJavaField field) { - if (hotSpotJDKReflectionGetField == null) { - return null; - } - try { - return (Field) hotSpotJDKReflectionGetField.invoke(null, field); - } catch (ReflectiveOperationException ex) { - if (ex.getCause() instanceof IllegalArgumentException) { - /** - * GR-41974: A bug in JVMCI prevents the lookup of the java.lang.reflect.Field. - * Since even calling getName() on the ResolvedJavaField crashes for such fields, we - * also cannot use Class.getDeclaredField as a workaround for lookup. Our only - * option is to return null for now. - */ - return null; - } - throw rethrow(ex.getCause()); - } - } + Objects.requireNonNull(field); + GraalError.guarantee(field instanceof HotSpotResolvedJavaField, "Unexpected implementation class: %s", field.getClass()); - @SuppressWarnings({"unchecked"}) - private static RuntimeException rethrow(Throwable ex) throws E { - throw (E) ex; + return runtime().getMirror(field); } } diff --git a/substratevm/src/com.oracle.graal.pointsto.standalone/src/com/oracle/graal/pointsto/standalone/meta/StandaloneConstantReflectionProvider.java b/substratevm/src/com.oracle.graal.pointsto.standalone/src/com/oracle/graal/pointsto/standalone/meta/StandaloneConstantReflectionProvider.java index dd45f2324702..b829feb07def 100644 --- a/substratevm/src/com.oracle.graal.pointsto.standalone/src/com/oracle/graal/pointsto/standalone/meta/StandaloneConstantReflectionProvider.java +++ b/substratevm/src/com.oracle.graal.pointsto.standalone/src/com/oracle/graal/pointsto/standalone/meta/StandaloneConstantReflectionProvider.java @@ -29,8 +29,8 @@ import com.oracle.graal.pointsto.meta.AnalysisField; import com.oracle.graal.pointsto.meta.AnalysisType; import com.oracle.graal.pointsto.meta.AnalysisUniverse; -import com.oracle.graal.pointsto.meta.UninitializedStaticFieldValueReader; import com.oracle.graal.pointsto.standalone.StandaloneHost; + import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; import jdk.vm.ci.hotspot.HotSpotObjectConstant; @@ -52,7 +52,7 @@ public final JavaConstant readFieldValue(ResolvedJavaField field, JavaConstant r AnalysisField analysisField = (AnalysisField) field; JavaConstant ret = universe.lookup(super.readFieldValue(analysisField.wrapped, universe.toHosted(receiver))); if (ret == null) { - ret = UninitializedStaticFieldValueReader.readUninitializedStaticValue(analysisField, value -> universe.getSnippetReflection().forObject(value)); + ret = analysisField.getConstantValue(); } return ret; } diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/infrastructure/WrappedConstantPool.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/infrastructure/WrappedConstantPool.java index 2f37314fcb25..a1da8527c3bd 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/infrastructure/WrappedConstantPool.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/infrastructure/WrappedConstantPool.java @@ -38,7 +38,6 @@ import com.oracle.graal.pointsto.util.AnalysisError.TypeNotFoundError; import com.oracle.svm.util.ReflectionUtil; -import jdk.vm.ci.hotspot.HotSpotConstantPool; import jdk.vm.ci.meta.ConstantPool; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaField; @@ -87,18 +86,11 @@ public int length() { private static final Method bsmGetType = bsmClass == null ? null : ReflectionUtil.lookupMethod(bsmClass, "getType"); private static final Method bsmGetStaticArguments = bsmClass == null ? null : ReflectionUtil.lookupMethod(bsmClass, "getStaticArguments"); - public static void loadReferencedType(ConstantPool cp, int cpi, int opcode, boolean initialize) { - ConstantPool root = cp; - while (root instanceof WrappedConstantPool) { - root = ((WrappedConstantPool) root).wrapped; - } - + @Override + public void loadReferencedType(int cpi, int opcode, boolean initialize) { + GraalError.guarantee(!initialize, "Must not initialize classes"); try { - /* - * GR-41975: loadReferencedType without triggering class initialization is available in - * HotSpotConstantPool, but not yet in ConstantPool. - */ - ((HotSpotConstantPool) root).loadReferencedType(cpi, opcode, initialize); + wrapped.loadReferencedType(cpi, opcode, initialize); } catch (Throwable ex) { Throwable cause = ex; if (cause instanceof BootstrapMethodError && cause.getCause() != null) { @@ -112,7 +104,7 @@ public static void loadReferencedType(ConstantPool cp, int cpi, int opcode, bool @Override public void loadReferencedType(int cpi, int opcode) { - loadReferencedType(wrapped, cpi, opcode, false); + loadReferencedType(cpi, opcode, false); } @Override diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisField.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisField.java index 594cf2c5b483..08d3319223c6 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisField.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisField.java @@ -50,6 +50,7 @@ import com.oracle.svm.util.UnsafePartitionKind; import jdk.vm.ci.code.BytecodePosition; +import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.ResolvedJavaField; import jdk.vm.ci.meta.ResolvedJavaType; @@ -552,4 +553,9 @@ public interface AnalysisFieldObserver { TypeState interceptTypeState(AnalysisField field, TypeState typestate); } + + @Override + public JavaConstant getConstantValue() { + return getUniverse().lookup(getWrapped().getConstantValue()); + } } diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/UninitializedStaticFieldValueReader.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/UninitializedStaticFieldValueReader.java deleted file mode 100644 index c6fc08540be8..000000000000 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/UninitializedStaticFieldValueReader.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2022, 2022, Alibaba Group Holding Limited. 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -package com.oracle.graal.pointsto.meta; - -import com.oracle.graal.pointsto.util.AnalysisError; -import jdk.internal.misc.Unsafe; -import jdk.vm.ci.meta.JavaConstant; -import jdk.vm.ci.meta.JavaKind; - -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.function.Function; - -public class UninitializedStaticFieldValueReader { - /* - * Static fields of classes that are initialized at run time have the default (uninitialized) - * value in the image heap. But there is one important exception: - * - * Fields that are static final and either primitive or of type String are initialized using the - * ConstantValue attribute of the class file, not using a class initializer. While we have class - * initializers available at run time, we no longer have the class files. So we need to preserve - * the values from the ConstantValue attribute in a different form. The easiest way is to just - * have these values as the default value of the static field in the image heap. - * - * Unfortunately, JVMCI does not allow us to access the default value: since the class is still - * uninitialized in the image generator, the JVMCI methods to read the field do not return a - * value. But the Java HotSpot VM actually already has the fields initialized to the values - * defined in the ConstantValue attributes. So reading the field via Unsafe actually produces - * the correct value that we want. - * - * Another complication are classes that are re-initialized at run time, i.e., initialized both - * during image generation and at run time. We must not return a value for a field that is - * initialized by a class initializer (that could be an arbitrary and wrong value from the image - * generator). Fortunately, the ConstantValue attribute is only used for static final fields of - * primitive types or the String type. By limiting the Unsafe read to these narrow cases, it is - * pretty likely (although not guaranteed) that we are not returning an unintended value for a - * class that is re-initialized at run time. - * - * GR-41856 should provide a proper JVMCI API to read the ConstantValue attribute of a field, - * which then makes this method unnecessary. - */ - public static JavaConstant readUninitializedStaticValue(AnalysisField field, Function function) { - JavaKind kind = field.getJavaKind(); - - boolean canHaveConstantValueAttribute = kind.isPrimitive() || field.getType().getName().equals("Ljava/lang/String;"); - if (!canHaveConstantValueAttribute || !field.isFinal()) { - return JavaConstant.defaultForKind(kind); - } - - assert Modifier.isStatic(field.getModifiers()); - - /* On HotSpot the base of a static field is the Class object. */ - Object base = field.getDeclaringClass().getJavaClass(); - long offset = field.wrapped.getOffset(); - - /* - * We cannot rely on the reflectionField because it can be null if there is some incomplete - * classpath issue or the field is either missing or hidden from reflection. However we can - * still use it to double check our assumptions. - */ - Field reflectionField = field.getJavaField(); - if (reflectionField != null) { - assert kind == JavaKind.fromJavaClass(reflectionField.getType()); - - Object reflectionFieldBase = Unsafe.getUnsafe().staticFieldBase(reflectionField); - long reflectionFieldOffset = Unsafe.getUnsafe().staticFieldOffset(reflectionField); - - AnalysisError.guarantee(reflectionFieldBase == base && reflectionFieldOffset == offset); - } - - switch (kind) { - case Boolean: - return JavaConstant.forBoolean(Unsafe.getUnsafe().getBoolean(base, offset)); - case Byte: - return JavaConstant.forByte(Unsafe.getUnsafe().getByte(base, offset)); - case Char: - return JavaConstant.forChar(Unsafe.getUnsafe().getChar(base, offset)); - case Short: - return JavaConstant.forShort(Unsafe.getUnsafe().getShort(base, offset)); - case Int: - return JavaConstant.forInt(Unsafe.getUnsafe().getInt(base, offset)); - case Long: - return JavaConstant.forLong(Unsafe.getUnsafe().getLong(base, offset)); - case Float: - return JavaConstant.forFloat(Unsafe.getUnsafe().getFloat(base, offset)); - case Double: - return JavaConstant.forDouble(Unsafe.getUnsafe().getDouble(base, offset)); - case Object: - Object value = Unsafe.getUnsafe().getObject(base, offset); - assert value == null || value instanceof String : "String is currently the only specified object type for the ConstantValue class file attribute"; - return function.apply(value); - default: - throw AnalysisError.shouldNotReachHere(); - } - } -} diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/phases/NoClassInitializationPlugin.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/phases/NoClassInitializationPlugin.java index d7ebceed74da..deae6c2dc5b1 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/phases/NoClassInitializationPlugin.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/phases/NoClassInitializationPlugin.java @@ -32,7 +32,6 @@ import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import com.oracle.graal.pointsto.constraints.UnresolvedElementException; -import com.oracle.graal.pointsto.infrastructure.WrappedConstantPool; import jdk.vm.ci.meta.ConstantPool; import jdk.vm.ci.meta.ResolvedJavaType; @@ -52,7 +51,7 @@ public boolean supportsLazyInitialization(ConstantPool cp) { public void loadReferencedType(GraphBuilderContext builder, ConstantPool cp, int cpi, int bytecode) { /* Do not trigger class initialization. */ try { - WrappedConstantPool.loadReferencedType(cp, cpi, bytecode, false); + cp.loadReferencedType(cpi, bytecode, false); } catch (UnresolvedElementException uee) { /* Plugin should be non-intrusive. Therefore we ignore missing class-path failures. */ } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ameta/AnalysisConstantReflectionProvider.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ameta/AnalysisConstantReflectionProvider.java index d5c0738c8fbc..7db8ff88b031 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ameta/AnalysisConstantReflectionProvider.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ameta/AnalysisConstantReflectionProvider.java @@ -39,7 +39,6 @@ import com.oracle.graal.pointsto.meta.AnalysisField; import com.oracle.graal.pointsto.meta.AnalysisType; import com.oracle.graal.pointsto.meta.AnalysisUniverse; -import com.oracle.graal.pointsto.meta.UninitializedStaticFieldValueReader; import com.oracle.svm.core.BuildPhaseProvider; import com.oracle.svm.core.RuntimeAssertionsSupport; import com.oracle.svm.core.annotate.InjectAccessors; @@ -195,9 +194,18 @@ public ValueSupplier readHostedFieldValue(AnalysisField field, Hos return ValueSupplier.eagerValue(universe.lookup(originalConstantReflection.readFieldValue(field.wrapped, receiver))); } - public JavaConstant readUninitializedStaticValue(AnalysisField field) { + private JavaConstant readUninitializedStaticValue(AnalysisField field) { assert classInitializationSupport.shouldInitializeAtRuntime(field.getDeclaringClass()); - return UninitializedStaticFieldValueReader.readUninitializedStaticValue(field, val -> SubstrateObjectConstant.forObject(val)); + + /* + * Use the value from the constant pool attribute for the static field. That is the value + * before the class initializer is executed. + */ + JavaConstant constantValue = field.getConstantValue(); + if (constantValue != null) { + return constantValue; + } + return JavaConstant.defaultForKind(field.getStorageKind()); } public JavaConstant interceptValue(UniverseMetaAccess suppliedMetaAccess, AnalysisField field, JavaConstant value) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/annotation/AnnotationSubstitutionField.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/annotation/AnnotationSubstitutionField.java index 6fcb8b92eb1e..0ec400fca1ed 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/annotation/AnnotationSubstitutionField.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/annotation/AnnotationSubstitutionField.java @@ -153,6 +153,11 @@ public boolean injectFinalForRuntimeCompilation() { return true; } + @Override + public JavaConstant getConstantValue() { + throw VMError.shouldNotReachHere("Not used for static fields, so this value should never be queried"); + } + @Override public String toString() { return "AnnotationField<" + format("%h.%n") + ">"; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedField.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedField.java index 79284cc72585..e4d0a4fae851 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedField.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedField.java @@ -209,4 +209,9 @@ public JavaKind getStorageKind() { public Field getJavaField() { return OriginalFieldProvider.getJavaField(getDeclaringClass().universe.getSnippetReflection(), wrapped); } + + @Override + public JavaConstant getConstantValue() { + return universe.lookup(getWrapped().getConstantValue()); + } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/AnnotatedField.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/AnnotatedField.java index f8d4cb59fa2b..2ac59583b46a 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/AnnotatedField.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/AnnotatedField.java @@ -137,4 +137,9 @@ public String toString() { public Field getJavaField() { return OriginalFieldProvider.getJavaField(GraalAccess.getOriginalSnippetReflection(), original); } + + @Override + public JavaConstant getConstantValue() { + return original.getConstantValue(); + } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/ComputedValueField.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/ComputedValueField.java index e13b27f4023f..55f9dd3ccd44 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/ComputedValueField.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/ComputedValueField.java @@ -536,4 +536,9 @@ public String toString() { public Field getJavaField() { return OriginalFieldProvider.getJavaField(GraalAccess.getOriginalSnippetReflection(), original); } + + @Override + public JavaConstant getConstantValue() { + throw VMError.shouldNotReachHere("Declaring class must be initialized, so this value should never be queried"); + } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/SubstitutionField.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/SubstitutionField.java index 51e1f17d8ab9..db3a1027e2d2 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/SubstitutionField.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/SubstitutionField.java @@ -30,6 +30,7 @@ import com.oracle.graal.pointsto.infrastructure.OriginalFieldProvider; import com.oracle.graal.pointsto.util.GraalAccess; import com.oracle.svm.core.meta.ReadableJavaField; +import com.oracle.svm.core.util.VMError; import com.oracle.svm.util.AnnotationWrapper; import jdk.vm.ci.meta.JavaConstant; @@ -79,6 +80,11 @@ public JavaConstant readValue(MetaAccessProvider metaAccess, JavaConstant receiv return value; } + @Override + public JavaConstant getConstantValue() { + throw VMError.shouldNotReachHere("Declaring class must be initialized, so this value should never be queried"); + } + public boolean isUserSubstitution() { return isUserSubstitution; } From 5075a4645939c37effefaed66bf479b53ef55531 Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Wed, 2 Nov 2022 13:36:11 +0100 Subject: [PATCH 4/6] fixed ComputedValueField.getConstantValue --- .../com/oracle/svm/hosted/substitute/ComputedValueField.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/ComputedValueField.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/ComputedValueField.java index 55f9dd3ccd44..926a7754e2d7 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/ComputedValueField.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/ComputedValueField.java @@ -539,6 +539,6 @@ public Field getJavaField() { @Override public JavaConstant getConstantValue() { - throw VMError.shouldNotReachHere("Declaring class must be initialized, so this value should never be queried"); + return original.getConstantValue(); } } From 989316d68d11dc05caf59bc85955a08b63fe304e Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Tue, 8 Nov 2022 21:54:20 +0100 Subject: [PATCH 5/6] fixed StandaloneImageHeapScanner --- .../heap/StandaloneImageHeapScanner.java | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/substratevm/src/com.oracle.graal.pointsto.standalone/src/com/oracle/graal/pointsto/standalone/heap/StandaloneImageHeapScanner.java b/substratevm/src/com.oracle.graal.pointsto.standalone/src/com/oracle/graal/pointsto/standalone/heap/StandaloneImageHeapScanner.java index 166bf5ca4080..8d0d0ffd69b2 100644 --- a/substratevm/src/com.oracle.graal.pointsto.standalone/src/com/oracle/graal/pointsto/standalone/heap/StandaloneImageHeapScanner.java +++ b/substratevm/src/com.oracle.graal.pointsto.standalone/src/com/oracle/graal/pointsto/standalone/heap/StandaloneImageHeapScanner.java @@ -26,6 +26,8 @@ package com.oracle.graal.pointsto.standalone.heap; +import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; + import com.oracle.graal.pointsto.BigBang; import com.oracle.graal.pointsto.ObjectScanningObserver; import com.oracle.graal.pointsto.heap.ImageHeap; @@ -33,11 +35,10 @@ import com.oracle.graal.pointsto.heap.value.ValueSupplier; import com.oracle.graal.pointsto.meta.AnalysisField; import com.oracle.graal.pointsto.meta.AnalysisMetaAccess; -import com.oracle.graal.pointsto.meta.UninitializedStaticFieldValueReader; import com.oracle.graal.pointsto.util.AnalysisError; + import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.JavaConstant; -import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; public class StandaloneImageHeapScanner extends ImageHeapScanner { private ClassLoader classLoader; @@ -63,8 +64,15 @@ protected Class getClass(String className) { protected ValueSupplier readHostedFieldValue(AnalysisField field, JavaConstant receiver) { ValueSupplier ret = super.readHostedFieldValue(field, receiver); if (ret.get() == null) { - JavaConstant constant = UninitializedStaticFieldValueReader.readUninitializedStaticValue(field, value -> universe.getSnippetReflection().forObject(value)); - return ValueSupplier.eagerValue(constant); + /* + * Use the value from the constant pool attribute for the static field. That is the + * value before the class initializer is executed. + */ + JavaConstant constantValue = field.getConstantValue(); + if (constantValue == null) { + constantValue = JavaConstant.defaultForKind(field.getStorageKind()); + } + return ValueSupplier.eagerValue(constantValue); } else { return ret; } From 1eaf01e5942daf618a927b8374cc5266e1773604 Mon Sep 17 00:00:00 2001 From: Christian Wimmer Date: Sun, 13 Nov 2022 22:26:31 -0800 Subject: [PATCH 6/6] Ignore all exceptions in NoClassInitializationPlugin --- .../graal/pointsto/phases/NoClassInitializationPlugin.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/phases/NoClassInitializationPlugin.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/phases/NoClassInitializationPlugin.java index deae6c2dc5b1..9c5cdba28a2b 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/phases/NoClassInitializationPlugin.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/phases/NoClassInitializationPlugin.java @@ -31,8 +31,6 @@ import org.graalvm.compiler.nodes.graphbuilderconf.ClassInitializationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; -import com.oracle.graal.pointsto.constraints.UnresolvedElementException; - import jdk.vm.ci.meta.ConstantPool; import jdk.vm.ci.meta.ResolvedJavaType; @@ -52,7 +50,7 @@ public void loadReferencedType(GraphBuilderContext builder, ConstantPool cp, int /* Do not trigger class initialization. */ try { cp.loadReferencedType(cpi, bytecode, false); - } catch (UnresolvedElementException uee) { + } catch (Throwable ex) { /* Plugin should be non-intrusive. Therefore we ignore missing class-path failures. */ } }