|
144 | 144 | import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyContextFunctions.ReturnType;
|
145 | 145 | import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyNodes.HPyAttachFunctionTypeNode;
|
146 | 146 | import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyNodes.PCallHPyFunction;
|
| 147 | +import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyNodesFactory.HPyAsPythonObjectNodeGen; |
147 | 148 | import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyNodesFactory.HPyGetNativeSpacePointerNodeGen;
|
148 | 149 | import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyNodesFactory.HPyRaiseNodeGen;
|
149 | 150 | import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyNodesFactory.HPyTransformExceptionToNativeNodeGen;
|
150 | 151 | import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyNodesFactory.PCallHPyFunctionNodeGen;
|
151 | 152 | import com.oracle.graal.python.builtins.objects.cext.hpy.HPyExternalFunctionNodes.HPyCheckFunctionResultNode;
|
| 153 | +import com.oracle.graal.python.builtins.objects.common.EmptyStorage; |
| 154 | +import com.oracle.graal.python.builtins.objects.common.HashMapStorage; |
| 155 | +import com.oracle.graal.python.builtins.objects.common.HashingStorage; |
| 156 | +import com.oracle.graal.python.builtins.objects.common.HashingStorageLibrary; |
152 | 157 | import com.oracle.graal.python.builtins.objects.dict.PDict;
|
153 | 158 | import com.oracle.graal.python.builtins.objects.ellipsis.PEllipsis;
|
154 | 159 | import com.oracle.graal.python.builtins.objects.frame.PFrame;
|
155 | 160 | import com.oracle.graal.python.builtins.objects.function.PArguments;
|
156 | 161 | import com.oracle.graal.python.builtins.objects.function.Signature;
|
| 162 | +import com.oracle.graal.python.builtins.objects.list.PList; |
157 | 163 | import com.oracle.graal.python.builtins.objects.object.PythonObject;
|
158 | 164 | import com.oracle.graal.python.builtins.objects.type.PythonClass;
|
159 | 165 | import com.oracle.graal.python.builtins.objects.type.SpecialMethodSlot;
|
|
165 | 171 | import com.oracle.graal.python.lib.PyObjectSizeNodeGen;
|
166 | 172 | import com.oracle.graal.python.nodes.BuiltinNames;
|
167 | 173 | import com.oracle.graal.python.nodes.ErrorMessages;
|
| 174 | +import com.oracle.graal.python.nodes.PGuards; |
| 175 | +import com.oracle.graal.python.nodes.PRaiseNode; |
168 | 176 | import com.oracle.graal.python.nodes.PRootNode;
|
169 | 177 | import com.oracle.graal.python.nodes.attributes.LookupCallableSlotInMRONode;
|
170 | 178 | import com.oracle.graal.python.nodes.call.CallTargetInvokeNode;
|
171 | 179 | import com.oracle.graal.python.nodes.call.GenericInvokeNode;
|
| 180 | +import com.oracle.graal.python.nodes.call.special.CallTernaryMethodNode; |
172 | 181 | import com.oracle.graal.python.nodes.classes.IsSubtypeNodeGen;
|
173 | 182 | import com.oracle.graal.python.nodes.expression.BinaryArithmetic;
|
174 | 183 | import com.oracle.graal.python.nodes.expression.InplaceArithmetic;
|
|
185 | 194 | import com.oracle.graal.python.runtime.sequence.PSequence;
|
186 | 195 | import com.oracle.graal.python.runtime.sequence.storage.DoubleSequenceStorage;
|
187 | 196 | import com.oracle.graal.python.runtime.sequence.storage.IntSequenceStorage;
|
| 197 | +import com.oracle.graal.python.runtime.sequence.storage.LongSequenceStorage; |
| 198 | +import com.oracle.graal.python.runtime.sequence.storage.ObjectSequenceStorage; |
188 | 199 | import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage;
|
189 | 200 | import com.oracle.graal.python.util.PythonUtils;
|
190 | 201 | import com.oracle.truffle.api.CallTarget;
|
@@ -1212,6 +1223,8 @@ public enum Counter {
|
1212 | 1223 | UpcallClose,
|
1213 | 1224 | UpcallTrackerNew,
|
1214 | 1225 | UpcallGetItemI,
|
| 1226 | + UpcallSetItem, |
| 1227 | + UpcallSetItemI, |
1215 | 1228 | UpcallDup,
|
1216 | 1229 | UpcallNumberCheck,
|
1217 | 1230 | UpcallLength,
|
@@ -1384,29 +1397,152 @@ public final long ctxDup(long handle) {
|
1384 | 1397 | }
|
1385 | 1398 | }
|
1386 | 1399 |
|
1387 |
| - public final long ctxGetItemi(long handle, long idx) { |
| 1400 | + public final long ctxGetItemi(long handle, long lidx) { |
1388 | 1401 | Counter.UpcallGetItemI.increment();
|
1389 |
| - assert GraalHPyBoxing.isBoxedHandle(handle); |
1390 | 1402 | try {
|
| 1403 | + // If handle 'hSequence' is a boxed int or double, the object is not subscriptable. |
| 1404 | + if (!GraalHPyBoxing.isBoxedHandle(handle)) { |
| 1405 | + throw PRaiseNode.raiseUncached(null, PythonBuiltinClassType.TypeError, ErrorMessages.OBJ_NOT_SUBSCRIPTABLE, 0); |
| 1406 | + } |
1391 | 1407 | Object receiver = getObjectForHPyHandle(GraalHPyBoxing.unboxHandle(handle)).getDelegate();
|
1392 | 1408 | Object clazz = GetClassNode.getUncached().execute(receiver);
|
1393 | 1409 | if (clazz == PythonBuiltinClassType.PList || clazz == PythonBuiltinClassType.PTuple) {
|
| 1410 | + int idx = 0; |
| 1411 | + if (!com.oracle.graal.python.builtins.objects.ints.PInt.isIntRange(lidx)) { |
| 1412 | + throw PRaiseNode.raiseUncached(null, PythonBuiltinClassType.IndexError, ErrorMessages.CANNOT_FIT_P_INTO_INDEXSIZED_INT, lidx); |
| 1413 | + } |
1394 | 1414 | PSequence sequence = (PSequence) receiver;
|
1395 | 1415 | SequenceStorage storage = sequence.getSequenceStorage();
|
1396 | 1416 | if (storage instanceof IntSequenceStorage) {
|
1397 |
| - return GraalHPyBoxing.boxInt(((IntSequenceStorage) storage).getIntItemNormalized((int) idx)); |
| 1417 | + return GraalHPyBoxing.boxInt(((IntSequenceStorage) storage).getIntItemNormalized(idx)); |
1398 | 1418 | } else if (storage instanceof DoubleSequenceStorage) {
|
1399 |
| - return GraalHPyBoxing.boxDouble(((DoubleSequenceStorage) storage).getDoubleItemNormalized((int) idx)); |
| 1419 | + return GraalHPyBoxing.boxDouble(((DoubleSequenceStorage) storage).getDoubleItemNormalized(idx)); |
| 1420 | + } else if (storage instanceof LongSequenceStorage) { |
| 1421 | + long lresult = ((LongSequenceStorage) storage).getLongItemNormalized(idx); |
| 1422 | + if (com.oracle.graal.python.builtins.objects.ints.PInt.isIntRange(lresult)) { |
| 1423 | + return GraalHPyBoxing.boxInt((int) lresult); |
| 1424 | + } |
| 1425 | + return GraalHPyBoxing.boxHandle(createHandle(lresult).getId(this, ConditionProfile.getUncached())); |
| 1426 | + } else if (storage instanceof ObjectSequenceStorage) { |
| 1427 | + Object result = ((ObjectSequenceStorage) storage).getItemNormalized(idx); |
| 1428 | + return GraalHPyBoxing.boxHandle(createHandle(result).getId(this, ConditionProfile.getUncached())); |
1400 | 1429 | }
|
1401 | 1430 | // TODO: other storages...
|
1402 | 1431 | }
|
1403 |
| - Object result = PInteropSubscriptNode.getUncached().execute(receiver, idx); |
| 1432 | + Object result = PInteropSubscriptNode.getUncached().execute(receiver, lidx); |
1404 | 1433 | return GraalHPyBoxing.boxHandle(createHandle(result).getId(this, ConditionProfile.getUncached()));
|
1405 |
| - } catch (Throwable t) { |
1406 |
| - t.printStackTrace(); |
1407 |
| - System.exit(-1); |
1408 |
| - throw CompilerDirectives.shouldNotReachHere(); |
| 1434 | + } catch (PException e) { |
| 1435 | + HPyTransformExceptionToNativeNodeGen.getUncached().execute(this, e); |
| 1436 | + // NULL handle |
| 1437 | + return 0; |
| 1438 | + } |
| 1439 | + } |
| 1440 | + |
| 1441 | + /** |
| 1442 | + * HPy signature: {@code HPy_SetItem(HPyContext ctx, HPy obj, HPy key, HPy value)} |
| 1443 | + * |
| 1444 | + * @param hSequence |
| 1445 | + * @param hKey |
| 1446 | + * @param hValue |
| 1447 | + * @return {@code 0} on success; {@code -1} on error |
| 1448 | + */ |
| 1449 | + public final int ctxSetItem(long hSequence, long hKey, long hValue) { |
| 1450 | + Counter.UpcallSetItem.increment(); |
| 1451 | + try { |
| 1452 | + // If handle 'hSequence' is a boxed int or double, the object is not a sequence. |
| 1453 | + if (!GraalHPyBoxing.isBoxedHandle(hSequence)) { |
| 1454 | + throw PRaiseNode.raiseUncached(null, PythonBuiltinClassType.TypeError, ErrorMessages.OBJ_DOES_NOT_SUPPORT_ITEM_ASSIGMENT, 0); |
| 1455 | + } |
| 1456 | + Object receiver = getObjectForHPyHandle(GraalHPyBoxing.unboxHandle(hSequence)).getDelegate(); |
| 1457 | + Object clazz = GetClassNode.getUncached().execute(receiver); |
| 1458 | + Object key = HPyAsPythonObjectNodeGen.getUncached().execute(this, hKey); |
| 1459 | + Object value = HPyAsPythonObjectNodeGen.getUncached().execute(this, hValue); |
| 1460 | + |
| 1461 | + // fast path |
| 1462 | + if (clazz == PythonBuiltinClassType.PDict) { |
| 1463 | + PDict dict = (PDict) receiver; |
| 1464 | + HashingStorage dictStorage = dict.getDictStorage(); |
| 1465 | + |
| 1466 | + // super-fast path for string keys |
| 1467 | + if (key instanceof String) { |
| 1468 | + if (dictStorage instanceof EmptyStorage) { |
| 1469 | + dictStorage = PDict.createNewStorage(true, 1); |
| 1470 | + dict.setDictStorage(dictStorage); |
| 1471 | + } |
| 1472 | + |
| 1473 | + if (dictStorage instanceof HashMapStorage) { |
| 1474 | + ((HashMapStorage) dictStorage).put((String) key, null); |
| 1475 | + } |
| 1476 | + } else { |
| 1477 | + dict.setDictStorage(HashingStorageLibrary.getUncached().setItem(dictStorage, key, value)); |
| 1478 | + } |
| 1479 | + return 0; |
| 1480 | + } else if (clazz == PythonBuiltinClassType.PList && PGuards.isInteger(key) && ctxListSetItem(receiver, ((Number) key).longValue(), hValue)) { |
| 1481 | + return 0; |
| 1482 | + } |
| 1483 | + return setItemGeneric(receiver, clazz, key, value); |
| 1484 | + } catch (PException e) { |
| 1485 | + HPyTransformExceptionToNativeNodeGen.getUncached().execute(this, e); |
| 1486 | + // non-null value indicates an error |
| 1487 | + return -1; |
| 1488 | + } |
| 1489 | + } |
| 1490 | + |
| 1491 | + public final int ctxSetItemi(long hSequence, long lidx, long hValue) { |
| 1492 | + Counter.UpcallSetItemI.increment(); |
| 1493 | + try { |
| 1494 | + // If handle 'hSequence' is a boxed int or double, the object is not a sequence. |
| 1495 | + if (!GraalHPyBoxing.isBoxedHandle(hSequence)) { |
| 1496 | + throw PRaiseNode.raiseUncached(null, PythonBuiltinClassType.TypeError, ErrorMessages.OBJ_DOES_NOT_SUPPORT_ITEM_ASSIGMENT, 0); |
| 1497 | + } |
| 1498 | + Object receiver = getObjectForHPyHandle(GraalHPyBoxing.unboxHandle(hSequence)).getDelegate(); |
| 1499 | + Object clazz = GetClassNode.getUncached().execute(receiver); |
| 1500 | + |
| 1501 | + if (clazz == PythonBuiltinClassType.PList && ctxListSetItem(receiver, lidx, hValue)) { |
| 1502 | + return 0; |
| 1503 | + } |
| 1504 | + Object value = HPyAsPythonObjectNodeGen.getUncached().execute(this, hValue); |
| 1505 | + return setItemGeneric(receiver, clazz, lidx, value); |
| 1506 | + } catch (PException e) { |
| 1507 | + HPyTransformExceptionToNativeNodeGen.getUncached().execute(this, e); |
| 1508 | + // non-null value indicates an error |
| 1509 | + return -1; |
| 1510 | + } |
| 1511 | + } |
| 1512 | + |
| 1513 | + private boolean ctxListSetItem(Object receiver, long lidx, long hValue) { |
| 1514 | + // fast path for list |
| 1515 | + int idx = 0; |
| 1516 | + if (!com.oracle.graal.python.builtins.objects.ints.PInt.isIntRange(lidx)) { |
| 1517 | + throw PRaiseNode.raiseUncached(null, PythonBuiltinClassType.IndexError, ErrorMessages.CANNOT_FIT_P_INTO_INDEXSIZED_INT, lidx); |
| 1518 | + } |
| 1519 | + com.oracle.graal.python.builtins.objects.list.PList sequence = (PList) receiver; |
| 1520 | + SequenceStorage storage = sequence.getSequenceStorage(); |
| 1521 | + if (storage instanceof IntSequenceStorage && GraalHPyBoxing.isBoxedInt(hValue)) { |
| 1522 | + ((IntSequenceStorage) storage).setIntItemNormalized(idx, GraalHPyBoxing.unboxInt(hValue)); |
| 1523 | + return true; |
| 1524 | + } else if (storage instanceof DoubleSequenceStorage && GraalHPyBoxing.isBoxedDouble(hValue)) { |
| 1525 | + ((DoubleSequenceStorage) storage).setDoubleItemNormalized(idx, GraalHPyBoxing.unboxDouble(hValue)); |
| 1526 | + return true; |
| 1527 | + } else if (storage instanceof LongSequenceStorage && GraalHPyBoxing.isBoxedInt(hValue)) { |
| 1528 | + ((LongSequenceStorage) storage).setLongItemNormalized(idx, GraalHPyBoxing.unboxInt(hValue)); |
| 1529 | + return true; |
| 1530 | + } else if (storage instanceof ObjectSequenceStorage) { |
| 1531 | + Object value = getObjectForHPyHandle(GraalHPyBoxing.unboxHandle(hValue)).getDelegate(); |
| 1532 | + ((ObjectSequenceStorage) storage).setItemNormalized(idx, value); |
| 1533 | + return true; |
| 1534 | + } |
| 1535 | + // TODO: other storages... |
| 1536 | + return false; |
| 1537 | + } |
| 1538 | + |
| 1539 | + private static int setItemGeneric(Object receiver, Object clazz, Object key, Object value) { |
| 1540 | + Object setItemAttribute = LookupCallableSlotInMRONode.getUncached(SpecialMethodSlot.SetItem).execute(clazz); |
| 1541 | + if (setItemAttribute == PNone.NO_VALUE) { |
| 1542 | + throw PRaiseNode.raiseUncached(null, PythonBuiltinClassType.TypeError, ErrorMessages.OBJ_NOT_SUBSCRIPTABLE, receiver); |
1409 | 1543 | }
|
| 1544 | + CallTernaryMethodNode.getUncached().execute(null, setItemAttribute, receiver, key, value); |
| 1545 | + return 0; |
1410 | 1546 | }
|
1411 | 1547 |
|
1412 | 1548 | public final int ctxNumberCheck(long handle) {
|
|
0 commit comments