Search in sources :

Example 16 with WasmMemory

use of org.graalvm.wasm.memory.WasmMemory in project graal by oracle.

the class WasmBlockNode method execute.

@Override
@BytecodeInterpreterSwitch
@BytecodeInterpreterSwitchBoundary
@ExplodeLoop(kind = ExplodeLoop.LoopExplosionKind.FULL_EXPLODE_UNTIL_RETURN)
@SuppressWarnings("UnusedAssignment")
public int execute(WasmContext context, VirtualFrame frame) {
    final WasmCodeEntry codeEntry = codeEntry();
    final int numLocals = codeEntry.numLocals();
    final byte[] data = codeEntry.data();
    final int[] intConstants = codeEntry.intConstants();
    final int[] profileCounters = codeEntry.profileCounters();
    final int blockByteLength = byteLength();
    final int offsetLimit = startOffset + blockByteLength;
    int childrenOffset = 0;
    int intConstantOffset = initialIntConstantOffset;
    int branchTableOffset = initialBranchTableOffset;
    int stackPointer = numLocals + initialStackPointer;
    int profileOffset = initialProfileOffset;
    int offset = startOffset;
    WasmMemory memory = instance().memory();
    check(data.length, (1 << 31) - 1);
    check(intConstants.length, (1 << 31) - 1);
    check(profileCounters.length, (1 << 31) - 1);
    int opcode = UNREACHABLE;
    while (offset < offsetLimit) {
        byte byteOpcode = BinaryStreamParser.rawPeek1(data, offset);
        opcode = byteOpcode & 0xFF;
        offset++;
        CompilerAsserts.partialEvaluationConstant(offset);
        switch(opcode) {
            case UNREACHABLE:
                errorBranch();
                throw WasmException.create(Failure.UNREACHABLE, this);
            case NOP:
                break;
            case BLOCK:
                {
                    WasmBlockNode block = (WasmBlockNode) children[childrenOffset];
                    // The unwind counter indicates how many levels up we need to branch from
                    // within the block.
                    int unwindCounter = block.execute(context, frame);
                    if (blockUnwindProfile.profile(unwindCounter > 0)) {
                        return unwindCounter - 1;
                    }
                    childrenOffset++;
                    offset += block.byteLength();
                    stackPointer += block.returnLength();
                    intConstantOffset += block.intConstantLength();
                    branchTableOffset += block.branchTableLength();
                    profileOffset += block.profileCount();
                    break;
                }
            case LOOP:
                {
                    LoopNode loopNode = (LoopNode) children[childrenOffset];
                    final WasmBlockNode loopBody = (WasmBlockNode) loopNode.getRepeatingNode();
                    // The unwind counter indicates how many levels up we need to branch from
                    // within the loop block.
                    // There are three possibilities for the value of unwind counter:
                    // - A value equal to -1 indicates normal loop completion and that the flow
                    // should continue after the loop end (break out of the loop).
                    // - A value equal to 0 indicates that we need to branch to the beginning of
                    // the loop (repeat loop).
                    // This is handled internally by Truffle and the executing loop should never
                    // return 0 here.
                    // - A value larger than 0 indicates that we need to branch to a level
                    // "shallower" than the current loop block
                    // (break out of the loop and even further).
                    int unwindCounter = executeLoopNode(childrenOffset, frame);
                    if (loopUnwindProfile.profile(unwindCounter > 0)) {
                        return unwindCounter - 1;
                    }
                    // The unwind counter cannot be 0 at this point.
                    assert unwindCounter == -1 : "Unwind counter after loop exit: " + unwindCounter;
                    childrenOffset++;
                    offset += loopBody.byteLength();
                    stackPointer += loopBody.returnLength();
                    intConstantOffset += loopBody.intConstantLength();
                    branchTableOffset += loopBody.branchTableLength();
                    profileOffset += loopBody.profileCount();
                    break;
                }
            case IF:
                {
                    WasmIfNode ifNode = (WasmIfNode) children[childrenOffset];
                    stackPointer--;
                    int unwindCounter = ifNode.execute(context, frame);
                    if (ifUnwindProfile.profile(unwindCounter > 0)) {
                        return unwindCounter - 1;
                    }
                    childrenOffset++;
                    offset += ifNode.byteLength();
                    stackPointer += ifNode.returnLength();
                    intConstantOffset += ifNode.intConstantLength();
                    branchTableOffset += ifNode.branchTableLength();
                    profileOffset += ifNode.profileCount();
                    break;
                }
            case ELSE:
                break;
            case END:
                break;
            case BR:
                {
                    // region Load LEB128 Unsigned32 -> unwindCounter
                    long valueLength = unsignedIntConstantAndLength(data, offset);
                    int unwindCounter = value(valueLength);
                    int offsetDelta = length(valueLength);
                    offset += offsetDelta;
                    // endregion
                    // Reset the stack pointer to the target block stack pointer.
                    // region Load int continuationStackPointer
                    int continuationStackPointer = intConstants[intConstantOffset];
                    intConstantOffset++;
                    // endregion
                    // region Load int targetBlockReturnLength
                    int targetBlockReturnLength = intConstants[intConstantOffset];
                    intConstantOffset++;
                    // endregion
                    // Populate the stack with the return values of the current block (the one
                    // we are escaping from).
                    unwindStack(frame, stackPointer, numLocals + continuationStackPointer, targetBlockReturnLength);
                    return unwindCounter;
                }
            case BR_IF:
                {
                    stackPointer--;
                    // region Load LEB128 Unsigned32 -> unwindCounter
                    long valueLength = unsignedIntConstantAndLength(data, offset);
                    int unwindCounter = value(valueLength);
                    int offsetDelta = length(valueLength);
                    offset += offsetDelta;
                    // endregion
                    // region Load int continuationStackPointer
                    int continuationStackPointer = intConstants[intConstantOffset];
                    intConstantOffset++;
                    // endregion
                    // region Load int targetBlockReturnLength
                    int targetBlockReturnLength = intConstants[intConstantOffset];
                    intConstantOffset++;
                    // endregion
                    boolean condition = WasmCodeEntry.profileCondition(profileCounters, profileOffset, popBoolean(frame, stackPointer));
                    ++profileOffset;
                    if (condition) {
                        // Populate the stack with the return values of the current block (the
                        // one we are escaping from).
                        unwindStack(frame, stackPointer, numLocals + continuationStackPointer, targetBlockReturnLength);
                        return unwindCounter;
                    }
                    break;
                }
            case BR_TABLE:
                {
                    stackPointer--;
                    int index = popInt(frame, stackPointer);
                    int[] table = codeEntry.branchTable(branchTableOffset);
                    index = index < 0 || index >= (table.length - 1) / 2 ? (table.length - 1) / 2 - 1 : index;
                    // Technically, we should increment the branchTableOffset at this point,
                    // but since we are returning, it does not really matter.
                    int returnTypeLength = table[0];
                    for (int i = 0; i < (table.length - 1) / 2; ++i) {
                        if (i == index) {
                            int unwindCounter = table[1 + 2 * i];
                            int continuationStackPointer = table[1 + 2 * i + 1];
                            // Populate the stack with the return values of the current block
                            // (the one we are escaping from).
                            unwindStack(frame, stackPointer, numLocals + continuationStackPointer, returnTypeLength);
                            return unwindCounter;
                        }
                    }
                    errorBranch();
                    throw WasmException.create(Failure.UNSPECIFIED_INTERNAL, this, "Should not reach here");
                }
            case RETURN:
                {
                    // A return statement causes the termination of the current function, i.e.
                    // causes the execution to resume after the instruction that invoked
                    // the current frame.
                    // region Load int unwindCounterValue
                    int unwindCounter = intConstants[intConstantOffset];
                    intConstantOffset++;
                    // endregion
                    // region Load int rootBlockReturnLength
                    int rootBlockReturnLength = intConstants[intConstantOffset];
                    intConstantOffset++;
                    // endregion
                    unwindStack(frame, stackPointer, numLocals, rootBlockReturnLength);
                    return unwindCounter;
                }
            case CALL:
                {
                    // region Load LEB128 Unsigned32 -> functionIndex
                    long valueLength = unsignedIntConstantAndLength(data, offset);
                    int functionIndex = value(valueLength);
                    int offsetDelta = length(valueLength);
                    offset += offsetDelta;
                    // endregion
                    WasmFunction function = instance().symbolTable().function(functionIndex);
                    byte returnType = function.returnType();
                    CompilerAsserts.partialEvaluationConstant(returnType);
                    int numArgs = function.numArguments();
                    Object[] args = createArgumentsForCall(frame, function.typeIndex(), numArgs, stackPointer);
                    stackPointer -= args.length;
                    Object result = executeDirectCall(childrenOffset, function, args);
                    childrenOffset++;
                    // this restriction may be lifted in the future.
                    switch(returnType) {
                        case WasmType.I32_TYPE:
                            {
                                pushInt(frame, stackPointer, (int) result);
                                stackPointer++;
                                break;
                            }
                        case WasmType.I64_TYPE:
                            {
                                pushLong(frame, stackPointer, (long) result);
                                stackPointer++;
                                break;
                            }
                        case WasmType.F32_TYPE:
                            {
                                pushFloat(frame, stackPointer, (float) result);
                                stackPointer++;
                                break;
                            }
                        case WasmType.F64_TYPE:
                            {
                                pushDouble(frame, stackPointer, (double) result);
                                stackPointer++;
                                break;
                            }
                        case WasmType.VOID_TYPE:
                            {
                                // Void return type - do nothing.
                                break;
                            }
                        default:
                            {
                                throw WasmException.format(Failure.UNSPECIFIED_TRAP, this, "Unknown return type: %d", returnType);
                            }
                    }
                    break;
                }
            case CALL_INDIRECT:
                {
                    // Extract the function object.
                    stackPointer--;
                    final SymbolTable symtab = instance().symbolTable();
                    final WasmTable table = instance().table();
                    final Object[] elements = table.elements();
                    final int elementIndex = popInt(frame, stackPointer);
                    if (elementIndex < 0 || elementIndex >= elements.length) {
                        errorBranch();
                        throw WasmException.format(Failure.UNDEFINED_ELEMENT, this, "Element index '%d' out of table bounds.", elementIndex);
                    }
                    // Currently, table elements may only be functions.
                    // We can add a check here when this changes in the future.
                    final Object element = elements[elementIndex];
                    if (element == null) {
                        errorBranch();
                        throw WasmException.format(Failure.UNINITIALIZED_ELEMENT, this, "Table element at index %d is uninitialized.", elementIndex);
                    }
                    final WasmFunctionInstance functionInstance;
                    final WasmFunction function;
                    final CallTarget target;
                    final WasmContext functionInstanceContext;
                    if (element instanceof WasmFunctionInstance) {
                        functionInstance = (WasmFunctionInstance) element;
                        function = functionInstance.function();
                        target = functionInstance.target();
                        functionInstanceContext = functionInstance.context();
                    } else {
                        errorBranch();
                        throw WasmException.format(Failure.UNSPECIFIED_TRAP, this, "Unknown table element type: %s", element);
                    }
                    // Extract the function type index.
                    // region Load LEB128 Unsigned32 -> expectedFunctionTypeIndex
                    long valueLength = unsignedIntConstantAndLength(data, offset);
                    int expectedFunctionTypeIndex = value(valueLength);
                    int offsetDelta = length(valueLength);
                    offset += offsetDelta;
                    // endregion
                    int expectedTypeEquivalenceClass = symtab.equivalenceClass(expectedFunctionTypeIndex);
                    // Consume the ZERO_TABLE constant at the end of the CALL_INDIRECT
                    // instruction.
                    offset += 1;
                    // Validate that the function type matches the expected type.
                    boolean functionFromCurrentContext = WasmCodeEntry.profileCondition(profileCounters, profileOffset++, functionInstanceContext == context);
                    if (functionFromCurrentContext) {
                        // We can do a quick equivalence-class check.
                        if (expectedTypeEquivalenceClass != function.typeEquivalenceClass()) {
                            errorBranch();
                            failFunctionTypeCheck(function, expectedFunctionTypeIndex);
                        }
                    } else {
                        // provided externally (e.g. comes from a different language).
                        if (function != null && !function.type().equals(symtab.typeAt(expectedFunctionTypeIndex))) {
                            errorBranch();
                            failFunctionTypeCheck(function, expectedFunctionTypeIndex);
                        }
                    }
                    // Invoke the resolved function.
                    int numArgs = instance().symbolTable().functionTypeArgumentCount(expectedFunctionTypeIndex);
                    Object[] args = createArgumentsForCall(frame, expectedFunctionTypeIndex, numArgs, stackPointer);
                    stackPointer -= args.length;
                    // Enter function's context when it is not from the current one
                    final boolean enterContext = !functionFromCurrentContext;
                    TruffleContext truffleContext;
                    Object prev;
                    if (enterContext) {
                        truffleContext = functionInstanceContext.environment().getContext();
                        prev = truffleContext.enter(this);
                    } else {
                        truffleContext = null;
                        prev = null;
                    }
                    final Object result;
                    try {
                        result = executeIndirectCallNode(childrenOffset, target, args);
                    } finally {
                        if (enterContext) {
                            truffleContext.leave(this, prev);
                        }
                    }
                    childrenOffset++;
                    // At the moment, WebAssembly functions may return up to one value.
                    // As per the WebAssembly specification, this restriction may be lifted in
                    // the future.
                    byte returnType = instance().symbolTable().functionTypeReturnType(expectedFunctionTypeIndex);
                    CompilerAsserts.partialEvaluationConstant(returnType);
                    switch(returnType) {
                        case WasmType.I32_TYPE:
                            {
                                pushInt(frame, stackPointer, (int) result);
                                stackPointer++;
                                break;
                            }
                        case WasmType.I64_TYPE:
                            {
                                pushLong(frame, stackPointer, (long) result);
                                stackPointer++;
                                break;
                            }
                        case WasmType.F32_TYPE:
                            {
                                pushFloat(frame, stackPointer, (float) result);
                                stackPointer++;
                                break;
                            }
                        case WasmType.F64_TYPE:
                            {
                                pushDouble(frame, stackPointer, (double) result);
                                stackPointer++;
                                break;
                            }
                        case WasmType.VOID_TYPE:
                            {
                                // Void return type - do nothing.
                                break;
                            }
                        default:
                            {
                                throw WasmException.format(Failure.UNSPECIFIED_TRAP, this, "Unknown return type: %d", returnType);
                            }
                    }
                    break;
                }
            case DROP:
                {
                    stackPointer--;
                    drop(frame, stackPointer);
                    break;
                }
            case SELECT:
                {
                    int cond = popInt(frame, stackPointer - 1);
                    if (cond != 0) {
                        drop(frame, stackPointer - 2);
                    } else {
                        WasmFrame.copy(frame, stackPointer - 2, stackPointer - 3);
                        drop(frame, stackPointer - 2);
                    }
                    stackPointer -= 2;
                    break;
                }
            case LOCAL_GET:
                {
                    // region Load LEB128 Unsigned32 -> index
                    long valueLength = unsignedIntConstantAndLength(data, offset);
                    int index = value(valueLength);
                    int offsetDelta = length(valueLength);
                    offset += offsetDelta;
                    // endregion
                    local_get(frame, stackPointer, index);
                    stackPointer++;
                    break;
                }
            case LOCAL_SET:
                {
                    // region Load LEB128 Unsigned32 -> index
                    long valueLength = unsignedIntConstantAndLength(data, offset);
                    int index = value(valueLength);
                    int offsetDelta = length(valueLength);
                    offset += offsetDelta;
                    // endregion
                    stackPointer--;
                    local_set(frame, stackPointer, index);
                    break;
                }
            case LOCAL_TEE:
                {
                    // region Load LEB128 Unsigned32 -> index
                    long valueLength = unsignedIntConstantAndLength(data, offset);
                    int index = value(valueLength);
                    int offsetDelta = length(valueLength);
                    offset += offsetDelta;
                    // endregion
                    local_tee(frame, stackPointer - 1, index);
                    break;
                }
            case GLOBAL_GET:
                {
                    // region Load LEB128 Unsigned32 -> index
                    long valueLength = unsignedIntConstantAndLength(data, offset);
                    int index = value(valueLength);
                    int offsetDelta = length(valueLength);
                    offset += offsetDelta;
                    // endregion
                    global_get(context, frame, stackPointer, index);
                    stackPointer++;
                    break;
                }
            case GLOBAL_SET:
                {
                    // region Load LEB128 Unsigned32 -> index
                    long valueLength = unsignedIntConstantAndLength(data, offset);
                    int index = value(valueLength);
                    int offsetDelta = length(valueLength);
                    offset += offsetDelta;
                    // endregion
                    stackPointer--;
                    global_set(context, frame, stackPointer, index);
                    break;
                }
            case I32_LOAD:
                {
                    /* The memAlign hint is not currently used or taken into account. */
                    int memAlignOffsetDelta = offsetDelta(data, offset);
                    offset += memAlignOffsetDelta;
                    // region Load LEB128 Unsigned32 -> memOffset
                    long valueLength = unsignedIntConstantAndLength(data, offset);
                    int memOffset = value(valueLength);
                    int offsetDelta = length(valueLength);
                    offset += offsetDelta;
                    // endregion
                    int baseAddress = popInt(frame, stackPointer - 1);
                    final long address = effectiveMemoryAddress(memOffset, baseAddress);
                    int value = memory.load_i32(this, address);
                    pushInt(frame, stackPointer - 1, value);
                    break;
                }
            case I64_LOAD:
            case F32_LOAD:
            case F64_LOAD:
            case I32_LOAD8_S:
            case I32_LOAD8_U:
            case I32_LOAD16_S:
            case I32_LOAD16_U:
            case I64_LOAD8_S:
            case I64_LOAD8_U:
            case I64_LOAD16_S:
            case I64_LOAD16_U:
            case I64_LOAD32_S:
            case I64_LOAD32_U:
                {
                    /* The memAlign hint is not currently used or taken into account. */
                    int memAlignOffsetDelta = offsetDelta(data, offset);
                    offset += memAlignOffsetDelta;
                    // region Load LEB128 Unsigned32 -> memOffset
                    long valueLength = unsignedIntConstantAndLength(data, offset);
                    int memOffset = value(valueLength);
                    int offsetDelta = length(valueLength);
                    offset += offsetDelta;
                    // endregion
                    load(memory, frame, stackPointer - 1, opcode, memOffset);
                    break;
                }
            case I32_STORE:
            case I64_STORE:
            case F32_STORE:
            case F64_STORE:
            case I32_STORE_8:
            case I32_STORE_16:
            case I64_STORE_8:
            case I64_STORE_16:
            case I64_STORE_32:
                {
                    /* The memAlign hint is not currently used or taken into account. */
                    int memAlignOffsetDelta = offsetDelta(data, offset);
                    offset += memAlignOffsetDelta;
                    // region Load LEB128 Unsigned32 -> memOffset
                    long valueLength = unsignedIntConstantAndLength(data, offset);
                    int memOffset = value(valueLength);
                    int offsetDelta = length(valueLength);
                    offset += offsetDelta;
                    // endregion
                    store(memory, frame, stackPointer, opcode, memOffset);
                    stackPointer -= 2;
                    break;
                }
            case MEMORY_SIZE:
                {
                    // Skip the 0x00 constant.
                    offset++;
                    int pageSize = memory.size();
                    pushInt(frame, stackPointer, pageSize);
                    stackPointer++;
                    break;
                }
            case MEMORY_GROW:
                {
                    // Skip the 0x00 constant.
                    offset++;
                    stackPointer--;
                    int extraSize = popInt(frame, stackPointer);
                    int pageSize = memory.size();
                    if (memory.grow(extraSize)) {
                        pushInt(frame, stackPointer, pageSize);
                        stackPointer++;
                    } else {
                        pushInt(frame, stackPointer, -1);
                        stackPointer++;
                    }
                    break;
                }
            case I32_CONST:
                {
                    // region Load LEB128 Signed32 -> value
                    long valueAndLength = signedIntConstantAndLength(data, offset);
                    int offsetDelta = length(valueAndLength);
                    offset += offsetDelta;
                    // endregion
                    pushInt(frame, stackPointer, value(valueAndLength));
                    stackPointer++;
                    break;
                }
            case I64_CONST:
                {
                    // region Load LEB128 Signed64 -> value
                    long value = signedLongConstant(data, offset);
                    int offsetDelta = offsetDelta(data, offset);
                    offset += offsetDelta;
                    // endregion
                    pushLong(frame, stackPointer, value);
                    stackPointer++;
                    break;
                }
            case I32_EQZ:
                i32_eqz(frame, stackPointer);
                break;
            case I32_EQ:
                i32_eq(frame, stackPointer);
                stackPointer--;
                break;
            case I32_NE:
                i32_ne(frame, stackPointer);
                stackPointer--;
                break;
            case I32_LT_S:
                i32_lt_s(frame, stackPointer);
                stackPointer--;
                break;
            case I32_LT_U:
                i32_lt_u(frame, stackPointer);
                stackPointer--;
                break;
            case I32_GT_S:
                i32_gt_s(frame, stackPointer);
                stackPointer--;
                break;
            case I32_GT_U:
                i32_gt_u(frame, stackPointer);
                stackPointer--;
                break;
            case I32_LE_S:
                i32_le_s(frame, stackPointer);
                stackPointer--;
                break;
            case I32_LE_U:
                i32_le_u(frame, stackPointer);
                stackPointer--;
                break;
            case I32_GE_S:
                i32_ge_s(frame, stackPointer);
                stackPointer--;
                break;
            case I32_GE_U:
                i32_ge_u(frame, stackPointer);
                stackPointer--;
                break;
            case I64_EQZ:
                i64_eqz(frame, stackPointer);
                break;
            case I64_EQ:
                i64_eq(frame, stackPointer);
                stackPointer--;
                break;
            case I64_NE:
                i64_ne(frame, stackPointer);
                stackPointer--;
                break;
            case I64_LT_S:
                i64_lt_s(frame, stackPointer);
                stackPointer--;
                break;
            case I64_LT_U:
                i64_lt_u(frame, stackPointer);
                stackPointer--;
                break;
            case I64_GT_S:
                i64_gt_s(frame, stackPointer);
                stackPointer--;
                break;
            case I64_GT_U:
                i64_gt_u(frame, stackPointer);
                stackPointer--;
                break;
            case I64_LE_S:
                i64_le_s(frame, stackPointer);
                stackPointer--;
                break;
            case I64_LE_U:
                i64_le_u(frame, stackPointer);
                stackPointer--;
                break;
            case I64_GE_S:
                i64_ge_s(frame, stackPointer);
                stackPointer--;
                break;
            case I64_GE_U:
                i64_ge_u(frame, stackPointer);
                stackPointer--;
                break;
            case F32_EQ:
                f32_eq(frame, stackPointer);
                stackPointer--;
                break;
            case F32_NE:
                f32_ne(frame, stackPointer);
                stackPointer--;
                break;
            case F32_LT:
                f32_lt(frame, stackPointer);
                stackPointer--;
                break;
            case F32_GT:
                f32_gt(frame, stackPointer);
                stackPointer--;
                break;
            case F32_LE:
                f32_le(frame, stackPointer);
                stackPointer--;
                break;
            case F32_GE:
                f32_ge(frame, stackPointer);
                stackPointer--;
                break;
            case F64_EQ:
                f64_eq(frame, stackPointer);
                stackPointer--;
                break;
            case F64_NE:
                f64_ne(frame, stackPointer);
                stackPointer--;
                break;
            case F64_LT:
                f64_lt(frame, stackPointer);
                stackPointer--;
                break;
            case F64_GT:
                f64_gt(frame, stackPointer);
                stackPointer--;
                break;
            case F64_LE:
                f64_le(frame, stackPointer);
                stackPointer--;
                break;
            case F64_GE:
                f64_ge(frame, stackPointer);
                stackPointer--;
                break;
            case I32_CLZ:
                i32_clz(frame, stackPointer);
                break;
            case I32_CTZ:
                i32_ctz(frame, stackPointer);
                break;
            case I32_POPCNT:
                i32_popcnt(frame, stackPointer);
                break;
            case I32_ADD:
                i32_add(frame, stackPointer);
                stackPointer--;
                break;
            case I32_SUB:
                i32_sub(frame, stackPointer);
                stackPointer--;
                break;
            case I32_MUL:
                i32_mul(frame, stackPointer);
                stackPointer--;
                break;
            case I32_DIV_S:
                i32_div_s(frame, stackPointer);
                stackPointer--;
                break;
            case I32_DIV_U:
                i32_div_u(frame, stackPointer);
                stackPointer--;
                break;
            case I32_REM_S:
                i32_rem_s(frame, stackPointer);
                stackPointer--;
                break;
            case I32_REM_U:
                i32_rem_u(frame, stackPointer);
                stackPointer--;
                break;
            case I32_AND:
                i32_and(frame, stackPointer);
                stackPointer--;
                break;
            case I32_OR:
                i32_or(frame, stackPointer);
                stackPointer--;
                break;
            case I32_XOR:
                i32_xor(frame, stackPointer);
                stackPointer--;
                break;
            case I32_SHL:
                i32_shl(frame, stackPointer);
                stackPointer--;
                break;
            case I32_SHR_S:
                i32_shr_s(frame, stackPointer);
                stackPointer--;
                break;
            case I32_SHR_U:
                i32_shr_u(frame, stackPointer);
                stackPointer--;
                break;
            case I32_ROTL:
                i32_rotl(frame, stackPointer);
                stackPointer--;
                break;
            case I32_ROTR:
                i32_rotr(frame, stackPointer);
                stackPointer--;
                break;
            case I64_CLZ:
                i64_clz(frame, stackPointer);
                break;
            case I64_CTZ:
                i64_ctz(frame, stackPointer);
                break;
            case I64_POPCNT:
                i64_popcnt(frame, stackPointer);
                break;
            case I64_ADD:
                i64_add(frame, stackPointer);
                stackPointer--;
                break;
            case I64_SUB:
                i64_sub(frame, stackPointer);
                stackPointer--;
                break;
            case I64_MUL:
                i64_mul(frame, stackPointer);
                stackPointer--;
                break;
            case I64_DIV_S:
                i64_div_s(frame, stackPointer);
                stackPointer--;
                break;
            case I64_DIV_U:
                i64_div_u(frame, stackPointer);
                stackPointer--;
                break;
            case I64_REM_S:
                i64_rem_s(frame, stackPointer);
                stackPointer--;
                break;
            case I64_REM_U:
                i64_rem_u(frame, stackPointer);
                stackPointer--;
                break;
            case I64_AND:
                i64_and(frame, stackPointer);
                stackPointer--;
                break;
            case I64_OR:
                i64_or(frame, stackPointer);
                stackPointer--;
                break;
            case I64_XOR:
                i64_xor(frame, stackPointer);
                stackPointer--;
                break;
            case I64_SHL:
                i64_shl(frame, stackPointer);
                stackPointer--;
                break;
            case I64_SHR_S:
                i64_shr_s(frame, stackPointer);
                stackPointer--;
                break;
            case I64_SHR_U:
                i64_shr_u(frame, stackPointer);
                stackPointer--;
                break;
            case I64_ROTL:
                i64_rotl(frame, stackPointer);
                stackPointer--;
                break;
            case I64_ROTR:
                i64_rotr(frame, stackPointer);
                stackPointer--;
                break;
            case F32_CONST:
                {
                    // region Load int value
                    float value = Float.intBitsToFloat(BinaryStreamParser.peek4(data, offset));
                    // endregion
                    offset += 4;
                    pushFloat(frame, stackPointer, value);
                    stackPointer++;
                    break;
                }
            case F32_ABS:
                f32_abs(frame, stackPointer);
                break;
            case F32_NEG:
                f32_neg(frame, stackPointer);
                break;
            case F32_CEIL:
                f32_ceil(frame, stackPointer);
                break;
            case F32_FLOOR:
                f32_floor(frame, stackPointer);
                break;
            case F32_TRUNC:
                f32_trunc(frame, stackPointer);
                break;
            case F32_NEAREST:
                f32_nearest(frame, stackPointer);
                break;
            case F32_SQRT:
                f32_sqrt(frame, stackPointer);
                break;
            case F32_ADD:
                f32_add(frame, stackPointer);
                stackPointer--;
                break;
            case F32_SUB:
                f32_sub(frame, stackPointer);
                stackPointer--;
                break;
            case F32_MUL:
                f32_mul(frame, stackPointer);
                stackPointer--;
                break;
            case F32_DIV:
                f32_div(frame, stackPointer);
                stackPointer--;
                break;
            case F32_MIN:
                f32_min(frame, stackPointer);
                stackPointer--;
                break;
            case F32_MAX:
                f32_max(frame, stackPointer);
                stackPointer--;
                break;
            case F32_COPYSIGN:
                f32_copysign(frame, stackPointer);
                stackPointer--;
                break;
            case F64_CONST:
                {
                    // region Load long value
                    double value = Double.longBitsToDouble(BinaryStreamParser.peek8(data, offset));
                    // endregion
                    offset += 8;
                    pushDouble(frame, stackPointer, value);
                    stackPointer++;
                    break;
                }
            case F64_ABS:
                f64_abs(frame, stackPointer);
                break;
            case F64_NEG:
                f64_neg(frame, stackPointer);
                break;
            case F64_CEIL:
                f64_ceil(frame, stackPointer);
                break;
            case F64_FLOOR:
                f64_floor(frame, stackPointer);
                break;
            case F64_TRUNC:
                f64_trunc(frame, stackPointer);
                break;
            case F64_NEAREST:
                f64_nearest(frame, stackPointer);
                break;
            case F64_SQRT:
                f64_sqrt(frame, stackPointer);
                break;
            case F64_ADD:
                f64_add(frame, stackPointer);
                stackPointer--;
                break;
            case F64_SUB:
                f64_sub(frame, stackPointer);
                stackPointer--;
                break;
            case F64_MUL:
                f64_mul(frame, stackPointer);
                stackPointer--;
                break;
            case F64_DIV:
                f64_div(frame, stackPointer);
                stackPointer--;
                break;
            case F64_MIN:
                f64_min(frame, stackPointer);
                stackPointer--;
                break;
            case F64_MAX:
                f64_max(frame, stackPointer);
                stackPointer--;
                break;
            case F64_COPYSIGN:
                f64_copysign(frame, stackPointer);
                stackPointer--;
                break;
            case I32_WRAP_I64:
                i32_wrap_i64(frame, stackPointer);
                break;
            case I32_TRUNC_F32_S:
                i32_trunc_f32_s(frame, stackPointer);
                break;
            case I32_TRUNC_F32_U:
                i32_trunc_f32_u(frame, stackPointer);
                break;
            case I32_TRUNC_F64_S:
                i32_trunc_f64_s(frame, stackPointer);
                break;
            case I32_TRUNC_F64_U:
                i32_trunc_f64_u(frame, stackPointer);
                break;
            case I64_EXTEND_I32_S:
                i64_extend_i32_s(frame, stackPointer);
                break;
            case I64_EXTEND_I32_U:
                i64_extend_i32_u(frame, stackPointer);
                break;
            case I64_TRUNC_F32_S:
                i64_trunc_f32_s(frame, stackPointer);
                break;
            case I64_TRUNC_F32_U:
                i64_trunc_f32_u(frame, stackPointer);
                break;
            case I64_TRUNC_F64_S:
                i64_trunc_f64_s(frame, stackPointer);
                break;
            case I64_TRUNC_F64_U:
                i64_trunc_f64_u(frame, stackPointer);
                break;
            case F32_CONVERT_I32_S:
                f32_convert_i32_s(frame, stackPointer);
                break;
            case F32_CONVERT_I32_U:
                f32_convert_i32_u(frame, stackPointer);
                break;
            case F32_CONVERT_I64_S:
                f32_convert_i64_s(frame, stackPointer);
                break;
            case F32_CONVERT_I64_U:
                f32_convert_i64_u(frame, stackPointer);
                break;
            case F32_DEMOTE_F64:
                f32_demote_f64(frame, stackPointer);
                break;
            case F64_CONVERT_I32_S:
                f64_convert_i32_s(frame, stackPointer);
                break;
            case F64_CONVERT_I32_U:
                f64_convert_i32_u(frame, stackPointer);
                break;
            case F64_CONVERT_I64_S:
                f64_convert_i64_s(frame, stackPointer);
                break;
            case F64_CONVERT_I64_U:
                f64_convert_i64_u(frame, stackPointer);
                break;
            case F64_PROMOTE_F32:
                f64_promote_f32(frame, stackPointer);
                break;
            case I32_REINTERPRET_F32:
                i32_reinterpret_f32(frame, stackPointer);
                break;
            case I64_REINTERPRET_F64:
                i64_reinterpret_f64(frame, stackPointer);
                break;
            case F32_REINTERPRET_I32:
                f32_reinterpret_i32(frame, stackPointer);
                break;
            case F64_REINTERPRET_I64:
                f64_reinterpret_i64(frame, stackPointer);
                break;
            case MISC:
                byte miscByteOpcode = BinaryStreamParser.rawPeek1(data, offset);
                int miscOpcode = miscByteOpcode & 0xFF;
                offset++;
                CompilerAsserts.partialEvaluationConstant(offset);
                switch(miscOpcode) {
                    case I32_TRUNC_SAT_F32_S:
                        i32_trunc_sat_f32_s(frame, stackPointer);
                        break;
                    case I32_TRUNC_SAT_F32_U:
                        i32_trunc_sat_f32_u(frame, stackPointer);
                        break;
                    case I32_TRUNC_SAT_F64_S:
                        i32_trunc_sat_f64_s(frame, stackPointer);
                        break;
                    case I32_TRUNC_SAT_F64_U:
                        i32_trunc_sat_f64_u(frame, stackPointer);
                        break;
                    case I64_TRUNC_SAT_F32_S:
                        i64_trunc_sat_f32_s(frame, stackPointer);
                        break;
                    case I64_TRUNC_SAT_F32_U:
                        i64_trunc_sat_f32_u(frame, stackPointer);
                        break;
                    case I64_TRUNC_SAT_F64_S:
                        i64_trunc_sat_f64_s(frame, stackPointer);
                        break;
                    case I64_TRUNC_SAT_F64_U:
                        i64_trunc_sat_f64_u(frame, stackPointer);
                        break;
                    default:
                        throw CompilerDirectives.shouldNotReachHere();
                }
                break;
            case I32_EXTEND8_S:
                i32_extend8_s(frame, stackPointer);
                break;
            case I32_EXTEND16_S:
                i32_extend16_s(frame, stackPointer);
                break;
            case I64_EXTEND8_S:
                i64_extend8_s(frame, stackPointer);
                break;
            case I64_EXTEND16_S:
                i64_extend16_s(frame, stackPointer);
                break;
            case I64_EXTEND32_S:
                i64_extend32_s(frame, stackPointer);
                break;
            default:
                throw CompilerDirectives.shouldNotReachHere();
        }
    }
    return -1;
}
Also used : LoopNode(com.oracle.truffle.api.nodes.LoopNode) CallTarget(com.oracle.truffle.api.CallTarget) WasmTable(org.graalvm.wasm.WasmTable) TruffleContext(com.oracle.truffle.api.TruffleContext) SymbolTable(org.graalvm.wasm.SymbolTable) WasmCodeEntry(org.graalvm.wasm.WasmCodeEntry) WasmFunction(org.graalvm.wasm.WasmFunction) WasmContext(org.graalvm.wasm.WasmContext) WasmFunctionInstance(org.graalvm.wasm.WasmFunctionInstance) WasmMemory(org.graalvm.wasm.memory.WasmMemory) BytecodeInterpreterSwitch(com.oracle.truffle.api.HostCompilerDirectives.BytecodeInterpreterSwitch) ExplodeLoop(com.oracle.truffle.api.nodes.ExplodeLoop) BytecodeInterpreterSwitchBoundary(com.oracle.truffle.api.HostCompilerDirectives.BytecodeInterpreterSwitchBoundary)

Example 17 with WasmMemory

use of org.graalvm.wasm.memory.WasmMemory in project graal by oracle.

the class WebAssembly method memSetGrowCallback.

private static Object memSetGrowCallback(Object[] args) {
    InteropLibrary lib = InteropLibrary.getUncached();
    if (!(args[0] instanceof WasmMemory)) {
        throw new WasmJsApiException(WasmJsApiException.Kind.TypeError, "First argument must be wasm memory");
    }
    if (!lib.isExecutable(args[1])) {
        throw new WasmJsApiException(WasmJsApiException.Kind.TypeError, "Second argument must be executable");
    }
    WasmMemory memory = (WasmMemory) args[0];
    return memSetGrowCallback(memory, args[1]);
}
Also used : WasmJsApiException(org.graalvm.wasm.exception.WasmJsApiException) InteropLibrary(com.oracle.truffle.api.interop.InteropLibrary) UnsafeWasmMemory(org.graalvm.wasm.memory.UnsafeWasmMemory) WasmMemory(org.graalvm.wasm.memory.WasmMemory) ByteArrayWasmMemory(org.graalvm.wasm.memory.ByteArrayWasmMemory)

Example 18 with WasmMemory

use of org.graalvm.wasm.memory.WasmMemory in project graal by oracle.

the class WebAssembly method memGrow.

private static Object memGrow(Object[] args) {
    checkArgumentCount(args, 2);
    if (!(args[0] instanceof WasmMemory)) {
        throw new WasmJsApiException(WasmJsApiException.Kind.TypeError, "First argument must be wasm memory");
    }
    if (!(args[1] instanceof Integer)) {
        throw new WasmJsApiException(WasmJsApiException.Kind.TypeError, "Second argument must be integer");
    }
    WasmMemory memory = (WasmMemory) args[0];
    int delta = (Integer) args[1];
    return memGrow(memory, delta);
}
Also used : WasmJsApiException(org.graalvm.wasm.exception.WasmJsApiException) UnsafeWasmMemory(org.graalvm.wasm.memory.UnsafeWasmMemory) WasmMemory(org.graalvm.wasm.memory.WasmMemory) ByteArrayWasmMemory(org.graalvm.wasm.memory.ByteArrayWasmMemory)

Example 19 with WasmMemory

use of org.graalvm.wasm.memory.WasmMemory in project graal by oracle.

the class WebAssembly method memAsByteBuffer.

private static Object memAsByteBuffer(Object[] args) {
    checkArgumentCount(args, 1);
    if (args[0] instanceof WasmMemory) {
        WasmMemory memory = (WasmMemory) args[0];
        ByteBuffer buffer = memory.asByteBuffer();
        if (buffer != null) {
            return WasmContext.get(null).environment().asGuestValue(buffer);
        }
    }
    return WasmVoidResult.getInstance();
}
Also used : UnsafeWasmMemory(org.graalvm.wasm.memory.UnsafeWasmMemory) WasmMemory(org.graalvm.wasm.memory.WasmMemory) ByteArrayWasmMemory(org.graalvm.wasm.memory.ByteArrayWasmMemory) ByteBuffer(java.nio.ByteBuffer)

Example 20 with WasmMemory

use of org.graalvm.wasm.memory.WasmMemory in project graal by oracle.

the class WasmLanguage method finalizeContext.

@Override
protected void finalizeContext(WasmContext context) {
    super.finalizeContext(context);
    for (int i = 0; i < context.memories().count(); ++i) {
        final WasmMemory memory = context.memories().memory(i);
        memory.close();
    }
    try {
        context.fdManager().close();
    } catch (IOException e) {
        throw new RuntimeException("Error while closing WasmFilesManager.");
    }
}
Also used : IOException(java.io.IOException) WasmMemory(org.graalvm.wasm.memory.WasmMemory)

Aggregations

WasmMemory (org.graalvm.wasm.memory.WasmMemory)23 ByteArrayWasmMemory (org.graalvm.wasm.memory.ByteArrayWasmMemory)6 UnsafeWasmMemory (org.graalvm.wasm.memory.UnsafeWasmMemory)6 WasmJsApiException (org.graalvm.wasm.exception.WasmJsApiException)4 Test (org.junit.Test)4 WasmFunction (org.graalvm.wasm.WasmFunction)3 WasmInstance (org.graalvm.wasm.WasmInstance)3 WasmTable (org.graalvm.wasm.WasmTable)3 InteropException (com.oracle.truffle.api.interop.InteropException)2 InteropLibrary (com.oracle.truffle.api.interop.InteropLibrary)2 TruffleObject (com.oracle.truffle.api.interop.TruffleObject)2 IOException (java.io.IOException)2 ArrayList (java.util.ArrayList)2 HashMap (java.util.HashMap)2 GlobalRegistry (org.graalvm.wasm.GlobalRegistry)2 ExportMemorySym (org.graalvm.wasm.Linker.ResolutionDag.ExportMemorySym)2 ImportMemorySym (org.graalvm.wasm.Linker.ResolutionDag.ImportMemorySym)2 SymbolTable (org.graalvm.wasm.SymbolTable)2 WasmContext (org.graalvm.wasm.WasmContext)2 WasmFunctionInstance (org.graalvm.wasm.WasmFunctionInstance)2