|
54 | 54 | import com.oracle.graal.python.builtins.objects.cext.CExtNodes.ConvertArgsToSulongNode;
|
55 | 55 | import com.oracle.graal.python.builtins.objects.cext.CExtNodes.SubRefCntNode;
|
56 | 56 | import com.oracle.graal.python.builtins.objects.cext.CExtNodes.ToJavaStealingNode;
|
| 57 | +import com.oracle.graal.python.builtins.objects.cext.CExtNodes.ToNewRefNode; |
57 | 58 | import com.oracle.graal.python.builtins.objects.cext.CExtNodesFactory.ToJavaStealingNodeGen;
|
58 | 59 | import com.oracle.graal.python.builtins.objects.cext.common.CExtCommonNodes.ConvertPIntToPrimitiveNode;
|
59 | 60 | import com.oracle.graal.python.builtins.objects.cext.common.CExtCommonNodesFactory.ConvertPIntToPrimitiveNodeGen;
|
| 61 | +import com.oracle.graal.python.builtins.objects.cext.CExtNodesFactory.ToNewRefNodeGen; |
60 | 62 | import com.oracle.graal.python.builtins.objects.cext.DynamicObjectNativeWrapper;
|
61 | 63 | import com.oracle.graal.python.builtins.objects.cext.PythonNativeWrapper;
|
62 | 64 | import com.oracle.graal.python.builtins.objects.cext.PythonNativeWrapperLibrary;
|
@@ -1030,24 +1032,46 @@ abstract static class CreateArgsTupleNode extends Node {
|
1030 | 1032 | @ExplodeLoop(kind = LoopExplosionKind.FULL_UNROLL)
|
1031 | 1033 | static PTuple doCachedLen(PythonObjectFactory factory, Object[] args,
|
1032 | 1034 | @Cached("args.length") int cachedLen,
|
| 1035 | + @Cached("createToNewRefNodes(args.length)") ToNewRefNode[] toNewRefNodes, |
1033 | 1036 | @Cached("createMaterializeNodes(args.length)") MaterializePrimitiveNode[] materializePrimitiveNodes) {
|
1034 | 1037 |
|
1035 | 1038 | for (int i = 0; i < cachedLen; i++) {
|
1036 |
| - args[i] = materializePrimitiveNodes[i].execute(factory, args[i]); |
| 1039 | + args[i] = prepareReference(args[i], factory, materializePrimitiveNodes[i], toNewRefNodes[i]); |
1037 | 1040 | }
|
1038 | 1041 | return factory.createTuple(args);
|
1039 | 1042 | }
|
1040 | 1043 |
|
1041 | 1044 | @Specialization(replaces = "doCachedLen")
|
1042 | 1045 | static PTuple doGeneric(PythonObjectFactory factory, Object[] args,
|
| 1046 | + @Cached ToNewRefNode toNewRefNode, |
1043 | 1047 | @Cached MaterializePrimitiveNode materializePrimitiveNode) {
|
1044 | 1048 |
|
1045 | 1049 | for (int i = 0; i < args.length; i++) {
|
1046 |
| - args[i] = materializePrimitiveNode.execute(factory, args[i]); |
| 1050 | + args[i] = prepareReference(args[i], factory, materializePrimitiveNode, toNewRefNode); |
1047 | 1051 | }
|
1048 | 1052 | return factory.createTuple(args);
|
1049 | 1053 | }
|
1050 | 1054 |
|
| 1055 | + private static Object prepareReference(Object arg, PythonObjectFactory factory, MaterializePrimitiveNode materializePrimitiveNode, ToNewRefNode toNewRefNode) { |
| 1056 | + Object result = materializePrimitiveNode.execute(factory, arg); |
| 1057 | + |
| 1058 | + // Tuples are actually stealing the reference of their items. That's why we need to |
| 1059 | + // increase the reference count by 1 at this point. However, it could be that the |
| 1060 | + // object does not have a native wrapper yet. We use ToNewRefNode to ensure that the |
| 1061 | + // object has a native wrapper or to increase the reference count by 1 if a native |
| 1062 | + // wrapper already exists. |
| 1063 | + toNewRefNode.execute(result); |
| 1064 | + return result; |
| 1065 | + } |
| 1066 | + |
| 1067 | + static ToNewRefNode[] createToNewRefNodes(int length) { |
| 1068 | + ToNewRefNode[] newRefNodes = new ToNewRefNode[length]; |
| 1069 | + for (int i = 0; i < length; i++) { |
| 1070 | + newRefNodes[i] = ToNewRefNodeGen.create(); |
| 1071 | + } |
| 1072 | + return newRefNodes; |
| 1073 | + } |
| 1074 | + |
1051 | 1075 | static MaterializePrimitiveNode[] createMaterializeNodes(int length) {
|
1052 | 1076 | MaterializePrimitiveNode[] materializePrimitiveNodes = new MaterializePrimitiveNode[length];
|
1053 | 1077 | for (int i = 0; i < length; i++) {
|
|
0 commit comments