Skip to content

Commit 64cdc03

Browse files
committed
move more parts of __build_class__ behind TruffleBoundary
1 parent 63566e3 commit 64cdc03

File tree

3 files changed

+79
-65
lines changed

3 files changed

+79
-65
lines changed

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

Lines changed: 68 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@
123123
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
124124
import com.oracle.graal.python.builtins.objects.type.TypeBuiltins;
125125
import com.oracle.graal.python.builtins.objects.type.TypeNodes;
126+
import com.oracle.graal.python.builtins.objects.type.TypeNodes.IsTypeNode;
126127
import com.oracle.graal.python.lib.PyNumberAsSizeNode;
127128
import com.oracle.graal.python.lib.PyNumberIndexNode;
128129
import com.oracle.graal.python.nodes.BuiltinNames;
@@ -1957,19 +1958,18 @@ protected ArgumentClinicProvider getArgumentClinic() {
19571958
@ImportStatic(SpecialMethodNames.class)
19581959
abstract static class UpdateBasesNode extends PNodeWithRaise {
19591960

1960-
abstract PTuple execute(VirtualFrame frame, PTuple bases, Object[] arguments, int nargs);
1961+
abstract PTuple execute(PTuple bases, Object[] arguments, int nargs);
19611962

19621963
@Specialization
1963-
PTuple update(VirtualFrame frame, PTuple bases, Object[] arguments, int nargs,
1964+
PTuple update(PTuple bases, Object[] arguments, int nargs,
19641965
@Cached PythonObjectFactory factory,
1965-
@CachedLibrary(limit = "3") InteropLibrary interop,
19661966
@Cached GetClassNode getMroClass,
19671967
@Cached(parameters = "__MRO_ENTRIES__") LookupAttributeInMRONode getMroEntries,
19681968
@Cached CallBinaryMethodNode callMroEntries) {
19691969
ArrayList<Object> newBases = null;
19701970
for (int i = 0; i < nargs; i++) {
19711971
Object base = arguments[i];
1972-
if (PGuards.isClass(base, interop)) {
1972+
if (IsTypeNode.getUncached().execute(base)) {
19731973
if (newBases != null) {
19741974
// If we already have made a replacement, then we append every normal base,
19751975
// otherwise just skip it.
@@ -1985,7 +1985,7 @@ PTuple update(VirtualFrame frame, PTuple bases, Object[] arguments, int nargs,
19851985
}
19861986
continue;
19871987
}
1988-
Object newBase = callMroEntries.executeObject(frame, meth, base, bases);
1988+
Object newBase = callMroEntries.executeObject(null, meth, base, bases);
19891989
if (newBase == null) {
19901990
// error
19911991
return null;
@@ -2051,13 +2051,10 @@ Object calculate(Object metatype, PTuple bases,
20512051
@Builtin(name = BuiltinNames.__BUILD_CLASS__, minNumOfPositionalArgs = 1, takesVarArgs = true, takesVarKeywordArgs = true)
20522052
@GenerateNodeFactory
20532053
public abstract static class BuildClassNode extends PythonVarargsBuiltinNode {
2054-
@Child private com.oracle.graal.python.nodes.call.CallNode callNode = com.oracle.graal.python.nodes.call.CallNode.create();
20552054

20562055
@Specialization
20572056
protected Object doItNonFunction(VirtualFrame frame, Object function, Object[] arguments, PKeyword[] keywords,
20582057
@CachedContext(PythonLanguage.class) ContextReference<PythonContext> contextRef,
2059-
@CachedLibrary(limit = "3") InteropLibrary interop,
2060-
@Cached CastToJavaStringNode castToString,
20612058
@Cached PythonObjectFactory factory,
20622059
@Cached CalculateMetaclassNode calculateMetaClass,
20632060
@Cached(parameters = "__PREPARE__") LookupAttributeInMRONode getPrepare,
@@ -2070,84 +2067,91 @@ protected Object doItNonFunction(VirtualFrame frame, Object function, Object[] a
20702067
@Cached SetItemNode setOrigBases,
20712068
@Cached GetClassNode getClass) {
20722069

2073-
boolean isClass = false;
2070+
class InitializeBuildClass {
2071+
String name;
2072+
boolean isClass;
2073+
Object meta;
2074+
PKeyword[] mkw;
2075+
PTuple bases;
2076+
PTuple origBases;
2077+
2078+
@TruffleBoundary
2079+
InitializeBuildClass() {
2080+
if (arguments.length < 1) {
2081+
throw raise(PythonErrorType.TypeError, "__build_class__: not enough arguments");
2082+
}
20742083

2075-
if (arguments.length < 1) {
2076-
throw raise(PythonErrorType.TypeError, "__build_class__: not enough arguments");
2077-
}
2084+
if (!PGuards.isFunction(function)) {
2085+
throw raise(PythonErrorType.TypeError, "__build_class__: func must be a function");
2086+
}
2087+
try {
2088+
name = CastToJavaStringNode.getUncached().execute(arguments[0]);
2089+
} catch (CannotCastException e) {
2090+
throw raise(PythonErrorType.TypeError, "__build_class__: name is not a string");
2091+
}
20782092

2079-
if (!PGuards.isFunction(function)) {
2080-
throw raise(PythonErrorType.TypeError, "__build_class__: func must be a function");
2081-
}
2082-
String name;
2083-
try {
2084-
name = castToString.execute(arguments[0]);
2085-
} catch (CannotCastException e) {
2086-
throw raise(PythonErrorType.TypeError, "__build_class__: name is not a string");
2087-
}
2093+
Object[] basesArray = Arrays.copyOfRange(arguments, 1, arguments.length);
2094+
origBases = factory.createTuple(basesArray);
20882095

2089-
Object[] basesArray = Arrays.copyOfRange(arguments, 1, arguments.length);
2090-
PTuple origBases = factory.createTuple(basesArray);
2096+
bases = update.execute(origBases, basesArray, basesArray.length);
20912097

2092-
PTuple bases = update.execute(frame, origBases, basesArray, basesArray.length);
2098+
mkw = keywords;
2099+
for (int i = 0; i < keywords.length; i++) {
2100+
if ("metaclass".equals(keywords[i].getName())) {
2101+
meta = keywords[i].getValue();
2102+
mkw = new PKeyword[keywords.length - 1];
20932103

2094-
Object meta = null;
2095-
PKeyword[] mkw = keywords;
2096-
if (keywords.length > 0) {
2097-
for (int i = 0; i < keywords.length; i++) {
2098-
if ("metaclass".equals(keywords[i].getName())) {
2099-
meta = keywords[i].getValue();
2100-
mkw = new PKeyword[keywords.length - 1];
2101-
System.arraycopy(keywords, 0, mkw, 0, i);
2102-
System.arraycopy(keywords, i + 1, mkw, i, mkw.length - i);
2104+
PythonUtils.arraycopy(keywords, 0, mkw, 0, i);
2105+
PythonUtils.arraycopy(keywords, i + 1, mkw, i, mkw.length - i);
21032106

2104-
// metaclass is explicitly given, check if it's indeed a class
2105-
isClass = PGuards.isClass(meta, interop);
2106-
break;
2107+
// metaclass is explicitly given, check if it's indeed a class
2108+
isClass = IsTypeNode.getUncached().equals(meta);
2109+
break;
2110+
}
21072111
}
2112+
if (meta == null) {
2113+
// if there are no bases, use type:
2114+
if (bases.getSequenceStorage().length() == 0) {
2115+
meta = contextRef.get().getCore().lookupType(PythonBuiltinClassType.PythonClass);
2116+
} else {
2117+
// else get the type of the first base
2118+
meta = getClass.execute(bases.getSequenceStorage().getItemNormalized(0));
2119+
}
2120+
isClass = true; // meta is really a class
2121+
}
2122+
if (isClass) {
2123+
// meta is really a class, so check for a more derived metaclass, or
2124+
// possible
2125+
// metaclass conflicts:
2126+
meta = calculateMetaClass.execute(meta, bases);
2127+
}
2128+
// else: meta is not a class, so we cannot do the metaclass calculation, so we
2129+
// will
2130+
// use the explicitly given object as it is
21082131
}
21092132
}
2110-
if (meta == null) {
2111-
// if there are no bases, use type:
2112-
if (bases.getSequenceStorage().length() == 0) {
2113-
meta = contextRef.get().getCore().lookupType(PythonBuiltinClassType.PythonClass);
2114-
} else {
2115-
// else get the type of the first base
2116-
meta = getClass.execute(bases.getSequenceStorage().getItemNormalized(0));
2117-
}
2118-
isClass = true; // meta is really a class
2119-
}
2133+
InitializeBuildClass init = new InitializeBuildClass();
21202134

2121-
if (isClass) {
2122-
// meta is really a class, so check for a more derived metaclass, or possible
2123-
// metaclass conflicts:
2124-
meta = calculateMetaClass.execute(meta, bases);
2125-
}
2126-
// else: meta is not a class, so we cannot do the metaclass calculation, so we will
2127-
// use the explicitly given object as it is
2128-
Object prep = getPrepare.execute(meta);
2135+
Object prep = getPrepare.execute(init.meta);
21292136
Object ns;
21302137
if (PGuards.isNoValue(prep)) {
21312138
ns = factory.createDict();
21322139
} else {
2133-
if (PGuards.isFunction(prep)) {
2134-
ns = callPrep.execute(frame, prep, new Object[]{name, bases}, mkw);
2135-
} else {
2136-
ns = callPrep.execute(frame, prep, new Object[]{meta, name, bases}, mkw);
2137-
}
2140+
Object[] args = PGuards.isFunction(prep) ? new Object[]{init.name, init.bases} : new Object[]{init.meta, init.name, init.bases};
2141+
ns = callPrep.execute(frame, prep, args, init.mkw);
21382142
}
21392143
if (PGuards.isNoValue(getGetItem.execute(getGetItemClass.execute(ns)))) {
2140-
if (isClass) {
2141-
throw raise(PythonErrorType.TypeError, "%p.__prepare__() must return a mapping, not %p", meta, ns);
2144+
if (init.isClass) {
2145+
throw raise(PythonErrorType.TypeError, "%p.__prepare__() must return a mapping, not %p", init.meta, ns);
21422146
} else {
21432147
throw raise(PythonErrorType.TypeError, "<metaclass>.__prepare__() must return a mapping, not %p", ns);
21442148
}
21452149
}
21462150
callBody.executeObject(frame, function, ns);
2147-
if (bases != origBases) {
2148-
setOrigBases.executeWith(frame, ns, SpecialAttributeNames.__ORIG_BASES__, origBases);
2151+
if (init.bases != init.origBases) {
2152+
setOrigBases.executeWith(frame, ns, SpecialAttributeNames.__ORIG_BASES__, init.origBases);
21492153
}
2150-
Object cls = callType.execute(frame, meta, new Object[]{name, bases, ns}, mkw);
2154+
Object cls = callType.execute(frame, init.meta, new Object[]{init.name, init.bases, ns}, init.mkw);
21512155

21522156
/*
21532157
* We could check here and throw "__class__ not set defining..." errors.

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/str/StringUtils.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,11 @@ public static String strip(String str, String chars, StripKind stripKind) {
213213
return str.substring(i, j);
214214
}
215215

216+
@TruffleBoundary
217+
public static boolean equalsBoundary(String a, String b) {
218+
return a.equals(b);
219+
}
220+
216221
@TruffleBoundary
217222
public static boolean containsNullCharacter(String value) {
218223
return value.indexOf(0) > 0;

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1360,7 +1360,12 @@ public abstract static class IsTypeNode extends Node {
13601360
public abstract boolean execute(Object obj);
13611361

13621362
@Specialization
1363-
boolean doManagedClass(@SuppressWarnings("unused") PythonManagedClass obj) {
1363+
boolean doManagedClass(@SuppressWarnings("unused") PythonClass obj) {
1364+
return true;
1365+
}
1366+
1367+
@Specialization
1368+
boolean doManagedClass(@SuppressWarnings("unused") PythonBuiltinClass obj) {
13641369
return true;
13651370
}
13661371

0 commit comments

Comments
 (0)