Skip to content

Commit 7eababa

Browse files
committed
add wrappers for java arrays and maps to truffle, use these for scopes
1 parent 5b43016 commit 7eababa

File tree

4 files changed

+278
-8
lines changed

4 files changed

+278
-8
lines changed

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

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import com.oracle.graal.python.builtins.objects.PNone;
3939
import com.oracle.graal.python.builtins.objects.PythonAbstractObject;
4040
import com.oracle.graal.python.builtins.objects.code.PCode;
41+
import com.oracle.graal.python.builtins.objects.dict.PDict;
4142
import com.oracle.graal.python.builtins.objects.function.PArguments;
4243
import com.oracle.graal.python.builtins.objects.function.PBuiltinFunction;
4344
import com.oracle.graal.python.builtins.objects.function.PFunction;
@@ -62,6 +63,7 @@
6263
import com.oracle.graal.python.runtime.PythonOptions;
6364
import com.oracle.graal.python.runtime.PythonParser.ParserMode;
6465
import com.oracle.graal.python.runtime.exception.PException;
66+
import com.oracle.graal.python.runtime.interop.InteropMap;
6567
import com.oracle.truffle.api.Assumption;
6668
import com.oracle.truffle.api.CallTarget;
6769
import com.oracle.truffle.api.CompilerAsserts;
@@ -338,6 +340,7 @@ protected boolean isVisible(PythonContext context, Object value) {
338340
}
339341

340342
@Override
343+
@TruffleBoundary
341344
protected Iterable<Scope> findLocalScopes(PythonContext context, Node node, Frame frame) {
342345
ArrayList<Scope> scopes = new ArrayList<>();
343346
for (Scope s : super.findLocalScopes(context, node, frame)) {
@@ -346,7 +349,7 @@ protected Iterable<Scope> findLocalScopes(PythonContext context, Node node, Fram
346349
if (frame != null) {
347350
PythonObject globals = PArguments.getGlobalsSafe(frame);
348351
if (globals != null) {
349-
scopes.add(Scope.newBuilder("globals()", globals).build());
352+
scopes.add(Scope.newBuilder("globals()", scopeFromObject(globals)).build());
350353
}
351354
Frame generatorFrame = PArguments.getGeneratorFrameSafe(frame);
352355
if (generatorFrame != null) {
@@ -358,13 +361,21 @@ protected Iterable<Scope> findLocalScopes(PythonContext context, Node node, Fram
358361
return scopes;
359362
}
360363

364+
private static InteropMap scopeFromObject(PythonObject globals) {
365+
if (globals instanceof PDict) {
366+
return InteropMap.fromPDict((PDict) globals);
367+
} else {
368+
return InteropMap.fromPythonObject(globals);
369+
}
370+
}
371+
361372
@Override
362373
protected Iterable<Scope> findTopScopes(PythonContext context) {
363374
ArrayList<Scope> scopes = new ArrayList<>();
364375
if (context.getBuiltins() != null) {
365376
// false during initialization
366-
scopes.add(Scope.newBuilder("__main__", context.getMainModule()).build());
367-
scopes.add(Scope.newBuilder("builtins", context.getBuiltins()).build());
377+
scopes.add(Scope.newBuilder("__main__", scopeFromObject(context.getMainModule())).build());
378+
scopes.add(Scope.newBuilder("builtins", scopeFromObject(context.getBuiltins())).build());
368379
}
369380
return scopes;
370381
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/*
2+
* Copyright (c) 2018, 2018, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* The Universal Permissive License (UPL), Version 1.0
6+
*
7+
* Subject to the condition set forth below, permission is hereby granted to any
8+
* person obtaining a copy of this software, associated documentation and/or
9+
* data (collectively the "Software"), free of charge and under any and all
10+
* copyright rights in the Software, and any and all patent rights owned or
11+
* freely licensable by each licensor hereunder covering either (i) the
12+
* unmodified Software as contributed to or provided by such licensor, or (ii)
13+
* the Larger Works (as defined below), to deal in both
14+
*
15+
* (a) the Software, and
16+
*
17+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
18+
* one is included with the Software each a "Larger Work" to which the Software
19+
* is contributed by such licensors),
20+
*
21+
* without restriction, including without limitation the rights to copy, create
22+
* derivative works of, display, perform, and distribute the Software and make,
23+
* use, sell, offer for sale, import, export, have made, and have sold the
24+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
25+
* either these or other terms.
26+
*
27+
* This license is subject to the following condition:
28+
*
29+
* The above copyright notice and either this complete permission notice or at a
30+
* minimum a reference to the UPL must be included in all copies or substantial
31+
* portions of the Software.
32+
*
33+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39+
* SOFTWARE.
40+
*/
41+
package com.oracle.graal.python.runtime.interop;
42+
43+
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
44+
import com.oracle.truffle.api.interop.ForeignAccess;
45+
import com.oracle.truffle.api.interop.MessageResolution;
46+
import com.oracle.truffle.api.interop.Resolve;
47+
import com.oracle.truffle.api.interop.TruffleObject;
48+
import com.oracle.truffle.api.nodes.Node;
49+
50+
public class InteropArray implements TruffleObject {
51+
52+
private final Object[] array;
53+
54+
InteropArray(Object[] array) {
55+
this.array = array;
56+
}
57+
58+
@Override
59+
public ForeignAccess getForeignAccess() {
60+
return InteropArrayMRForeign.ACCESS;
61+
}
62+
63+
public Object getKeyAt(int pos) {
64+
return array[pos];
65+
}
66+
67+
public int size() {
68+
return array.length;
69+
}
70+
71+
static boolean isInstance(TruffleObject object) {
72+
return object instanceof InteropArray;
73+
}
74+
75+
@MessageResolution(receiverType = InteropArray.class)
76+
static class InteropArrayMR {
77+
78+
@Resolve(message = "READ")
79+
abstract static class Read extends Node {
80+
@TruffleBoundary
81+
public Object access(InteropArray target, Number index) {
82+
return target.getKeyAt(index.intValue());
83+
}
84+
}
85+
86+
@Resolve(message = "HAS_SIZE")
87+
abstract static class HasSize extends Node {
88+
89+
public boolean access(@SuppressWarnings("unused") InteropArray target) {
90+
return true;
91+
}
92+
}
93+
94+
@Resolve(message = "GET_SIZE")
95+
abstract static class GetSize extends Node {
96+
97+
public Object access(InteropArray target) {
98+
return target.size();
99+
}
100+
}
101+
}
102+
103+
}
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
/*
2+
* Copyright (c) 2018, 2018, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* The Universal Permissive License (UPL), Version 1.0
6+
*
7+
* Subject to the condition set forth below, permission is hereby granted to any
8+
* person obtaining a copy of this software, associated documentation and/or
9+
* data (collectively the "Software"), free of charge and under any and all
10+
* copyright rights in the Software, and any and all patent rights owned or
11+
* freely licensable by each licensor hereunder covering either (i) the
12+
* unmodified Software as contributed to or provided by such licensor, or (ii)
13+
* the Larger Works (as defined below), to deal in both
14+
*
15+
* (a) the Software, and
16+
*
17+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
18+
* one is included with the Software each a "Larger Work" to which the Software
19+
* is contributed by such licensors),
20+
*
21+
* without restriction, including without limitation the rights to copy, create
22+
* derivative works of, display, perform, and distribute the Software and make,
23+
* use, sell, offer for sale, import, export, have made, and have sold the
24+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
25+
* either these or other terms.
26+
*
27+
* This license is subject to the following condition:
28+
*
29+
* The above copyright notice and either this complete permission notice or at a
30+
* minimum a reference to the UPL must be included in all copies or substantial
31+
* portions of the Software.
32+
*
33+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39+
* SOFTWARE.
40+
*/
41+
package com.oracle.graal.python.runtime.interop;
42+
43+
import java.util.HashMap;
44+
import java.util.Map;
45+
46+
import com.oracle.graal.python.builtins.objects.common.HashingStorage.DictEntry;
47+
import com.oracle.graal.python.builtins.objects.dict.PDict;
48+
import com.oracle.graal.python.builtins.objects.object.PythonObject;
49+
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
50+
import com.oracle.truffle.api.interop.ForeignAccess;
51+
import com.oracle.truffle.api.interop.KeyInfo;
52+
import com.oracle.truffle.api.interop.MessageResolution;
53+
import com.oracle.truffle.api.interop.Resolve;
54+
import com.oracle.truffle.api.interop.TruffleObject;
55+
import com.oracle.truffle.api.nodes.Node;
56+
57+
/**
58+
* A container class used to store per-node attributes used by the instrumentation framework.
59+
*
60+
*/
61+
public class InteropMap implements TruffleObject {
62+
63+
private final Map<String, Object> data = new HashMap<>();
64+
65+
@Override
66+
public ForeignAccess getForeignAccess() {
67+
return InteropMapMRForeign.ACCESS;
68+
}
69+
70+
@TruffleBoundary
71+
public void addProperty(String name, Object value) {
72+
data.put(name, value);
73+
}
74+
75+
@TruffleBoundary
76+
public int size() {
77+
return data.size();
78+
}
79+
80+
@TruffleBoundary
81+
public Object getProperty(String name) {
82+
assert hasProperty(name);
83+
return data.get(name);
84+
}
85+
86+
@TruffleBoundary
87+
public boolean hasProperty(String name) {
88+
return data.containsKey(name);
89+
}
90+
91+
@TruffleBoundary
92+
public TruffleObject getPropertyNames() {
93+
return new InteropArray(data.keySet().toArray());
94+
}
95+
96+
@TruffleBoundary
97+
public static InteropMap fromPDict(PDict dict) {
98+
InteropMap map = new InteropMap();
99+
for (DictEntry s : dict.getDictStorage().entries()) {
100+
map.addProperty(s.getKey().toString(), s.getValue());
101+
}
102+
return map;
103+
}
104+
105+
@TruffleBoundary
106+
public static InteropMap fromPythonObject(PythonObject globals) {
107+
InteropMap map = new InteropMap();
108+
for (String name : globals.getAttributeNames()) {
109+
map.addProperty(name, globals.getAttribute(name));
110+
}
111+
return map;
112+
}
113+
114+
static boolean isInstance(TruffleObject object) {
115+
return object instanceof InteropMap;
116+
}
117+
118+
@MessageResolution(receiverType = InteropMap.class)
119+
static class InteropMapMR {
120+
121+
@Resolve(message = "READ")
122+
abstract static class Read extends Node {
123+
public Object access(InteropMap target, String key) {
124+
return target.getProperty(key);
125+
}
126+
}
127+
128+
@Resolve(message = "HAS_KEYS")
129+
abstract static class HasKeys extends Node {
130+
131+
public Object access(@SuppressWarnings("unused") Object target) {
132+
return true;
133+
}
134+
}
135+
136+
@Resolve(message = "KEYS")
137+
abstract static class Keys extends Node {
138+
public Object access(InteropMap target) {
139+
return target.getPropertyNames();
140+
}
141+
}
142+
143+
@Resolve(message = "KEY_INFO")
144+
abstract static class KeyInfoMR extends Node {
145+
public Object access(InteropMap target, Object key) {
146+
if (key instanceof String && target.hasProperty((String) key)) {
147+
return KeyInfo.READABLE;
148+
} else {
149+
return 0;
150+
}
151+
}
152+
}
153+
}
154+
155+
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/interop/PythonMessageResolution.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
import static com.oracle.graal.python.nodes.SpecialMethodNames.__GETITEM__;
4747
import static com.oracle.graal.python.nodes.SpecialMethodNames.__SETITEM__;
4848

49-
import java.util.ArrayList;
49+
import java.util.HashSet;
5050

5151
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
5252
import com.oracle.graal.python.builtins.modules.BuiltinFunctions;
@@ -240,8 +240,9 @@ public Object execute(Object obj, boolean includeInternal) {
240240
}
241241
PythonAbstractObject object = (PythonAbstractObject) obj;
242242

243-
ArrayList<String> keys = new ArrayList<>();
244-
for (PythonObject o : getClass.execute(object).getMethodResolutionOrder()) {
243+
HashSet<String> keys = new HashSet<>();
244+
PythonClass klass = getClass.execute(object);
245+
for (PythonObject o : klass.getMethodResolutionOrder()) {
245246
addKeysFromObject(keys, o);
246247
}
247248
if (object instanceof PythonObject) {
@@ -258,7 +259,7 @@ public Object execute(Object obj, boolean includeInternal) {
258259
PList mapKeys = castToList.executeWith(keysNode.executeObject(object));
259260
int len = lenNode.execute(mapKeys);
260261
for (int i = 0; i < len; i++) {
261-
Object key = getItemNode.execute(object, i);
262+
Object key = getItemNode.execute(mapKeys, i);
262263
if (key instanceof String) {
263264
keys.add("[" + (String) key);
264265
} else if (key instanceof PString) {
@@ -271,7 +272,7 @@ public Object execute(Object obj, boolean includeInternal) {
271272
return factory.createTuple(keys.toArray(new String[keys.size()]));
272273
}
273274

274-
private static void addKeysFromObject(ArrayList<String> keys, PythonObject o) {
275+
private static void addKeysFromObject(HashSet<String> keys, PythonObject o) {
275276
for (Object k : o.getStorage().getShape().getKeys()) {
276277
if (k instanceof String) {
277278
keys.add((String) k);

0 commit comments

Comments
 (0)