Skip to content

Commit ea73176

Browse files
committed
Merge bytecode handlers for call_indirect and call_ref
1 parent 03945cf commit ea73176

File tree

6 files changed

+89
-114
lines changed

6 files changed

+89
-114
lines changed

wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/BinaryParser.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -987,6 +987,7 @@ private CodeEntry readFunction(int functionIndex, int[] locals, int sourceCodeEn
987987
final int elementType = module.tableElementType(index);
988988
state.popChecked(I32_TYPE);
989989
state.push(elementType);
990+
state.addMiscFlag();
990991
state.addInstruction(Bytecode.TABLE_GET, index);
991992
break;
992993
}
@@ -996,6 +997,7 @@ private CodeEntry readFunction(int functionIndex, int[] locals, int sourceCodeEn
996997
final int elementType = module.tableElementType(index);
997998
state.popChecked(elementType);
998999
state.popChecked(I32_TYPE);
1000+
state.addMiscFlag();
9991001
state.addInstruction(Bytecode.TABLE_SET, index);
10001002
break;
10011003
}

wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/constants/Bytecode.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -333,8 +333,8 @@ public class Bytecode {
333333
public static final int REF_IS_NULL = 0xF7;
334334
public static final int REF_FUNC = 0xF8;
335335

336-
public static final int TABLE_GET = 0xF9;
337-
public static final int TABLE_SET = 0xFA;
336+
public static final int CALL_REF_U8 = 0xF9;
337+
public static final int CALL_REF_I32 = 0xFA;
338338

339339
public static final int MISC = 0xFB;
340340

@@ -376,8 +376,8 @@ public class Bytecode {
376376
public static final int THROW_REF = 0x1C;
377377

378378
// Typed function references opcodes
379-
public static final int CALL_REF_U8 = 0x1D;
380-
public static final int CALL_REF_I32 = 0x1E;
379+
public static final int TABLE_GET = 0x1D;
380+
public static final int TABLE_SET = 0x1E;
381381
public static final int REF_AS_NON_NULL = 0x1F;
382382
public static final int BR_ON_NULL_U8 = 0x20;
383383
public static final int BR_ON_NULL_I32 = 0x21;

wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/constants/StackEffects.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,8 @@ public final class StackEffects {
9191
// followed by throw
9292
miscOpStackEffects[Bytecode.THROW_REF] = UNREACHABLE; // unused, because stack effect is
9393
// followed by throw
94-
miscOpStackEffects[Bytecode.CALL_REF_U8] = UNREACHABLE; // unused, because stack effect is
95-
// variable
96-
miscOpStackEffects[Bytecode.CALL_REF_I32] = UNREACHABLE; // unused, because stack effect is
97-
// variable
94+
miscOpStackEffects[Bytecode.TABLE_GET] = NO_EFFECT;
95+
miscOpStackEffects[Bytecode.TABLE_SET] = POP_2;
9896
miscOpStackEffects[Bytecode.REF_AS_NON_NULL] = NO_EFFECT;
9997
miscOpStackEffects[Bytecode.BR_ON_NULL_U8] = UNREACHABLE; // unused, because stack effect is
10098
// dynamic

wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/nodes/WasmFunctionNode.java

Lines changed: 73 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -535,9 +535,9 @@ public Object executeBodyFromOffset(WasmInstance instance, VirtualFrame frame, i
535535
break;
536536
}
537537
case Bytecode.CALL_INDIRECT_U8:
538-
case Bytecode.CALL_INDIRECT_I32: {
539-
// Extract the function object.
540-
stackPointer--;
538+
case Bytecode.CALL_INDIRECT_I32:
539+
case Bytecode.CALL_REF_U8:
540+
case Bytecode.CALL_REF_I32: {
541541
final SymbolTable symtab = module.symbolTable();
542542

543543
final int callNodeIndex;
@@ -548,53 +548,83 @@ public Object executeBodyFromOffset(WasmInstance instance, VirtualFrame frame, i
548548
expectedFunctionTypeIndex = rawPeekU8(bytecode, offset + 1);
549549
tableIndex = rawPeekU8(bytecode, offset + 2);
550550
offset += 3;
551-
} else {
551+
} else if (opcode == Bytecode.CALL_INDIRECT_I32) {
552552
callNodeIndex = rawPeekI32(bytecode, offset);
553553
expectedFunctionTypeIndex = rawPeekI32(bytecode, offset + 4);
554554
tableIndex = rawPeekI32(bytecode, offset + 8);
555555
offset += 12;
556+
} else if (opcode == Bytecode.CALL_REF_U8) {
557+
callNodeIndex = rawPeekU8(bytecode, offset);
558+
expectedFunctionTypeIndex = rawPeekU8(bytecode, offset + 1);
559+
tableIndex = -1;
560+
offset += 2;
561+
} else {
562+
assert opcode == Bytecode.CALL_REF_I32;
563+
callNodeIndex = rawPeekI32(bytecode, offset);
564+
expectedFunctionTypeIndex = rawPeekI32(bytecode, offset + 4);
565+
tableIndex = -1;
566+
offset += 8;
556567
}
557-
final WasmTable table = instance.store().tables().table(instance.tableAddress(tableIndex));
558-
final Object[] elements = table.elements();
559-
final int elementIndex = popInt(frame, stackPointer);
560-
if (elementIndex < 0 || elementIndex >= elements.length) {
561-
enterErrorBranch();
562-
throw WasmException.format(Failure.UNDEFINED_ELEMENT, this, "Element index '%d' out of table bounds.", elementIndex);
563-
}
564-
// Currently, table elements may only be functions.
565-
// We can add a check here when this changes in the future.
566-
final Object element = elements[elementIndex];
567-
if (element == WasmConstant.NULL) {
568-
enterErrorBranch();
569-
throw WasmException.format(Failure.UNINITIALIZED_ELEMENT, this, "Table element at index %d is uninitialized.", elementIndex);
568+
569+
// Extract the function object.
570+
final Object functionCandidate;
571+
final int elementIndex;
572+
if (opcode == Bytecode.CALL_INDIRECT_U8 || opcode == Bytecode.CALL_INDIRECT_I32) {
573+
final WasmTable table = instance.store().tables().table(instance.tableAddress(tableIndex));
574+
final Object[] elements = table.elements();
575+
elementIndex = popInt(frame, --stackPointer);
576+
if (elementIndex < 0 || elementIndex >= elements.length) {
577+
enterErrorBranch();
578+
throw WasmException.format(Failure.UNDEFINED_ELEMENT, this, "Element index '%d' out of table bounds.", elementIndex);
579+
}
580+
// Currently, table elements may only be functions.
581+
// We can add a check here when this changes in the future.
582+
functionCandidate = elements[elementIndex];
583+
} else {
584+
assert opcode == Bytecode.CALL_REF_U8 || opcode == Bytecode.CALL_REF_I32;
585+
functionCandidate = popReference(frame, --stackPointer);
586+
elementIndex = -1;
570587
}
571588
final WasmFunctionInstance functionInstance;
572589
final WasmFunction function;
573590
final CallTarget target;
574591
final WasmContext functionInstanceContext;
575-
if (element instanceof WasmFunctionInstance) {
576-
functionInstance = (WasmFunctionInstance) element;
592+
if (functionCandidate == WasmConstant.NULL) {
593+
enterErrorBranch();
594+
if (opcode == Bytecode.CALL_INDIRECT_U8 || opcode == Bytecode.CALL_INDIRECT_I32) {
595+
throw WasmException.format(Failure.UNINITIALIZED_ELEMENT, this, "Table element at index %d is uninitialized.", elementIndex);
596+
} else {
597+
assert opcode == Bytecode.CALL_REF_U8 || opcode == Bytecode.CALL_REF_I32;
598+
throw WasmException.format(Failure.NULL_FUNCTION_REFERENCE, this, "Function reference is null");
599+
}
600+
} else if (functionCandidate instanceof WasmFunctionInstance) {
601+
functionInstance = (WasmFunctionInstance) functionCandidate;
577602
function = functionInstance.function();
578603
target = functionInstance.target();
579604
functionInstanceContext = functionInstance.context();
580605
} else {
581606
enterErrorBranch();
582-
throw WasmException.format(Failure.UNSPECIFIED_TRAP, this, "Unknown table element type: %s", element);
607+
if (opcode == Bytecode.CALL_INDIRECT_U8 || opcode == Bytecode.CALL_INDIRECT_I32) {
608+
throw WasmException.format(Failure.UNSPECIFIED_TRAP, this, "Unknown table element type: %s", functionCandidate);
609+
} else {
610+
assert opcode == Bytecode.CALL_REF_U8 || opcode == Bytecode.CALL_REF_I32;
611+
throw WasmException.format(Failure.UNSPECIFIED_TRAP, this, "Unknown function object: %s", functionCandidate);
612+
}
583613
}
584614

585-
int expectedTypeEquivalenceClass = symtab.equivalenceClass(expectedFunctionTypeIndex);
586-
587615
// Target function instance must be from the same context.
588616
assert functionInstanceContext == WasmContext.get(this);
589617

590-
// Validate that the target function type matches the expected type of the
591-
// indirect call. We first try if the types are equivalent using the
592-
// equivalence classes. If they are not equivalent, we run the full subtype
593-
// matching procedure.
594-
if (expectedTypeEquivalenceClass != function.typeEquivalenceClass() &&
595-
!symtab.closedTypeAt(expectedFunctionTypeIndex).isSupertypeOf(function.closedType())) {
596-
enterErrorBranch();
597-
failFunctionTypeCheck(function, expectedFunctionTypeIndex);
618+
if (opcode == Bytecode.CALL_INDIRECT_U8 || opcode == Bytecode.CALL_INDIRECT_I32) {
619+
// Validate that the target function type matches the expected type of
620+
// the indirect call. We first try if the types are equivalent using the
621+
// equivalence classes. If they are not equivalent, we run the full
622+
// subtype matching procedure.
623+
if (symtab.equivalenceClass(expectedFunctionTypeIndex) != function.typeEquivalenceClass() &&
624+
!symtab.closedTypeAt(expectedFunctionTypeIndex).isSupertypeOf(function.closedType())) {
625+
enterErrorBranch();
626+
failFunctionTypeCheck(function, expectedFunctionTypeIndex);
627+
}
598628
}
599629

600630
// Invoke the resolved function.
@@ -1509,19 +1539,6 @@ public Object executeBodyFromOffset(WasmInstance instance, VirtualFrame frame, i
15091539
offset += 4;
15101540
break;
15111541
}
1512-
case Bytecode.TABLE_GET: {
1513-
final int tableIndex = rawPeekI32(bytecode, offset);
1514-
table_get(instance, frame, stackPointer, tableIndex);
1515-
offset += 4;
1516-
break;
1517-
}
1518-
case Bytecode.TABLE_SET: {
1519-
final int tableIndex = rawPeekI32(bytecode, offset);
1520-
table_set(instance, frame, stackPointer, tableIndex);
1521-
stackPointer -= 2;
1522-
offset += 4;
1523-
break;
1524-
}
15251542
case Bytecode.MISC: {
15261543
final int miscOpcode = rawPeekU8(bytecode, offset);
15271544
offset++;
@@ -1548,51 +1565,6 @@ public Object executeBodyFromOffset(WasmInstance instance, VirtualFrame frame, i
15481565
assert exception instanceof WasmRuntimeException : "Only wasm exceptions can be thrown by throw_ref";
15491566
throw (WasmRuntimeException) exception;
15501567
}
1551-
case Bytecode.CALL_REF_U8:
1552-
case Bytecode.CALL_REF_I32: {
1553-
final int callNodeIndex;
1554-
final int expectedFunctionTypeIndex;
1555-
if (miscOpcode == Bytecode.CALL_REF_U8) {
1556-
callNodeIndex = rawPeekU8(bytecode, offset);
1557-
expectedFunctionTypeIndex = rawPeekU8(bytecode, offset + 1);
1558-
offset += 2;
1559-
} else {
1560-
callNodeIndex = rawPeekI32(bytecode, offset);
1561-
expectedFunctionTypeIndex = rawPeekI32(bytecode, offset + 4);
1562-
offset += 8;
1563-
}
1564-
1565-
// Extract the function object.
1566-
final WasmFunctionInstance functionInstance;
1567-
final CallTarget target;
1568-
final WasmContext functionInstanceContext;
1569-
final Object functionOrNull = popReference(frame, --stackPointer);
1570-
if (functionOrNull == WasmConstant.NULL) {
1571-
enterErrorBranch();
1572-
throw WasmException.format(Failure.NULL_FUNCTION_REFERENCE, this, "Function reference is null");
1573-
} else if (functionOrNull instanceof WasmFunctionInstance) {
1574-
functionInstance = (WasmFunctionInstance) functionOrNull;
1575-
target = functionInstance.target();
1576-
functionInstanceContext = functionInstance.context();
1577-
} else {
1578-
enterErrorBranch();
1579-
throw WasmException.format(Failure.UNSPECIFIED_TRAP, this, "Unknown function object: %s", functionOrNull);
1580-
}
1581-
1582-
// Target function instance must be from the same context.
1583-
assert functionInstanceContext == WasmContext.get(this);
1584-
1585-
// Invoke the resolved function.
1586-
int paramCount = module.symbolTable().functionTypeParamCount(expectedFunctionTypeIndex);
1587-
Object[] args = createArgumentsForCall(frame, expectedFunctionTypeIndex, paramCount, stackPointer);
1588-
stackPointer -= paramCount;
1589-
WasmArguments.setModuleInstance(args, functionInstance.moduleInstance());
1590-
1591-
final Object result = executeIndirectCallNode(callNodeIndex, target, args);
1592-
stackPointer = pushIndirectCallResult(frame, stackPointer, expectedFunctionTypeIndex, result, WasmLanguage.get(this));
1593-
CompilerAsserts.partialEvaluationConstant(stackPointer);
1594-
break;
1595-
}
15961568
case Bytecode.BR_ON_NULL_U8: {
15971569
Object reference = popReference(frame, --stackPointer);
15981570
if (profileCondition(bytecode, offset + 1, reference == WasmConstant.NULL)) {
@@ -2271,6 +2243,19 @@ private int executeMisc(WasmInstance instance, VirtualFrame frame, int startingO
22712243
pushLong(frame, stackPointer - 1, previousSize);
22722244
break;
22732245
}
2246+
case Bytecode.TABLE_GET: {
2247+
final int tableIndex = rawPeekI32(bytecode, offset);
2248+
table_get(instance, frame, stackPointer, tableIndex);
2249+
offset += 4;
2250+
break;
2251+
}
2252+
case Bytecode.TABLE_SET: {
2253+
final int tableIndex = rawPeekI32(bytecode, offset);
2254+
table_set(instance, frame, stackPointer, tableIndex);
2255+
stackPointer -= 2;
2256+
offset += 4;
2257+
break;
2258+
}
22742259
case Bytecode.REF_AS_NON_NULL: {
22752260
Object reference = popReference(frame, stackPointer - 1);
22762261
if (reference == WasmConstant.NULL) {

wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/parser/bytecode/BytecodeParser.java

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -483,12 +483,14 @@ private static List<CallNode> readCallNodes(byte[] bytecode, int startOffset, in
483483
offset += 8;
484484
break;
485485
}
486-
case Bytecode.CALL_INDIRECT_U8: {
486+
case Bytecode.CALL_INDIRECT_U8:
487+
case Bytecode.CALL_REF_U8: {
487488
callNodes.add(new CallNode(originalOffset));
488489
offset += 3;
489490
break;
490491
}
491-
case Bytecode.CALL_INDIRECT_I32: {
492+
case Bytecode.CALL_INDIRECT_I32:
493+
case Bytecode.CALL_REF_I32: {
492494
callNodes.add(new CallNode(originalOffset));
493495
offset += 12;
494496
break;
@@ -722,9 +724,7 @@ private static List<CallNode> readCallNodes(byte[] bytecode, int startOffset, in
722724
case Bytecode.I64_STORE_32_I32:
723725
case Bytecode.I32_CONST_I32:
724726
case Bytecode.F32_CONST:
725-
case Bytecode.REF_FUNC:
726-
case Bytecode.TABLE_GET:
727-
case Bytecode.TABLE_SET: {
727+
case Bytecode.REF_FUNC: {
728728
offset += 4;
729729
break;
730730
}
@@ -797,16 +797,6 @@ private static List<CallNode> readCallNodes(byte[] bytecode, int startOffset, in
797797
int miscOpcode = rawPeekU8(bytecode, offset);
798798
offset++;
799799
switch (miscOpcode) {
800-
case Bytecode.CALL_REF_U8: {
801-
callNodes.add(new CallNode(originalOffset));
802-
offset += 3;
803-
break;
804-
}
805-
case Bytecode.CALL_REF_I32: {
806-
callNodes.add(new CallNode(originalOffset));
807-
offset += 12;
808-
break;
809-
}
810800
case Bytecode.I32_TRUNC_SAT_F32_S:
811801
case Bytecode.I32_TRUNC_SAT_F32_U:
812802
case Bytecode.I32_TRUNC_SAT_F64_S:
@@ -832,7 +822,9 @@ private static List<CallNode> readCallNodes(byte[] bytecode, int startOffset, in
832822
case Bytecode.TABLE_GROW:
833823
case Bytecode.TABLE_SIZE:
834824
case Bytecode.TABLE_FILL:
835-
case Bytecode.THROW: {
825+
case Bytecode.THROW:
826+
case Bytecode.TABLE_GET:
827+
case Bytecode.TABLE_SET: {
836828
offset += 4;
837829
break;
838830
}

0 commit comments

Comments
 (0)