|
40 | 40 | */
|
41 | 41 | package com.oracle.graal.python.nodes.frame;
|
42 | 42 |
|
43 |
| -import com.oracle.graal.python.builtins.PythonBuiltinClassType; |
44 | 43 | import com.oracle.graal.python.builtins.objects.cell.PCell;
|
| 44 | +import com.oracle.graal.python.builtins.objects.dict.PDict; |
45 | 45 | 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; |
48 | 48 | 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; |
51 | 49 | import com.oracle.graal.python.runtime.object.PythonObjectFactory;
|
| 50 | +import com.oracle.truffle.api.dsl.Bind; |
52 | 51 | import com.oracle.truffle.api.dsl.Cached;
|
| 52 | +import com.oracle.truffle.api.dsl.Cached.Shared; |
53 | 53 | import com.oracle.truffle.api.dsl.GenerateUncached;
|
54 | 54 | import com.oracle.truffle.api.dsl.NeverDefault;
|
55 | 55 | import com.oracle.truffle.api.dsl.Specialization;
|
| 56 | +import com.oracle.truffle.api.frame.FrameDescriptor; |
56 | 57 | import com.oracle.truffle.api.frame.MaterializedFrame;
|
57 |
| -import com.oracle.truffle.api.frame.VirtualFrame; |
| 58 | +import com.oracle.truffle.api.nodes.ExplodeLoop; |
58 | 59 | import com.oracle.truffle.api.nodes.Node;
|
59 | 60 | import com.oracle.truffle.api.strings.TruffleString;
|
60 | 61 |
|
|
65 | 66 | */
|
66 | 67 | @GenerateUncached
|
67 | 68 | public abstract class GetFrameLocalsNode extends Node {
|
68 |
| - public abstract Object execute(VirtualFrame frame, PFrame pyFrame); |
| 69 | + public abstract Object execute(PFrame pyFrame); |
69 | 70 |
|
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, |
73 | 73 | @Cached PythonObjectFactory factory,
|
74 |
| - @Cached PyObjectSetItem setItem, |
75 |
| - @Cached PyObjectDelItem delItem) { |
76 |
| - // TODO do argcells need special handling? |
| 74 | + @Cached CopyLocalsToDict copyLocalsToDict) { |
77 | 75 | 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(); |
79 | 78 | if (localsDict == null) {
|
80 | 79 | localsDict = factory.createDict();
|
81 | 80 | pyFrame.setLocalsDict(localsDict);
|
82 | 81 | }
|
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); |
101 | 83 | return localsDict;
|
102 | 84 | }
|
103 | 85 |
|
104 |
| - @Specialization(guards = "!hasLocals(pyFrame)") |
| 86 | + @Specialization(guards = "pyFrame.hasCustomLocals()") |
105 | 87 | static Object doCustomLocals(PFrame pyFrame) {
|
106 | 88 | Object localsDict = pyFrame.getLocalsDict();
|
107 | 89 | assert localsDict != null;
|
108 | 90 | return localsDict;
|
109 | 91 | }
|
110 | 92 |
|
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 | + } |
113 | 137 | }
|
114 | 138 |
|
115 | 139 | @NeverDefault
|
|
0 commit comments