Skip to content

Commit 8616405

Browse files
committed
Compute super constructor at type creation time
1 parent 9da0b6e commit 8616405

File tree

2 files changed

+49
-48
lines changed

2 files changed

+49
-48
lines changed

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

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,16 @@
106106
import com.oracle.graal.python.builtins.objects.object.PythonObject;
107107
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
108108
import com.oracle.graal.python.builtins.objects.type.PythonClass;
109+
import com.oracle.graal.python.builtins.objects.type.SpecialMethodSlot;
110+
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetSuperClassNode;
111+
import com.oracle.graal.python.builtins.objects.type.TypeNodes.IsSameTypeNode;
109112
import com.oracle.graal.python.nodes.BuiltinNames;
110113
import com.oracle.graal.python.nodes.PGuards;
111114
import com.oracle.graal.python.nodes.PNodeWithContext;
112115
import com.oracle.graal.python.nodes.PRaiseNode;
113116
import com.oracle.graal.python.nodes.SpecialAttributeNames;
114117
import com.oracle.graal.python.nodes.SpecialMethodNames;
118+
import com.oracle.graal.python.nodes.attributes.LookupCallableSlotInMRONode;
115119
import com.oracle.graal.python.nodes.attributes.ReadAttributeFromDynamicObjectNode;
116120
import com.oracle.graal.python.nodes.attributes.ReadAttributeFromObjectNode;
117121
import com.oracle.graal.python.nodes.attributes.WriteAttributeToDynamicObjectNode;
@@ -1851,6 +1855,7 @@ static Object doPointer(GraalHPyContext hpyContext, PythonNativeObject n, @Suppr
18511855
* } HPyType_Spec;
18521856
* </pre>
18531857
*/
1858+
@ImportStatic(SpecialMethodSlot.class)
18541859
@GenerateUncached
18551860
abstract static class HPyCreateTypeFromSpecNode extends Node {
18561861

@@ -1873,7 +1878,9 @@ static Object doGeneric(GraalHPyContext context, Object typeSpec, Object typeSpe
18731878
@Cached HPyCreateSlotNode addSlotNode,
18741879
@Cached HPyCreateLegacySlotNode createLegacySlotNode,
18751880
@Cached HPyCreateGetSetDescriptorNode createGetSetDescriptorNode,
1876-
@Cached ReadAttributeFromObjectNode readNewNode,
1881+
@Cached GetSuperClassNode getSuperClassNode,
1882+
@Cached IsSameTypeNode isSameTypeNode,
1883+
@Cached(parameters = "New") LookupCallableSlotInMRONode lookupNewNode,
18771884
@Cached HPyAsPythonObjectNode hPyAsPythonObjectNode,
18781885
@Cached PRaiseNode raiseNode) {
18791886

@@ -1929,6 +1936,8 @@ static Object doGeneric(GraalHPyContext context, Object typeSpec, Object typeSpe
19291936
clazz.itemSize = itemSize;
19301937
}
19311938

1939+
boolean seenNew = false;
1940+
19321941
// process defines
19331942
Object defines = callHelperFunctionNode.call(context, GraalHPyNativeSymbol.GRAAL_HPY_TYPE_SPEC_GET_DEFINES, typeSpec);
19341943
// field 'defines' may be 'NULL'
@@ -1951,6 +1960,9 @@ static Object doGeneric(GraalHPyContext context, Object typeSpec, Object typeSpe
19511960
case GraalHPyDef.HPY_DEF_KIND_SLOT:
19521961
Object slotDef = callHelperFunctionNode.call(context, GRAAL_HPY_DEF_GET_SLOT, moduleDefine);
19531962
property = addSlotNode.execute(context, newType, slotDef);
1963+
if (SpecialMethodNames.__NEW__.equals(property.key)) {
1964+
seenNew = true;
1965+
}
19541966
break;
19551967
case GraalHPyDef.HPY_DEF_KIND_MEMBER:
19561968
Object memberDef = callHelperFunctionNode.call(context, GRAAL_HPY_DEF_GET_MEMBER, moduleDefine);
@@ -1985,11 +1997,22 @@ static Object doGeneric(GraalHPyContext context, Object typeSpec, Object typeSpe
19851997
}
19861998

19871999
/*
1988-
* Ensure that we don't use 'object.__new__' because that would not allocate the
1989-
* native space if a basicsize is given.
2000+
* If 'basicsize > 0' and no explicit constructor is given, the constructor of the
2001+
* object needs to allocate the native space for the object. However, the inherited
2002+
* constructors won't usually do that. So, we compute the constructor here and
2003+
* decorate it.
19902004
*/
1991-
if (readNewNode.execute(newType, SpecialMethodNames.__NEW__) == PNone.NO_VALUE) {
1992-
writeAttributeToObjectNode.execute(newType, SpecialMethodNames.__NEW__, HPyObjectNewNode.createBuiltinFunction(PythonLanguage.get(raiseNode)));
2005+
if (basicSize > 0 && !seenNew) {
2006+
Object inheritedConstructor = null;
2007+
2008+
Object baseClass = getSuperClassNode.execute(newType);
2009+
if (!isSameTypeNode.execute(baseClass, PythonBuiltinClassType.PythonObject)) {
2010+
// Lookup the inherited constructor and pass it to the HPy decorator.
2011+
inheritedConstructor = lookupNewNode.execute(baseClass);
2012+
}
2013+
2014+
PBuiltinFunction constructorDecorator = HPyObjectNewNode.createBuiltinFunction(PythonLanguage.get(raiseNode), inheritedConstructor);
2015+
writeAttributeToObjectNode.execute(newType, SpecialMethodNames.__NEW__, constructorDecorator);
19932016
}
19942017

19952018
return newType;

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

Lines changed: 21 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -45,25 +45,19 @@
4545

4646
import com.oracle.graal.python.PythonLanguage;
4747
import com.oracle.graal.python.builtins.Builtin;
48-
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
4948
import com.oracle.graal.python.builtins.objects.PNone;
5049
import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyNodes.PCallHPyFunction;
5150
import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyNodesFactory.PCallHPyFunctionNodeGen;
5251
import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyObjectBuiltinsFactory.HPyObjectNewNodeGen;
5352
import com.oracle.graal.python.builtins.objects.function.PBuiltinFunction;
5453
import com.oracle.graal.python.builtins.objects.function.PKeyword;
5554
import com.oracle.graal.python.builtins.objects.type.PythonClass;
56-
import com.oracle.graal.python.builtins.objects.type.SpecialMethodSlot;
57-
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetSuperClassNode;
58-
import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetSuperClassNodeGen;
5955
import com.oracle.graal.python.nodes.SpecialMethodNames;
60-
import com.oracle.graal.python.nodes.attributes.LookupCallableSlotInMRONode;
6156
import com.oracle.graal.python.nodes.attributes.WriteAttributeToObjectNode;
6257
import com.oracle.graal.python.nodes.call.special.CallVarargsMethodNode;
6358
import com.oracle.graal.python.nodes.function.BuiltinFunctionRootNode;
6459
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
6560
import com.oracle.graal.python.nodes.function.builtins.PythonVarargsBuiltinNode;
66-
import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile;
6761
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
6862
import com.oracle.graal.python.util.PythonUtils;
6963
import com.oracle.truffle.api.CompilerAsserts;
@@ -122,15 +116,22 @@ public List<Class<? extends Node>> getExecutionSignature() {
122116

123117
@Builtin(name = SpecialMethodNames.__NEW__, minNumOfPositionalArgs = 1, takesVarArgs = true, takesVarKeywordArgs = true)
124118
abstract static class HPyObjectNewNode extends PythonVarargsBuiltinNode {
119+
private static final String KW_SUPER_CONSTRUCTOR = "$supercons";
120+
private static final String[] KEYWORDS_HIDDEN_CALLABLE = {KW_SUPER_CONSTRUCTOR};
121+
122+
private static PKeyword[] createKwDefaults(Object superConstructor) {
123+
if (superConstructor != null) {
124+
return new PKeyword[]{new PKeyword(KW_SUPER_CONSTRUCTOR, superConstructor)};
125+
}
126+
return PKeyword.EMPTY_KEYWORDS;
127+
}
128+
125129
private static final Builtin BUILTIN = HPyObjectNewNode.class.getAnnotation(Builtin.class);
126130
private static final TruffleLogger LOGGER = PythonLanguage.getLogger(HPyObjectNewNode.class);
127131

128132
@Child private PCallHPyFunction callHPyFunctionNode;
129-
@Child private LookupCallableSlotInMRONode lookupNewNode;
130133
@Child private CallVarargsMethodNode callNewNode;
131-
@Child private GetSuperClassNode getBaseClassNode;
132134
@Child private WriteAttributeToObjectNode writeNativeSpaceNode;
133-
@Child private IsBuiltinClassProfile isObjectProfile;
134135

135136
@Override
136137
public Object varArgExecute(VirtualFrame frame, Object self, Object[] arguments, PKeyword[] keywords) throws VarargsBuiltinDirectInvocationNotSupported {
@@ -178,14 +179,13 @@ Object doGeneric(VirtualFrame frame, Object explicitSelf, Object[] arguments, PK
178179
}
179180
}
180181

181-
Object baseClass = ensureGetBaseClassNode().execute(self);
182+
Object inheritedConstructor = extractInheritedConstructor(arguments, keywords);
182183
Object pythonObject;
183-
if (ensureIsObjectProfile().profileClass(baseClass, PythonBuiltinClassType.PythonObject)) {
184+
if (inheritedConstructor == null) {
184185
// fast-path if the super class is 'object'
185186
pythonObject = factory().createPythonHPyObject(self, dataPtr);
186187
} else {
187-
Object superNew = ensureLookupNewNode().execute(baseClass);
188-
pythonObject = ensureCallNewNode().execute(frame, superNew, argsWithSelf, keywords);
188+
pythonObject = ensureCallNewNode().execute(frame, inheritedConstructor, argsWithSelf, keywords);
189189

190190
/*
191191
* Since we are creating an object with an unknown constructor, the Java type may be
@@ -196,13 +196,15 @@ Object doGeneric(VirtualFrame frame, Object explicitSelf, Object[] arguments, PK
196196
ensureWriteNativeSpaceNode().execute(pythonObject, GraalHPyDef.OBJECT_HPY_NATIVE_SPACE, dataPtr);
197197
}
198198
}
199-
200-
if (pythonObject == null) {
201-
pythonObject = factory().createPythonObject(self);
202-
}
203199
return pythonObject;
204200
}
205201

202+
@SuppressWarnings("unused")
203+
private Object extractInheritedConstructor(Object[] arguments, PKeyword[] keywords) {
204+
// TODO(fa): not yet implemented
205+
return null;
206+
}
207+
206208
private PCallHPyFunction ensureCallHPyFunctionNode() {
207209
if (callHPyFunctionNode == null) {
208210
CompilerDirectives.transferToInterpreterAndInvalidate();
@@ -219,22 +221,6 @@ private CallVarargsMethodNode ensureCallNewNode() {
219221
return callNewNode;
220222
}
221223

222-
private LookupCallableSlotInMRONode ensureLookupNewNode() {
223-
if (lookupNewNode == null) {
224-
CompilerDirectives.transferToInterpreterAndInvalidate();
225-
lookupNewNode = insert(LookupCallableSlotInMRONode.create(SpecialMethodSlot.New));
226-
}
227-
return lookupNewNode;
228-
}
229-
230-
private GetSuperClassNode ensureGetBaseClassNode() {
231-
if (getBaseClassNode == null) {
232-
CompilerDirectives.transferToInterpreterAndInvalidate();
233-
getBaseClassNode = insert(GetSuperClassNodeGen.create());
234-
}
235-
return getBaseClassNode;
236-
}
237-
238224
private WriteAttributeToObjectNode ensureWriteNativeSpaceNode() {
239225
if (writeNativeSpaceNode == null) {
240226
CompilerDirectives.transferToInterpreterAndInvalidate();
@@ -243,20 +229,12 @@ private WriteAttributeToObjectNode ensureWriteNativeSpaceNode() {
243229
return writeNativeSpaceNode;
244230
}
245231

246-
private IsBuiltinClassProfile ensureIsObjectProfile() {
247-
if (isObjectProfile == null) {
248-
CompilerDirectives.transferToInterpreterAndInvalidate();
249-
isObjectProfile = insert(IsBuiltinClassProfile.create());
250-
}
251-
return isObjectProfile;
252-
}
253-
254232
@TruffleBoundary
255-
public static PBuiltinFunction createBuiltinFunction(PythonLanguage language) {
233+
public static PBuiltinFunction createBuiltinFunction(PythonLanguage language, Object superConstructor) {
256234
RootCallTarget callTarget = language.createCachedCallTarget(l -> new BuiltinFunctionRootNode(l, BUILTIN, new HPyObjectNewNodeFactory<>(HPyObjectNewNodeGen.create()), true),
257235
HPyObjectNewNode.class, BUILTIN.name());
258236
int flags = PBuiltinFunction.getFlags(BUILTIN, callTarget);
259-
return PythonObjectFactory.getUncached().createBuiltinFunction(SpecialMethodNames.__NEW__, null, 0, flags, callTarget);
237+
return PythonObjectFactory.getUncached().createBuiltinFunction(SpecialMethodNames.__NEW__, null, PythonUtils.EMPTY_OBJECT_ARRAY, createKwDefaults(superConstructor), flags, callTarget);
260238
}
261239
}
262240
}

0 commit comments

Comments
 (0)