4848import com .oracle .graal .python .util .NumericSupport ;
4949import com .oracle .graal .python .util .OverflowException ;
5050import com .oracle .truffle .api .dsl .Cached ;
51+ import com .oracle .truffle .api .dsl .Cached .Shared ;
5152import com .oracle .truffle .api .dsl .Specialization ;
5253import com .oracle .truffle .api .nodes .Node ;
54+ import java .math .BigInteger ;
5355
5456/**
5557 * Namespace containing equivalent nodes of {@code _Pylong_XXX} private function from
@@ -111,17 +113,43 @@ static int doPInt(PInt value) {
111113 public abstract static class PyLongAsByteArray extends Node {
112114 public abstract byte [] execute (Object value , int size , boolean bigEndian );
113115
116+ protected static int asWellSizedData (int len ) {
117+ switch (len ) {
118+ case 1 :
119+ case 2 :
120+ case 4 :
121+ case 8 :
122+ return len ;
123+ default :
124+ return -1 ;
125+ }
126+ }
127+
128+ @ Specialization (guards = "size == cachedDataLen" , limit = "4" )
129+ static byte [] doPrimitive (long value , int size , boolean bigEndian ,
130+ @ Cached ("asWellSizedData(size)" ) int cachedDataLen ) {
131+ final byte [] bytes = new byte [size ];
132+ NumericSupport support = bigEndian ? NumericSupport .bigEndian () : NumericSupport .littleEndian ();
133+ support .putLong (bytes , 0 , value , cachedDataLen );
134+ return bytes ;
135+ }
136+
114137 @ Specialization
115- static byte [] doLong (long value , int size , boolean bigEndian ) {
138+ static byte [] doArbitraryBytesLong (long value , int size , boolean bigEndian ,
139+ @ Shared ("raiseNode" ) @ Cached PRaiseNode raiseNode ) {
116140 final byte [] bytes = new byte [size ];
117141 NumericSupport support = bigEndian ? NumericSupport .bigEndian () : NumericSupport .littleEndian ();
118- support .putLong (bytes , 0 , value );
142+ try {
143+ support .putBigInteger (bytes , 0 , PInt .longToBigInteger (value ), size );
144+ } catch (OverflowException oe ) {
145+ throw raiseNode .raise (PythonBuiltinClassType .OverflowError , TOO_LARGE_TO_CONVERT , "int" );
146+ }
119147 return bytes ;
120148 }
121149
122150 @ Specialization
123151 static byte [] doPInt (PInt value , int size , boolean bigEndian ,
124- @ Cached PRaiseNode raiseNode ) {
152+ @ Shared ( "raiseNode" ) @ Cached PRaiseNode raiseNode ) {
125153 final byte [] bytes = new byte [size ];
126154 NumericSupport support = bigEndian ? NumericSupport .bigEndian () : NumericSupport .littleEndian ();
127155 try {
@@ -140,14 +168,35 @@ static byte[] doPInt(PInt value, int size, boolean bigEndian,
140168 public abstract static class PyLongFromByteArray extends Node {
141169 public abstract Object execute (byte [] data , boolean bigEndian );
142170
143- protected boolean fitsInLong (byte [] data ) {
171+ protected static boolean fitsInLong (byte [] data ) {
144172 return data .length <= Long .BYTES ;
145173 }
146174
175+ protected static int asWellSizedData (int len ) {
176+ switch (len ) {
177+ case 1 :
178+ case 2 :
179+ case 4 :
180+ case 8 :
181+ return len ;
182+ default :
183+ return -1 ;
184+ }
185+ }
186+
187+ @ Specialization (guards = "data.length == cachedDataLen" , limit = "4" )
188+ static Object doLong (byte [] data , boolean bigEndian ,
189+ @ Cached ("asWellSizedData(data.length)" ) int cachedDataLen ) {
190+ NumericSupport support = bigEndian ? NumericSupport .bigEndian () : NumericSupport .littleEndian ();
191+ return support .getLong (data , 0 , cachedDataLen );
192+ }
193+
147194 @ Specialization (guards = "fitsInLong(data)" )
148- static Object doLong (byte [] data , boolean bigEndian ) {
195+ static long doArbitraryBytesLong (byte [] data , boolean bigEndian ,
196+ @ Cached PythonObjectFactory factory ) {
149197 NumericSupport support = bigEndian ? NumericSupport .bigEndian () : NumericSupport .littleEndian ();
150- return support .getLong (data , 0 );
198+ BigInteger integer = support .getBigInteger (data , 0 );
199+ return PInt .longValue (integer );
151200 }
152201
153202 @ Specialization (guards = "!fitsInLong(data)" )
0 commit comments