|
76 | 76 |
|
77 | 77 | import com.oracle.graal.python.PythonLanguage;
|
78 | 78 | import com.oracle.graal.python.builtins.PythonBuiltinClassType;
|
| 79 | +import static com.oracle.graal.python.builtins.PythonBuiltinClassType.OverflowError; |
79 | 80 | import com.oracle.graal.python.builtins.modules.BuiltinFunctions;
|
80 | 81 | import com.oracle.graal.python.builtins.modules.MathGuards;
|
81 | 82 | import com.oracle.graal.python.builtins.modules.WarningsModuleBuiltins.WarnNode;
|
@@ -645,25 +646,32 @@ public boolean isSequence(@CachedLibrary("this") PythonObjectLibrary plib,
|
645 | 646 | public int lengthWithState(ThreadState state,
|
646 | 647 | @CachedLibrary("this") PythonObjectLibrary plib,
|
647 | 648 | @Shared("methodLib") @CachedLibrary(limit = "2") PythonObjectLibrary methodLib,
|
648 |
| - @Shared("gotState") @Cached ConditionProfile gotState, |
649 | 649 | @Exclusive @Cached ConditionProfile hasLen,
|
650 | 650 | @Exclusive @Cached ConditionProfile ltZero,
|
651 | 651 | @Shared("raise") @Cached PRaiseNode raiseNode,
|
652 |
| - @Exclusive @CachedLibrary(limit = "1") PythonObjectLibrary lib) { |
| 652 | + @Exclusive @CachedLibrary(limit = "1") PythonObjectLibrary lib, |
| 653 | + @Exclusive @Cached CastToJavaLongLossyNode toLong, |
| 654 | + @Exclusive @Cached ConditionProfile ignoreOverflow, |
| 655 | + @Exclusive @Cached BranchProfile overflow) { |
653 | 656 | Object lenFunc = plib.lookupAttributeOnType(this, __LEN__);
|
654 | 657 | if (hasLen.profile(lenFunc != PNone.NO_VALUE)) {
|
655 | 658 | Object lenResult = methodLib.callUnboundMethodWithState(lenFunc, state, this);
|
656 |
| - int len; |
657 |
| - if (gotState.profile(state == null)) { |
658 |
| - len = lib.asSize(lenResult); |
659 |
| - } else { |
660 |
| - len = lib.asSizeWithState(lenResult, state); |
661 |
| - } |
662 |
| - if (ltZero.profile(len < 0)) { |
663 |
| - throw raiseNode.raise(PythonBuiltinClassType.ValueError, ErrorMessages.LEN_SHOULD_RETURN_MT_ZERO); |
664 |
| - } else { |
665 |
| - return len; |
| 659 | + // the following mimics typeobject.c#slot_sq_length() |
| 660 | + // - PyNumber_Index is called first |
| 661 | + // - checked if negative |
| 662 | + // - PyNumber_AsSsize_t is called, in scope of which PyNumber_Index is called again |
| 663 | + lenResult = lib.asIndexWithState(lenResult, state); |
| 664 | + long longResult; |
| 665 | + try { |
| 666 | + longResult = toLong.execute(lenResult); // this is a lossy cast |
| 667 | + if (ltZero.profile(longResult < 0)) { |
| 668 | + throw raiseNode.raise(PythonBuiltinClassType.ValueError, ErrorMessages.LEN_SHOULD_RETURN_MT_ZERO); |
| 669 | + } |
| 670 | + } catch (CannotCastException e) { |
| 671 | + CompilerDirectives.transferToInterpreterAndInvalidate(); |
| 672 | + throw new IllegalStateException("cannot cast index to long - must not happen because then the #asIndex message impl should have raised"); |
666 | 673 | }
|
| 674 | + return longToInt(longResult, overflow, ignoreOverflow, OverflowError, raiseNode, lenResult); |
667 | 675 | } else {
|
668 | 676 | throw raiseNode.raiseHasNoLength(this);
|
669 | 677 | }
|
@@ -1105,6 +1113,10 @@ public int asSizeWithState(Object type, ThreadState state,
|
1105 | 1113 | CompilerDirectives.transferToInterpreterAndInvalidate();
|
1106 | 1114 | throw new IllegalStateException("cannot cast index to long - must not happen because then the #asIndex message impl should have raised");
|
1107 | 1115 | }
|
| 1116 | + return longToInt(longResult, overflow, ignoreOverflow, type, raise, result); |
| 1117 | + } |
| 1118 | + |
| 1119 | + private static int longToInt(long longResult, BranchProfile overflow, ConditionProfile ignoreOverflow, Object type, PRaiseNode raise, Object result) throws PException { |
1108 | 1120 | try {
|
1109 | 1121 | return PInt.intValueExact(longResult);
|
1110 | 1122 | } catch (OverflowException e) {
|
|
0 commit comments