Skip to content

Commit e745d01

Browse files
committed
[GR-14802] Improve function object creation for fast path.
PullRequest: graalpython/482
2 parents 83a6900 + c4221e8 commit e745d01

File tree

16 files changed

+125
-87
lines changed

16 files changed

+125
-87
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cell/PCell.java

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -40,22 +40,17 @@
4040
*/
4141
package com.oracle.graal.python.builtins.objects.cell;
4242

43-
import java.util.ArrayList;
44-
import java.util.List;
45-
46-
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
47-
import com.oracle.graal.python.builtins.objects.object.PythonBuiltinObject;
43+
import com.oracle.graal.python.builtins.objects.PythonAbstractObject;
4844
import com.oracle.truffle.api.Assumption;
4945
import com.oracle.truffle.api.CompilerAsserts;
50-
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
51-
import com.oracle.truffle.api.Truffle;
46+
import com.oracle.truffle.api.CompilerDirectives;
5247

53-
public class PCell extends PythonBuiltinObject {
54-
private final Assumption effectivelyFinal = Truffle.getRuntime().createAssumption("cell is effectively final");
48+
public final class PCell extends PythonAbstractObject {
49+
private final Assumption effectivelyFinal;
5550
private Object ref;
5651

57-
public PCell() {
58-
super(PythonBuiltinClassType.PCell);
52+
public PCell(Assumption effectivelyFinalAssumption) {
53+
this.effectivelyFinal = effectivelyFinalAssumption;
5954
}
6055

6156
public Object getRef() {
@@ -79,14 +74,6 @@ public Assumption isEffectivelyFinalAssumption() {
7974
return effectivelyFinal;
8075
}
8176

82-
@Override
83-
@TruffleBoundary
84-
public List<String> getAttributeNames() {
85-
ArrayList<String> arrayList = new ArrayList<>();
86-
arrayList.add("cell_contents");
87-
return arrayList;
88-
}
89-
9077
@Override
9178
public String toString() {
9279
CompilerAsserts.neverPartOfCompilation();
@@ -95,4 +82,10 @@ public String toString() {
9582
}
9683
return String.format("<cell at %s: %s object at %s>", hashCode(), ref.getClass().getSimpleName(), ref.hashCode());
9784
}
85+
86+
@Override
87+
public int compareTo(Object o) {
88+
CompilerDirectives.transferToInterpreter();
89+
throw new UnsupportedOperationException();
90+
}
9891
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/CodeNodes.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ public PCode execute(LazyPythonClass cls, int argcount, int kwonlyargcount,
115115
Object ident = freevars[i];
116116
FrameSlot slot = frameDescriptor.addFrameSlot(ident);
117117
frameDescriptor.setFrameSlotKind(slot, FrameSlotKind.Object);
118-
frame.setObject(slot, new PCell());
118+
frame.setObject(slot, new PCell(Truffle.getRuntime().createAssumption("cell is effectively final")));
119119
}
120120
}
121121
rootNode = (RootNode) core.getParser().parse(ParserMode.File, core, Source.newBuilder(PythonLanguage.ID, new String(codestring), name).build(), frame);

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PFunction.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ public class PFunction extends PythonObject {
5050
private static final Object[] EMPTY_DEFAULTS = new Object[0];
5151
private final String name;
5252
private final String enclosingClassName;
53-
private final Assumption codeStableAssumption = Truffle.getRuntime().createAssumption();
54-
private final Assumption defaultsStableAssumption = Truffle.getRuntime().createAssumption();
53+
private final Assumption codeStableAssumption;
54+
private final Assumption defaultsStableAssumption;
5555
private final PythonObject globals;
5656
private final PCell[] closure;
5757
private final boolean isStatic;
@@ -65,11 +65,11 @@ public PFunction(LazyPythonClass clazz, String name, String enclosingClassName,
6565

6666
public PFunction(LazyPythonClass clazz, String name, String enclosingClassName, RootCallTarget callTarget, PythonObject globals, Object[] defaultValues, PKeyword[] kwDefaultValues,
6767
PCell[] closure) {
68-
this(clazz, name, enclosingClassName, callTarget, globals, defaultValues, kwDefaultValues, closure, null);
68+
this(clazz, name, enclosingClassName, callTarget, globals, defaultValues, kwDefaultValues, closure, null, Truffle.getRuntime().createAssumption(), Truffle.getRuntime().createAssumption());
6969
}
7070

7171
public PFunction(LazyPythonClass clazz, String name, String enclosingClassName, RootCallTarget callTarget, PythonObject globals, Object[] defaultValues, PKeyword[] kwDefaultValues,
72-
PCell[] closure, WriteAttributeToDynamicObjectNode writeAttrNode) {
72+
PCell[] closure, WriteAttributeToDynamicObjectNode writeAttrNode, Assumption codeStableAssumption, Assumption defaultsStableAssumption) {
7373
super(clazz);
7474
this.name = name;
7575
this.code = new PCode(PythonBuiltinClassType.PCode, callTarget);
@@ -79,6 +79,8 @@ public PFunction(LazyPythonClass clazz, String name, String enclosingClassName,
7979
this.defaultValues = defaultValues == null ? EMPTY_DEFAULTS : defaultValues;
8080
this.kwDefaultValues = kwDefaultValues == null ? PKeyword.EMPTY_KEYWORDS : kwDefaultValues;
8181
this.closure = closure;
82+
this.codeStableAssumption = codeStableAssumption;
83+
this.defaultsStableAssumption = defaultsStableAssumption;
8284
addDefaultConstants(writeAttrNode, getStorage(), name, enclosingClassName);
8385
}
8486

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/generator/PGenerator.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import com.oracle.graal.python.builtins.objects.object.PythonBuiltinObject;
3232
import com.oracle.graal.python.builtins.objects.type.LazyPythonClass;
3333
import com.oracle.graal.python.parser.ExecutionCellSlots;
34+
import com.oracle.truffle.api.Assumption;
3435
import com.oracle.truffle.api.CompilerDirectives;
3536
import com.oracle.truffle.api.RootCallTarget;
3637
import com.oracle.truffle.api.Truffle;
@@ -61,6 +62,7 @@ public static PGenerator create(LazyPythonClass clazz, String name, RootCallTarg
6162
// set generator closure to the generator frame locals
6263
FrameSlot[] freeVarSlots = cellSlots.getFreeVarSlots();
6364
FrameSlot[] cellVarSlots = cellSlots.getCellVarSlots();
65+
Assumption[] cellVarAssumptions = cellSlots.getCellVarAssumptions();
6466

6567
if (closure != null) {
6668
assert closure.length == freeVarSlots.length : "generator creation: the closure must have the same length as the free var slots array";
@@ -72,8 +74,8 @@ public static PGenerator create(LazyPythonClass clazz, String name, RootCallTarg
7274
}
7375
// initialize own cell vars to new cells (these cells will be used by nested functions to
7476
// create their own closures)
75-
for (FrameSlot frameSlot : cellVarSlots) {
76-
generatorFrame.setObject(frameSlot, new PCell());
77+
for (int i = 0; i < cellVarSlots.length; i++) {
78+
generatorFrame.setObject(cellVarSlots[i], new PCell(cellVarAssumptions[i]));
7779
}
7880
return new PGenerator(clazz, name, callTarget, frameDescriptor, arguments, closure);
7981
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PClosureFunctionRootNode.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,18 +42,21 @@
4242

4343
import com.oracle.graal.python.builtins.objects.function.Signature;
4444
import com.oracle.graal.python.parser.ExecutionCellSlots;
45+
import com.oracle.truffle.api.Assumption;
4546
import com.oracle.truffle.api.CompilerDirectives;
4647
import com.oracle.truffle.api.TruffleLanguage;
4748
import com.oracle.truffle.api.frame.FrameDescriptor;
4849
import com.oracle.truffle.api.frame.FrameSlot;
4950

5051
public abstract class PClosureFunctionRootNode extends PClosureRootNode {
5152
@CompilerDirectives.CompilationFinal(dimensions = 1) protected final FrameSlot[] cellVarSlots;
53+
@CompilerDirectives.CompilationFinal(dimensions = 1) protected final Assumption[] cellEffectivelyFinalAssumptions;
5254
private final Signature signature;
5355

5456
protected PClosureFunctionRootNode(TruffleLanguage<?> language, FrameDescriptor frameDescriptor, ExecutionCellSlots executionCellSlots, Signature signature) {
5557
super(language, frameDescriptor, executionCellSlots.getFreeVarSlots());
5658
this.cellVarSlots = executionCellSlots.getCellVarSlots();
59+
this.cellEffectivelyFinalAssumptions = executionCellSlots.getCellVarAssumptions();
5760
this.signature = signature;
5861
}
5962

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/cell/CellSupplier.java

Lines changed: 0 additions & 35 deletions
This file was deleted.

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/cell/WriteCellVarNode.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2018, Oracle and/or its affiliates.
2+
* Copyright (c) 2017, 2019, Oracle and/or its affiliates.
33
* Copyright (c) 2013, Regents of the University of California
44
*
55
* All rights reserved.
@@ -27,6 +27,7 @@
2727

2828
import com.oracle.graal.python.builtins.objects.cell.PCell;
2929
import com.oracle.graal.python.nodes.expression.ExpressionNode;
30+
import com.oracle.graal.python.nodes.function.FunctionRootNode;
3031
import com.oracle.graal.python.nodes.statement.StatementNode;
3132
import com.oracle.truffle.api.dsl.Specialization;
3233
import com.oracle.truffle.api.frame.FrameSlot;
@@ -36,10 +37,10 @@
3637
@NodeInfo(shortName = "write_cellvar")
3738
public abstract class WriteCellVarNode extends StatementNode {
3839
private int cellIndex = -1;
39-
private final CellSupplier cellSupplier;
40+
private final FunctionRootNode cellSupplier;
4041
@Child private ExpressionNode readNode;
4142

42-
WriteCellVarNode(ExpressionNode readNode, CellSupplier cellSupplier, String identifier) {
43+
WriteCellVarNode(ExpressionNode readNode, FunctionRootNode cellSupplier, String identifier) {
4344
this.readNode = readNode;
4445
this.cellSupplier = cellSupplier;
4546

@@ -53,7 +54,7 @@ public abstract class WriteCellVarNode extends StatementNode {
5354
}
5455
}
5556

56-
public static WriteCellVarNode create(ExpressionNode readNode, CellSupplier cellSupplier, String identifier) {
57+
public static WriteCellVarNode create(ExpressionNode readNode, FunctionRootNode cellSupplier, String identifier) {
5758
return WriteCellVarNodeGen.create(readNode, cellSupplier, identifier);
5859
}
5960

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/cell/WriteLocalCellNode.java

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,14 @@
3333
import com.oracle.graal.python.nodes.frame.WriteIdentifierNode;
3434
import com.oracle.graal.python.nodes.statement.StatementNode;
3535
import com.oracle.truffle.api.CompilerDirectives;
36+
import com.oracle.truffle.api.dsl.Cached;
3637
import com.oracle.truffle.api.dsl.NodeChild;
3738
import com.oracle.truffle.api.dsl.Specialization;
3839
import com.oracle.truffle.api.frame.FrameSlot;
3940
import com.oracle.truffle.api.frame.VirtualFrame;
41+
import com.oracle.truffle.api.nodes.Node;
4042
import com.oracle.truffle.api.nodes.NodeInfo;
43+
import com.oracle.truffle.api.profiles.ConditionProfile;
4144

4245
@NodeInfo(shortName = "write_cell")
4346
@NodeChild(value = "rhs", type = ExpressionNode.class)
@@ -63,15 +66,12 @@ public void doWrite(VirtualFrame frame, Object value) {
6366
public abstract void executeWithValue(VirtualFrame frame, Object value);
6467

6568
@Specialization
66-
void writeObject(VirtualFrame frame, Object value) {
69+
void writeObject(VirtualFrame frame, Object value,
70+
@Cached WriteToCellNode writeToCellNode,
71+
@Cached("createBinaryProfile()") ConditionProfile profile) {
6772
Object localValue = readLocal.execute(frame);
68-
if (localValue instanceof PCell) {
69-
PCell cell = (PCell) localValue;
70-
if (value == NO_VALUE) {
71-
cell.clearRef();
72-
} else {
73-
cell.setRef(value);
74-
}
73+
if (profile.profile(localValue instanceof PCell)) {
74+
writeToCellNode.execute((PCell) localValue, value);
7575
return;
7676
}
7777
CompilerDirectives.transferToInterpreter();
@@ -82,4 +82,24 @@ void writeObject(VirtualFrame frame, Object value) {
8282
public Object getIdentifier() {
8383
return frameSlot.getIdentifier();
8484
}
85+
86+
abstract static class WriteToCellNode extends Node {
87+
88+
public abstract void execute(PCell cell, Object value);
89+
90+
@Specialization(guards = "cell == cachedCell", limit = "1")
91+
void doWriteCached(@SuppressWarnings("unused") PCell cell, Object value,
92+
@Cached("cell") PCell cachedCell) {
93+
doWriteGeneric(cachedCell, value);
94+
}
95+
96+
@Specialization(replaces = "doWriteCached")
97+
void doWriteGeneric(PCell cell, Object value) {
98+
if (value == NO_VALUE) {
99+
cell.clearRef();
100+
} else {
101+
cell.setRef(value);
102+
}
103+
}
104+
}
85105
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/function/FunctionDefinitionNode.java

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,10 @@
3838
import com.oracle.graal.python.parser.ExecutionCellSlots;
3939
import com.oracle.graal.python.runtime.PythonContext;
4040
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
41+
import com.oracle.truffle.api.Assumption;
42+
import com.oracle.truffle.api.CompilerDirectives;
4143
import com.oracle.truffle.api.RootCallTarget;
44+
import com.oracle.truffle.api.Truffle;
4245
import com.oracle.truffle.api.TruffleLanguage.ContextReference;
4346
import com.oracle.truffle.api.frame.VirtualFrame;
4447
import com.oracle.truffle.api.nodes.ExplodeLoop;
@@ -57,6 +60,9 @@ public class FunctionDefinitionNode extends ExpressionDefinitionNode {
5760
@Child private WriteAttributeToDynamicObjectNode writeNameNode = WriteAttributeToDynamicObjectNode.create();
5861
@Child private PythonObjectFactory factory = PythonObjectFactory.create();
5962

63+
private final Assumption sharedCodeStableAssumption = Truffle.getRuntime().createAssumption("shared code stable assumption");
64+
private final Assumption sharedDefaultsStableAssumption = Truffle.getRuntime().createAssumption("shared defaults stable assumption");
65+
6066
public FunctionDefinitionNode(String functionName, String enclosingClassName, ExpressionNode doc, ExpressionNode[] defaults, KwDefaultExpressionNode[] kwDefaults,
6167
RootCallTarget callTarget,
6268
DefinitionCellSlots definitionCellSlots, ExecutionCellSlots executionCellSlots) {
@@ -94,7 +100,26 @@ public Object execute(VirtualFrame frame) {
94100
Object[] defaultValues = computeDefaultValues(frame);
95101
PKeyword[] kwDefaultValues = computeKwDefaultValues(frame);
96102
PCell[] closure = getClosureFromGeneratorOrFunctionLocals(frame);
97-
return withDocString(frame, factory().createFunction(functionName, enclosingClassName, callTarget, PArguments.getGlobals(frame), defaultValues, kwDefaultValues, closure, writeNameNode));
103+
Assumption codeStableAssumption;
104+
Assumption defaultsStableAssumption;
105+
if (CompilerDirectives.inCompiledCode()) {
106+
codeStableAssumption = getSharedCodeStableAssumption();
107+
defaultsStableAssumption = getSharedDefaultsStableAssumption();
108+
} else {
109+
codeStableAssumption = Truffle.getRuntime().createAssumption();
110+
defaultsStableAssumption = Truffle.getRuntime().createAssumption();
111+
}
112+
return withDocString(frame, factory().createFunction(functionName, enclosingClassName, callTarget, PArguments.getGlobals(frame), defaultValues, kwDefaultValues, closure, writeNameNode,
113+
codeStableAssumption, defaultsStableAssumption));
114+
115+
}
116+
117+
private Assumption getSharedDefaultsStableAssumption() {
118+
return sharedDefaultsStableAssumption;
119+
}
120+
121+
private Assumption getSharedCodeStableAssumption() {
122+
return sharedCodeStableAssumption;
98123
}
99124

100125
@ExplodeLoop

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/function/FunctionRootNode.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
import com.oracle.graal.python.builtins.objects.function.PArguments;
3131
import com.oracle.graal.python.builtins.objects.function.Signature;
3232
import com.oracle.graal.python.nodes.PClosureFunctionRootNode;
33-
import com.oracle.graal.python.nodes.cell.CellSupplier;
3433
import com.oracle.graal.python.nodes.expression.ExpressionNode;
3534
import com.oracle.graal.python.parser.ExecutionCellSlots;
3635
import com.oracle.graal.python.runtime.PythonContext;
@@ -50,7 +49,7 @@
5049
/**
5150
* RootNode of a Python Function body. It is invoked by a CallTarget.
5251
*/
53-
public class FunctionRootNode extends PClosureFunctionRootNode implements CellSupplier {
52+
public class FunctionRootNode extends PClosureFunctionRootNode {
5453
private final ContextReference<PythonContext> contextRef;
5554
private final PCell[] cells;
5655
private final ExecutionCellSlots executionCellSlots;
@@ -88,12 +87,10 @@ public String getName() {
8887
return functionName;
8988
}
9089

91-
@Override
9290
public PCell[] getCells() {
9391
return cells;
9492
}
9593

96-
@Override
9794
public FrameSlot[] getCellVarSlots() {
9895
return cellVarSlots;
9996
}
@@ -114,7 +111,7 @@ private void initializeCellVars(Frame frame) {
114111
cell = (PCell) FrameUtil.getObjectSafe(frame, frameSlot);
115112
}
116113
if (cell == null) {
117-
cell = new PCell();
114+
cell = new PCell(cellEffectivelyFinalAssumptions[i]);
118115
}
119116

120117
// store the cell as a local var

0 commit comments

Comments
 (0)