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:
translatenix
2024-04-17 14:04:01 -07:00
committed by Daniel Chao
parent 76f1b92039
commit 5de90d5868
4 changed files with 11 additions and 35 deletions

View File

@@ -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]]

View File

@@ -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();
}
}
}

View File

@@ -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.

View File

@@ -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);
}