Skip to content

Commit 0927888

Browse files
committed
Optimize GetFrameLocalsNode
1 parent 0f79c70 commit 0927888

File tree

7 files changed

+73
-41
lines changed

7 files changed

+73
-41
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -597,7 +597,7 @@ public Object execute(VirtualFrame frame) {
597597
Object[] arguments = PArguments.create();
598598
// escape?
599599
PFrame pFrame = materializeFrameNode.execute(this, false, true, frame);
600-
Object locals = getFrameLocalsNode.execute(frame, pFrame);
600+
Object locals = getFrameLocalsNode.execute(pFrame);
601601
PArguments.setSpecialArgument(arguments, locals);
602602
PArguments.setGlobals(arguments, PArguments.getGlobals(frame));
603603
boolean wasAcquired = gilNode.acquire();

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -861,8 +861,8 @@ private static void inheritGlobals(PFrame callerFrame, Object[] args) {
861861
PArguments.setGlobals(args, callerFrame.getGlobals());
862862
}
863863

864-
private static void inheritLocals(VirtualFrame frame, PFrame callerFrame, Object[] args, GetFrameLocalsNode getFrameLocalsNode) {
865-
Object callerLocals = getFrameLocalsNode.execute(frame, callerFrame);
864+
private static void inheritLocals(PFrame callerFrame, Object[] args, GetFrameLocalsNode getFrameLocalsNode) {
865+
Object callerLocals = getFrameLocalsNode.execute(callerFrame);
866866
setCustomLocals(args, callerLocals);
867867
}
868868

@@ -895,7 +895,7 @@ Object execInheritGlobalsInheritLocals(VirtualFrame frame, Object source, @Suppr
895895
PFrame callerFrame = readCallerFrameNode.executeWith(frame, 0);
896896
Object[] args = PArguments.create();
897897
inheritGlobals(callerFrame, args);
898-
inheritLocals(frame, callerFrame, args, getFrameLocalsNode);
898+
inheritLocals(callerFrame, args, getFrameLocalsNode);
899899

900900
return invokeNode.execute(frame, getCt.execute(code), args);
901901
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/frame/FrameBuiltins.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ Object getUpdating(VirtualFrame frame, PFrame self,
232232
PFrame pyFrame = materializeNode.execute(false, true, frame);
233233
assert pyFrame == self;
234234
}
235-
return getFrameLocalsNode.execute(frame, self);
235+
return getFrameLocalsNode.execute(self);
236236
}
237237
}
238238

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/frame/PFrame.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,10 @@ public Object getLocalsDict() {
191191
return localsDict;
192192
}
193193

194+
public boolean hasCustomLocals() {
195+
return locals == null;
196+
}
197+
194198
public void setLocalsDict(Object dict) {
195199
localsDict = dict;
196200
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/lib/PyDictSetItem.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ public static void executeUncached(PDict dict, Object key, Object item) {
6565
getUncached().execute(null, dict, key, item);
6666
}
6767

68+
public final void execute(PDict dict, TruffleString key, Object item) {
69+
execute(null, dict, key, item);
70+
}
71+
6872
public abstract void execute(Frame frame, PDict dict, Object key, Object item);
6973

7074
// We never need a frame for setting string keys

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/lib/PyEvalGetLocals.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,6 @@ static Object getLocals(VirtualFrame frame,
5656
@Cached ReadCallerFrameNode readCallerFrameNode,
5757
@Cached GetFrameLocalsNode getFrameLocalsNode) {
5858
PFrame callerFrame = readCallerFrameNode.executeWith(frame, 0);
59-
return getFrameLocalsNode.execute(frame, callerFrame);
59+
return getFrameLocalsNode.execute(callerFrame);
6060
}
6161
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/GetFrameLocalsNode.java

Lines changed: 59 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -40,21 +40,22 @@
4040
*/
4141
package com.oracle.graal.python.nodes.frame;
4242

43-
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
4443
import com.oracle.graal.python.builtins.objects.cell.PCell;
44+
import com.oracle.graal.python.builtins.objects.dict.PDict;
4545
import com.oracle.graal.python.builtins.objects.frame.PFrame;
46-
import com.oracle.graal.python.lib.PyObjectDelItem;
47-
import com.oracle.graal.python.lib.PyObjectSetItem;
46+
import com.oracle.graal.python.lib.PyDictDelItem;
47+
import com.oracle.graal.python.lib.PyDictSetItem;
4848
import com.oracle.graal.python.nodes.bytecode.FrameInfo;
49-
import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile;
50-
import com.oracle.graal.python.runtime.exception.PException;
5149
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
50+
import com.oracle.truffle.api.dsl.Bind;
5251
import com.oracle.truffle.api.dsl.Cached;
52+
import com.oracle.truffle.api.dsl.Cached.Shared;
5353
import com.oracle.truffle.api.dsl.GenerateUncached;
5454
import com.oracle.truffle.api.dsl.NeverDefault;
5555
import com.oracle.truffle.api.dsl.Specialization;
56+
import com.oracle.truffle.api.frame.FrameDescriptor;
5657
import com.oracle.truffle.api.frame.MaterializedFrame;
57-
import com.oracle.truffle.api.frame.VirtualFrame;
58+
import com.oracle.truffle.api.nodes.ExplodeLoop;
5859
import com.oracle.truffle.api.nodes.Node;
5960
import com.oracle.truffle.api.strings.TruffleString;
6061

@@ -65,51 +66,74 @@
6566
*/
6667
@GenerateUncached
6768
public abstract class GetFrameLocalsNode extends Node {
68-
public abstract Object execute(VirtualFrame frame, PFrame pyFrame);
69+
public abstract Object execute(PFrame pyFrame);
6970

70-
// TODO cache fd, explode
71-
@Specialization(guards = "hasLocals(pyFrame)")
72-
static Object doLoop(VirtualFrame frame, PFrame pyFrame,
71+
@Specialization(guards = "!pyFrame.hasCustomLocals()")
72+
static Object doLoop(PFrame pyFrame,
7373
@Cached PythonObjectFactory factory,
74-
@Cached PyObjectSetItem setItem,
75-
@Cached PyObjectDelItem delItem) {
76-
// TODO do argcells need special handling?
74+
@Cached CopyLocalsToDict copyLocalsToDict) {
7775
MaterializedFrame locals = pyFrame.getLocals();
78-
Object localsDict = pyFrame.getLocalsDict();
76+
// It doesn't have custom locals, so it has to be a builtin dict or null
77+
PDict localsDict = (PDict) pyFrame.getLocalsDict();
7978
if (localsDict == null) {
8079
localsDict = factory.createDict();
8180
pyFrame.setLocalsDict(localsDict);
8281
}
83-
FrameInfo frameInfo = (FrameInfo) locals.getFrameDescriptor().getInfo();
84-
for (int i = 0; i < frameInfo.getVariableCount(); i++) {
85-
TruffleString name = frameInfo.getVariableName(i);
86-
Object value = locals.getValue(i);
87-
if (value instanceof PCell) {
88-
value = ((PCell) value).getRef();
89-
}
90-
if (value == null) {
91-
try {
92-
delItem.execute(frame, localsDict, name);
93-
} catch (PException e) {
94-
// TODO
95-
e.expect(PythonBuiltinClassType.KeyError, IsBuiltinClassProfile.getUncached());
96-
}
97-
} else {
98-
setItem.execute(frame, localsDict, name, value);
99-
}
100-
}
82+
copyLocalsToDict.execute(locals, localsDict);
10183
return localsDict;
10284
}
10385

104-
@Specialization(guards = "!hasLocals(pyFrame)")
86+
@Specialization(guards = "pyFrame.hasCustomLocals()")
10587
static Object doCustomLocals(PFrame pyFrame) {
10688
Object localsDict = pyFrame.getLocalsDict();
10789
assert localsDict != null;
10890
return localsDict;
10991
}
11092

111-
protected static boolean hasLocals(PFrame pyFrame) {
112-
return pyFrame.getLocals() != null;
93+
@GenerateUncached
94+
abstract static class CopyLocalsToDict extends Node {
95+
abstract void execute(MaterializedFrame locals, PDict dict);
96+
97+
@Specialization(guards = {"cachedFd == locals.getFrameDescriptor()", "count < 32"}, limit = "1")
98+
@ExplodeLoop
99+
void doCachedFd(MaterializedFrame locals, PDict dict,
100+
@SuppressWarnings("unused") @Cached("locals.getFrameDescriptor()") FrameDescriptor cachedFd,
101+
@Bind("getInfo(cachedFd)") FrameInfo info,
102+
@Bind("info.getVariableCount()") int count,
103+
@Shared("setItem") @Cached PyDictSetItem setItem,
104+
@Shared("delItem") @Cached PyDictDelItem delItem) {
105+
for (int i = 0; i < count; i++) {
106+
copyItem(locals, info, dict, setItem, delItem, i);
107+
}
108+
}
109+
110+
@Specialization(replaces = "doCachedFd")
111+
void doGeneric(MaterializedFrame locals, PDict dict,
112+
@Shared("setItem") @Cached PyDictSetItem setItem,
113+
@Shared("delItem") @Cached PyDictDelItem delItem) {
114+
FrameInfo info = getInfo(locals.getFrameDescriptor());
115+
int count = info.getVariableCount();
116+
for (int i = 0; i < count; i++) {
117+
copyItem(locals, info, dict, setItem, delItem, i);
118+
}
119+
}
120+
121+
private static void copyItem(MaterializedFrame locals, FrameInfo info, PDict dict, PyDictSetItem setItem, PyDictDelItem delItem, int i) {
122+
TruffleString name = info.getVariableName(i);
123+
Object value = locals.getValue(i);
124+
if (value instanceof PCell) {
125+
value = ((PCell) value).getRef();
126+
}
127+
if (value == null) {
128+
delItem.execute(dict, name);
129+
} else {
130+
setItem.execute(dict, name, value);
131+
}
132+
}
133+
134+
protected static FrameInfo getInfo(FrameDescriptor fd) {
135+
return (FrameInfo) fd.getInfo();
136+
}
113137
}
114138

115139
@NeverDefault

0 commit comments

Comments
 (0)