mirror of
https://github.com/apple/pkl.git
synced 2026-03-24 10:01:10 +01:00
Improve method.isConst() checks in InvokeMethodVirtualNode
- Check `method.isConst()` every time a method is resolved instead of once per node instance (`isConstChecked`). Given that `needsConst` only happens in very specific circumstances, I'm not entirely sure if every resolved method needs to be checked. However, it's a cleaner solution in any case, and `method.isConst()` is a fast check that also never happens on the `evalCached` fast path. - Do not check for const-ness of `FunctionN.apply` methods. This check seems unnecessary and would always fail if triggered. (According to `base.pkl`, none of the `FunctionN.apply` methods is const.) - Remove unnecessary Truffle boundaries for modifier checks, which are just bitwise operations. - Improve const/import docs.
This commit is contained in:
committed by
Daniel Chao
parent
76f1b92039
commit
5de90d5868
@@ -989,8 +989,8 @@ Because a `local` property is added to the lexical scope, but not (observably) t
|
||||
====
|
||||
|
||||
An _import clause_ defines a local property in the containing module.
|
||||
This means `import "someModule.pkl"` is equivalent to `local someModule = import("someModule.pkl")`.
|
||||
Also, `import "someModule.pkl" as otherName` is equivalent to `local otherName = import("someModule.pkl")`.
|
||||
This means `import "someModule.pkl"` is effectively `const local someModule = import("someModule.pkl")`.
|
||||
Also, `import "someModule.pkl" as otherName` is effectively `const local otherName = import("someModule.pkl")`.
|
||||
====
|
||||
|
||||
[[fixed-properties]]
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
package org.pkl.core.ast.expression.member;
|
||||
|
||||
import com.oracle.truffle.api.CompilerDirectives;
|
||||
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
|
||||
import com.oracle.truffle.api.RootCallTarget;
|
||||
import com.oracle.truffle.api.dsl.Cached;
|
||||
import com.oracle.truffle.api.dsl.ImportStatic;
|
||||
@@ -44,7 +43,6 @@ public abstract class InvokeMethodVirtualNode extends ExpressionNode {
|
||||
@Children private final ExpressionNode[] argumentNodes;
|
||||
private final MemberLookupMode lookupMode;
|
||||
private final boolean needsConst;
|
||||
@CompilationFinal private boolean isConstChecked;
|
||||
|
||||
protected InvokeMethodVirtualNode(
|
||||
SourceSection sourceSection,
|
||||
@@ -101,10 +99,9 @@ public abstract class InvokeMethodVirtualNode extends ExpressionNode {
|
||||
protected Object evalFunction(
|
||||
VirtualFrame frame,
|
||||
VmFunction receiver,
|
||||
VmClass receiverClass,
|
||||
@SuppressWarnings("unused") VmClass receiverClass,
|
||||
@Cached("create()") IndirectCallNode callNode) {
|
||||
|
||||
checkConst(receiverClass);
|
||||
var args = new Object[2 + argumentNodes.length];
|
||||
args[0] = receiver.getThisValue();
|
||||
args[1] = receiver;
|
||||
@@ -125,7 +122,6 @@ public abstract class InvokeMethodVirtualNode extends ExpressionNode {
|
||||
@Cached("resolveMethod(receiverClass)") ClassMethod method,
|
||||
@Cached("create(method.getCallTarget(sourceSection))") DirectCallNode callNode) {
|
||||
|
||||
checkConst(method);
|
||||
var args = new Object[2 + argumentNodes.length];
|
||||
args[0] = receiver;
|
||||
args[1] = method.getOwner();
|
||||
@@ -145,8 +141,6 @@ public abstract class InvokeMethodVirtualNode extends ExpressionNode {
|
||||
@Cached("create()") IndirectCallNode callNode) {
|
||||
|
||||
var method = resolveMethod(receiverClass);
|
||||
checkConst(method);
|
||||
|
||||
var args = new Object[2 + argumentNodes.length];
|
||||
args[0] = receiver;
|
||||
args[1] = method.getOwner();
|
||||
@@ -161,7 +155,10 @@ public abstract class InvokeMethodVirtualNode extends ExpressionNode {
|
||||
|
||||
protected ClassMethod resolveMethod(VmClass receiverClass) {
|
||||
var method = receiverClass.getMethod(methodName);
|
||||
if (method != null) return method;
|
||||
if (method != null) {
|
||||
checkConst(method);
|
||||
return method;
|
||||
}
|
||||
|
||||
CompilerDirectives.transferToInterpreter();
|
||||
|
||||
@@ -174,17 +171,10 @@ public abstract class InvokeMethodVirtualNode extends ExpressionNode {
|
||||
.build();
|
||||
}
|
||||
|
||||
private void checkConst(VmClass receiverClass) {
|
||||
checkConst(resolveMethod(receiverClass));
|
||||
}
|
||||
|
||||
private void checkConst(ClassMethod method) {
|
||||
if (needsConst && !isConstChecked) {
|
||||
CompilerDirectives.transferToInterpreterAndInvalidate();
|
||||
if (!method.isConst()) {
|
||||
throw exceptionBuilder().evalError("methodMustBeConst", methodName.toString()).build();
|
||||
}
|
||||
isConstChecked = true;
|
||||
if (needsConst && !method.isConst()) {
|
||||
CompilerDirectives.transferToInterpreter();
|
||||
throw exceptionBuilder().evalError("methodMustBeConst", methodName.toString()).build();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,7 +194,7 @@ public final class ResolveVariableNode extends ExpressionNode {
|
||||
}
|
||||
}
|
||||
|
||||
// Assuming this method exists at all, it must be a method accessible through `this`.
|
||||
// Assuming this property exists at all, it must be a property accessible through `this`.
|
||||
///
|
||||
// Reading a property off of implicit `this` needs a const check if this node is not in a const
|
||||
// scope.
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package org.pkl.core.ast.member;
|
||||
|
||||
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
|
||||
import com.oracle.truffle.api.source.SourceSection;
|
||||
import org.pkl.core.ast.VmModifier;
|
||||
import org.pkl.core.runtime.Identifier;
|
||||
@@ -76,42 +75,34 @@ public abstract class Member {
|
||||
/** For use in user-facing messages. Non-null iff getName() is non-null. */
|
||||
public abstract @Nullable String getCallSignature();
|
||||
|
||||
@TruffleBoundary
|
||||
public final boolean isLocal() {
|
||||
return VmModifier.isLocal(modifiers);
|
||||
}
|
||||
|
||||
@TruffleBoundary
|
||||
public final boolean isConst() {
|
||||
return VmModifier.isConst(modifiers);
|
||||
}
|
||||
|
||||
@TruffleBoundary
|
||||
public final boolean isFixed() {
|
||||
return VmModifier.isFixed(modifiers);
|
||||
}
|
||||
|
||||
@TruffleBoundary
|
||||
public final boolean isHidden() {
|
||||
return VmModifier.isHidden(modifiers);
|
||||
}
|
||||
|
||||
@TruffleBoundary
|
||||
public final boolean isExternal() {
|
||||
return VmModifier.isExternal(modifiers);
|
||||
}
|
||||
|
||||
@TruffleBoundary
|
||||
public final boolean isClass() {
|
||||
return VmModifier.isClass(modifiers);
|
||||
}
|
||||
|
||||
@TruffleBoundary
|
||||
public final boolean isTypeAlias() {
|
||||
return VmModifier.isTypeAlias(modifiers);
|
||||
}
|
||||
|
||||
@TruffleBoundary
|
||||
public final boolean isImport() {
|
||||
return VmModifier.isImport(modifiers);
|
||||
}
|
||||
@@ -120,27 +111,22 @@ public abstract class Member {
|
||||
return VmModifier.isGlob(modifiers);
|
||||
}
|
||||
|
||||
@TruffleBoundary
|
||||
public final boolean isAbstract() {
|
||||
return VmModifier.isAbstract(modifiers);
|
||||
}
|
||||
|
||||
@TruffleBoundary
|
||||
public final boolean isType() {
|
||||
return VmModifier.isType(modifiers);
|
||||
}
|
||||
|
||||
@TruffleBoundary
|
||||
public final boolean isLocalOrExternalOrHidden() {
|
||||
return VmModifier.isLocalOrExternalOrHidden(modifiers);
|
||||
}
|
||||
|
||||
@TruffleBoundary
|
||||
public final boolean isConstOrFixed() {
|
||||
return VmModifier.isConstOrFixed(modifiers);
|
||||
}
|
||||
|
||||
@TruffleBoundary
|
||||
public final boolean isLocalOrExternalOrAbstract() {
|
||||
return VmModifier.isLocalOrExternalOrAbstract(modifiers);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user