mirror of
https://github.com/apple/pkl.git
synced 2026-09-09 19:31:51 +02:00
Make listing/mapping typecasts more PE-friendly (#1837)
This rewrites the listing/mapping typecast nodes to be more friendly to partial-evaluation. This is because the compiler bails out of deeply recursive calls.
This commit is contained in:
@@ -51,7 +51,7 @@ public abstract class ElementOrEntryNode extends RegularMemberNode {
|
|||||||
@Cached("create()") @Shared("callNode") IndirectCallNode callNode) {
|
@Cached("create()") @Shared("callNode") IndirectCallNode callNode) {
|
||||||
var result = bodyNode.executeGeneric(frame);
|
var result = bodyNode.executeGeneric(frame);
|
||||||
return VmUtils.shouldRunTypeCheck(frame)
|
return VmUtils.shouldRunTypeCheck(frame)
|
||||||
? receiver.executeTypeCasts(result, VmUtils.getOwner(frame), callNode, null, null)
|
? receiver.executeTypeCasts(result, VmUtils.getOwner(frame), callNode, null)
|
||||||
: result;
|
: result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,7 +62,7 @@ public abstract class ElementOrEntryNode extends RegularMemberNode {
|
|||||||
@Cached("create()") @Shared("callNode") IndirectCallNode callNode) {
|
@Cached("create()") @Shared("callNode") IndirectCallNode callNode) {
|
||||||
var result = bodyNode.executeGeneric(frame);
|
var result = bodyNode.executeGeneric(frame);
|
||||||
return VmUtils.shouldRunTypeCheck(frame)
|
return VmUtils.shouldRunTypeCheck(frame)
|
||||||
? receiver.executeTypeCasts(result, VmUtils.getOwner(frame), callNode, null, null)
|
? receiver.executeTypeCasts(result, VmUtils.getOwner(frame), callNode, null)
|
||||||
: result;
|
: result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -55,30 +55,24 @@ public abstract class VmListingOrMapping extends VmObject {
|
|||||||
this.typeCheckOwner = typeCheckOwner;
|
this.typeCheckOwner = typeCheckOwner;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recursively executes type casts between `owner` and `this` and returns the resulting value.
|
// Executes type casts for every parent between `owner` and `this` and returns the resulting
|
||||||
|
// value.
|
||||||
public final Object executeTypeCasts(
|
public final Object executeTypeCasts(
|
||||||
Object value,
|
Object value,
|
||||||
VmObjectLike owner,
|
VmObjectLike owner,
|
||||||
IndirectCallNode callNode,
|
IndirectCallNode callNode,
|
||||||
// if non-null, a stack frame for this member is inserted if a type cast fails
|
// if non-null, a stack frame for this member is inserted if a type cast fails
|
||||||
@Nullable ObjectMember member,
|
@Nullable ObjectMember member) {
|
||||||
// Next type cast to be performed by the caller.
|
var result = value;
|
||||||
// Avoids repeating the same type cast in some cases.
|
VmObject parent = this;
|
||||||
@Nullable ListingOrMappingTypeCastNode nextTypeCastNode) {
|
ListingOrMappingTypeCastNode prevTypeCastNode = null;
|
||||||
var newNextTypeCastNode = typeCastNode != null ? typeCastNode : nextTypeCastNode;
|
while (parent != null && parent != owner) {
|
||||||
Object result;
|
var obj = (VmListingOrMapping) parent;
|
||||||
if (this == owner) {
|
if (obj.typeCastNode != null && obj.typeCastNode != prevTypeCastNode) {
|
||||||
result = value;
|
var callTarget = obj.typeCastNode.getCallTarget();
|
||||||
} else {
|
|
||||||
assert parent != null;
|
|
||||||
result =
|
|
||||||
((VmListingOrMapping) parent)
|
|
||||||
.executeTypeCasts(value, owner, callNode, member, newNextTypeCastNode);
|
|
||||||
}
|
|
||||||
if (typeCastNode == null || typeCastNode == nextTypeCastNode) return result;
|
|
||||||
var callTarget = typeCastNode.getCallTarget();
|
|
||||||
try {
|
try {
|
||||||
return callNode.call(callTarget, typeCheckReceiver, typeCheckOwner, result);
|
result = callNode.call(callTarget, obj.typeCheckReceiver, obj.typeCheckOwner, result);
|
||||||
|
prevTypeCastNode = obj.typeCastNode;
|
||||||
} catch (VmException e) {
|
} catch (VmException e) {
|
||||||
CompilerDirectives.transferToInterpreter();
|
CompilerDirectives.transferToInterpreter();
|
||||||
if (member != null) {
|
if (member != null) {
|
||||||
@@ -87,6 +81,10 @@ public abstract class VmListingOrMapping extends VmObject {
|
|||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
parent = parent.parent;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@TruffleBoundary
|
@TruffleBoundary
|
||||||
|
|||||||
@@ -396,7 +396,7 @@ public final class VmUtils {
|
|||||||
&& owner instanceof VmListingOrMapping) {
|
&& owner instanceof VmListingOrMapping) {
|
||||||
// `owner instanceof VmListingOrMapping` guards against
|
// `owner instanceof VmListingOrMapping` guards against
|
||||||
// PropertiesRenderer amending VmDynamic with VmListing (hack?)
|
// PropertiesRenderer amending VmDynamic with VmListing (hack?)
|
||||||
result = listingOrMapping.executeTypeCasts(constantValue, owner, callNode, member, null);
|
result = listingOrMapping.executeTypeCasts(constantValue, owner, callNode, member);
|
||||||
}
|
}
|
||||||
|
|
||||||
receiver.setCachedValue(memberKey, result);
|
receiver.setCachedValue(memberKey, result);
|
||||||
|
|||||||
Reference in New Issue
Block a user