Skip to content

Commit fcd7379

Browse files
committed
use assumption to invalidate constancy of super object fields
1 parent d1151fc commit fcd7379

File tree

2 files changed

+95
-22
lines changed

2 files changed

+95
-22
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/superobject/SuperBuiltins.java

Lines changed: 84 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@
5252
import com.oracle.graal.python.builtins.objects.function.PArguments;
5353
import com.oracle.graal.python.builtins.objects.function.PKeyword;
5454
import com.oracle.graal.python.builtins.objects.str.PString;
55+
import com.oracle.graal.python.builtins.objects.superobject.SuperBuiltinsFactory.GetObjectNodeGen;
56+
import com.oracle.graal.python.builtins.objects.superobject.SuperBuiltinsFactory.GetObjectTypeNodeGen;
57+
import com.oracle.graal.python.builtins.objects.superobject.SuperBuiltinsFactory.GetTypeNodeGen;
5558
import com.oracle.graal.python.builtins.objects.superobject.SuperBuiltinsFactory.SuperInitNodeFactory;
5659
import com.oracle.graal.python.builtins.objects.type.PythonClass;
5760
import com.oracle.graal.python.nodes.SpecialAttributeNames;
@@ -84,6 +87,7 @@
8487
import com.oracle.truffle.api.frame.FrameSlot;
8588
import com.oracle.truffle.api.frame.FrameSlotTypeException;
8689
import com.oracle.truffle.api.frame.VirtualFrame;
90+
import com.oracle.truffle.api.nodes.Node;
8791
import com.oracle.truffle.api.profiles.ConditionProfile;
8892

8993
@CoreFunctions(extendClasses = PythonBuiltinClassType.Super)
@@ -93,6 +97,54 @@ protected List<? extends NodeFactory<? extends PythonBuiltinBaseNode>> getNodeFa
9397
return SuperBuiltinsFactory.getFactories();
9498
}
9599

100+
abstract static class GetTypeNode extends Node {
101+
abstract Object execute(SuperObject self);
102+
103+
@Specialization(guards = "self == cachedSelf", assumptions = "cachedSelf.getNeverReinitializedAssumption()", limit = "1")
104+
Object cached(@SuppressWarnings("unused") SuperObject self,
105+
@SuppressWarnings("unused") @Cached("self") SuperObject cachedSelf,
106+
@Cached("self.getType()") Object type) {
107+
return type;
108+
}
109+
110+
@Specialization(replaces = "cached")
111+
Object uncached(SuperObject self) {
112+
return self.getType();
113+
}
114+
}
115+
116+
abstract static class GetObjectTypeNode extends Node {
117+
abstract PythonClass execute(SuperObject self);
118+
119+
@Specialization(guards = "self == cachedSelf", assumptions = "cachedSelf.getNeverReinitializedAssumption()", limit = "1")
120+
PythonClass cached(@SuppressWarnings("unused") SuperObject self,
121+
@SuppressWarnings("unused") @Cached("self") SuperObject cachedSelf,
122+
@Cached("self.getObjectType()") PythonClass type) {
123+
return type;
124+
}
125+
126+
@Specialization(replaces = "cached")
127+
PythonClass uncached(SuperObject self) {
128+
return self.getObjectType();
129+
}
130+
}
131+
132+
abstract static class GetObjectNode extends Node {
133+
abstract Object execute(SuperObject self);
134+
135+
@Specialization(guards = "self == cachedSelf", assumptions = "cachedSelf.getNeverReinitializedAssumption()", limit = "1")
136+
Object cached(@SuppressWarnings("unused") SuperObject self,
137+
@SuppressWarnings("unused") @Cached("self") SuperObject cachedSelf,
138+
@Cached("self.getObject()") Object object) {
139+
return object;
140+
}
141+
142+
@Specialization(replaces = "cached")
143+
Object uncached(SuperObject self) {
144+
return self.getObject();
145+
}
146+
}
147+
96148
@Builtin(name = SpecialMethodNames.__INIT__, minNumOfPositionalArgs = 1, takesVarArgs = true, takesVarKeywordArgs = true, alwaysNeedsCallerFrame = true)
97149
@GenerateNodeFactory
98150
public abstract static class SuperInitNode extends PythonVarargsBuiltinNode {
@@ -307,20 +359,23 @@ private PythonClass supercheck(Object cls, Object object) {
307359
@Builtin(name = SpecialMethodNames.__GET__, fixedNumOfPositionalArgs = 2, keywordArguments = {"type"})
308360
@GenerateNodeFactory
309361
public abstract static class GetNode extends PythonTernaryBuiltinNode {
362+
@Child GetObjectNode getObject = GetObjectNodeGen.create();
363+
@Child GetTypeNode getType;
310364
@Child SuperInitNode superInit;
311365

312366
@Specialization
313367
public Object get(SuperObject self, Object obj, @SuppressWarnings("unused") Object type) {
314-
if (obj == PNone.NONE || self.getObject() != null) {
368+
if (obj == PNone.NONE || getObject.execute(self) != null) {
315369
// not binding to an object or already bound
316370
return this;
317371
} else {
318372
if (superInit == null) {
319373
CompilerDirectives.transferToInterpreterAndInvalidate();
320374
superInit = insert(SuperInitNodeFactory.create());
375+
getType = insert(GetTypeNodeGen.create());
321376
}
322377
SuperObject newSuper = factory().createSuperObject(self.getPythonClass());
323-
superInit.execute(null, newSuper, self.getType(), obj);
378+
superInit.execute(null, newSuper, getType.execute(self), obj);
324379
return newSuper;
325380
}
326381
}
@@ -331,6 +386,9 @@ public Object get(SuperObject self, Object obj, @SuppressWarnings("unused") Obje
331386
public abstract static class GetattributeNode extends PythonBinaryBuiltinNode {
332387
@Child ReadAttributeFromObjectNode readFromDict = ReadAttributeFromObjectNode.create();
333388
@Child LookupInheritedAttributeNode readGet = LookupInheritedAttributeNode.create(SpecialMethodNames.__GET__);
389+
@Child GetObjectTypeNode getObjectType = GetObjectTypeNodeGen.create();
390+
@Child GetTypeNode getType;
391+
@Child GetObjectNode getObject;
334392
@Child CallTernaryMethodNode callGet;
335393
@Child LookupAndCallBinaryNode getAttr;
336394

@@ -342,17 +400,9 @@ private Object genericGetAttr(Object object, Object attr) {
342400
return getAttr.executeObject(object, attr);
343401
}
344402

345-
private CallTernaryMethodNode getCallGet() {
346-
if (callGet == null) {
347-
CompilerDirectives.transferToInterpreterAndInvalidate();
348-
callGet = insert(CallTernaryMethodNode.create());
349-
}
350-
return callGet;
351-
}
352-
353403
@Specialization
354404
public Object get(SuperObject self, Object attr) {
355-
PythonClass startType = self.getObjectType();
405+
PythonClass startType = getObjectType.execute(self);
356406
if (startType == null) {
357407
return genericGetAttr(self, attr);
358408
}
@@ -373,12 +423,18 @@ public Object get(SuperObject self, Object attr) {
373423
}
374424
}
375425

426+
// acts as a branch profile
427+
if (getType == null) {
428+
CompilerDirectives.transferToInterpreterAndInvalidate();
429+
getType = insert(GetTypeNodeGen.create());
430+
}
431+
376432
PythonClass[] mro = startType.getMethodResolutionOrder();
377433
/* No need to check the last one: it's gonna be skipped anyway. */
378434
int i = 0;
379435
int n = mro.length;
380436
for (i = 0; i + 1 < n; i++) {
381-
if (self.getType() == mro[i]) {
437+
if (getType.execute(self) == mro[i]) {
382438
break;
383439
}
384440
}
@@ -396,7 +452,13 @@ public Object get(SuperObject self, Object attr) {
396452
/*
397453
* Only pass 'obj' param if this is instance-mode super (See SF ID #743627)
398454
*/
399-
res = getCallGet().execute(get, res, self.getObject() == startType ? PNone.NO_VALUE : self.getObject(), startType);
455+
// acts as a branch profile
456+
if (getObject == null) {
457+
CompilerDirectives.transferToInterpreterAndInvalidate();
458+
getObject = insert(GetObjectNodeGen.create());
459+
callGet = insert(CallTernaryMethodNode.create());
460+
}
461+
res = callGet.execute(get, res, getObject.execute(self) == startType ? PNone.NO_VALUE : self.getObject(), startType);
400462
}
401463
return res;
402464
}
@@ -409,9 +471,11 @@ public Object get(SuperObject self, Object attr) {
409471
@Builtin(name = "__thisclass__", fixedNumOfPositionalArgs = 1, isGetter = true)
410472
@GenerateNodeFactory
411473
public abstract static class ThisClassNode extends PythonUnaryBuiltinNode {
474+
@Child GetTypeNode getType = GetTypeNodeGen.create();
475+
412476
@Specialization
413477
Object getClass(SuperObject self) {
414-
Object type = self.getType();
478+
Object type = getType.execute(self);
415479
if (type == null) {
416480
return PNone.NONE;
417481
}
@@ -422,9 +486,11 @@ Object getClass(SuperObject self) {
422486
@Builtin(name = "__self__", fixedNumOfPositionalArgs = 1, isGetter = true)
423487
@GenerateNodeFactory
424488
public abstract static class SelfNode extends PythonUnaryBuiltinNode {
489+
@Child GetObjectNode getObject = GetObjectNodeGen.create();
490+
425491
@Specialization
426492
Object getClass(SuperObject self) {
427-
Object object = self.getObject();
493+
Object object = getObject.execute(self);
428494
if (object == null) {
429495
return PNone.NONE;
430496
}
@@ -435,9 +501,11 @@ Object getClass(SuperObject self) {
435501
@Builtin(name = "__self_class__", fixedNumOfPositionalArgs = 1, isGetter = true)
436502
@GenerateNodeFactory
437503
public abstract static class SelfClassNode extends PythonUnaryBuiltinNode {
504+
@Child GetObjectTypeNode getObjectType = GetObjectTypeNodeGen.create();
505+
438506
@Specialization
439507
Object getClass(SuperObject self) {
440-
PythonClass objectType = self.getObjectType();
508+
PythonClass objectType = getObjectType.execute(self);
441509
if (objectType == null) {
442510
return PNone.NONE;
443511
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/superobject/SuperObject.java

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,21 +42,22 @@
4242

4343
import com.oracle.graal.python.builtins.objects.object.PythonBuiltinObject;
4444
import com.oracle.graal.python.builtins.objects.type.PythonClass;
45-
import com.oracle.truffle.api.CompilerDirectives;
46-
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
45+
import com.oracle.truffle.api.Assumption;
46+
import com.oracle.truffle.api.Truffle;
4747

4848
public class SuperObject extends PythonBuiltinObject {
49-
@CompilationFinal private Object type;
50-
@CompilationFinal private PythonClass objecttype;
51-
@CompilationFinal private Object object;
49+
private final Assumption neverReinitialized = Truffle.getRuntime().createAssumption("super object was never reinitialized");
50+
private Object type;
51+
private PythonClass objecttype;
52+
private Object object;
5253

5354
public SuperObject(PythonClass cls) {
5455
super(cls);
5556
}
5657

5758
public void init(Object newType, PythonClass newObjecttype, Object newObject) {
5859
if (this.type != null) {
59-
CompilerDirectives.transferToInterpreterAndInvalidate();
60+
neverReinitialized.invalidate();
6061
}
6162
this.type = newType;
6263
this.objecttype = newObjecttype;
@@ -74,4 +75,8 @@ public Object getType() {
7475
public Object getObject() {
7576
return object;
7677
}
78+
79+
public Assumption getNeverReinitializedAssumption() {
80+
return neverReinitialized;
81+
}
7782
}

0 commit comments

Comments
 (0)