Skip to content

Commit 96bfcc6

Browse files
committed
[GR-16291] Use a layout to unify the shape with the class, the dict, and the assumptions on them changing
PullRequest: graalpython/535
2 parents 6266719 + f012892 commit 96bfcc6

27 files changed

+435
-314
lines changed

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

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,6 @@
8686
import com.oracle.truffle.api.nodes.ExplodeLoop;
8787
import com.oracle.truffle.api.nodes.Node;
8888
import com.oracle.truffle.api.nodes.RootNode;
89-
import com.oracle.truffle.api.object.Layout;
90-
import com.oracle.truffle.api.object.ObjectType;
91-
import com.oracle.truffle.api.object.Shape;
9289
import com.oracle.truffle.api.source.Source;
9390
import com.oracle.truffle.api.source.Source.SourceBuilder;
9491
import com.oracle.truffle.api.source.SourceSection;
@@ -122,9 +119,6 @@ public final class PythonLanguage extends TruffleLanguage<PythonContext> {
122119
private final NodeFactory nodeFactory;
123120
public final ConcurrentHashMap<Class<? extends PythonBuiltinBaseNode>, RootCallTarget> builtinCallTargetCache = new ConcurrentHashMap<>();
124121

125-
private static final Layout objectLayout = Layout.newLayout().build();
126-
private static final Shape newShape = objectLayout.createShape(new ObjectType());
127-
128122
private static final Object[] CONTEXT_INSENSITIVE_SINGLETONS = new Object[]{PNone.NONE, PNone.NO_VALUE, PEllipsis.INSTANCE, PNotImplemented.NOT_IMPLEMENTED};
129123

130124
public static int getNumberOfSpecialSingletons() {
@@ -605,10 +599,6 @@ public CallTarget cacheCode(String filename, Supplier<CallTarget> createCode, St
605599
return ct;
606600
}
607601

608-
public static Shape freshShape() {
609-
return newShape;
610-
}
611-
612602
@Override
613603
protected boolean isThreadAccessAllowed(Thread thread, boolean singleThreaded) {
614604
if (singleThreaded) {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltinClassType.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727

2828
import java.util.HashSet;
2929

30-
import com.oracle.graal.python.PythonLanguage;
3130
import com.oracle.graal.python.builtins.objects.type.LazyPythonClass;
3231
import com.oracle.graal.python.nodes.BuiltinNames;
3332
import com.oracle.truffle.api.CompilerAsserts;
@@ -182,7 +181,7 @@ public enum PythonBuiltinClassType implements LazyPythonClass {
182181
PythonBuiltinClassType(String name, String publicInModule) {
183182
this.name = name;
184183
this.publicInModule = publicInModule;
185-
this.instanceShape = PythonLanguage.freshShape();
184+
this.instanceShape = com.oracle.graal.python.builtins.objects.object.PythonObject.freshShape(this);
186185
}
187186

188187
PythonBuiltinClassType(String name) {

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1487,12 +1487,12 @@ Object doObjectDirect(@SuppressWarnings("unused") PythonManagedClass self, Objec
14871487
@Specialization(limit = "getCallSiteInlineCacheMaxDepth()", //
14881488
guards = {"getInstanceShape(self) == cachedInstanceShape", "!self.needsNativeAllocation()"}, //
14891489
replaces = "doObjectDirect")
1490-
Object doObjectCachedInstanceShape(PythonManagedClass self, Object[] varargs, PKeyword[] kwargs,
1490+
Object doObjectCachedInstanceShape(@SuppressWarnings("unused") PythonManagedClass self, Object[] varargs, PKeyword[] kwargs,
14911491
@Cached("getInstanceShape(self)") Shape cachedInstanceShape) {
14921492
if (varargs.length > 0 || kwargs.length > 0) {
14931493
// TODO: tfel: this should throw an error only if init isn't overridden
14941494
}
1495-
return factory().createPythonObject(self, cachedInstanceShape);
1495+
return factory().createPythonObject(cachedInstanceShape);
14961496
}
14971497

14981498
@Specialization(guards = "!self.needsNativeAllocation()", replaces = "doObjectCachedInstanceShape")

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

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,10 +1021,10 @@ public abstract static class LseekNode extends PythonFileNode {
10211021
private final ConditionProfile noFile = ConditionProfile.createBinaryProfile();
10221022

10231023
@Specialization
1024-
Object lseek(VirtualFrame frame, int fd, long pos, int how,
1024+
Object lseek(VirtualFrame frame, long fd, long pos, int how,
10251025
@Cached PRaiseOSErrorNode raise,
10261026
@Cached("createClassProfile()") ValueProfile channelClassProfile) {
1027-
Channel channel = getResources().getFileChannel(fd, channelClassProfile);
1027+
Channel channel = getResources().getFileChannel((int) fd, channelClassProfile);
10281028
if (noFile.profile(channel == null || !(channel instanceof SeekableByteChannel))) {
10291029
throw raise.raiseOSError(frame, OSErrorEnum.ESPIPE);
10301030
}
@@ -1062,8 +1062,10 @@ public abstract static class CloseNode extends PythonFileNode {
10621062
private final ConditionProfile noFile = ConditionProfile.createBinaryProfile();
10631063

10641064
@Specialization
1065-
Object close(int fd,
1065+
Object close(Object fdObject,
1066+
@Cached CastToIndexNode castToIndex,
10661067
@Cached("createClassProfile()") ValueProfile channelClassProfile) {
1068+
int fd = castToIndex.execute(fdObject);
10671069
PosixResources resources = getResources();
10681070
Channel channel = resources.getFileChannel(fd, channelClassProfile);
10691071
if (noFile.profile(channel == null)) {
@@ -1244,16 +1246,18 @@ Object read(@SuppressWarnings("unused") VirtualFrame frame, int fd, long request
12441246
@TypeSystemReference(PythonArithmeticTypes.class)
12451247
public abstract static class IsATTYNode extends PythonBuiltinNode {
12461248
@Specialization
1247-
boolean isATTY(int fd) {
1248-
switch (fd) {
1249-
case 0:
1250-
case 1:
1251-
case 2:
1252-
return terminalIsInteractive(getContext());
1253-
default:
1254-
return false;
1249+
boolean isATTY(long fd) {
1250+
if (fd >= 0 && fd <= 2) {
1251+
return terminalIsInteractive(getContext());
1252+
} else {
1253+
return false;
12551254
}
12561255
}
1256+
1257+
@Fallback
1258+
boolean isATTY(@SuppressWarnings("unused") Object fd) {
1259+
return false;
1260+
}
12571261
}
12581262

12591263
@Builtin(name = "_exit", minNumOfPositionalArgs = 1)

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,6 @@
126126
import com.oracle.graal.python.builtins.objects.type.PythonClass;
127127
import com.oracle.graal.python.builtins.objects.type.PythonManagedClass;
128128
import com.oracle.graal.python.builtins.objects.type.TypeNodes;
129-
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetInstanceShape;
130129
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetTypeFlagsNode;
131130
import com.oracle.graal.python.nodes.PGuards;
132131
import com.oracle.graal.python.nodes.PNodeWithContext;
@@ -222,7 +221,7 @@ public void initialize(PythonCore core) {
222221
PythonClass errorHandlerClass = core.factory().createPythonClass(PythonBuiltinClassType.PythonClass, "CErrorHandler",
223222
new PythonAbstractClass[]{core.lookupType(PythonBuiltinClassType.PythonObject)});
224223
builtinConstants.put("CErrorHandler", errorHandlerClass);
225-
builtinConstants.put(ERROR_HANDLER, core.factory().createPythonObject(errorHandlerClass, GetInstanceShape.doSlowPath(errorHandlerClass)));
224+
builtinConstants.put(ERROR_HANDLER, core.factory().createPythonObject(errorHandlerClass));
226225
builtinConstants.put(NATIVE_NULL, new PythonNativeNull());
227226
}
228227

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@
5252
import com.oracle.graal.python.builtins.objects.object.PythonObject;
5353
import com.oracle.graal.python.builtins.objects.str.PString;
5454
import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass;
55-
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetInstanceShape;
5655
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
5756
import com.oracle.graal.python.runtime.PythonCore;
5857
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
@@ -160,7 +159,7 @@ public void initialize(PythonCore core) {
160159
super.initialize(core);
161160
builtinConstants.put("version", getUnicodeVersion());
162161
PythonBuiltinClass objectType = core.lookupType(PythonBuiltinClassType.PythonObject);
163-
PythonObject ucd_3_2_0 = core.factory().createPythonObject(objectType, GetInstanceShape.doSlowPath(objectType));
162+
PythonObject ucd_3_2_0 = core.factory().createPythonObject(objectType);
164163
ucd_3_2_0.setAttribute("unidata_version", "3.2.0");
165164
builtinConstants.put("ucd_3_2_0", ucd_3_2_0); // TODO this is a fake object, just satisfy
166165
// pip installer import

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cell/PCell.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,19 @@ public void setRef(Object ref) {
7070
this.ref = ref;
7171
}
7272

73+
/**
74+
* Use this to pass in the effectivelyFinal assumption from a node that made it constant.
75+
*/
76+
public void setRef(Object ref, Assumption constantAssumption) {
77+
assert constantAssumption == effectivelyFinal;
78+
if (constantAssumption.isValid()) {
79+
if (this.ref != null) {
80+
constantAssumption.invalidate();
81+
}
82+
}
83+
this.ref = ref;
84+
}
85+
7386
public Assumption isEffectivelyFinalAssumption() {
7487
return effectivelyFinal;
7588
}

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

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,6 @@
130130
import com.oracle.graal.python.runtime.interop.InteropArray;
131131
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
132132
import com.oracle.graal.python.runtime.sequence.PSequence;
133-
import com.oracle.truffle.api.Assumption;
134133
import com.oracle.truffle.api.CompilerAsserts;
135134
import com.oracle.truffle.api.CompilerDirectives;
136135
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
@@ -175,12 +174,8 @@ public DynamicObjectNativeWrapper(Object delegate) {
175174
}
176175

177176
public PythonObjectDictStorage createNativeMemberStore() {
178-
return createNativeMemberStore(null);
179-
}
180-
181-
public PythonObjectDictStorage createNativeMemberStore(Assumption dictStableAssumption) {
182177
if (nativeMemberStore == null) {
183-
nativeMemberStore = new PythonObjectDictStorage(SHAPE.newInstance(), dictStableAssumption);
178+
nativeMemberStore = new PythonObjectDictStorage(SHAPE.newInstance());
184179
}
185180
return nativeMemberStore;
186181
}
@@ -857,7 +852,7 @@ Object doMdDef(PythonObject object, @SuppressWarnings("unused") String key, Obje
857852
@Shared("setItemNode") @Cached HashingStorageNodes.DynamicObjectSetItemNode setItemNode) {
858853
DynamicObjectNativeWrapper nativeWrapper = ((PythonAbstractObject) object).getNativeWrapper();
859854
assert nativeWrapper != null;
860-
setItemNode.passState().execute(nativeWrapper.createNativeMemberStore(object.getDictUnsetOrSameAsStorageAssumption()), MD_DEF, value);
855+
setItemNode.passState().execute(nativeWrapper.createNativeMemberStore(), MD_DEF, value);
861856
return value;
862857
}
863858

@@ -878,7 +873,7 @@ Object doTpDict(PythonManagedClass object, @SuppressWarnings("unused") String ke
878873
if (existing != null) {
879874
d.setDictStorage(existing.getDictStorage());
880875
} else {
881-
d.setDictStorage(new DynamicObjectStorage.PythonObjectDictStorage(object.getStorage(), object.getDictUnsetOrSameAsStorageAssumption()));
876+
d.setDictStorage(new DynamicObjectStorage.PythonObjectDictStorage(object.getStorage()));
882877
}
883878
object.setDict(d);
884879
} else {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/DynamicObjectStorage.java

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@
4343
import java.util.ArrayList;
4444

4545
import com.oracle.graal.python.runtime.sequence.storage.MroSequenceStorage;
46-
import com.oracle.truffle.api.Assumption;
4746
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
4847
import com.oracle.truffle.api.object.DynamicObject;
4948
import com.oracle.truffle.api.object.Layout;
@@ -161,19 +160,8 @@ public HashingStorage copy(Equivalence eq) {
161160
}
162161

163162
public static final class PythonObjectDictStorage extends DynamicObjectStorage {
164-
private final Assumption dictUnsetOrSameAsStorage;
165-
166163
public PythonObjectDictStorage(DynamicObject store) {
167-
this(store, null);
168-
}
169-
170-
public PythonObjectDictStorage(DynamicObject store, Assumption dictUnsetOrSameAsStorage) {
171164
super(store);
172-
this.dictUnsetOrSameAsStorage = dictUnsetOrSameAsStorage;
173-
}
174-
175-
public Assumption getDictUnsetOrSameAsStorage() {
176-
return dictUnsetOrSameAsStorage;
177165
}
178166

179167
@Override

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/HashingStorageNodes.java

Lines changed: 34 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@
8686
import com.oracle.graal.python.nodes.PRaiseNode;
8787
import com.oracle.graal.python.nodes.SpecialMethodNames;
8888
import com.oracle.graal.python.nodes.attributes.LookupInheritedAttributeNode;
89+
import com.oracle.graal.python.nodes.attributes.ReadAttributeFromDynamicObjectNode;
8990
import com.oracle.graal.python.nodes.builtins.ListNodes.FastConstructListNode;
9091
import com.oracle.graal.python.nodes.call.special.LookupAndCallBinaryNode;
9192
import com.oracle.graal.python.nodes.call.special.LookupAndCallUnaryNode;
@@ -102,13 +103,13 @@
102103
import com.oracle.graal.python.runtime.exception.PException;
103104
import com.oracle.graal.python.runtime.exception.PythonErrorType;
104105
import com.oracle.graal.python.runtime.sequence.PSequence;
105-
import com.oracle.truffle.api.Assumption;
106106
import com.oracle.truffle.api.CompilerAsserts;
107107
import com.oracle.truffle.api.CompilerDirectives;
108108
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
109109
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
110110
import com.oracle.truffle.api.TruffleLanguage.ContextReference;
111111
import com.oracle.truffle.api.dsl.Cached;
112+
import com.oracle.truffle.api.dsl.Cached.Shared;
112113
import com.oracle.truffle.api.dsl.Fallback;
113114
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
114115
import com.oracle.truffle.api.dsl.GenerateUncached;
@@ -309,10 +310,6 @@ protected static DynamicObjectStorage switchToFastDictStorage(HashingStorage sto
309310
}
310311

311312
protected static PythonObjectHybridDictStorage switchToHybridDictStorage(PythonObjectDictStorage dictStorage) {
312-
Assumption dictUnsetOrSameAsStorage = dictStorage.getDictUnsetOrSameAsStorage();
313-
if (dictUnsetOrSameAsStorage != null) {
314-
dictUnsetOrSameAsStorage.invalidate();
315-
}
316313
return new PythonObjectHybridDictStorage(dictStorage);
317314
}
318315

@@ -1085,6 +1082,7 @@ public HashingStorage execute(DynamicObjectStorage storage, Object key, Object v
10851082
}
10861083

10871084
public abstract static class GetItemNode extends DictStorageBaseNode {
1085+
protected static final int MAX_DYNAMIC_STORAGES = 3;
10881086

10891087
public static GetItemNode create() {
10901088
return GetItemNodeGen.create();
@@ -1098,73 +1096,50 @@ Object doEmptyStorage(VirtualFrame frame, EmptyStorage storage, Object key) {
10981096
return null;
10991097
}
11001098

1101-
@Specialization(limit = "3", //
1102-
guards = {
1103-
"cachedName.equals(name)",
1104-
"shapeCheck(shape, storage.getStore())"
1105-
}, //
1106-
assumptions = {
1107-
"shape.getValidAssumption()"
1108-
})
1109-
protected static Object doDynamicObjectString(DynamicObjectStorage storage, @SuppressWarnings("unused") String name,
1110-
@SuppressWarnings("unused") @Cached("name") String cachedName,
1111-
@Cached("lookupShape(storage.getStore())") Shape shape,
1112-
@Cached("lookupLocation(shape, name)") Location location) {
1113-
1114-
return location != null ? location.get(storage.getStore(), shape) : null;
1115-
}
1116-
1117-
@TruffleBoundary
1118-
@Specialization(replaces = {"doDynamicObjectString"}, guards = "storage.getStore().getShape().isValid()")
1119-
protected Object doDynamicObjectUncached(DynamicObjectStorage storage, String name) {
1120-
return storage.getStore().get(name);
1099+
// this is just a minor performance optimization
1100+
@Specialization
1101+
static Object doPythonObjectString(PythonObjectDictStorage storage, String key,
1102+
@Shared("readKey") @Cached ReadAttributeFromDynamicObjectNode readKey) {
1103+
return doDynamicObjectString(storage, key, readKey);
11211104
}
11221105

1123-
@Specialization(guards = "!storage.getStore().getShape().isValid()")
1124-
protected Object doDynamicObjectUpdateShape(DynamicObjectStorage storage, String name) {
1125-
CompilerDirectives.transferToInterpreter();
1126-
storage.getStore().updateShape();
1127-
return doDynamicObjectUncached(storage, name);
1106+
// this is just a minor performance optimization
1107+
@Specialization
1108+
static Object doPythonObjectPString(PythonObjectDictStorage storage, PString key,
1109+
@Shared("readKey") @Cached ReadAttributeFromDynamicObjectNode readKey) {
1110+
return doDynamicObjectPString(storage, key, readKey);
11281111
}
11291112

1130-
@Specialization(limit = "3", //
1131-
guards = {
1132-
"wrappedString(name)",
1133-
"cachedName.equals(name.getValue())",
1134-
"shapeCheck(shape, storage.getStore())"
1135-
}, //
1136-
assumptions = {
1137-
"shape.getValidAssumption()"
1138-
})
1139-
protected static Object doDynamicObjectPString(DynamicObjectStorage storage, @SuppressWarnings("unused") PString name,
1140-
@SuppressWarnings("unused") @Cached("name.getValue()") String cachedName,
1141-
@Cached("lookupShape(storage.getStore())") Shape shape,
1142-
@Cached("lookupLocation(shape, cachedName)") Location location) {
1143-
1144-
return location != null ? location.get(storage.getStore(), shape) : null;
1113+
// this will read from the dynamic object
1114+
@Specialization
1115+
static Object doDynamicObjectString(DynamicObjectStorage storage, String key,
1116+
@Shared("readKey") @Cached ReadAttributeFromDynamicObjectNode readKey) {
1117+
Object result = readKey.execute(storage.getStore(), key);
1118+
return result == PNone.NO_VALUE ? null : result;
11451119
}
11461120

1147-
@TruffleBoundary
1148-
@Specialization(replaces = {"doDynamicObjectPString"}, guards = {"wrappedString(name)", "storage.getStore().getShape().isValid()"})
1149-
protected Object doDynamicObjectUncachedPString(DynamicObjectStorage storage, PString name) {
1150-
return storage.getStore().get(name.getValue());
1121+
@Specialization
1122+
static Object doDynamicObjectPString(DynamicObjectStorage storage, PString key,
1123+
@Shared("readKey") @Cached ReadAttributeFromDynamicObjectNode readKey) {
1124+
Object result = readKey.execute(storage.getStore(), key);
1125+
return result == PNone.NO_VALUE ? null : result;
11511126
}
11521127

1153-
@Specialization(guards = {"wrappedString(name)", "!storage.getStore().getShape().isValid()"})
1154-
protected Object doDynamicObjectUpdateShapePString(DynamicObjectStorage storage, PString name) {
1155-
CompilerDirectives.transferToInterpreter();
1156-
storage.getStore().updateShape();
1157-
return doDynamicObjectUncachedPString(storage, name);
1128+
// this must read from the non-dynamic object storage
1129+
@Specialization(guards = {"!isString(key)", "isHashable(frame, key)"})
1130+
Object doDynamicStorage(@SuppressWarnings("unused") VirtualFrame frame, PythonObjectHybridDictStorage s, Object key) {
1131+
return s.getItem(key, getEquivalence());
11581132
}
11591133

1160-
@Specialization(guards = {"!isJavaString(key)", "isHashable(frame, key)"})
1161-
Object doDynamicObject(@SuppressWarnings("unused") VirtualFrame frame, PythonObjectHybridDictStorage storage, Object key) {
1162-
return storage.getItem(key, getEquivalence());
1134+
protected static boolean isPythonObjectHybridStorage(DynamicObjectStorage s) {
1135+
return s instanceof PythonObjectHybridDictStorage;
11631136
}
11641137

1165-
@Specialization(guards = {"!isJavaString(key)", "isHashable(frame, key)"})
1138+
// any dynamic object storage that isn't hybridized cannot store
1139+
// non-string keys
1140+
@Specialization(guards = {"!isString(key)", "isHashable(frame, key)", "!isPythonObjectHybridStorage(s)"})
11661141
@SuppressWarnings("unused")
1167-
Object doDynamicObject(VirtualFrame frame, DynamicObjectStorage storage, Object key) {
1142+
Object doDynamicStorage(VirtualFrame frame, DynamicObjectStorage s, Object key) {
11681143
return null;
11691144
}
11701145

0 commit comments

Comments
 (0)