Skip to content

Commit 14eebb6

Browse files
committed
Use VarHandle and ByteArraySupport to read/write i16/i32/i64 values.
1 parent 8929585 commit 14eebb6

File tree

1 file changed

+45
-39
lines changed

1 file changed

+45
-39
lines changed

wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/BinaryStreamParser.java

Lines changed: 45 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -42,19 +42,28 @@
4242

4343
import static com.oracle.truffle.api.nodes.ExplodeLoop.LoopExplosionKind.FULL_EXPLODE_UNTIL_RETURN;
4444

45+
import java.lang.invoke.MethodHandles;
46+
import java.lang.invoke.VarHandle;
47+
import java.nio.ByteOrder;
48+
import java.util.Arrays;
49+
4550
import org.graalvm.wasm.constants.GlobalModifier;
4651
import org.graalvm.wasm.exception.Failure;
4752
import org.graalvm.wasm.exception.WasmException;
4853

54+
import com.oracle.truffle.api.CompilerDirectives;
4955
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
56+
import com.oracle.truffle.api.memory.ByteArraySupport;
5057
import com.oracle.truffle.api.nodes.ExplodeLoop;
5158

52-
import java.util.Arrays;
53-
5459
public abstract class BinaryStreamParser {
5560
protected static final int SINGLE_RESULT_VALUE = 0;
5661
protected static final int MULTI_RESULT_VALUE = 1;
5762

63+
private static final VarHandle I16LE = MethodHandles.byteArrayViewVarHandle(short[].class, ByteOrder.LITTLE_ENDIAN);
64+
private static final VarHandle I32LE = MethodHandles.byteArrayViewVarHandle(int[].class, ByteOrder.LITTLE_ENDIAN);
65+
private static final VarHandle I64LE = MethodHandles.byteArrayViewVarHandle(long[].class, ByteOrder.LITTLE_ENDIAN);
66+
5867
@CompilationFinal(dimensions = 1) protected byte[] data;
5968
protected int offset;
6069

@@ -353,7 +362,7 @@ public static byte peekLeb128Length(byte[] data, int initialOffset) {
353362

354363
/**
355364
* Reads the unsigned byte value at the given bytecode offset.
356-
*
365+
*
357366
* @param bytecode The bytecode
358367
* @param offset The offset in the bytecode
359368
* @return the unsigned byte value at the given bytecode offset.
@@ -364,7 +373,7 @@ public static int rawPeekU8(byte[] bytecode, int offset) {
364373

365374
/**
366375
* Reads the signed byte value at the given bytecode offset.
367-
*
376+
*
368377
* @param bytecode The bytecode
369378
* @param offset The offset in the bytecode
370379
* @return The signed byte value at the given bytecode offset.
@@ -375,27 +384,38 @@ public static byte rawPeekI8(byte[] bytecode, int offset) {
375384

376385
/**
377386
* Reads the unsigned short value at the given bytecode offset.
378-
*
387+
*
379388
* @param bytecode The bytecode
380389
* @param offset The offset in the bytecode
381390
* @return The unsigned short value at the given bytecode offset.
382391
*/
383392
public static int rawPeekU16(byte[] bytecode, int offset) {
384-
return ((bytecode[offset] & 0xFF) | ((bytecode[offset + 1] & 0xFF) << 8));
393+
return Short.toUnsignedInt(rawPeekI16(bytecode, offset));
394+
}
395+
396+
/**
397+
* Reads the signed short value at the given bytecode offset.
398+
*
399+
* @param bytecode The bytecode
400+
* @param offset The offset in the bytecode
401+
* @return The signed short value at the given bytecode offset.
402+
*/
403+
public static short rawPeekI16(byte[] bytecode, int offset) {
404+
if (CompilerDirectives.inCompiledCode()) {
405+
return ByteArraySupport.littleEndian().getShortUnaligned(bytecode, offset);
406+
}
407+
return (short) I16LE.get(bytecode, offset);
385408
}
386409

387410
/**
388411
* Writes the unsigned short value to the given bytecode offset.
389-
*
412+
*
390413
* @param bytecode The bytecode
391414
* @param offset The offset in the bytecode
392415
* @param value The value that should be written
393416
*/
394417
public static void writeU16(byte[] bytecode, int offset, int value) {
395-
final byte low = (byte) (value & 0xFF);
396-
final byte high = (byte) ((value >> 8) & 0xFF);
397-
bytecode[offset] = low;
398-
bytecode[offset + 1] = high;
418+
I16LE.set(bytecode, offset, (short) value);
399419
}
400420

401421
/**
@@ -406,60 +426,46 @@ public static void writeU16(byte[] bytecode, int offset, int value) {
406426
* @return The unsigned integer value at the given bytecode offset.
407427
*/
408428
public static long rawPeekU32(byte[] bytecode, int offset) {
409-
return (bytecode[offset] & 0xFFL) |
410-
((bytecode[offset + 1] & 0xFFL) << 8) |
411-
((bytecode[offset + 2] & 0xFFL) << 16) |
412-
((bytecode[offset + 3] & 0xFFL) << 24);
429+
return Integer.toUnsignedLong(rawPeekI32(bytecode, offset));
413430
}
414431

415432
/**
416433
* Reads the signed integer value at the given bytecode offset.
417-
*
434+
*
418435
* @param bytecode The bytecode
419436
* @param offset The offset in the bytecode.
420437
* @return The signed integer value at the given bytecode offset.
421438
*/
422439
public static int rawPeekI32(byte[] bytecode, int offset) {
423-
return (bytecode[offset] & 0xFF) |
424-
((bytecode[offset + 1] & 0xFF) << 8) |
425-
((bytecode[offset + 2] & 0xFF) << 16) |
426-
((bytecode[offset + 3] & 0xFF) << 24);
440+
if (CompilerDirectives.inCompiledCode()) {
441+
return ByteArraySupport.littleEndian().getIntUnaligned(bytecode, offset);
442+
}
443+
return (int) I32LE.get(bytecode, offset);
427444
}
428445

429446
/**
430447
* Reads the signed long value at the given bytecode offset.
431-
*
448+
*
432449
* @param bytecode The bytecode
433450
* @param offset The offset in the bytecode.
434451
* @return The signed long value at the given bytecode offset.
435452
*/
436453
public static long rawPeekI64(byte[] bytecode, int offset) {
437-
return (bytecode[offset] & 0xFFL) |
438-
((bytecode[offset + 1] & 0xFFL) << 8) |
439-
((bytecode[offset + 2] & 0xFFL) << 16) |
440-
((bytecode[offset + 3] & 0xFFL) << 24) |
441-
((bytecode[offset + 4] & 0xFFL) << 32) |
442-
((bytecode[offset + 5] & 0xFFL) << 40) |
443-
((bytecode[offset + 6] & 0xFFL) << 48) |
444-
((bytecode[offset + 7] & 0xFFL) << 56);
454+
if (CompilerDirectives.inCompiledCode()) {
455+
return ByteArraySupport.littleEndian().getLongUnaligned(bytecode, offset);
456+
}
457+
return (long) I64LE.get(bytecode, offset);
445458
}
446459

447460
/**
448461
* Writes the signed long value to the given bytecode offset.
449-
*
462+
*
450463
* @param bytecode The bytecode
451464
* @param offset The offset in the bytecode
452465
* @param value The value that should be written
453466
*/
454467
public static void writeI64(byte[] bytecode, int offset, long value) {
455-
bytecode[offset] = (byte) (value & 0xFF);
456-
bytecode[offset + 1] = (byte) ((value >> 8) & 0xFF);
457-
bytecode[offset + 2] = (byte) ((value >> 16) & 0xFF);
458-
bytecode[offset + 3] = (byte) ((value >> 24) & 0xFF);
459-
bytecode[offset + 4] = (byte) ((value >> 32) & 0xFF);
460-
bytecode[offset + 5] = (byte) ((value >> 40) & 0xFF);
461-
bytecode[offset + 6] = (byte) ((value >> 48) & 0xFF);
462-
bytecode[offset + 7] = (byte) ((value >> 56) & 0xFF);
468+
I64LE.set(bytecode, offset, value);
463469
}
464470

465471
/**

0 commit comments

Comments
 (0)