48
48
import com .oracle .graal .python .util .NumericSupport ;
49
49
import com .oracle .graal .python .util .OverflowException ;
50
50
import com .oracle .truffle .api .dsl .Cached ;
51
+ import com .oracle .truffle .api .dsl .Cached .Shared ;
51
52
import com .oracle .truffle .api .dsl .Specialization ;
52
53
import com .oracle .truffle .api .nodes .Node ;
54
+ import java .math .BigInteger ;
53
55
54
56
/**
55
57
* Namespace containing equivalent nodes of {@code _Pylong_XXX} private function from
@@ -111,17 +113,43 @@ static int doPInt(PInt value) {
111
113
public abstract static class PyLongAsByteArray extends Node {
112
114
public abstract byte [] execute (Object value , int size , boolean bigEndian );
113
115
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
+
114
137
@ 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 ) {
116
140
final byte [] bytes = new byte [size ];
117
141
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
+ }
119
147
return bytes ;
120
148
}
121
149
122
150
@ Specialization
123
151
static byte [] doPInt (PInt value , int size , boolean bigEndian ,
124
- @ Cached PRaiseNode raiseNode ) {
152
+ @ Shared ( "raiseNode" ) @ Cached PRaiseNode raiseNode ) {
125
153
final byte [] bytes = new byte [size ];
126
154
NumericSupport support = bigEndian ? NumericSupport .bigEndian () : NumericSupport .littleEndian ();
127
155
try {
@@ -140,14 +168,35 @@ static byte[] doPInt(PInt value, int size, boolean bigEndian,
140
168
public abstract static class PyLongFromByteArray extends Node {
141
169
public abstract Object execute (byte [] data , boolean bigEndian );
142
170
143
- protected boolean fitsInLong (byte [] data ) {
171
+ protected static boolean fitsInLong (byte [] data ) {
144
172
return data .length <= Long .BYTES ;
145
173
}
146
174
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
+
147
194
@ Specialization (guards = "fitsInLong(data)" )
148
- static Object doLong (byte [] data , boolean bigEndian ) {
195
+ static long doArbitraryBytesLong (byte [] data , boolean bigEndian ,
196
+ @ Cached PythonObjectFactory factory ) {
149
197
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 );
151
200
}
152
201
153
202
@ Specialization (guards = "!fitsInLong(data)" )
0 commit comments