mirror of
https://github.com/apple/pkl.git
synced 2026-04-20 23:41:27 +02:00
Add optimization for generator bodies that don't introduce new members (#1013)
If a generator object literal doesn't add any object members, we can simply use the parent in its place. Co-authored-by: Kushal Pisavadia <kushi.p@gmail.com>
This commit is contained in:
@@ -73,6 +73,9 @@ public abstract class GeneratorObjectLiteralNode extends ObjectLiteralNode {
|
|||||||
@Specialization(guards = "checkObjectCannotHaveParameters()")
|
@Specialization(guards = "checkObjectCannotHaveParameters()")
|
||||||
protected VmDynamic evalDynamic(VirtualFrame frame, VmDynamic parent) {
|
protected VmDynamic evalDynamic(VirtualFrame frame, VmDynamic parent) {
|
||||||
var data = executeChildren(frame, parent, parent.getLength());
|
var data = executeChildren(frame, parent, parent.getLength());
|
||||||
|
if (data.hasNoMembers()) {
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
var result = new VmDynamic(frame.materialize(), parent, data.members(), data.length());
|
var result = new VmDynamic(frame.materialize(), parent, data.members(), data.length());
|
||||||
return data.storeGeneratorFrames(result);
|
return data.storeGeneratorFrames(result);
|
||||||
}
|
}
|
||||||
@@ -81,6 +84,9 @@ public abstract class GeneratorObjectLiteralNode extends ObjectLiteralNode {
|
|||||||
protected VmTyped evalTyped(VirtualFrame frame, VmTyped parent) {
|
protected VmTyped evalTyped(VirtualFrame frame, VmTyped parent) {
|
||||||
VmUtils.checkIsInstantiable(parent.getVmClass(), getParentNode());
|
VmUtils.checkIsInstantiable(parent.getVmClass(), getParentNode());
|
||||||
var data = executeChildren(frame, parent, 0);
|
var data = executeChildren(frame, parent, 0);
|
||||||
|
if (data.hasNoMembers()) {
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
assert data.hasNoGeneratorFrames();
|
assert data.hasNoGeneratorFrames();
|
||||||
return new VmTyped(frame.materialize(), parent, parent.getVmClass(), data.members());
|
return new VmTyped(frame.materialize(), parent, parent.getVmClass(), data.members());
|
||||||
}
|
}
|
||||||
@@ -88,6 +94,9 @@ public abstract class GeneratorObjectLiteralNode extends ObjectLiteralNode {
|
|||||||
@Specialization(guards = "checkListingCannotHaveParameters()")
|
@Specialization(guards = "checkListingCannotHaveParameters()")
|
||||||
protected VmListing evalListing(VirtualFrame frame, VmListing parent) {
|
protected VmListing evalListing(VirtualFrame frame, VmListing parent) {
|
||||||
var data = executeChildren(frame, parent, parent.getLength());
|
var data = executeChildren(frame, parent, parent.getLength());
|
||||||
|
if (data.hasNoMembers()) {
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
var result = new VmListing(frame.materialize(), parent, data.members(), data.length());
|
var result = new VmListing(frame.materialize(), parent, data.members(), data.length());
|
||||||
return data.storeGeneratorFrames(result);
|
return data.storeGeneratorFrames(result);
|
||||||
}
|
}
|
||||||
@@ -95,6 +104,9 @@ public abstract class GeneratorObjectLiteralNode extends ObjectLiteralNode {
|
|||||||
@Specialization(guards = "checkMappingCannotHaveParameters()")
|
@Specialization(guards = "checkMappingCannotHaveParameters()")
|
||||||
protected VmMapping evalMapping(VirtualFrame frame, VmMapping parent) {
|
protected VmMapping evalMapping(VirtualFrame frame, VmMapping parent) {
|
||||||
var data = executeChildren(frame, parent, 0);
|
var data = executeChildren(frame, parent, 0);
|
||||||
|
if (data.hasNoMembers()) {
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
var result = new VmMapping(frame.materialize(), parent, data.members());
|
var result = new VmMapping(frame.materialize(), parent, data.members());
|
||||||
return data.storeGeneratorFrames(result);
|
return data.storeGeneratorFrames(result);
|
||||||
}
|
}
|
||||||
@@ -118,6 +130,9 @@ public abstract class GeneratorObjectLiteralNode extends ObjectLiteralNode {
|
|||||||
@Specialization(guards = {"parent == getDynamicClass()", "checkObjectCannotHaveParameters()"})
|
@Specialization(guards = {"parent == getDynamicClass()", "checkObjectCannotHaveParameters()"})
|
||||||
protected VmDynamic evalDynamicClass(VirtualFrame frame, VmClass parent) {
|
protected VmDynamic evalDynamicClass(VirtualFrame frame, VmClass parent) {
|
||||||
var data = executeChildren(frame, parent, 0);
|
var data = executeChildren(frame, parent, 0);
|
||||||
|
if (data.hasNoMembers()) {
|
||||||
|
return VmDynamic.empty();
|
||||||
|
}
|
||||||
var result =
|
var result =
|
||||||
new VmDynamic(frame.materialize(), parent.getPrototype(), data.members(), data.length());
|
new VmDynamic(frame.materialize(), parent.getPrototype(), data.members(), data.length());
|
||||||
return data.storeGeneratorFrames(result);
|
return data.storeGeneratorFrames(result);
|
||||||
@@ -126,6 +141,9 @@ public abstract class GeneratorObjectLiteralNode extends ObjectLiteralNode {
|
|||||||
@Specialization(guards = {"parent == getMappingClass()", "checkMappingCannotHaveParameters()"})
|
@Specialization(guards = {"parent == getMappingClass()", "checkMappingCannotHaveParameters()"})
|
||||||
protected VmMapping evalMappingClass(VirtualFrame frame, VmClass parent) {
|
protected VmMapping evalMappingClass(VirtualFrame frame, VmClass parent) {
|
||||||
var data = executeChildren(frame, parent, 0);
|
var data = executeChildren(frame, parent, 0);
|
||||||
|
if (data.hasNoMembers()) {
|
||||||
|
return VmMapping.empty();
|
||||||
|
}
|
||||||
var result = new VmMapping(frame.materialize(), parent.getPrototype(), data.members());
|
var result = new VmMapping(frame.materialize(), parent.getPrototype(), data.members());
|
||||||
return data.storeGeneratorFrames(result);
|
return data.storeGeneratorFrames(result);
|
||||||
}
|
}
|
||||||
@@ -133,6 +151,9 @@ public abstract class GeneratorObjectLiteralNode extends ObjectLiteralNode {
|
|||||||
@Specialization(guards = {"parent == getListingClass()", "checkListingCannotHaveParameters()"})
|
@Specialization(guards = {"parent == getListingClass()", "checkListingCannotHaveParameters()"})
|
||||||
protected VmListing evalListingClass(VirtualFrame frame, VmClass parent) {
|
protected VmListing evalListingClass(VirtualFrame frame, VmClass parent) {
|
||||||
var data = executeChildren(frame, parent, 0);
|
var data = executeChildren(frame, parent, 0);
|
||||||
|
if (data.hasNoMembers()) {
|
||||||
|
return VmListing.empty();
|
||||||
|
}
|
||||||
var result =
|
var result =
|
||||||
new VmListing(frame.materialize(), parent.getPrototype(), data.members(), data.length());
|
new VmListing(frame.materialize(), parent.getPrototype(), data.members(), data.length());
|
||||||
return data.storeGeneratorFrames(result);
|
return data.storeGeneratorFrames(result);
|
||||||
@@ -142,6 +163,9 @@ public abstract class GeneratorObjectLiteralNode extends ObjectLiteralNode {
|
|||||||
protected VmTyped evalTypedObjectClass(VirtualFrame frame, VmClass parent) {
|
protected VmTyped evalTypedObjectClass(VirtualFrame frame, VmClass parent) {
|
||||||
VmUtils.checkIsInstantiable(parent, getParentNode());
|
VmUtils.checkIsInstantiable(parent, getParentNode());
|
||||||
var data = executeChildren(frame, parent, 0);
|
var data = executeChildren(frame, parent, 0);
|
||||||
|
if (data.hasNoMembers()) {
|
||||||
|
return parent.getPrototype();
|
||||||
|
}
|
||||||
assert data.hasNoGeneratorFrames();
|
assert data.hasNoGeneratorFrames();
|
||||||
return new VmTyped(frame.materialize(), parent.getPrototype(), parent, data.members());
|
return new VmTyped(frame.materialize(), parent.getPrototype(), parent, data.members());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,6 +55,10 @@ public final class ObjectData {
|
|||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean hasNoMembers() {
|
||||||
|
return members.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
boolean hasNoGeneratorFrames() {
|
boolean hasNoGeneratorFrames() {
|
||||||
return generatorFrames.isEmpty();
|
return generatorFrames.isEmpty();
|
||||||
}
|
}
|
||||||
|
|||||||
46
pkl-core/src/test/files/LanguageSnippetTests/input/generators/generatorNoMembers.pkl
vendored
Normal file
46
pkl-core/src/test/files/LanguageSnippetTests/input/generators/generatorNoMembers.pkl
vendored
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
// should only result in one trace in the output; generator object literals that don't add any
|
||||||
|
// members should be optimized away.
|
||||||
|
res1 {
|
||||||
|
prop = trace("hello")
|
||||||
|
}
|
||||||
|
|
||||||
|
res2 = (res1) {
|
||||||
|
when (false) {
|
||||||
|
prop2 = 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res3 = (res1) {
|
||||||
|
for (_ in List()) {
|
||||||
|
"hello"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res4 = (res1) {
|
||||||
|
...List()
|
||||||
|
}
|
||||||
|
|
||||||
|
res5 = (res1) {
|
||||||
|
when (true) {
|
||||||
|
} else {
|
||||||
|
prop3 = 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res6 = (Dynamic) {
|
||||||
|
when (true) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
res7 = (Mapping) {
|
||||||
|
when (true) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Person {}
|
||||||
|
|
||||||
|
res8 = (Person) {
|
||||||
|
when (true) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
res9 = (Listing) {
|
||||||
|
when (true) {}
|
||||||
|
}
|
||||||
20
pkl-core/src/test/files/LanguageSnippetTests/output/generators/generatorNoMembers.err
vendored
Normal file
20
pkl-core/src/test/files/LanguageSnippetTests/output/generators/generatorNoMembers.err
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
res1 {
|
||||||
|
prop = "hello"
|
||||||
|
}
|
||||||
|
res2 {
|
||||||
|
prop = "hello"
|
||||||
|
}
|
||||||
|
res3 {
|
||||||
|
prop = "hello"
|
||||||
|
}
|
||||||
|
res4 {
|
||||||
|
prop = "hello"
|
||||||
|
}
|
||||||
|
res5 {
|
||||||
|
prop = "hello"
|
||||||
|
}
|
||||||
|
res6 {}
|
||||||
|
res7 {}
|
||||||
|
res8 {}
|
||||||
|
res9 {}
|
||||||
|
pkl: TRACE: "hello" = "hello" (file:///$snippetsDir/input/generators/generatorNoMembers.pkl)
|
||||||
Reference in New Issue
Block a user