Skip to content

Commit 46d6e69

Browse files
author
rocky
committed
Improve graal 3.12 bytecode handling
1 parent 8833867 commit 46d6e69

File tree

3 files changed

+54
-5
lines changed

3 files changed

+54
-5
lines changed

xdis/lineoffsets_graal.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,15 @@ def __init__(
8282
self.next_column = start_column
8383
self.next_line = start_line
8484
offset = 0
85+
# print(f"XXX0 len: {n}") # debug
8586
while offset < n:
8687

8788
# code[offset] is an int 0..255 in Python 3 when indexing bytes
89+
# print(f"offset: {offset}") # debug
8890
op_byte = bytecode[offset]
91+
# print(f"{opc.opname[op_byte]}") # debug
8992
op_len = arg_counts[op_byte] + 1
93+
# print(f"op_len: {op_len}") # debug
9094

9195
try:
9296
start_line, start_column = self._next_line_and_column()

xdis/opcodes/opcode_312graal.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,7 @@
551551
#
552552
# Pushes: the cell object
553553
#
554-
free_op_graal(loc, "LOAD_CLOSURE", 81, 1, 0, 1)
554+
free_op_graal(loc, "LOAD_CLOSURE", 0x52, 1, 0, 1)
555555
#
556556
# Reduces multiple stack items into an array of cell objects.
557557
#
@@ -560,7 +560,7 @@
560560
# Pushes: cell object array ({@code PCell[]})
561561
#
562562
def_op_graal(
563-
loc, "CLOSURE_FROM_STACK", 82, 1
563+
loc, "CLOSURE_FROM_STACK", 0x53, 1
564564
) # , (oparg, followingArgs, withJump) -> oparg, 1)
565565
#
566566
# Creates a function object. The first immediate argument is an index to the constants array

xdis/unmarshal.py

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
import io
3030
import marshal
3131
import sys
32-
from struct import unpack
32+
from struct import unpack, unpack_from
3333
from types import EllipsisType
3434
from typing import Any, Dict, Tuple, Union
3535

@@ -147,6 +147,9 @@ def long(n: int) -> LongTypeForPython3:
147147
TYPE_UNKNOWN: "unknown",
148148
}
149149

150+
# Used by graal
151+
JAVA_MARSHAL_SHIFT = 15
152+
JAVA_MARSHAL_BASE = 1 << JAVA_MARSHAL_SHIFT
150153

151154
def compat_str(s: Union[str, bytes]) -> Union[str, bytes]:
152155
"""
@@ -244,8 +247,8 @@ def t_graal_readArray(self, save_ref: bool, bytes_for_s: bool) -> tuple:
244247
# print(marshal_type) # debug
245248

246249
match marshal_type:
247-
# case "B":
248-
# ret = tuple()
250+
case "B":
251+
ret = self.graal_readBigInteger()
249252
# case "b":
250253
# return "OK"
251254
case "d":
@@ -269,6 +272,48 @@ def t_graal_readArray(self, save_ref: bool, bytes_for_s: bool) -> tuple:
269272
self.intern_objects.append(ret)
270273
return ret
271274

275+
def graal_readBigInteger(self):
276+
"""
277+
Reads a marshaled big integer from the input stream.
278+
"""
279+
negative = False
280+
sz = self.graal_readInt() # Get the size in shorts
281+
if sz < 0:
282+
negative = True
283+
sz = -sz
284+
285+
# size is in shorts, convert to size in bytes
286+
sz *= 2
287+
288+
data = bytes([self.graal_readByte() for _ in range(sz)])
289+
290+
i = 0
291+
292+
# Read the first 2 bytes as a 16-bit signed integer (short)
293+
# '>h' specifies big-endian signed short
294+
digit = unpack_from('>h', data, i)[0]
295+
i += 2
296+
297+
# Python int handles arbitrarily large numbers
298+
result = digit
299+
300+
while i < sz:
301+
# Calculate the power based on the number of shorts processed so far
302+
power = i // 2
303+
# Read the next 2 bytes as a 16-bit signed integer
304+
digit = unpack_from('>h', data, i)[0]
305+
i += 2
306+
307+
# In Python, int supports all these operations directly
308+
# The Java code effectively reconstructs the number using base 2^16 (MARSHAL_BASE)
309+
term = digit * (JAVA_MARSHAL_BASE ** power)
310+
result += term
311+
312+
if negative:
313+
return -result
314+
else:
315+
return result
316+
272317
def graal_readByte(self) -> int:
273318
"""
274319
Python equivalent of Python Graal's readBytes() from

0 commit comments

Comments
 (0)