Skip to content

Commit

Permalink
Do not re-execute bootstrap method if a previous resolution failed.
Browse files Browse the repository at this point in the history
  • Loading branch information
rakachan committed Jul 19, 2021
1 parent a3409e4 commit 5dc7e7a
Show file tree
Hide file tree
Showing 4 changed files with 171 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -150,11 +150,15 @@ public StaticObject resolvedMethodTypeAt(Klass accessingKlass, int index) {
}

public InvokeDynamicConstant.Resolved resolvedInvokeDynamicAt(Klass accessingKlass, int index) {
return (InvokeDynamicConstant.Resolved) outOfLockResolvedAt(accessingKlass, index, "invokedynamic");
InvokeDynamicConstant.Resolved invokeDynamic = (InvokeDynamicConstant.Resolved) outOfLockResolvedAt(accessingKlass, index, "invokedynamic");
invokeDynamic.checkFail();
return invokeDynamic;
}

public DynamicConstant.Resolved resolvedDynamicConstantAt(Klass accessingKlass, int index) {
return (DynamicConstant.Resolved) outOfLockResolvedAt(accessingKlass, index, "dynamic constant");
DynamicConstant.Resolved dynamicConstant = (DynamicConstant.Resolved) outOfLockResolvedAt(accessingKlass, index, "dynamic constant");
dynamicConstant.checkFail();
return dynamicConstant;
}

public StaticObject getClassLoader() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,39 +109,43 @@ public void dump(ByteBuffer buf) {
public ResolvedConstant resolve(RuntimeConstantPool pool, int thisIndex, Klass accessingKlass) {
Meta meta = accessingKlass.getMeta();

// Indy constant resolving.
// Condy constant resolving.
BootstrapMethodsAttribute bms = (BootstrapMethodsAttribute) ((ObjectKlass) accessingKlass).getAttribute(BootstrapMethodsAttribute.NAME);

assert (bms != null);
// TODO(garcia) cache bootstrap method resolution
// Bootstrap method resolution
BootstrapMethodsAttribute.Entry bsEntry = bms.at(getBootstrapMethodAttrIndex());

StaticObject bootstrapmethodMethodHandle = bsEntry.getMethodHandle(accessingKlass, pool);
StaticObject[] args = bsEntry.getStaticArguments(accessingKlass, pool);

StaticObject fieldName = meta.toGuestString(getName(pool));
Klass fieldType = meta.resolveSymbolOrFail(Types.fromDescriptor(getSignature(pool)),
accessingKlass.getDefiningClassLoader(),
accessingKlass.protectionDomain());

Object result = meta.java_lang_invoke_MethodHandleNatives_linkDynamicConstant.invokeDirect(
null,
accessingKlass.mirror(),
thisIndex,
bootstrapmethodMethodHandle,
fieldName, fieldType.mirror(),
StaticObject.wrap(args, meta));
try {
return makeResolved(fieldType, (StaticObject) result);
} catch (ClassCastException | NullPointerException e) {
throw meta.throwException(meta.java_lang_BootstrapMethodError);
} catch (EspressoException e) {
if (meta.java_lang_NullPointerException.isAssignableFrom(e.getExceptionObject().getKlass()) ||
meta.java_lang_ClassCastException.isAssignableFrom(e.getExceptionObject().getKlass())) {
throw meta.throwExceptionWithCause(meta.java_lang_BootstrapMethodError, e.getExceptionObject());
BootstrapMethodsAttribute.Entry bsEntry = bms.at(getBootstrapMethodAttrIndex());

StaticObject bootstrapmethodMethodHandle = bsEntry.getMethodHandle(accessingKlass, pool);
StaticObject[] args = bsEntry.getStaticArguments(accessingKlass, pool);

StaticObject fieldName = meta.toGuestString(getName(pool));
Klass fieldType = meta.resolveSymbolOrFail(Types.fromDescriptor(getSignature(pool)),
accessingKlass.getDefiningClassLoader(),
accessingKlass.protectionDomain());

Object result = meta.java_lang_invoke_MethodHandleNatives_linkDynamicConstant.invokeDirect(
null,
accessingKlass.mirror(),
thisIndex,
bootstrapmethodMethodHandle,
fieldName, fieldType.mirror(),
StaticObject.wrap(args, meta));
try {
return makeResolved(fieldType, (StaticObject) result);
} catch (ClassCastException | NullPointerException e) {
throw meta.throwException(meta.java_lang_BootstrapMethodError);
} catch (EspressoException e) {
if (meta.java_lang_NullPointerException.isAssignableFrom(e.getExceptionObject().getKlass()) ||
meta.java_lang_ClassCastException.isAssignableFrom(e.getExceptionObject().getKlass())) {
throw meta.throwExceptionWithCause(meta.java_lang_BootstrapMethodError, e.getExceptionObject());
}
throw e;
}
throw e;
} catch (EspressoException e) {
return new ResolvedFail(e);
}
}
}
Expand All @@ -161,6 +165,9 @@ default StaticObject guestBoxedValue(Meta meta) {
}
return Meta.box(meta, value);
}

default void checkFail() {
}
}

final class ResolvedObject implements Resolved {
Expand Down Expand Up @@ -277,4 +284,32 @@ public String toString(ConstantPool pool) {
return "ResolvedDynamicConstant(" + resolved + ")";
}
}

final class ResolvedFail implements Resolved {
final EspressoException failure;

public ResolvedFail(EspressoException failure) {
this.failure = failure;
}

@Override
public void checkFail() {
throw failure;
}

@Override
public void putResolved(long[] primitives, Object[] refs, int top, BytecodeNode node) {
throw EspressoError.shouldNotReachHere("Failure should have arose earlier.");
}

@Override
public Object value() {
throw EspressoError.shouldNotReachHere("Failure should have arose earlier.");
}

@Override
public String toString(ConstantPool pool) {
return "ResolvedDynamicConstant(" + failure + ")";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
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;

public interface InvokeDynamicConstant extends BootstrapMethodConstant {
Expand Down Expand Up @@ -68,40 +69,43 @@ public ResolvedConstant resolve(RuntimeConstantPool pool, int thisIndex, Klass a
assert (bms != null);
// TODO(garcia) cache bootstrap method resolution
// Bootstrap method resolution
BootstrapMethodsAttribute.Entry bsEntry = bms.at(getBootstrapMethodAttrIndex());

StaticObject bootstrapmethodMethodHandle = bsEntry.getMethodHandle(accessingKlass, pool);
StaticObject[] args = bsEntry.getStaticArguments(accessingKlass, pool);

// Preparing Bootstrap call.
StaticObject name = meta.toGuestString(getName(pool));
Symbol<Signature> invokeSignature = getSignature(pool);
Symbol<Type>[] parsedInvokeSignature = meta.getSignatures().parsed(invokeSignature);
StaticObject methodType = MethodTypeConstant.signatureToMethodType(parsedInvokeSignature, accessingKlass, meta.getContext().getJavaVersion().java8OrEarlier(), meta);
StaticObject appendix = StaticObject.createArray(meta.java_lang_Object_array, new StaticObject[1]);
StaticObject memberName;
if (meta.getJavaVersion().varHandlesEnabled()) {
memberName = (StaticObject) meta.java_lang_invoke_MethodHandleNatives_linkCallSite.invokeDirect(
null,
accessingKlass.mirror(),
thisIndex,
bootstrapmethodMethodHandle,
name, methodType,
StaticObject.createArray(meta.java_lang_Object_array, args),
appendix);
} else {
memberName = (StaticObject) meta.java_lang_invoke_MethodHandleNatives_linkCallSite.invokeDirect(
null,
accessingKlass.mirror(),
bootstrapmethodMethodHandle,
name, methodType,
StaticObject.createArray(meta.java_lang_Object_array, args),
appendix);
try {
BootstrapMethodsAttribute.Entry bsEntry = bms.at(getBootstrapMethodAttrIndex());

StaticObject bootstrapmethodMethodHandle = bsEntry.getMethodHandle(accessingKlass, pool);
StaticObject[] args = bsEntry.getStaticArguments(accessingKlass, pool);

// Preparing Bootstrap call.
StaticObject name = meta.toGuestString(getName(pool));
Symbol<Signature> invokeSignature = getSignature(pool);
Symbol<Type>[] parsedInvokeSignature = meta.getSignatures().parsed(invokeSignature);
StaticObject methodType = MethodTypeConstant.signatureToMethodType(parsedInvokeSignature, accessingKlass, meta.getContext().getJavaVersion().java8OrEarlier(), meta);
StaticObject appendix = StaticObject.createArray(meta.java_lang_Object_array, new StaticObject[1]);
StaticObject memberName;
if (meta.getJavaVersion().varHandlesEnabled()) {
memberName = (StaticObject) meta.java_lang_invoke_MethodHandleNatives_linkCallSite.invokeDirect(
null,
accessingKlass.mirror(),
thisIndex,
bootstrapmethodMethodHandle,
name, methodType,
StaticObject.createArray(meta.java_lang_Object_array, args),
appendix);
} else {
memberName = (StaticObject) meta.java_lang_invoke_MethodHandleNatives_linkCallSite.invokeDirect(
null,
accessingKlass.mirror(),
bootstrapmethodMethodHandle,
name, methodType,
StaticObject.createArray(meta.java_lang_Object_array, args),
appendix);
}
StaticObject unboxedAppendix = appendix.get(0);

return new ResolvedSuccess(memberName, unboxedAppendix, parsedInvokeSignature);
} catch (EspressoException e) {
return new ResolvedFail(e);
}

StaticObject unboxedAppendix = appendix.get(0);

return new InvokeDynamicConstant.Resolved(memberName, unboxedAppendix, parsedInvokeSignature);
}

@Override
Expand All @@ -116,25 +120,42 @@ public String toString(ConstantPool pool) {
}
}

final class Resolved implements InvokeDynamicConstant, Resolvable.ResolvedConstant {
interface Resolved extends InvokeDynamicConstant, Resolvable.ResolvedConstant {
StaticObject getMemberName();

StaticObject getUnboxedAppendix();

Symbol<Type>[] getParsedSignature();

void checkFail();
}

final class ResolvedSuccess implements Resolved {
final StaticObject memberName;
final StaticObject unboxedAppendix;
@CompilerDirectives.CompilationFinal(dimensions = 1) final Symbol<Type>[] parsedSignature;

public Resolved(StaticObject memberName, StaticObject unboxedAppendix, Symbol<Type>[] parsedSignature) {
public ResolvedSuccess(StaticObject memberName, StaticObject unboxedAppendix, Symbol<Type>[] parsedSignature) {
this.memberName = memberName;
this.unboxedAppendix = unboxedAppendix;
this.parsedSignature = parsedSignature;
}

@Override
public void checkFail() {
}

@Override
public StaticObject getMemberName() {
return memberName;
}

@Override
public StaticObject getUnboxedAppendix() {
return unboxedAppendix;
}

@Override
public Symbol<Type>[] getParsedSignature() {
return parsedSignature;
}
Expand Down Expand Up @@ -164,4 +185,52 @@ public Object value() {
throw EspressoError.shouldNotReachHere("Resolved method handle returns multiple values. Use getMemberName(), getUnboxedAppendix() or getParsedSignature().");
}
}

final class ResolvedFail implements Resolved {
private final EspressoException failure;

public ResolvedFail(EspressoException failure) {
this.failure = failure;
}

@Override
public void checkFail() {
throw failure;
}

@Override
public Object value() {
throw EspressoError.shouldNotReachHere("Invoke dynamic already resolved to failure.");
}

@Override
public StaticObject getMemberName() {
throw EspressoError.shouldNotReachHere("Invoke dynamic already resolved to failure.");
}

@Override
public StaticObject getUnboxedAppendix() {
throw EspressoError.shouldNotReachHere("Invoke dynamic already resolved to failure.");
}

@Override
public Symbol<Type>[] getParsedSignature() {
throw EspressoError.shouldNotReachHere("Invoke dynamic already resolved to failure.");
}

@Override
public int getBootstrapMethodAttrIndex() {
throw EspressoError.shouldNotReachHere("Invoke dynamic already resolved.");
}

@Override
public Symbol<Symbol.Name> getName(ConstantPool pool) {
throw EspressoError.shouldNotReachHere("Invoke dynamic already resolved.");
}

@Override
public Symbol<Signature> getSignature(ConstantPool pool) {
throw EspressoError.shouldNotReachHere("Invoke dynamic already resolved.");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1702,7 +1702,6 @@ private void putPoolConstant(long[] primitives, Object[] refs, int top, char cpi
} else if (constant instanceof DynamicConstant) {
DynamicConstant.Resolved dynamicConstant = pool.resolvedDynamicConstantAt(getMethod().getDeclaringKlass(), cpi);
dynamicConstant.putResolved(primitives, refs, top, this);

} else {
CompilerDirectives.transferToInterpreter();
throw EspressoError.unimplemented(constant.toString());
Expand Down

0 comments on commit 5dc7e7a

Please sign in to comment.