Skip to content

Commit c2d61a0

Browse files
committed
Quicken attribute stores
1 parent f0c0d69 commit c2d61a0

2 files changed

Lines changed: 51 additions & 16 deletions

File tree

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode_dsl/PBytecodeDSLRootNode.java

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,6 @@
310310
import com.oracle.truffle.api.nodes.Node;
311311
import com.oracle.truffle.api.nodes.RootNode;
312312
import com.oracle.truffle.api.object.DynamicObject;
313-
import com.oracle.truffle.api.object.Property;
314313
import com.oracle.truffle.api.object.PropertyGetter;
315314
import com.oracle.truffle.api.object.Shape;
316315
import com.oracle.truffle.api.profiles.InlinedBranchProfile;
@@ -1928,19 +1927,8 @@ public static Object doIt(VirtualFrame frame,
19281927

19291928
@Operation(storeBytecodeIndex = true)
19301929
@ConstantOperand(type = TruffleString.class)
1931-
@ImportStatic({PGuards.class, TpSlots.class})
1930+
@ImportStatic({PGuards.class, TpSlots.class, PythonUtils.class})
19321931
public static final class GetAttribute {
1933-
static PropertyGetter getPropertyGetterWithFinalAssumption(Shape shape, Object key) {
1934-
PropertyGetter getter = shape.makePropertyGetter(key);
1935-
if (getter != null) {
1936-
Property property = shape.getProperty(key);
1937-
if (property != null) {
1938-
property.getLocation().getFinalAssumption();
1939-
}
1940-
}
1941-
return getter;
1942-
}
1943-
19441932
// Builtin module object fast-path: we know there aren't any descriptors for other than
19451933
// dunder (__xxx__) names
19461934
public static Object loadModuleValue(PythonModule object, Shape cachedShape, PropertyGetter cachedPropertyGetter) {
@@ -2013,7 +2001,7 @@ static Object doType(VirtualFrame frame, TruffleString key, PythonManagedClass r
20132001
return value;
20142002
}
20152003

2016-
// Object instance field fast-path: for cases where there is no descriptor and it's just
2004+
// Object instance field fast-path: for cases where there is no descriptor, and it's just
20172005
// simple DOM property read
20182006
public static Object loadInstanceValue(Node inliningTarget, PythonObject object, LookupAttributeInMRONode getDesc, Shape cachedShape, PropertyGetter cachedPropertyGetter,
20192007
InlineWeakValueProfile slotsValueProfile) {
@@ -2081,13 +2069,46 @@ public static Object doItUncached(VirtualFrame frame, TruffleString key, Object
20812069
@Operation(storeBytecodeIndex = true)
20822070
@ConstantOperand(type = TruffleString.class)
20832071
public static final class SetAttribute {
2084-
@Specialization
2072+
public static boolean canStoreInstanceValue(Node inliningTarget, PythonObject object, Shape cachedShape, LookupAttributeInMRONode getDesc,
2073+
GetObjectSlotsNode getDescSlotsNode, InlineWeakValueProfile slotsValueProfile) {
2074+
TpSlots slots;
2075+
Object type = cachedShape.getDynamicType();
2076+
if (type instanceof PythonBuiltinClassType pbct) {
2077+
slots = pbct.getSlots();
2078+
} else if (type instanceof PythonManagedClass klass) {
2079+
slots = slotsValueProfile.execute(inliningTarget, klass.getTpSlots());
2080+
} else {
2081+
return false;
2082+
}
2083+
if (slots.tp_setattro() == ObjectBuiltins.SLOTS.tp_setattro()) {
2084+
Object descr = getDesc.execute(type);
2085+
if (descr == PNone.NO_VALUE || getDescSlotsNode.execute(inliningTarget, descr).tp_descr_set() == null) {
2086+
assert object.checkDictFlags();
2087+
return (cachedShape.getFlags() & (PythonObject.HAS_MATERIALIZED_DICT | PythonObject.HAS_SLOTS_BUT_NO_DICT_FLAG)) == 0;
2088+
}
2089+
}
2090+
return false;
2091+
}
2092+
2093+
@ForceQuickening
2094+
@Specialization(guards = {"cachedShape.check(receiver)", "canStoreInstanceValue(inliningTarget, receiver, cachedShape, getDesc, getDescSlotsNode, slotsValueProfile)"}, limit = "3")
2095+
static void doInstanceValue(TruffleString key, Object value, PythonObject receiver,
2096+
@Bind Node inliningTarget,
2097+
@Cached("receiver.getShape()") Shape cachedShape,
2098+
@Cached("create(key)") LookupAttributeInMRONode getDesc,
2099+
@Cached GetObjectSlotsNode getDescSlotsNode,
2100+
@Cached InlineWeakValueProfile slotsValueProfile,
2101+
@Cached DynamicObject.PutNode putNode) {
2102+
putNode.execute(receiver, key, value);
2103+
}
2104+
2105+
@Specialization(replaces = "doInstanceValue")
20852106
public static void doIt(VirtualFrame frame,
20862107
TruffleString key,
20872108
Object value,
20882109
Object object,
20892110
@Bind Node inliningTarget,
2090-
@Cached PyObjectSetAttr setAttrNode) {
2111+
@Exclusive @Cached PyObjectSetAttr setAttrNode) {
20912112
setAttrNode.execute(frame, inliningTarget, object, key, value);
20922113
}
20932114
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/util/PythonUtils.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@
100100
import com.oracle.truffle.api.nodes.NodeUtil;
101101
import com.oracle.truffle.api.nodes.NodeVisitor;
102102
import com.oracle.truffle.api.nodes.RootNode;
103+
import com.oracle.truffle.api.object.Property;
104+
import com.oracle.truffle.api.object.PropertyGetter;
105+
import com.oracle.truffle.api.object.Shape;
103106
import com.oracle.truffle.api.profiles.ConditionProfile;
104107
import com.oracle.truffle.api.source.Source;
105108
import com.oracle.truffle.api.strings.TruffleString;
@@ -1097,4 +1100,15 @@ public List<Class<? extends Node>> getExecutionSignature() {
10971100
throw new IllegalAccessError();
10981101
}
10991102
}
1103+
1104+
public static PropertyGetter getPropertyGetterWithFinalAssumption(Shape shape, Object key) {
1105+
PropertyGetter getter = shape.makePropertyGetter(key);
1106+
if (getter != null) {
1107+
Property property = shape.getProperty(key);
1108+
if (property != null) {
1109+
property.getLocation().getFinalAssumption();
1110+
}
1111+
}
1112+
return getter;
1113+
}
11001114
}

0 commit comments

Comments
 (0)