Skip to content

Commit c2287de

Browse files
committed
split ReadAttributeFromObjectNode into ReadAttributeFromObjectNode and ReadAttributeFromDynamicObjectNode
1 parent afebb1a commit c2287de

File tree

6 files changed

+226
-107
lines changed

6 files changed

+226
-107
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PythonObjectNativeWrapperMR.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -680,7 +680,7 @@ Object doTpSubclasses(PythonClass object, @SuppressWarnings("unused") String key
680680
Object doMdDef(PythonObject object, @SuppressWarnings("unused") String key, Object value) {
681681
DynamicObjectNativeWrapper nativeWrapper = ((PythonAbstractObject) object).getNativeWrapper();
682682
assert nativeWrapper != null;
683-
getSetItemNode().execute(nativeWrapper.createNativeMemberStore(object.getDictStableAssumption()), NativeMemberNames.MD_DEF, value);
683+
getSetItemNode().execute(nativeWrapper.createNativeMemberStore(object.getDictUnsetOrSameAsStorageAssumption()), NativeMemberNames.MD_DEF, value);
684684
return value;
685685
}
686686

@@ -701,7 +701,7 @@ Object doTpDict(PythonClass object, @SuppressWarnings("unused") String key, Obje
701701
if (existing != null) {
702702
d.setDictStorage(existing.getDictStorage());
703703
} else {
704-
d.setDictStorage(new DynamicObjectStorage.PythonObjectDictStorage(object.getStorage(), object.getDictStableAssumption()));
704+
d.setDictStorage(new DynamicObjectStorage.PythonObjectDictStorage(object.getStorage(), object.getDictUnsetOrSameAsStorageAssumption()));
705705
}
706706
object.setDict(d);
707707
} else {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/ObjectBuiltins.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,7 @@ Object dict(PythonObject self, @SuppressWarnings("unused") PNone none) {
503503

504504
@Specialization(guards = {"!isBuiltinObjectExact(self)", "!isClass(self)", "!isExactObjectInstance(self)"})
505505
Object dict(PythonObject self, PDict dict) {
506-
self.getDictStableAssumption().invalidate();
506+
self.getDictUnsetOrSameAsStorageAssumption().invalidate();
507507
self.setDict(dict);
508508
return PNone.NONE;
509509
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/PythonObject.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
public class PythonObject extends PythonAbstractObject {
5151
@CompilationFinal private LazyPythonClass pythonClass;
5252
private final Assumption classStable = Truffle.getRuntime().createAssumption("class unchanged");
53-
private final Assumption dictStable = Truffle.getRuntime().createAssumption("dict unchanged from instance attributes");
53+
private final Assumption dictUnsetOrSameAsStorage = Truffle.getRuntime().createAssumption("dict unset or same as instance attributes");
5454
private final DynamicObject storage;
5555
private PHashingCollection dict;
5656

@@ -104,8 +104,8 @@ public final Assumption getClassStableAssumption() {
104104
return classStable;
105105
}
106106

107-
public final Assumption getDictStableAssumption() {
108-
return dictStable;
107+
public final Assumption getDictUnsetOrSameAsStorageAssumption() {
108+
return dictUnsetOrSameAsStorage;
109109
}
110110

111111
public final DynamicObject getStorage() {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
/*
2+
* Copyright (c) 2017, 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.nodes.attributes;
42+
43+
import com.oracle.graal.python.builtins.objects.PNone;
44+
import com.oracle.graal.python.builtins.objects.str.PString;
45+
import com.oracle.graal.python.nodes.PGuards;
46+
import com.oracle.graal.python.nodes.PNodeWithContext;
47+
import com.oracle.graal.python.runtime.PythonOptions;
48+
import com.oracle.truffle.api.Assumption;
49+
import com.oracle.truffle.api.CompilerDirectives;
50+
import com.oracle.truffle.api.dsl.Cached;
51+
import com.oracle.truffle.api.dsl.ImportStatic;
52+
import com.oracle.truffle.api.dsl.Specialization;
53+
import com.oracle.truffle.api.object.DynamicObject;
54+
import com.oracle.truffle.api.object.Location;
55+
import com.oracle.truffle.api.object.Property;
56+
import com.oracle.truffle.api.object.Shape;
57+
58+
@ImportStatic({PGuards.class, PythonOptions.class})
59+
public abstract class ReadAttributeFromDynamicObjectNode extends PNodeWithContext {
60+
public static ReadAttributeFromDynamicObjectNode create() {
61+
return ReadAttributeFromDynamicObjectNodeGen.create();
62+
}
63+
64+
public abstract Object execute(Object object, Object key);
65+
66+
protected static Location getLocationOrNull(Property prop) {
67+
return prop == null ? null : prop.getLocation();
68+
}
69+
70+
protected static boolean isNull(Object value) {
71+
return value == null;
72+
}
73+
74+
protected static Object readFinalValue(DynamicObject object, Location location) {
75+
Object value = location.get(object);
76+
return value == null ? PNone.NO_VALUE : value;
77+
}
78+
79+
/*
80+
* Includes "dynamicObject" as a parameter so that Truffle DSL sees this as a dynamic check.
81+
*/
82+
protected static boolean checkShape(@SuppressWarnings("unused") DynamicObject dynamicObject, DynamicObject cachedObject, Shape cachedShape) {
83+
return cachedObject.getShape() == cachedShape;
84+
}
85+
86+
protected Object attrKey(Object key) {
87+
if (key instanceof PString) {
88+
return ((PString) key).getValue();
89+
} else {
90+
return key;
91+
}
92+
}
93+
94+
private static boolean assertFinal(DynamicObject dynamicObject, Object key, Object cachedValue) {
95+
Object other = dynamicObject.get(key) == null ? PNone.NO_VALUE : dynamicObject.get(key);
96+
return cachedValue == other || cachedValue instanceof Number && other instanceof Number && ((Number) cachedValue).doubleValue() == ((Number) other).doubleValue();
97+
}
98+
99+
@SuppressWarnings("unused")
100+
@Specialization(limit = "1", //
101+
guards = {
102+
"dynamicObject == cachedDynamicObject",
103+
"checkShape(dynamicObject, cachedDynamicObject, cachedShape)",
104+
"key == cachedKey",
105+
"!isNull(loc)",
106+
"loc.isAssumedFinal()",
107+
}, //
108+
assumptions = {
109+
"layoutAssumption",
110+
"finalAssumption"
111+
})
112+
protected Object readDirectFinal(DynamicObject dynamicObject, Object key,
113+
@Cached("dynamicObject") DynamicObject cachedDynamicObject,
114+
@Cached("key") Object cachedKey,
115+
@Cached("attrKey(key)") Object attrKey,
116+
@Cached("dynamicObject.getShape()") Shape cachedShape,
117+
@Cached("cachedShape.getValidAssumption()") Assumption layoutAssumption,
118+
@Cached("getLocationOrNull(cachedShape.getProperty(attrKey))") Location loc,
119+
@Cached("loc.getFinalAssumption()") Assumption finalAssumption,
120+
@Cached("readFinalValue(dynamicObject, loc)") Object cachedValue) {
121+
assert assertFinal(dynamicObject, attrKey, cachedValue);
122+
return cachedValue;
123+
}
124+
125+
@SuppressWarnings("unused")
126+
@Specialization(limit = "getIntOption(getContext(), AttributeAccessInlineCacheMaxDepth)", //
127+
guards = {
128+
"dynamicObject.getShape() == cachedShape",
129+
"key == cachedKey",
130+
"isNull(loc) || !loc.isAssumedFinal()",
131+
}, //
132+
assumptions = {
133+
"layoutAssumption"
134+
})
135+
protected Object readDirect(DynamicObject dynamicObject, Object key,
136+
@Cached("key") Object cachedKey,
137+
@Cached("attrKey(cachedKey)") Object attrKey,
138+
@Cached("dynamicObject.getShape()") Shape cachedShape,
139+
@Cached("cachedShape.getValidAssumption()") Assumption layoutAssumption,
140+
@Cached("getLocationOrNull(cachedShape.getProperty(attrKey))") Location loc) {
141+
if (loc == null) {
142+
return PNone.NO_VALUE;
143+
} else {
144+
return loc.get(dynamicObject);
145+
}
146+
}
147+
148+
@SuppressWarnings("unused")
149+
@Specialization(guards = {
150+
"dynamicObject.getShape() == cachedShape",
151+
"!layoutAssumption.isValid()"
152+
})
153+
protected Object updateShapeAndRead(DynamicObject dynamicObject, Object key,
154+
@Cached("dynamicObject.getShape()") Shape cachedShape,
155+
@Cached("cachedShape.getValidAssumption()") Assumption layoutAssumption,
156+
@Cached("create()") ReadAttributeFromDynamicObjectNode nextNode) {
157+
CompilerDirectives.transferToInterpreter();
158+
dynamicObject.updateShape();
159+
return nextNode.execute(dynamicObject, key);
160+
}
161+
162+
@Specialization(replaces = "readDirect")
163+
protected Object readIndirect(DynamicObject dynamicObject, Object key) {
164+
Object value = dynamicObject.get(attrKey(key));
165+
if (value == null) {
166+
return PNone.NO_VALUE;
167+
} else {
168+
return value;
169+
}
170+
}
171+
}

0 commit comments

Comments
 (0)