|
77 | 77 | import com.oracle.graal.python.builtins.Python3Core;
|
78 | 78 | import com.oracle.graal.python.builtins.PythonBuiltinClassType;
|
79 | 79 | import com.oracle.graal.python.builtins.PythonBuiltins;
|
| 80 | +import com.oracle.graal.python.builtins.modules.PythonCextBuiltinsFactory.CreateFunctionNodeGen; |
80 | 81 | import com.oracle.graal.python.builtins.objects.PNone;
|
81 | 82 | import com.oracle.graal.python.builtins.objects.bytes.BytesBuiltins;
|
82 | 83 | import com.oracle.graal.python.builtins.objects.bytes.BytesNodes;
|
@@ -3478,6 +3479,71 @@ static Object getOwner(AsPythonObjectNode asPythonObjectNode, Object primary) {
|
3478 | 3479 | }
|
3479 | 3480 | }
|
3480 | 3481 |
|
| 3482 | + /** |
| 3483 | + * Signature: {@code add_slot(primary, tpDict, name", cfunc, flags, wrapper, doc)} |
| 3484 | + */ |
| 3485 | + // directly called without landing function |
| 3486 | + @Builtin(name = "add_slot", minNumOfPositionalArgs = 1, takesVarArgs = true, takesVarKeywordArgs = true, declaresExplicitSelf = true) |
| 3487 | + @GenerateNodeFactory |
| 3488 | + abstract static class AddSlotNode extends PythonVarargsBuiltinNode { |
| 3489 | + |
| 3490 | + @Override |
| 3491 | + public final Object varArgExecute(VirtualFrame frame, Object self, Object[] arguments, PKeyword[] keywords) { |
| 3492 | + return execute(frame, self, arguments, keywords); |
| 3493 | + } |
| 3494 | + |
| 3495 | + @Specialization |
| 3496 | + int doWithPrimitives(@SuppressWarnings("unused") Object self, Object[] arguments, @SuppressWarnings("unused") PKeyword[] keywords, |
| 3497 | + @Cached TransformExceptionToNativeNode transformExceptionToNativeNode) { |
| 3498 | + try { |
| 3499 | + if (arguments.length != 7) { |
| 3500 | + CompilerDirectives.transferToInterpreterAndInvalidate(); |
| 3501 | + throw PRaiseNode.raiseUncached(this, TypeError, ErrorMessages.TAKES_EXACTLY_D_ARGUMENTS_D_GIVEN, "add_slot", 7, arguments.length); |
| 3502 | + } |
| 3503 | + addSlot(arguments[0], arguments[1], arguments[2], arguments[3], castInt(arguments[4]), castInt(arguments[5]), arguments[6], |
| 3504 | + AsPythonObjectNodeGen.getUncached(), CastToJavaStringNode.getUncached(), FromCharPointerNodeGen.getUncached(), InteropLibrary.getUncached(), |
| 3505 | + CreateFunctionNodeGen.getUncached(), WriteAttributeToDynamicObjectNode.getUncached(), HashingStorageLibrary.getUncached()); |
| 3506 | + return 0; |
| 3507 | + } catch (PException e) { |
| 3508 | + transformExceptionToNativeNode.execute(e); |
| 3509 | + return -1; |
| 3510 | + } |
| 3511 | + } |
| 3512 | + |
| 3513 | + @TruffleBoundary |
| 3514 | + private static void addSlot(Object clsPtr, Object tpDictPtr, Object namePtr, Object cfunc, int flags, int wrapper, Object docPtr, |
| 3515 | + AsPythonObjectNode asPythonObjectNode, |
| 3516 | + CastToJavaStringNode castToJavaStringNode, |
| 3517 | + FromCharPointerNode fromCharPointerNode, |
| 3518 | + InteropLibrary docPtrLib, |
| 3519 | + CreateFunctionNode createFunctionNode, |
| 3520 | + WriteAttributeToDynamicObjectNode writeDocNode, |
| 3521 | + HashingStorageLibrary dictStorageLib) { |
| 3522 | + Object clazz = asPythonObjectNode.execute(clsPtr); |
| 3523 | + PDict tpDict = castPDict(asPythonObjectNode.execute(tpDictPtr)); |
| 3524 | + |
| 3525 | + String memberName; |
| 3526 | + try { |
| 3527 | + memberName = castToJavaStringNode.execute(asPythonObjectNode.execute(namePtr)); |
| 3528 | + } catch (CannotCastException e) { |
| 3529 | + throw CompilerDirectives.shouldNotReachHere("Cannot cast member name to string"); |
| 3530 | + } |
| 3531 | + // note: 'doc' may be NULL; in this case, we would store 'None' |
| 3532 | + Object memberDoc = CharPtrToJavaObjectNode.run(docPtr, fromCharPointerNode, docPtrLib); |
| 3533 | + |
| 3534 | + // create wrapper descriptor |
| 3535 | + Object wrapperDescriptor = createFunctionNode.execute(memberName, cfunc, wrapper, clazz, flags, PythonObjectFactory.getUncached()); |
| 3536 | + writeDocNode.execute(wrapperDescriptor, SpecialAttributeNames.__DOC__, memberDoc); |
| 3537 | + |
| 3538 | + // add wrapper descriptor to tp_dict |
| 3539 | + HashingStorage dictStorage = tpDict.getDictStorage(); |
| 3540 | + HashingStorage updatedStorage = dictStorageLib.setItem(dictStorage, memberName, wrapperDescriptor); |
| 3541 | + if (dictStorage != updatedStorage) { |
| 3542 | + tpDict.setDictStorage(updatedStorage); |
| 3543 | + } |
| 3544 | + } |
| 3545 | + } |
| 3546 | + |
3481 | 3547 | // directly called without landing function
|
3482 | 3548 | @Builtin(name = "PyDescr_NewClassMethod", minNumOfPositionalArgs = 6, parameterNames = {"name", "doc", "flags", "wrapper", "cfunc", "primary"})
|
3483 | 3549 | @ArgumentClinic(name = "name", conversion = ArgumentClinic.ClinicConversion.String)
|
@@ -3993,25 +4059,25 @@ private static void addMember(PythonLanguage language, Object clsPtr, Object tpD
|
3993 | 4059 | tpDict.setDictStorage(updatedStorage);
|
3994 | 4060 | }
|
3995 | 4061 | }
|
| 4062 | + } |
3996 | 4063 |
|
3997 |
| - private static PDict castPDict(Object tpDictObj) { |
3998 |
| - if (tpDictObj instanceof PDict) { |
3999 |
| - return (PDict) tpDictObj; |
4000 |
| - } |
4001 |
| - throw CompilerDirectives.shouldNotReachHere("tp_dict object must be a Python dict"); |
| 4064 | + static PDict castPDict(Object tpDictObj) { |
| 4065 | + if (tpDictObj instanceof PDict) { |
| 4066 | + return (PDict) tpDictObj; |
4002 | 4067 | }
|
| 4068 | + throw CompilerDirectives.shouldNotReachHere("tp_dict object must be a Python dict"); |
| 4069 | + } |
4003 | 4070 |
|
4004 |
| - private static int castInt(Object object) { |
4005 |
| - if (object instanceof Integer) { |
4006 |
| - return (int) object; |
4007 |
| - } else if (object instanceof Long) { |
4008 |
| - long lval = (long) object; |
4009 |
| - if (PInt.isIntRange(lval)) { |
4010 |
| - return (int) lval; |
4011 |
| - } |
| 4071 | + static int castInt(Object object) { |
| 4072 | + if (object instanceof Integer) { |
| 4073 | + return (int) object; |
| 4074 | + } else if (object instanceof Long) { |
| 4075 | + long lval = (long) object; |
| 4076 | + if (PInt.isIntRange(lval)) { |
| 4077 | + return (int) lval; |
4012 | 4078 | }
|
4013 |
| - throw CompilerDirectives.shouldNotReachHere("expected Java int"); |
4014 | 4079 | }
|
| 4080 | + throw CompilerDirectives.shouldNotReachHere("expected Java int"); |
4015 | 4081 | }
|
4016 | 4082 |
|
4017 | 4083 | abstract static class CreateGetSetNode extends Node {
|
@@ -4101,9 +4167,8 @@ int doGeneric(Object cls, Object tpDict, String name, Object getter, Object sett
|
4101 | 4167 | @CachedLibrary(limit = "1") HashingStorageLibrary dictStorageLib,
|
4102 | 4168 | @Cached TransformExceptionToNativeNode transformExceptionToNativeNode) {
|
4103 | 4169 | try {
|
4104 |
| - GetSetDescriptor descr = createGetSetNode.execute(name, cls, getter, setter, doc, closure, |
4105 |
| - getLanguage(), factory()); |
4106 |
| - PDict dict = AddMemberNode.castPDict(asPythonObjectNode.execute(tpDict)); |
| 4170 | + GetSetDescriptor descr = createGetSetNode.execute(name, cls, getter, setter, doc, closure, getLanguage(), factory()); |
| 4171 | + PDict dict = PythonCextBuiltins.castPDict(asPythonObjectNode.execute(tpDict)); |
4107 | 4172 | HashingStorage dictStorage = dict.getDictStorage();
|
4108 | 4173 | HashingStorage updatedStorage = dictStorageLib.setItem(dictStorage, name, descr);
|
4109 | 4174 | if (dictStorage != updatedStorage) {
|
|
0 commit comments