From d31453b030a73229f89c4f31cef6752cd828ab68 Mon Sep 17 00:00:00 2001 From: Gilles Duboscq Date: Fri, 17 Jan 2025 18:14:30 +0100 Subject: [PATCH 1/5] Make class resolution errors sticky in constant pool. Save linkage errors and rethrow them on further attempts. Common out the stick error mechanism for class, indy, and condy. Remove unused constant pool entry types. --- .../classfile/constantpool/ClassConstant.java | 31 ------ .../constantpool/AbstractFailedConstant.java | 60 +++++++++++ .../constantpool/CallSiteLinkingFailure.java | 4 +- .../espresso/constantpool/Resolution.java | 100 ++++++------------ .../constantpool/ResolvedClassConstant.java | 17 +-- .../constantpool/ResolvedDynamicConstant.java | 5 +- .../ResolvedFailClassConstant.java | 31 ++++++ .../ResolvedFailDynamicConstant.java | 17 +-- ...=> ResolvedFailInvokeDynamicConstant.java} | 16 +-- ...t.java => ResolvedFoundClassConstant.java} | 21 ++-- .../constantpool/RuntimeConstantPool.java | 10 +- .../constantpool/StickyFailureConstant.java | 30 ++++++ .../espresso/runtime/EspressoException.java | 7 +- 13 files changed, 182 insertions(+), 167 deletions(-) create mode 100644 espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/AbstractFailedConstant.java create mode 100644 espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedFailClassConstant.java rename espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/{FailInvokeDynamicConstant.java => ResolvedFailInvokeDynamicConstant.java} (79%) rename espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/{PreResolvedClassConstant.java => ResolvedFoundClassConstant.java} (65%) create mode 100644 espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/StickyFailureConstant.java diff --git a/espresso/src/com.oracle.truffle.espresso.classfile/src/com/oracle/truffle/espresso/classfile/constantpool/ClassConstant.java b/espresso/src/com.oracle.truffle.espresso.classfile/src/com/oracle/truffle/espresso/classfile/constantpool/ClassConstant.java index e46a70ab0934..3b01e619b43f 100644 --- a/espresso/src/com.oracle.truffle.espresso.classfile/src/com/oracle/truffle/espresso/classfile/constantpool/ClassConstant.java +++ b/espresso/src/com.oracle.truffle.espresso.classfile/src/com/oracle/truffle/espresso/classfile/constantpool/ClassConstant.java @@ -28,7 +28,6 @@ import com.oracle.truffle.espresso.classfile.ConstantPool.Tag; import com.oracle.truffle.espresso.classfile.descriptors.Name; import com.oracle.truffle.espresso.classfile.descriptors.Symbol; -import com.oracle.truffle.espresso.classfile.descriptors.Validation; import com.oracle.truffle.espresso.classfile.descriptors.ValidationException; /** @@ -40,10 +39,6 @@ static ImmutableClassConstant create(int classNameIndex) { return new Index(classNameIndex); } - static ImmutableClassConstant withString(Symbol name) { - return new WithString(name); - } - @Override default Tag tag() { return Tag.CLASS; @@ -93,30 +88,4 @@ public void dump(ByteBuffer buf) { buf.putChar(classNameIndex); } } - - final class WithString implements ImmutableClassConstant, Resolvable { - private final Symbol name; - - WithString(Symbol name) { - this.name = name; - } - - @Override - public Symbol getName(ConstantPool pool) { - return name; - } - - @Override - public void validate(ConstantPool pool) throws ValidationException { - // No UTF8 entry: cannot cache validation. - if (!Validation.validModifiedUTF8(name) || !Validation.validClassNameEntry(name)) { - throw ValidationException.raise("Invalid class name entry: " + name); - } - } - - @Override - public void dump(ByteBuffer buf) { - buf.putChar((char) 0); - } - } } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/AbstractFailedConstant.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/AbstractFailedConstant.java new file mode 100644 index 000000000000..526684125f0e --- /dev/null +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/AbstractFailedConstant.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2025, 2025, 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. + */ +package com.oracle.truffle.espresso.constantpool; + +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.espresso.impl.ObjectKlass; +import com.oracle.truffle.espresso.meta.EspressoError; +import com.oracle.truffle.espresso.meta.Meta; +import com.oracle.truffle.espresso.runtime.EspressoException; +import com.oracle.truffle.espresso.runtime.staticobject.StaticObject; + +public abstract class AbstractFailedConstant implements StickyFailureConstant { + private final ObjectKlass exceptionType; + private final StaticObject message; + private final StaticObject cause; + + public AbstractFailedConstant(EspressoException failure) { + StaticObject exception = failure.getGuestException(); + exceptionType = (ObjectKlass) exception.getKlass(); + message = EspressoException.getGuestMessage(exception); + cause = EspressoException.getGuestCause(exception); + } + + @Override + public final Object value() { + CompilerDirectives.transferToInterpreterAndInvalidate(); + throw EspressoError.shouldNotReachHere("Exception should have been thrown earlier by calling checkFail."); + } + + @Override + public final void checkFail(Meta meta) { + throw fail(meta); + } + + final EspressoException fail(Meta meta) { + StaticObject exception = Meta.initExceptionWithMessage(exceptionType, message); + meta.java_lang_Throwable_cause.set(exception, cause); + throw meta.throwException(exception); + } +} diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/CallSiteLinkingFailure.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/CallSiteLinkingFailure.java index 561fc5a00056..4f2d79330529 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/CallSiteLinkingFailure.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/CallSiteLinkingFailure.java @@ -33,8 +33,8 @@ public CallSiteLinkingFailure(EspressoException cause) { this.cause = cause; } - public FailInvokeDynamicConstant failConstant() { - return new FailInvokeDynamicConstant(cause); + public ResolvedFailInvokeDynamicConstant failConstant() { + return new ResolvedFailInvokeDynamicConstant(cause); } @Override diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/Resolution.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/Resolution.java index a4b9b099bc1e..96c563845a0a 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/Resolution.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/Resolution.java @@ -113,78 +113,44 @@ public static ResolvedClassConstant resolveClassConstant(ClassConstant.Index thi assert accessingKlass != null; CompilerDirectives.transferToInterpreterAndInvalidate(); Symbol klassName = thiz.getName(pool); - try { - EspressoContext context = pool.getContext(); - Symbol type = context.getTypes().fromClassNameEntry(klassName); - Klass klass = context.getMeta().resolveSymbolOrFail(type, accessingKlass.getDefiningClassLoader(), accessingKlass.protectionDomain()); - Klass checkedKlass = klass.getElementalType(); - if (!Klass.checkAccess(checkedKlass, accessingKlass, false)) { - Meta meta = context.getMeta(); - context.getLogger().log(Level.FINE, - "Access check of: " + checkedKlass.getType() + " from " + accessingKlass.getType() + " throws IllegalAccessError"); - StringBuilder errorMessage = new StringBuilder("failed to access class "); - errorMessage.append(checkedKlass.getExternalName()).append(" from class ").append(accessingKlass.getExternalName()); - if (context.getJavaVersion().modulesEnabled()) { - errorMessage.append(" ("); - if (accessingKlass.module() == checkedKlass.module()) { - errorMessage.append(checkedKlass.getExternalName()); - errorMessage.append(" and "); - ClassRegistry.classInModuleOfLoader(accessingKlass, true, errorMessage, meta); - } else { - // checkedKlass is not an array type (getElementalType) nor a - // primitive - // type (it would have passed the access checks) - ClassRegistry.classInModuleOfLoader((ObjectKlass) checkedKlass, false, errorMessage, meta); - errorMessage.append("; "); - ClassRegistry.classInModuleOfLoader(accessingKlass, false, errorMessage, meta); - } - errorMessage.append(")"); - } - throw meta.throwExceptionWithMessage(meta.java_lang_IllegalAccessError, errorMessage.toString()); - } - - return new ResolvedClassConstant(klass); - - } catch (VirtualMachineError e) { - // Comment from Hotspot: - // Just throw the exception and don't prevent these classes from - // being loaded for virtual machine errors like StackOverflow - // and OutOfMemoryError, etc. - // Needs clarification to section 5.4.3 of the JVM spec (see 6308271) - throw e; - } - } - } - - @SuppressWarnings("unused") - public static ResolvedClassConstant resolveClassConstant(PreResolvedClassConstant thiz, @SuppressWarnings("unused") RuntimeConstantPool pool, @SuppressWarnings("unused") int thisIndex, - @SuppressWarnings("unused") ObjectKlass accessingKlass) { - return new ResolvedClassConstant(thiz.getResolved()); - } - - public static ResolvedClassConstant resolveClassConstant(ClassConstant.WithString thiz, RuntimeConstantPool pool, @SuppressWarnings("unused") int thisIndex, ObjectKlass accessingKlass) { - CLASS_RESOLVE_COUNT.inc(); - assert accessingKlass != null; - CompilerDirectives.transferToInterpreterAndInvalidate(); - Symbol klassName = thiz.getName(pool); - try { EspressoContext context = pool.getContext(); - Meta meta = context.getMeta(); - Klass klass = meta.resolveSymbolOrFail(context.getTypes().fromClassNameEntryUnsafe(klassName), accessingKlass.getDefiningClassLoader(), accessingKlass.protectionDomain()); - if (!Klass.checkAccess(klass.getElementalType(), accessingKlass, false)) { + Symbol type = context.getTypes().fromClassNameEntry(klassName); + Klass klass = context.getMeta().resolveSymbolOrFail(type, accessingKlass.getDefiningClassLoader(), accessingKlass.protectionDomain()); + Klass checkedKlass = klass.getElementalType(); + if (!Klass.checkAccess(checkedKlass, accessingKlass, false)) { + Meta meta = context.getMeta(); context.getLogger().log(Level.FINE, - "Access check of: " + klass.getType() + " from " + accessingKlass.getType() + " throws IllegalAccessError"); - throw meta.throwExceptionWithMessage(meta.java_lang_IllegalAccessError, meta.toGuestString(klassName)); + "Access check of: " + checkedKlass.getType() + " from " + accessingKlass.getType() + " throws IllegalAccessError"); + StringBuilder errorMessage = new StringBuilder("failed to access class "); + errorMessage.append(checkedKlass.getExternalName()).append(" from class ").append(accessingKlass.getExternalName()); + if (context.getJavaVersion().modulesEnabled()) { + errorMessage.append(" ("); + if (accessingKlass.module() == checkedKlass.module()) { + errorMessage.append(checkedKlass.getExternalName()); + errorMessage.append(" and "); + ClassRegistry.classInModuleOfLoader(accessingKlass, true, errorMessage, meta); + } else { + // checkedKlass is not an array type (getElementalType) nor a + // primitive type (it would have passed the access checks) + ClassRegistry.classInModuleOfLoader((ObjectKlass) checkedKlass, false, errorMessage, meta); + errorMessage.append("; "); + ClassRegistry.classInModuleOfLoader(accessingKlass, false, errorMessage, meta); + } + errorMessage.append(")"); + } + throw meta.throwExceptionWithMessage(meta.java_lang_IllegalAccessError, errorMessage.toString()); } - - return new ResolvedClassConstant(klass); - - } catch (VirtualMachineError e) { + return new ResolvedFoundClassConstant(klass); + } catch (EspressoException e) { + CompilerDirectives.transferToInterpreter(); + Meta meta = pool.getContext().getMeta(); // Comment from Hotspot: - // Just throw the exception and don't prevent these classes from - // being loaded for virtual machine errors like StackOverflow - // and OutOfMemoryError, etc. + // Just throw the exception and don't prevent these classes from being loaded for + // virtual machine errors like StackOverflow and OutOfMemoryError, etc. // Needs clarification to section 5.4.3 of the JVM spec (see 6308271) + if (meta.java_lang_LinkageError.isAssignableFrom(e.getGuestException().getKlass())) { + return new ResolvedFailClassConstant(e); + } throw e; } } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedClassConstant.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedClassConstant.java index 8669b1656137..24137f06c26f 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedClassConstant.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedClassConstant.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2025, 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 @@ -22,21 +22,8 @@ */ package com.oracle.truffle.espresso.constantpool; -import java.util.Objects; - import com.oracle.truffle.espresso.classfile.constantpool.ClassConstant; import com.oracle.truffle.espresso.classfile.constantpool.Resolvable; -import com.oracle.truffle.espresso.impl.Klass; - -public final class ResolvedClassConstant implements ClassConstant, Resolvable.ResolvedConstant { - private final Klass resolved; - - public ResolvedClassConstant(Klass resolved) { - this.resolved = Objects.requireNonNull(resolved); - } - @Override - public Klass value() { - return resolved; - } +public interface ResolvedClassConstant extends ClassConstant, Resolvable.ResolvedConstant, StickyFailureConstant { } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedDynamicConstant.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedDynamicConstant.java index 2f0d8cc20230..e186e8bcf3d8 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedDynamicConstant.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedDynamicConstant.java @@ -25,12 +25,11 @@ import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.espresso.classfile.JavaKind; import com.oracle.truffle.espresso.classfile.constantpool.DynamicConstant; -import com.oracle.truffle.espresso.classfile.constantpool.Resolvable; import com.oracle.truffle.espresso.meta.Meta; import com.oracle.truffle.espresso.nodes.BytecodeNode; import com.oracle.truffle.espresso.runtime.staticobject.StaticObject; -public interface ResolvedDynamicConstant extends DynamicConstant, Resolvable.ResolvedConstant { +public interface ResolvedDynamicConstant extends DynamicConstant, StickyFailureConstant { void putResolved(VirtualFrame frame, int top, BytecodeNode node); JavaKind getKind(); @@ -43,6 +42,6 @@ default StaticObject guestBoxedValue(Meta meta) { return Meta.box(meta, value); } - default void checkFail() { + default void checkFail(Meta meta) { } } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedFailClassConstant.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedFailClassConstant.java new file mode 100644 index 000000000000..9493c529fd3d --- /dev/null +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedFailClassConstant.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2025, 2025, 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. + */ +package com.oracle.truffle.espresso.constantpool; + +import com.oracle.truffle.espresso.runtime.EspressoException; + +public final class ResolvedFailClassConstant extends AbstractFailedConstant implements ResolvedClassConstant { + public ResolvedFailClassConstant(EspressoException failure) { + super(failure); + } +} diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedFailDynamicConstant.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedFailDynamicConstant.java index c1db849b3236..761c21a1b398 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedFailDynamicConstant.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedFailDynamicConstant.java @@ -29,16 +29,9 @@ import com.oracle.truffle.espresso.nodes.BytecodeNode; import com.oracle.truffle.espresso.runtime.EspressoException; -public final class ResolvedFailDynamicConstant implements ResolvedDynamicConstant { - final EspressoException failure; - +public final class ResolvedFailDynamicConstant extends AbstractFailedConstant implements ResolvedDynamicConstant { public ResolvedFailDynamicConstant(EspressoException failure) { - this.failure = failure; - } - - @Override - public void checkFail() { - throw failure; + super(failure); } @Override @@ -47,12 +40,6 @@ public void putResolved(VirtualFrame frame, int top, BytecodeNode node) { throw EspressoError.shouldNotReachHere("Failure should have arose earlier."); } - @Override - public Object value() { - CompilerDirectives.transferToInterpreterAndInvalidate(); - throw EspressoError.shouldNotReachHere("Failure should have arose earlier."); - } - @Override public JavaKind getKind() { return JavaKind.Illegal; diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/FailInvokeDynamicConstant.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedFailInvokeDynamicConstant.java similarity index 79% rename from espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/FailInvokeDynamicConstant.java rename to espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedFailInvokeDynamicConstant.java index f276edae893e..725ac6c2bc1c 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/FailInvokeDynamicConstant.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedFailInvokeDynamicConstant.java @@ -30,22 +30,14 @@ import com.oracle.truffle.espresso.meta.EspressoError; import com.oracle.truffle.espresso.runtime.EspressoException; -public final class FailInvokeDynamicConstant implements LinkableInvokeDynamicConstant { - private final EspressoException failure; - - public FailInvokeDynamicConstant(EspressoException failure) { - this.failure = failure; +public final class ResolvedFailInvokeDynamicConstant extends AbstractFailedConstant implements LinkableInvokeDynamicConstant { + public ResolvedFailInvokeDynamicConstant(EspressoException failure) { + super(failure); } @Override public CallSiteLink link(RuntimeConstantPool pool, ObjectKlass accessingKlass, int thisIndex, Method method, int bci) { - throw failure; - } - - @Override - public Object value() { - CompilerDirectives.transferToInterpreterAndInvalidate(); - throw EspressoError.shouldNotReachHere("Use indy.link() rather than Resolved.value()"); + throw fail(method.getMeta()); } @Override diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/PreResolvedClassConstant.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedFoundClassConstant.java similarity index 65% rename from espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/PreResolvedClassConstant.java rename to espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedFoundClassConstant.java index 93cb6d787890..f1350ede788b 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/PreResolvedClassConstant.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedFoundClassConstant.java @@ -22,33 +22,24 @@ */ package com.oracle.truffle.espresso.constantpool; -import java.nio.ByteBuffer; import java.util.Objects; -import com.oracle.truffle.espresso.classfile.constantpool.ClassConstant; -import com.oracle.truffle.espresso.classfile.constantpool.Resolvable; import com.oracle.truffle.espresso.impl.Klass; +import com.oracle.truffle.espresso.meta.Meta; -/** - * Constant Pool patching inserts already resolved constants in the constant pool. However, at the - * time of patching, we do not have a Runtime CP. Therefore, we help the CP by inserting a - * Pre-Resolved constant. - *

- * This is also used to Pre-resolve anonymous classes. - */ -public final class PreResolvedClassConstant implements ClassConstant, Resolvable { +public final class ResolvedFoundClassConstant implements ResolvedClassConstant { private final Klass resolved; - PreResolvedClassConstant(Klass resolved) { + public ResolvedFoundClassConstant(Klass resolved) { this.resolved = Objects.requireNonNull(resolved); } - public Klass getResolved() { + @Override + public Klass value() { return resolved; } @Override - public void dump(ByteBuffer buf) { - buf.putChar((char) 0); + public void checkFail(Meta meta) { } } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/RuntimeConstantPool.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/RuntimeConstantPool.java index f3e575f1dcbd..b26c4dcb45f1 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/RuntimeConstantPool.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/RuntimeConstantPool.java @@ -148,7 +148,8 @@ public StaticObject resolvedStringAt(int index) { } public Klass resolvedKlassAt(ObjectKlass accessingKlass, int index) { - Resolvable.ResolvedConstant resolved = resolvedAt(accessingKlass, index, "klass"); + ResolvedClassConstant resolved = (ResolvedClassConstant) resolvedAt(accessingKlass, index, "klass"); + resolved.checkFail(getContext().getMeta()); return (Klass) resolved.value(); } @@ -248,7 +249,7 @@ public ResolvedInvokeDynamicConstant peekResolvedInvokeDynamic(int index) { public ResolvedDynamicConstant resolvedDynamicConstantAt(ObjectKlass accessingKlass, int index) { ResolvedDynamicConstant dynamicConstant = (ResolvedDynamicConstant) outOfLockResolvedAt(accessingKlass, index, "dynamic constant"); - dynamicConstant.checkFail(); + dynamicConstant.checkFail(getContext().getMeta()); return dynamicConstant; } @@ -265,7 +266,7 @@ public ObjectKlass getHolder() { } public void setKlassAt(int index, ObjectKlass klass) { - resolvedConstants[index] = new ResolvedClassConstant(klass); + resolvedConstants[index] = new ResolvedFoundClassConstant(klass); } @Override @@ -326,7 +327,6 @@ public StaticObject[] getStaticArguments(BootstrapMethodsAttribute.Entry entry, } Resolvable.ResolvedConstant resolve(Resolvable resolvable, int thisIndex, ObjectKlass accessingKlass) { - switch (resolvable.tag()) { case STRING: if (resolvable instanceof StringConstant.Index fromIndex) { @@ -371,8 +371,6 @@ Resolvable.ResolvedConstant resolve(Resolvable resolvable, int thisIndex, Object case CLASS: if (resolvable instanceof ClassConstant.Index fromIndex) { return Resolution.resolveClassConstant(fromIndex, this, thisIndex, accessingKlass); - } else if (resolvable instanceof ClassConstant.WithString fromString) { - return Resolution.resolveClassConstant(fromString, this, thisIndex, accessingKlass); } break; } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/StickyFailureConstant.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/StickyFailureConstant.java new file mode 100644 index 000000000000..f323407d4763 --- /dev/null +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/StickyFailureConstant.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2025, 2025, 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. + */ +package com.oracle.truffle.espresso.constantpool; + +import com.oracle.truffle.espresso.classfile.constantpool.Resolvable; +import com.oracle.truffle.espresso.meta.Meta; + +public interface StickyFailureConstant extends Resolvable.ResolvedConstant { + void checkFail(Meta meta); +} diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoException.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoException.java index 87caca6c35ae..cb6b3efbfcec 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoException.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoException.java @@ -71,11 +71,16 @@ public String getMessage() { return getMessage(exception); } - private static StaticObject getGuestMessage(StaticObject e) { + public static StaticObject getGuestMessage(StaticObject e) { // this is used in toString, too dangerous to call a method return (StaticObject) e.getKlass().getMeta().java_lang_Throwable_detailMessage.get(e); } + public static StaticObject getGuestCause(StaticObject e) { + // this is used in toString, too dangerous to call a method + return (StaticObject) e.getKlass().getMeta().java_lang_Throwable_cause.get(e); + } + public static String getMessage(StaticObject e) { return Meta.toHostStringStatic(getGuestMessage(e)); } From 11bad49fa9de03edf24a85b8394c180375f1e2dc Mon Sep 17 00:00:00 2001 From: Gilles Duboscq Date: Wed, 22 Jan 2025 16:12:21 +0100 Subject: [PATCH 2/5] Fix how indy linking failures are remembered Those should be remembered per call-site. --- .../constantpool/AbstractFailedConstant.java | 27 ++----- ...nstant.java => AbstractStickyFailure.java} | 37 ++++----- .../espresso/constantpool/CallSiteLink.java | 37 ++------- .../constantpool/CallSiteLinkingFailure.java | 45 ----------- .../constantpool/FailedCallSiteLink.java | 70 +++++++++++++++++ .../LinkableInvokeDynamicConstant.java | 32 -------- .../constantpool/ResolvedClassConstant.java | 2 +- .../constantpool/ResolvedDynamicConstant.java | 4 +- .../ResolvedInvokeDynamicConstant.java | 14 ++-- .../constantpool/RuntimeConstantPool.java | 15 +--- ...ilureConstant.java => StickyFallible.java} | 3 +- .../constantpool/SuccessfulCallSiteLink.java | 77 +++++++++++++++++++ ...resso_jvmci_meta_EspressoConstantPool.java | 17 ++-- 13 files changed, 199 insertions(+), 181 deletions(-) rename espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/{ResolvedFailInvokeDynamicConstant.java => AbstractStickyFailure.java} (56%) delete mode 100644 espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/CallSiteLinkingFailure.java create mode 100644 espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/FailedCallSiteLink.java delete mode 100644 espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/LinkableInvokeDynamicConstant.java rename espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/{StickyFailureConstant.java => StickyFallible.java} (88%) create mode 100644 espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/SuccessfulCallSiteLink.java diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/AbstractFailedConstant.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/AbstractFailedConstant.java index 526684125f0e..6379de0d4533 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/AbstractFailedConstant.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/AbstractFailedConstant.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, 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 @@ -23,22 +23,13 @@ package com.oracle.truffle.espresso.constantpool; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.espresso.impl.ObjectKlass; +import com.oracle.truffle.espresso.classfile.constantpool.Resolvable; import com.oracle.truffle.espresso.meta.EspressoError; -import com.oracle.truffle.espresso.meta.Meta; import com.oracle.truffle.espresso.runtime.EspressoException; -import com.oracle.truffle.espresso.runtime.staticobject.StaticObject; - -public abstract class AbstractFailedConstant implements StickyFailureConstant { - private final ObjectKlass exceptionType; - private final StaticObject message; - private final StaticObject cause; +public abstract class AbstractFailedConstant extends AbstractStickyFailure implements Resolvable.ResolvedConstant { public AbstractFailedConstant(EspressoException failure) { - StaticObject exception = failure.getGuestException(); - exceptionType = (ObjectKlass) exception.getKlass(); - message = EspressoException.getGuestMessage(exception); - cause = EspressoException.getGuestCause(exception); + super(failure); } @Override @@ -48,13 +39,7 @@ public final Object value() { } @Override - public final void checkFail(Meta meta) { - throw fail(meta); - } - - final EspressoException fail(Meta meta) { - StaticObject exception = Meta.initExceptionWithMessage(exceptionType, message); - meta.java_lang_Throwable_cause.set(exception, cause); - throw meta.throwException(exception); + public boolean isSuccess() { + return false; } } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedFailInvokeDynamicConstant.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/AbstractStickyFailure.java similarity index 56% rename from espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedFailInvokeDynamicConstant.java rename to espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/AbstractStickyFailure.java index 725ac6c2bc1c..ef27c5aa197e 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedFailInvokeDynamicConstant.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/AbstractStickyFailure.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2025, 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 @@ -22,32 +22,27 @@ */ package com.oracle.truffle.espresso.constantpool; -import java.nio.ByteBuffer; - -import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.espresso.impl.Method; import com.oracle.truffle.espresso.impl.ObjectKlass; -import com.oracle.truffle.espresso.meta.EspressoError; +import com.oracle.truffle.espresso.meta.Meta; import com.oracle.truffle.espresso.runtime.EspressoException; +import com.oracle.truffle.espresso.runtime.staticobject.StaticObject; -public final class ResolvedFailInvokeDynamicConstant extends AbstractFailedConstant implements LinkableInvokeDynamicConstant { - public ResolvedFailInvokeDynamicConstant(EspressoException failure) { - super(failure); - } - - @Override - public CallSiteLink link(RuntimeConstantPool pool, ObjectKlass accessingKlass, int thisIndex, Method method, int bci) { - throw fail(method.getMeta()); - } +public abstract class AbstractStickyFailure implements StickyFallible { + private final ObjectKlass exceptionType; + private final StaticObject message; + private final StaticObject cause; - @Override - public void dump(ByteBuffer buf) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - throw EspressoError.shouldNotReachHere("Invoke dynamic already resolved."); + public AbstractStickyFailure(EspressoException failure) { + StaticObject exception = failure.getGuestException(); + exceptionType = (ObjectKlass) exception.getKlass(); + message = EspressoException.getGuestMessage(exception); + cause = EspressoException.getGuestCause(exception); } @Override - public boolean isSuccess() { - return false; + public final void checkFail(Meta meta) { + StaticObject exception = Meta.initExceptionWithMessage(exceptionType, message); + meta.java_lang_Throwable_cause.set(exception, cause); + throw meta.throwException(exception); } } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/CallSiteLink.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/CallSiteLink.java index 46afa328475f..e997a71c9029 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/CallSiteLink.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/CallSiteLink.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, 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 @@ -22,42 +22,19 @@ */ package com.oracle.truffle.espresso.constantpool; -import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.espresso.classfile.descriptors.Symbol; import com.oracle.truffle.espresso.classfile.descriptors.Type; import com.oracle.truffle.espresso.impl.Method; import com.oracle.truffle.espresso.runtime.staticobject.StaticObject; -public final class CallSiteLink { - private final Method method; - private final int bci; - final StaticObject memberName; - final StaticObject unboxedAppendix; +public sealed interface CallSiteLink extends StickyFallible permits FailedCallSiteLink, SuccessfulCallSiteLink { + StaticObject getMemberName(); - @CompilationFinal(dimensions = 1) // - final Symbol[] parsedSignature; + StaticObject getUnboxedAppendix(); - public CallSiteLink(Method method, int bci, StaticObject memberName, StaticObject unboxedAppendix, Symbol[] parsedSignature) { - this.method = method; - this.bci = bci; - this.memberName = memberName; - this.unboxedAppendix = unboxedAppendix; - this.parsedSignature = parsedSignature; - } + Symbol[] getParsedSignature(); - public StaticObject getMemberName() { - return memberName; - } + boolean matchesCallSite(Method siteMethod, int siteBci); - public StaticObject getUnboxedAppendix() { - return unboxedAppendix; - } - - public Symbol[] getParsedSignature() { - return parsedSignature; - } - - public boolean matchesCallSite(Method siteMethod, int siteBci) { - return bci == siteBci && method == siteMethod; - } + boolean isFailed(); } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/CallSiteLinkingFailure.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/CallSiteLinkingFailure.java deleted file mode 100644 index 4f2d79330529..000000000000 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/CallSiteLinkingFailure.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2024, 2024, 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. - */ -package com.oracle.truffle.espresso.constantpool; - -import com.oracle.truffle.espresso.runtime.EspressoException; - -public final class CallSiteLinkingFailure extends RuntimeException { - private static final long serialVersionUID = 2567495832103023693L; - - public final EspressoException cause; - - public CallSiteLinkingFailure(EspressoException cause) { - this.cause = cause; - } - - public ResolvedFailInvokeDynamicConstant failConstant() { - return new ResolvedFailInvokeDynamicConstant(cause); - } - - @Override - @SuppressWarnings("sync-override") - public Throwable fillInStackTrace() { - return this; - } -} diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/FailedCallSiteLink.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/FailedCallSiteLink.java new file mode 100644 index 000000000000..156a99043582 --- /dev/null +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/FailedCallSiteLink.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2025, 2025, 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. + */ +package com.oracle.truffle.espresso.constantpool; + +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.espresso.classfile.descriptors.Symbol; +import com.oracle.truffle.espresso.classfile.descriptors.Type; +import com.oracle.truffle.espresso.impl.Method; +import com.oracle.truffle.espresso.meta.EspressoError; +import com.oracle.truffle.espresso.runtime.EspressoException; +import com.oracle.truffle.espresso.runtime.staticobject.StaticObject; + +public final class FailedCallSiteLink extends AbstractStickyFailure implements CallSiteLink { + private final Method method; + private final int bci; + + public FailedCallSiteLink(Method method, int bci, EspressoException failure) { + super(failure); + this.method = method; + this.bci = bci; + } + + @Override + public boolean isFailed() { + return true; + } + + @Override + public boolean matchesCallSite(Method siteMethod, int siteBci) { + return bci == siteBci && method == siteMethod; + } + + @Override + public StaticObject getMemberName() { + CompilerDirectives.transferToInterpreterAndInvalidate(); + throw EspressoError.shouldNotReachHere("Exception should have been thrown earlier by calling checkFail."); + } + + @Override + public StaticObject getUnboxedAppendix() { + CompilerDirectives.transferToInterpreterAndInvalidate(); + throw EspressoError.shouldNotReachHere("Exception should have been thrown earlier by calling checkFail."); + } + + @Override + public Symbol[] getParsedSignature() { + CompilerDirectives.transferToInterpreterAndInvalidate(); + throw EspressoError.shouldNotReachHere("Exception should have been thrown earlier by calling checkFail."); + } +} diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/LinkableInvokeDynamicConstant.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/LinkableInvokeDynamicConstant.java deleted file mode 100644 index f6eb31ac2b51..000000000000 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/LinkableInvokeDynamicConstant.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2024, 2024, 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. - */ -package com.oracle.truffle.espresso.constantpool; - -import com.oracle.truffle.espresso.classfile.constantpool.InvokeDynamicConstant; -import com.oracle.truffle.espresso.classfile.constantpool.Resolvable; -import com.oracle.truffle.espresso.impl.Method; -import com.oracle.truffle.espresso.impl.ObjectKlass; - -interface LinkableInvokeDynamicConstant extends InvokeDynamicConstant, Resolvable.ResolvedConstant { - CallSiteLink link(RuntimeConstantPool pool, ObjectKlass accessingKlass, int thisIndex, Method method, int bci); -} diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedClassConstant.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedClassConstant.java index 24137f06c26f..abb624758d25 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedClassConstant.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedClassConstant.java @@ -25,5 +25,5 @@ import com.oracle.truffle.espresso.classfile.constantpool.ClassConstant; import com.oracle.truffle.espresso.classfile.constantpool.Resolvable; -public interface ResolvedClassConstant extends ClassConstant, Resolvable.ResolvedConstant, StickyFailureConstant { +public interface ResolvedClassConstant extends ClassConstant, StickyFallible, Resolvable.ResolvedConstant { } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedDynamicConstant.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedDynamicConstant.java index e186e8bcf3d8..291608111d75 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedDynamicConstant.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedDynamicConstant.java @@ -25,11 +25,12 @@ import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.espresso.classfile.JavaKind; import com.oracle.truffle.espresso.classfile.constantpool.DynamicConstant; +import com.oracle.truffle.espresso.classfile.constantpool.Resolvable; import com.oracle.truffle.espresso.meta.Meta; import com.oracle.truffle.espresso.nodes.BytecodeNode; import com.oracle.truffle.espresso.runtime.staticobject.StaticObject; -public interface ResolvedDynamicConstant extends DynamicConstant, StickyFailureConstant { +public interface ResolvedDynamicConstant extends DynamicConstant, StickyFallible, Resolvable.ResolvedConstant { void putResolved(VirtualFrame frame, int top, BytecodeNode node); JavaKind getKind(); @@ -42,6 +43,7 @@ default StaticObject guestBoxedValue(Meta meta) { return Meta.box(meta, value); } + @Override default void checkFail(Meta meta) { } } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedInvokeDynamicConstant.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedInvokeDynamicConstant.java index 51ef2ab8dca5..f59ef9486b09 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedInvokeDynamicConstant.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedInvokeDynamicConstant.java @@ -27,6 +27,8 @@ import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.espresso.classfile.attributes.BootstrapMethodsAttribute; +import com.oracle.truffle.espresso.classfile.constantpool.InvokeDynamicConstant; +import com.oracle.truffle.espresso.classfile.constantpool.Resolvable; import com.oracle.truffle.espresso.classfile.descriptors.Name; import com.oracle.truffle.espresso.classfile.descriptors.Symbol; import com.oracle.truffle.espresso.classfile.descriptors.Type; @@ -37,7 +39,7 @@ import com.oracle.truffle.espresso.runtime.EspressoException; import com.oracle.truffle.espresso.runtime.staticobject.StaticObject; -public final class ResolvedInvokeDynamicConstant implements LinkableInvokeDynamicConstant { +public final class ResolvedInvokeDynamicConstant implements InvokeDynamicConstant, Resolvable.ResolvedConstant { private final BootstrapMethodsAttribute.Entry bootstrapMethod; private final Symbol[] parsedInvokeSignature; private final Symbol nameSymbol; @@ -82,7 +84,6 @@ public boolean isResolved() { * * @see RuntimeConstantPool#linkInvokeDynamic(ObjectKlass, int, Method, int) */ - @Override public CallSiteLink link(RuntimeConstantPool pool, ObjectKlass accessingKlass, int thisIndex, Method method, int bci) { CallSiteLink existingLink = getCallSiteLink(method, bci); if (existingLink != null) { @@ -104,7 +105,7 @@ public CallSiteLink link(RuntimeConstantPool pool, ObjectKlass accessingKlass, i CallSiteLink link = existingLinks[i]; if (link == null) { existingLinks[i] = newLink; - return existingLinks[i]; + return newLink; } if (link.matchesCallSite(method, bci)) { return link; @@ -171,9 +172,12 @@ private CallSiteLink createCallSiteLink(RuntimeConstantPool pool, ObjectKlass ac } StaticObject unboxedAppendix = appendix.get(meta.getLanguage(), 0); - return new CallSiteLink(method, bci, memberName, unboxedAppendix, parsedInvokeSignature); + return new SuccessfulCallSiteLink(method, bci, memberName, unboxedAppendix, parsedInvokeSignature); } catch (EspressoException e) { - throw new CallSiteLinkingFailure(e); + if (meta.java_lang_LinkageError.isAssignableFrom(e.getGuestException().getKlass())) { + return new FailedCallSiteLink(method, bci, e); + } + throw e; } } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/RuntimeConstantPool.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/RuntimeConstantPool.java index b26c4dcb45f1..401353e9df9f 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/RuntimeConstantPool.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/RuntimeConstantPool.java @@ -230,17 +230,10 @@ public StaticObject resolvedMethodTypeAt(ObjectKlass accessingKlass, int index) } public CallSiteLink linkInvokeDynamic(ObjectKlass accessingKlass, int index, Method method, int bci) { - LinkableInvokeDynamicConstant indy = (LinkableInvokeDynamicConstant) resolvedAt(accessingKlass, index, "indy"); - try { - return indy.link(this, accessingKlass, index, method, bci); - } catch (CallSiteLinkingFailure failure) { - // On failure, shortcut subsequent linking operations. - CompilerDirectives.transferToInterpreterAndInvalidate(); - synchronized (this) { - resolvedConstants[index] = failure.failConstant(); - } - throw failure.cause; - } + ResolvedInvokeDynamicConstant indy = (ResolvedInvokeDynamicConstant) resolvedAt(accessingKlass, index, "indy"); + CallSiteLink link = indy.link(this, accessingKlass, index, method, bci); + link.checkFail(getContext().getMeta()); + return link; } public ResolvedInvokeDynamicConstant peekResolvedInvokeDynamic(int index) { diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/StickyFailureConstant.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/StickyFallible.java similarity index 88% rename from espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/StickyFailureConstant.java rename to espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/StickyFallible.java index f323407d4763..a816823d927b 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/StickyFailureConstant.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/StickyFallible.java @@ -22,9 +22,8 @@ */ package com.oracle.truffle.espresso.constantpool; -import com.oracle.truffle.espresso.classfile.constantpool.Resolvable; import com.oracle.truffle.espresso.meta.Meta; -public interface StickyFailureConstant extends Resolvable.ResolvedConstant { +public interface StickyFallible { void checkFail(Meta meta); } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/SuccessfulCallSiteLink.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/SuccessfulCallSiteLink.java new file mode 100644 index 000000000000..f4c01c897e85 --- /dev/null +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/SuccessfulCallSiteLink.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2024, 2025, 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. + */ +package com.oracle.truffle.espresso.constantpool; + +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.espresso.classfile.descriptors.Symbol; +import com.oracle.truffle.espresso.classfile.descriptors.Type; +import com.oracle.truffle.espresso.impl.Method; +import com.oracle.truffle.espresso.meta.Meta; +import com.oracle.truffle.espresso.runtime.staticobject.StaticObject; + +public final class SuccessfulCallSiteLink implements CallSiteLink { + private final Method method; + private final int bci; + final StaticObject memberName; + final StaticObject unboxedAppendix; + + @CompilationFinal(dimensions = 1) // + final Symbol[] parsedSignature; + + public SuccessfulCallSiteLink(Method method, int bci, StaticObject memberName, StaticObject unboxedAppendix, Symbol[] parsedSignature) { + this.method = method; + this.bci = bci; + this.memberName = memberName; + this.unboxedAppendix = unboxedAppendix; + this.parsedSignature = parsedSignature; + } + + @Override + public StaticObject getMemberName() { + return memberName; + } + + @Override + public StaticObject getUnboxedAppendix() { + return unboxedAppendix; + } + + @Override + public Symbol[] getParsedSignature() { + return parsedSignature; + } + + @Override + public boolean matchesCallSite(Method siteMethod, int siteBci) { + return bci == siteBci && method == siteMethod; + } + + @Override + public void checkFail(Meta meta) { + } + + @Override + public boolean isFailed() { + return false; + } +} diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/Target_com_oracle_truffle_espresso_jvmci_meta_EspressoConstantPool.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/Target_com_oracle_truffle_espresso_jvmci_meta_EspressoConstantPool.java index 2264b6bdec12..b0e2a02a489f 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/Target_com_oracle_truffle_espresso_jvmci_meta_EspressoConstantPool.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/Target_com_oracle_truffle_espresso_jvmci_meta_EspressoConstantPool.java @@ -241,8 +241,8 @@ private static Field tryResolveField(FieldRefConstant.Indexes fieldRef, Klass sy if (opcode == INVOKEDYNAMIC) { LOGGER.finer(() -> "ECP.lookupResolvedMethod resolving indy in CP of %s at cpi=0x%08x".formatted(cpHolderKlass, cpi)); CallSiteLink callSiteLink = getCallSiteLink(self, cpi, meta); - if (callSiteLink == null) { - LOGGER.fine(() -> "ECP.lookupResolvedMethod no call site link in CP of %s at cpi=0x%08x".formatted(cpHolderKlass, cpi)); + if (callSiteLink == null || callSiteLink.isFailed()) { + LOGGER.fine(() -> "ECP.lookupResolvedMethod no call site link or failed link in CP of %s at cpi=0x%08x".formatted(cpHolderKlass, cpi)); return StaticObject.NULL; } Method target = (Method) meta.HIDDEN_VMTARGET.getHiddenObject(callSiteLink.getMemberName()); @@ -444,18 +444,11 @@ public static boolean loadReferencedType0(StaticObject self, int cpi, int opcode JVMCIIndyData.Location location = indyData.getLocation(cpi); assert location != null; int indyCpi = indyCpi(cpi); - RuntimeConstantPool constantPool1 = cpHolderKlass.getConstantPool(); - PoolConstant poolConstant = constantPool1.maybeResolvedAt(indyCpi, meta); - CallSiteLink callSiteLink = null; + PoolConstant poolConstant = constantPool.maybeResolvedAt(indyCpi, meta); if (!(poolConstant instanceof InvokeDynamicConstant)) { throw meta.throwIllegalArgumentExceptionBoundary(); } - if (poolConstant instanceof ResolvedInvokeDynamicConstant resolvedIndy) { - callSiteLink = resolvedIndy.getCallSiteLink(location.method(), location.bci()); - } - if (callSiteLink == null) { - constantPool.linkInvokeDynamic(cpHolderKlass, indyCpi, location.method(), location.bci()); - } + constantPool.linkInvokeDynamic(cpHolderKlass, indyCpi, location.method(), location.bci()); return false; } case Bytecodes.GETSTATIC: @@ -593,7 +586,7 @@ public static boolean loadReferencedType0(StaticObject self, int cpi, int opcode LOGGER.finer(() -> "ECP.lookupAppendix: Looking up CallSiteLink for index=" + Integer.toHexString(index) + " in " + meta.jvmci.HIDDEN_OBJECTKLASS_MIRROR.getHiddenObject(meta.jvmci.EspressoConstantPool_holder.getObject(self))); CallSiteLink callSiteLink = getCallSiteLink(self, index, meta); - if (callSiteLink == null) { + if (callSiteLink == null || callSiteLink.isFailed()) { return StaticObject.NULL; } return wrapEspressoObjectConstant(callSiteLink.getUnboxedAppendix(), meta); From 79817e025b38c822b973010750b0742d7338711d Mon Sep 17 00:00:00 2001 From: Gilles Duboscq Date: Thu, 23 Jan 2025 21:33:31 +0100 Subject: [PATCH 3/5] Improve creation of exception in AbstractStickyFailure --- .../constantpool/AbstractStickyFailure.java | 30 ++++++++++++------- .../espresso/descriptors/EspressoSymbols.java | 2 ++ .../espresso/meta/ExceptionDispatch.java | 17 ++++++++--- .../oracle/truffle/espresso/meta/Meta.java | 2 ++ .../espresso/runtime/EspressoException.java | 7 +++-- 5 files changed, 42 insertions(+), 16 deletions(-) diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/AbstractStickyFailure.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/AbstractStickyFailure.java index ef27c5aa197e..29b02f4f2560 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/AbstractStickyFailure.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/AbstractStickyFailure.java @@ -28,21 +28,31 @@ import com.oracle.truffle.espresso.runtime.staticobject.StaticObject; public abstract class AbstractStickyFailure implements StickyFallible { - private final ObjectKlass exceptionType; - private final StaticObject message; - private final StaticObject cause; + private final EspressoException originalWrappedException; public AbstractStickyFailure(EspressoException failure) { - StaticObject exception = failure.getGuestException(); - exceptionType = (ObjectKlass) exception.getKlass(); - message = EspressoException.getGuestMessage(exception); - cause = EspressoException.getGuestCause(exception); + originalWrappedException = failure; } @Override public final void checkFail(Meta meta) { - StaticObject exception = Meta.initExceptionWithMessage(exceptionType, message); - meta.java_lang_Throwable_cause.set(exception, cause); - throw meta.throwException(exception); + StaticObject originalException = originalWrappedException.getGuestException(); + ObjectKlass exceptionType = (ObjectKlass) originalException.getKlass(); + if (StaticObject.isNull(exceptionType.getDefiningClassLoader())) { + StaticObject message = EspressoException.getGuestMessage(originalException); + StaticObject cause = EspressoException.getGuestCause(originalException); + StaticObject exception; + if (StaticObject.notNull(message)) { + exception = Meta.initExceptionWithMessage(exceptionType, message); + } else { + exception = Meta.initException(exceptionType); + } + if (StaticObject.notNull(cause)) { + meta.java_lang_Throwable_initCause.invokeDirectVirtual(exception, cause); + } + throw meta.throwException(exception); + } else { + throw originalWrappedException; + } } } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/descriptors/EspressoSymbols.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/descriptors/EspressoSymbols.java index 32e259a4a49c..2fa0b11df50b 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/descriptors/EspressoSymbols.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/descriptors/EspressoSymbols.java @@ -588,6 +588,7 @@ public static class Names { public static final Symbol fillInStackTrace0 = SYMBOLS.putName("fillInStackTrace0"); public static final Symbol getMessage = SYMBOLS.putName("getMessage"); public static final Symbol getCause = SYMBOLS.putName("getCause"); + public static final Symbol initCause = SYMBOLS.putName("initCause"); public static final Symbol detailMessage = SYMBOLS.putName("detailMessage"); public static final Symbol printStackTrace = SYMBOLS.putName("printStackTrace"); public static final Symbol extendedMessageState = SYMBOLS.putName("extendedMessageState"); @@ -1019,6 +1020,7 @@ public static class Signatures { public static final Symbol _void_String_array = SYMBOLS.putSignature(Types._void, Types.java_lang_String_array); public static final Symbol Class_String_boolean_ClassLoader = SYMBOLS.putSignature(Types.java_lang_Class, Types.java_lang_String, Types._boolean, Types.java_lang_ClassLoader); public static final Symbol Throwable = SYMBOLS.putSignature(Types.java_lang_Throwable); + public static final Symbol Throwable_Throwable = SYMBOLS.putSignature(Types.java_lang_Throwable, Types.java_lang_Throwable); public static final Symbol _void_long_boolean_boolean = SYMBOLS.putSignature(Types._void, Types._long, Types._boolean, Types._boolean); public static final Symbol _void_long_boolean_boolean_boolean = SYMBOLS.putSignature(Types._void, Types._long, Types._boolean, Types._boolean, Types._boolean); public static final Symbol _byte_array_Module_ClassLoader_String_Class_ProtectionDomain_byte_array_boolean = SYMBOLS.putSignature( diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/meta/ExceptionDispatch.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/meta/ExceptionDispatch.java index e6c12d27bad9..a52a2f3e1a39 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/meta/ExceptionDispatch.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/meta/ExceptionDispatch.java @@ -27,6 +27,7 @@ import com.oracle.truffle.espresso.descriptors.EspressoSymbols.Names; import com.oracle.truffle.espresso.descriptors.EspressoSymbols.Signatures; import com.oracle.truffle.espresso.impl.ContextAccessImpl; +import com.oracle.truffle.espresso.impl.Method; import com.oracle.truffle.espresso.impl.ObjectKlass; import com.oracle.truffle.espresso.runtime.EspressoContext; import com.oracle.truffle.espresso.runtime.staticobject.StaticObject; @@ -114,21 +115,29 @@ private void slowInitEx(StaticObject ex, ObjectKlass klass, StaticObject message @CompilerDirectives.TruffleBoundary private static void doFullInit(StaticObject ex, ObjectKlass klass, StaticObject message, StaticObject cause) { - klass.lookupDeclaredMethod(Names._init_, Signatures._void_String_Throwable).invokeDirectSpecial(ex, message, cause); + Method method = klass.lookupDeclaredMethod(Names._init_, Signatures._void_String_Throwable); + assert method != null : "No (String, Throwable) constructor in " + klass; + method.invokeDirectSpecial(ex, message, cause); } @CompilerDirectives.TruffleBoundary private static void doCauseInit(StaticObject ex, ObjectKlass klass, StaticObject cause) { - klass.lookupDeclaredMethod(Names._init_, Signatures._void_Throwable).invokeDirectSpecial(ex, cause); + Method method = klass.lookupDeclaredMethod(Names._init_, Signatures._void_Throwable); + assert method != null : "No (Throwable) constructor in " + klass; + method.invokeDirectSpecial(ex, cause); } @CompilerDirectives.TruffleBoundary private static void doMessageInit(StaticObject ex, ObjectKlass klass, StaticObject message) { - klass.lookupDeclaredMethod(Names._init_, Signatures._void_String).invokeDirectSpecial(ex, message); + Method method = klass.lookupDeclaredMethod(Names._init_, Signatures._void_String); + assert method != null : "No (String) constructor in " + klass; + method.invokeDirectSpecial(ex, message); } @CompilerDirectives.TruffleBoundary private static void doInit(StaticObject ex, ObjectKlass klass) { - klass.lookupDeclaredMethod(Names._init_, Signatures._void).invokeDirectSpecial(ex); + Method method = klass.lookupDeclaredMethod(Names._init_, Signatures._void); + assert method != null : "No () constructor in " + klass; + method.invokeDirectSpecial(ex); } } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/meta/Meta.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/meta/Meta.java index bca45104a2d0..a843daf24ab4 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/meta/Meta.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/meta/Meta.java @@ -251,6 +251,7 @@ public Meta(EspressoContext context) { java_lang_Throwable_getStackTrace = java_lang_Throwable.requireDeclaredMethod(Names.getStackTrace, Signatures.StackTraceElement_array); java_lang_Throwable_getMessage = java_lang_Throwable.requireDeclaredMethod(Names.getMessage, Signatures.String); java_lang_Throwable_getCause = java_lang_Throwable.requireDeclaredMethod(Names.getCause, Signatures.Throwable); + java_lang_Throwable_initCause = java_lang_Throwable.requireDeclaredMethod(Names.initCause, Signatures.Throwable_Throwable); java_lang_Throwable_printStackTrace = java_lang_Throwable.requireDeclaredMethod(Names.printStackTrace, Signatures._void); HIDDEN_FRAMES = java_lang_Throwable.requireHiddenField(Names.HIDDEN_FRAMES); HIDDEN_EXCEPTION_WRAPPER = java_lang_Throwable.requireHiddenField(Names.HIDDEN_EXCEPTION_WRAPPER); @@ -1572,6 +1573,7 @@ private DiffVersionLoadHelper diff() { public final Method java_lang_Throwable_getStackTrace; public final Method java_lang_Throwable_getMessage; public final Method java_lang_Throwable_getCause; + public final Method java_lang_Throwable_initCause; public final Method java_lang_Throwable_printStackTrace; public final Field HIDDEN_FRAMES; public final Field HIDDEN_EXCEPTION_WRAPPER; diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoException.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoException.java index cb6b3efbfcec..1a5890efafea 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoException.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoException.java @@ -77,8 +77,11 @@ public static StaticObject getGuestMessage(StaticObject e) { } public static StaticObject getGuestCause(StaticObject e) { - // this is used in toString, too dangerous to call a method - return (StaticObject) e.getKlass().getMeta().java_lang_Throwable_cause.get(e); + StaticObject cause = (StaticObject) e.getKlass().getMeta().java_lang_Throwable_cause.get(e); + if (cause == e) { + return StaticObject.NULL; + } + return cause; } public static String getMessage(StaticObject e) { From 82c633e7f04e6a44743071d17331aa0db26845b9 Mon Sep 17 00:00:00 2001 From: Gilles Duboscq Date: Mon, 27 Jan 2025 14:12:39 +0100 Subject: [PATCH 4/5] Only remember LinkageErrors while resolving condy entries. --- .../espresso/constantpool/AbstractStickyFailure.java | 1 + .../oracle/truffle/espresso/constantpool/Resolution.java | 9 ++++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/AbstractStickyFailure.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/AbstractStickyFailure.java index 29b02f4f2560..fd041d1814ce 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/AbstractStickyFailure.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/AbstractStickyFailure.java @@ -31,6 +31,7 @@ public abstract class AbstractStickyFailure implements StickyFallible { private final EspressoException originalWrappedException; public AbstractStickyFailure(EspressoException failure) { + assert failure.getGuestException().getKlass().getMeta().java_lang_LinkageError.isAssignableFrom(failure.getGuestException().getKlass()); originalWrappedException = failure; } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/Resolution.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/Resolution.java index 96c563845a0a..bfec1a07be11 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/Resolution.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/Resolution.java @@ -561,7 +561,14 @@ public static Resolvable.ResolvedConstant resolveDynamicConstant(DynamicConstant throw e; } } catch (EspressoException e) { - return new ResolvedFailDynamicConstant(e); + // Comment from Hotspot: + // Just throw the exception and don't prevent these classes from being loaded for + // virtual machine errors like StackOverflow and OutOfMemoryError, etc. + // Needs clarification to section 5.4.3 of the JVM spec (see 6308271) + if (meta.java_lang_LinkageError.isAssignableFrom(e.getGuestException().getKlass())) { + return new ResolvedFailDynamicConstant(e); + } + throw e; } } From 1ff3b9825446a1f68b91642dc09c925a0e349fbc Mon Sep 17 00:00:00 2001 From: Gilles Duboscq Date: Fri, 31 Jan 2025 15:26:07 +0100 Subject: [PATCH 5/5] Improve API for failed constants * `AbstractFailedConstant` fail when their value is accessed so it's not necessary to remember to call `checkFail` * `ClassSiteLink` must be downcasted to the correct success/fail implementation to be able to access their data or throw their exception. --- .../constantpool/AbstractFailedConstant.java | 5 +--- .../constantpool/AbstractStickyFailure.java | 6 ++-- .../espresso/constantpool/CallSiteLink.java | 13 +-------- .../constantpool/FailedCallSiteLink.java | 28 ------------------ .../constantpool/ResolvedClassConstant.java | 2 +- .../constantpool/ResolvedDynamicConstant.java | 6 +--- .../ResolvedFailDynamicConstant.java | 5 +--- .../ResolvedFoundClassConstant.java | 5 ---- .../constantpool/RuntimeConstantPool.java | 10 +++---- .../espresso/constantpool/StickyFallible.java | 29 ------------------- .../constantpool/SuccessfulCallSiteLink.java | 13 --------- ...resso_jvmci_meta_EspressoConstantPool.java | 9 +++--- 12 files changed, 18 insertions(+), 113 deletions(-) delete mode 100644 espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/StickyFallible.java diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/AbstractFailedConstant.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/AbstractFailedConstant.java index 6379de0d4533..75d35fd66242 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/AbstractFailedConstant.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/AbstractFailedConstant.java @@ -22,9 +22,7 @@ */ package com.oracle.truffle.espresso.constantpool; -import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.espresso.classfile.constantpool.Resolvable; -import com.oracle.truffle.espresso.meta.EspressoError; import com.oracle.truffle.espresso.runtime.EspressoException; public abstract class AbstractFailedConstant extends AbstractStickyFailure implements Resolvable.ResolvedConstant { @@ -34,8 +32,7 @@ public AbstractFailedConstant(EspressoException failure) { @Override public final Object value() { - CompilerDirectives.transferToInterpreterAndInvalidate(); - throw EspressoError.shouldNotReachHere("Exception should have been thrown earlier by calling checkFail."); + throw fail(); } @Override diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/AbstractStickyFailure.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/AbstractStickyFailure.java index fd041d1814ce..810a9ee5192f 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/AbstractStickyFailure.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/AbstractStickyFailure.java @@ -27,7 +27,7 @@ import com.oracle.truffle.espresso.runtime.EspressoException; import com.oracle.truffle.espresso.runtime.staticobject.StaticObject; -public abstract class AbstractStickyFailure implements StickyFallible { +public abstract class AbstractStickyFailure { private final EspressoException originalWrappedException; public AbstractStickyFailure(EspressoException failure) { @@ -35,8 +35,7 @@ public AbstractStickyFailure(EspressoException failure) { originalWrappedException = failure; } - @Override - public final void checkFail(Meta meta) { + public EspressoException fail() { StaticObject originalException = originalWrappedException.getGuestException(); ObjectKlass exceptionType = (ObjectKlass) originalException.getKlass(); if (StaticObject.isNull(exceptionType.getDefiningClassLoader())) { @@ -48,6 +47,7 @@ public final void checkFail(Meta meta) { } else { exception = Meta.initException(exceptionType); } + Meta meta = exceptionType.getMeta(); if (StaticObject.notNull(cause)) { meta.java_lang_Throwable_initCause.invokeDirectVirtual(exception, cause); } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/CallSiteLink.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/CallSiteLink.java index e997a71c9029..8910d435d42c 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/CallSiteLink.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/CallSiteLink.java @@ -22,19 +22,8 @@ */ package com.oracle.truffle.espresso.constantpool; -import com.oracle.truffle.espresso.classfile.descriptors.Symbol; -import com.oracle.truffle.espresso.classfile.descriptors.Type; import com.oracle.truffle.espresso.impl.Method; -import com.oracle.truffle.espresso.runtime.staticobject.StaticObject; - -public sealed interface CallSiteLink extends StickyFallible permits FailedCallSiteLink, SuccessfulCallSiteLink { - StaticObject getMemberName(); - - StaticObject getUnboxedAppendix(); - - Symbol[] getParsedSignature(); +public sealed interface CallSiteLink permits FailedCallSiteLink, SuccessfulCallSiteLink { boolean matchesCallSite(Method siteMethod, int siteBci); - - boolean isFailed(); } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/FailedCallSiteLink.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/FailedCallSiteLink.java index 156a99043582..e1dee615e502 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/FailedCallSiteLink.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/FailedCallSiteLink.java @@ -22,13 +22,8 @@ */ package com.oracle.truffle.espresso.constantpool; -import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.espresso.classfile.descriptors.Symbol; -import com.oracle.truffle.espresso.classfile.descriptors.Type; import com.oracle.truffle.espresso.impl.Method; -import com.oracle.truffle.espresso.meta.EspressoError; import com.oracle.truffle.espresso.runtime.EspressoException; -import com.oracle.truffle.espresso.runtime.staticobject.StaticObject; public final class FailedCallSiteLink extends AbstractStickyFailure implements CallSiteLink { private final Method method; @@ -40,31 +35,8 @@ public FailedCallSiteLink(Method method, int bci, EspressoException failure) { this.bci = bci; } - @Override - public boolean isFailed() { - return true; - } - @Override public boolean matchesCallSite(Method siteMethod, int siteBci) { return bci == siteBci && method == siteMethod; } - - @Override - public StaticObject getMemberName() { - CompilerDirectives.transferToInterpreterAndInvalidate(); - throw EspressoError.shouldNotReachHere("Exception should have been thrown earlier by calling checkFail."); - } - - @Override - public StaticObject getUnboxedAppendix() { - CompilerDirectives.transferToInterpreterAndInvalidate(); - throw EspressoError.shouldNotReachHere("Exception should have been thrown earlier by calling checkFail."); - } - - @Override - public Symbol[] getParsedSignature() { - CompilerDirectives.transferToInterpreterAndInvalidate(); - throw EspressoError.shouldNotReachHere("Exception should have been thrown earlier by calling checkFail."); - } } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedClassConstant.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedClassConstant.java index abb624758d25..b3ad8434f968 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedClassConstant.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedClassConstant.java @@ -25,5 +25,5 @@ import com.oracle.truffle.espresso.classfile.constantpool.ClassConstant; import com.oracle.truffle.espresso.classfile.constantpool.Resolvable; -public interface ResolvedClassConstant extends ClassConstant, StickyFallible, Resolvable.ResolvedConstant { +public interface ResolvedClassConstant extends ClassConstant, Resolvable.ResolvedConstant { } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedDynamicConstant.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedDynamicConstant.java index 291608111d75..9d7297bb5cac 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedDynamicConstant.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedDynamicConstant.java @@ -30,7 +30,7 @@ import com.oracle.truffle.espresso.nodes.BytecodeNode; import com.oracle.truffle.espresso.runtime.staticobject.StaticObject; -public interface ResolvedDynamicConstant extends DynamicConstant, StickyFallible, Resolvable.ResolvedConstant { +public interface ResolvedDynamicConstant extends DynamicConstant, Resolvable.ResolvedConstant { void putResolved(VirtualFrame frame, int top, BytecodeNode node); JavaKind getKind(); @@ -42,8 +42,4 @@ default StaticObject guestBoxedValue(Meta meta) { } return Meta.box(meta, value); } - - @Override - default void checkFail(Meta meta) { - } } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedFailDynamicConstant.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedFailDynamicConstant.java index 761c21a1b398..3e9e5e0c60d1 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedFailDynamicConstant.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedFailDynamicConstant.java @@ -22,10 +22,8 @@ */ package com.oracle.truffle.espresso.constantpool; -import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.espresso.classfile.JavaKind; -import com.oracle.truffle.espresso.meta.EspressoError; import com.oracle.truffle.espresso.nodes.BytecodeNode; import com.oracle.truffle.espresso.runtime.EspressoException; @@ -36,8 +34,7 @@ public ResolvedFailDynamicConstant(EspressoException failure) { @Override public void putResolved(VirtualFrame frame, int top, BytecodeNode node) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - throw EspressoError.shouldNotReachHere("Failure should have arose earlier."); + throw fail(); } @Override diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedFoundClassConstant.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedFoundClassConstant.java index f1350ede788b..78c4c656adf3 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedFoundClassConstant.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/ResolvedFoundClassConstant.java @@ -25,7 +25,6 @@ import java.util.Objects; import com.oracle.truffle.espresso.impl.Klass; -import com.oracle.truffle.espresso.meta.Meta; public final class ResolvedFoundClassConstant implements ResolvedClassConstant { private final Klass resolved; @@ -38,8 +37,4 @@ public ResolvedFoundClassConstant(Klass resolved) { public Klass value() { return resolved; } - - @Override - public void checkFail(Meta meta) { - } } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/RuntimeConstantPool.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/RuntimeConstantPool.java index 401353e9df9f..4f85e0295214 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/RuntimeConstantPool.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/RuntimeConstantPool.java @@ -149,7 +149,6 @@ public StaticObject resolvedStringAt(int index) { public Klass resolvedKlassAt(ObjectKlass accessingKlass, int index) { ResolvedClassConstant resolved = (ResolvedClassConstant) resolvedAt(accessingKlass, index, "klass"); - resolved.checkFail(getContext().getMeta()); return (Klass) resolved.value(); } @@ -229,11 +228,13 @@ public StaticObject resolvedMethodTypeAt(ObjectKlass accessingKlass, int index) return (StaticObject) resolved.value(); } - public CallSiteLink linkInvokeDynamic(ObjectKlass accessingKlass, int index, Method method, int bci) { + public SuccessfulCallSiteLink linkInvokeDynamic(ObjectKlass accessingKlass, int index, Method method, int bci) { ResolvedInvokeDynamicConstant indy = (ResolvedInvokeDynamicConstant) resolvedAt(accessingKlass, index, "indy"); CallSiteLink link = indy.link(this, accessingKlass, index, method, bci); - link.checkFail(getContext().getMeta()); - return link; + if (link instanceof FailedCallSiteLink failed) { + throw failed.fail(); + } + return (SuccessfulCallSiteLink) link; } public ResolvedInvokeDynamicConstant peekResolvedInvokeDynamic(int index) { @@ -242,7 +243,6 @@ public ResolvedInvokeDynamicConstant peekResolvedInvokeDynamic(int index) { public ResolvedDynamicConstant resolvedDynamicConstantAt(ObjectKlass accessingKlass, int index) { ResolvedDynamicConstant dynamicConstant = (ResolvedDynamicConstant) outOfLockResolvedAt(accessingKlass, index, "dynamic constant"); - dynamicConstant.checkFail(getContext().getMeta()); return dynamicConstant; } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/StickyFallible.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/StickyFallible.java deleted file mode 100644 index a816823d927b..000000000000 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/StickyFallible.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2025, 2025, 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. - */ -package com.oracle.truffle.espresso.constantpool; - -import com.oracle.truffle.espresso.meta.Meta; - -public interface StickyFallible { - void checkFail(Meta meta); -} diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/SuccessfulCallSiteLink.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/SuccessfulCallSiteLink.java index f4c01c897e85..3490039d10de 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/SuccessfulCallSiteLink.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/constantpool/SuccessfulCallSiteLink.java @@ -26,7 +26,6 @@ import com.oracle.truffle.espresso.classfile.descriptors.Symbol; import com.oracle.truffle.espresso.classfile.descriptors.Type; import com.oracle.truffle.espresso.impl.Method; -import com.oracle.truffle.espresso.meta.Meta; import com.oracle.truffle.espresso.runtime.staticobject.StaticObject; public final class SuccessfulCallSiteLink implements CallSiteLink { @@ -46,17 +45,14 @@ public SuccessfulCallSiteLink(Method method, int bci, StaticObject memberName, S this.parsedSignature = parsedSignature; } - @Override public StaticObject getMemberName() { return memberName; } - @Override public StaticObject getUnboxedAppendix() { return unboxedAppendix; } - @Override public Symbol[] getParsedSignature() { return parsedSignature; } @@ -65,13 +61,4 @@ public Symbol[] getParsedSignature() { public boolean matchesCallSite(Method siteMethod, int siteBci) { return bci == siteBci && method == siteMethod; } - - @Override - public void checkFail(Meta meta) { - } - - @Override - public boolean isFailed() { - return false; - } } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/Target_com_oracle_truffle_espresso_jvmci_meta_EspressoConstantPool.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/Target_com_oracle_truffle_espresso_jvmci_meta_EspressoConstantPool.java index b0e2a02a489f..276e2ff4f912 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/Target_com_oracle_truffle_espresso_jvmci_meta_EspressoConstantPool.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/Target_com_oracle_truffle_espresso_jvmci_meta_EspressoConstantPool.java @@ -77,6 +77,7 @@ import com.oracle.truffle.espresso.constantpool.ResolvedInvokeDynamicConstant; import com.oracle.truffle.espresso.constantpool.ResolvedWithInvokerClassMethodRefConstant; import com.oracle.truffle.espresso.constantpool.RuntimeConstantPool; +import com.oracle.truffle.espresso.constantpool.SuccessfulCallSiteLink; import com.oracle.truffle.espresso.impl.Field; import com.oracle.truffle.espresso.impl.Klass; import com.oracle.truffle.espresso.impl.Method; @@ -241,11 +242,11 @@ private static Field tryResolveField(FieldRefConstant.Indexes fieldRef, Klass sy if (opcode == INVOKEDYNAMIC) { LOGGER.finer(() -> "ECP.lookupResolvedMethod resolving indy in CP of %s at cpi=0x%08x".formatted(cpHolderKlass, cpi)); CallSiteLink callSiteLink = getCallSiteLink(self, cpi, meta); - if (callSiteLink == null || callSiteLink.isFailed()) { + if (!(callSiteLink instanceof SuccessfulCallSiteLink successfulCallSiteLink)) { LOGGER.fine(() -> "ECP.lookupResolvedMethod no call site link or failed link in CP of %s at cpi=0x%08x".formatted(cpHolderKlass, cpi)); return StaticObject.NULL; } - Method target = (Method) meta.HIDDEN_VMTARGET.getHiddenObject(callSiteLink.getMemberName()); + Method target = (Method) meta.HIDDEN_VMTARGET.getHiddenObject(successfulCallSiteLink.getMemberName()); StaticObject holder = toJVMCIInstanceType(target.getDeclaringKlass(), meta); return toJVMCIMethod(target, holder, meta); } @@ -586,10 +587,10 @@ public static boolean loadReferencedType0(StaticObject self, int cpi, int opcode LOGGER.finer(() -> "ECP.lookupAppendix: Looking up CallSiteLink for index=" + Integer.toHexString(index) + " in " + meta.jvmci.HIDDEN_OBJECTKLASS_MIRROR.getHiddenObject(meta.jvmci.EspressoConstantPool_holder.getObject(self))); CallSiteLink callSiteLink = getCallSiteLink(self, index, meta); - if (callSiteLink == null || callSiteLink.isFailed()) { + if (!(callSiteLink instanceof SuccessfulCallSiteLink successfulCallSiteLink)) { return StaticObject.NULL; } - return wrapEspressoObjectConstant(callSiteLink.getUnboxedAppendix(), meta); + return wrapEspressoObjectConstant(successfulCallSiteLink.getUnboxedAppendix(), meta); } else { assert opcode == INVOKEVIRTUAL; StaticObject cpHolder = meta.jvmci.EspressoConstantPool_holder.getObject(self);