Optimization: execute const object bodies and typechecks only once (#915)

If the object member is const, it only needs to be executed once, and all children in the prototype chain can use its cached value.

There is a possible other optimization here, not included in this PR: we can avoid adding these values to the child object's cachedMembers.
This commit is contained in:
Daniel Chao
2025-01-29 07:19:55 -08:00
committed by GitHub
parent 90df0662af
commit 3815a0206b
3 changed files with 37 additions and 0 deletions

View File

@@ -254,6 +254,18 @@ public final class VmUtils {
IndirectCallNode callNode) {
final var constantValue = member.getConstantValue();
// const members only need to be executed once on the prototype, and its cached value
// can be re-used for all children in the amends chain.
if (member.isConst() && owner != receiver) {
assert member.isProp();
assert owner.isPrototype();
var result = readMemberOrNull(owner, memberKey, checkType, callNode);
assert result != null;
receiver.setCachedValue(memberKey, result);
return result;
}
if (constantValue != null) {
var result = constantValue;
// for a property, Listing element, or Mapping value, do a type check

View File

@@ -0,0 +1,13 @@
// should result in only one trace per property
class MyClass {
// property body only gets executed once
const prop = trace("hello")
// typecheck only happens once
const prop2: Int(let (_ = trace("hello again")) true) = 1
res: Int
}
a = new MyClass { res = 1 }
b = (a) { res = 2 }

View File

@@ -0,0 +1,12 @@
a {
prop = "hello"
prop2 = 1
res = 1
}
b {
prop = "hello"
prop2 = 1
res = 2
}
pkl: TRACE: "hello" = "hello" (file:///$snippetsDir/input/basic/constModifier5.pkl)
pkl: TRACE: "hello again" = "hello again" (file:///$snippetsDir/input/basic/constModifier5.pkl)