Changeset 283852 in webkit


Ignore:
Timestamp:
Oct 8, 2021 4:32:45 PM (9 months ago)
Author:
Tadeu Zagallo
Message:

Implement the WebAssembly exception handling proposal
https://bugs.webkit.org/show_bug.cgi?id=229681
<rdar://81603387>

JSTests:

Reviewed by Keith Miller.

Add new tests for the exception handling and import a set of tests used by V8 into wasm/v8.

  • wasm.yaml:
  • wasm/Builder.js:

(const._importExceptionContinuation.type.Import.field):
(export.default.Builder.prototype._registerSectionBuilders.const.section.in.WASM.description.section.switch.section.case.string_appeared_here.this.section):
(const._exportFunctionContinuation.type.Export.field): Deleted.
(const._exportFunctionContinuation): Deleted.

  • wasm/Builder_WebAssemblyBinary.js:

(const.emitters.Import):
(const.emitters.Export):
(const.emitters.Exception):

  • wasm/assert.js:
  • wasm/self-test/test_BuilderJSON.js:

(ImportBeforeTypeSections): Deleted.

  • wasm/stress/catch-with-delegate.js: Added.

(import.Builder.from.string_appeared_here.import.as.assert.from.string_appeared_here.callback):
(assert.throws):

  • wasm/stress/create-tag-from.js: Added.
  • wasm/stress/exception-cross-instance-2.js: Added.

(test):
(assert.eq):

  • wasm/stress/exception-cross-instance-3.js: Added.

(test):
(assert.eq):

  • wasm/stress/exception-cross-instance.js: Added.

(test):
(assert.throws):
(instB.new.WebAssembly.Instance):

  • wasm/stress/exception-liveness-tier-up.js: Added.

(import.Builder.from.string_appeared_here.import.as.assert.from.string_appeared_here.catch):
(assert.eq.):
(assert.eq):

  • wasm/stress/exception-multiple-instances.js: Added.

(import.Builder.from.string_appeared_here.import.as.assert.from.string_appeared_here.const.module.new.WebAssembly.Module):
(import.Builder.from.string_appeared_here.import.as.assert.from.string_appeared_here.inst.exports.throw):

  • wasm/stress/exception-simple-delegate.js: Added.

(import.Builder.from.string_appeared_here.import.as.assert.from.string_appeared_here.testSimpleThrowDelegate):
(testThrowDelegateSkip):
(testDelegateCaller):
(testSimpleDelegateMerge):

  • wasm/stress/exception-simple-throw-catch.js: Added.

(import.Builder.from.string_appeared_here.import.as.assert.from.string_appeared_here.testSimpleTryCatch):
(testSimpleTryCatchAll):
(testCallTryCatch):
(testCallTryCatchAll):
(testSimpleTryCatchValue):
(testCallTryCatchValue):
(testStackTryCatch):
(testLiveAfterTryCatch):
(testLiveAfterTryCatchAll):
(testUnifyTryCatchCatch):
(testUnifyTryCatchCatchAll):
(testUnifyTryNoThrow):
(testUnifyTryNoCatch):
(testNestedCatch):

  • wasm/stress/exception-thrown-from-js-to-wasm-catchall-rethrow.js: Added.

(import.Builder.from.string_appeared_here.import.as.assert.from.string_appeared_here.callback):

  • wasm/stress/exception-thrown-from-js-to-wasm-catchall.js: Added.

(import.Builder.from.string_appeared_here.import.as.assert.from.string_appeared_here.callback):

  • wasm/stress/exception-thrown-from-js-to-wasm.js: Added.

(import.Builder.from.string_appeared_here.import.as.assert.from.string_appeared_here.callback):

  • wasm/stress/exception-thrown-out-of-wasm.js: Added.
  • wasm/stress/exception-thrown-over-wasm.js: Added.

(import.Builder.from.string_appeared_here.import.as.assert.from.string_appeared_here.callback):

  • wasm/stress/exception-trap.js: Added.

(import.Builder.from.string_appeared_here.import.as.assert.from.string_appeared_here.testCannotCatchUnreachable):
(testCannotCatchOOB):
(testWasmAPIThrow):
(testJSCatchAndRethrow):

  • wasm/stress/rethrow-from-catch-to-catch.js: Added.

(import.Builder.from.string_appeared_here.import.as.assert.from.string_appeared_here.callback):

  • wasm/stress/rethrow-to-catch.js: Added.

(import.Builder.from.string_appeared_here.import.as.assert.from.string_appeared_here.callback):
(assert.throws.callback):
(assert.throws):

  • wasm/stress/rethrow-to-delegate-to-catch.js: Added.

(import.Builder.from.string_appeared_here.import.as.assert.from.string_appeared_here):
(assert.eq.exn.getArg):
(assert.throws):
(assert.throws.callback):
(assert.eq):

  • wasm/stress/simple-export-exception.js: Added.
  • wasm/v8/LICENSE: Added.
  • wasm/v8/exceptions-api.js: Added.

(TestImport):
(TestImportExport):
(TestExceptionConstructor):
(TestExceptionConstructorWithPayload):
(TestCatchJSException.js_func):
(js_func):
(TestCatchJS):
(TestCatchJSExceptionWithPayload):
(TestGetArg):

  • wasm/v8/exceptions-export.js: Added.

(TestExportMultiple):
(TestExportOutOfBounds):

  • wasm/v8/exceptions-externref.js: Added.

(TestThrowRefNull):
(TestThrowRefParam):

  • wasm/v8/exceptions-import.js: Added.

(NewExportedTag):
(TestImportSimple):
(TestImportMissing):

  • wasm/v8/exceptions-rethrow.js: Added.

(TestRethrowInCatch):
(TestRethrowInCatchAll):
(TestRethrowNested):
(TestRethrowRecatch):

  • wasm/v8/exceptions-shared.js: Added.

(NewExportedException):
(TestSingleInstance.let.instance.builder.instantiate.):
(TestSingleInstance):
(TestMultiInstanceNonShared.let.instance2.builder.instantiate.):
(TestMultiInstanceShared.let.instance2.builder.instantiate.):
(TestMultiModuleShared.let.instance2.builder2.instantiate.):

  • wasm/v8/exceptions-type-reflection.js: Added.

(TestExport):
(TestImportExport):

  • wasm/v8/exceptions-utils.js: Added.

(assertWasmThrows):

  • wasm/v8/exceptions.js: Added.

(TestThrowSimple):
(TestCatchSimple):
(TestTrapNotCaught):
(TestTrapViaJSNotCaught.js_import):
(TestManuallyThrownRuntimeErrorCaught.throw_exc):
(TestManuallyThrownRuntimeErrorCaught):
(TestExnWithWasmProtoNotCaught.js_import):
(TestExnWithWasmProtoNotCaught):
(TestStackOverflowNotCaught.stack_overflow):
(TestStackOverflowNotCaught):
(TestThrowParamI):
(TestThrowParamF):
(TestThrowParamL):
(TestThrowParamD):
(TestCatchCrossFunctions.throw_value):
(TestCatchCrossFunctions.throw_string):
(TestCatchCrossFunctions.throw_undefined):
(TestCatchCrossFunctions.throw_fp):
(TestCatchCrossFunctions.throw_large):
(TestDelegateNoThrow):
(TestDelegateThrow):
(TestDelegateThrowNoCatch):
(TestDelegateMerge):
(TestDelegate1):
(TestDelegateUnreachable):
(TestDelegateToCaller):
(TestUnreachableInCatchAll):
(TestThrowWithLocal):
(TestCatchlessTry):

  • wasm/v8/mjsunit.js: Added.

(MjsUnitAssertionError):
(MjsUnitAssertionError.prototype.toString):
(catch):
(classOf):
(ValueOf):
(prettyPrinted):
(prettyPrintedArrayElement):
(failWithMessage):
(formatFailureText):
(fail):
(deepObjectEquals):
(deepEquals):
(assertSame):
(assertNotSame):
(assertEquals):
(assertNotEquals):
(assertEqualsDelta):
(assertArrayEquals):
(assertPropertiesEqual):
(assertToStringEquals):
(assertTrue):
(assertFalse):
(assertNull):
(assertNotNull):
(executeCode):
(checkException):
(assertThrows):
(assertThrowsEquals):
(assertThrowsAsync):
(assertInstanceof):
(assertDoesNotThrow):
(assertUnreachable):
(assertContains):
(assertMatches):
(concatenateErrors):
(assertPromiseResult):
(OptimizationStatus):
(assertUnoptimized):
(assertOptimized):
(isNeverOptimizeLiteMode):
(isNeverOptimize):
(isAlwaysOptimize):
(isInterpreted):
(isBaseline):
(isUnoptimized):
(isOptimized):
(isTurboFanned):
(MjsUnitAssertionError.prepareStackTrace):

  • wasm/v8/wasm-module-builder.js: Added.

(bytes):
(wasmOptRefType):
(wasmRefType):
(wasmRtt):
(wasmRttNoDepth):
(makeSig):
(makeSig_v_x):
(makeSig_x_v):
(makeSig_v_xx):
(makeSig_r_v):
(makeSig_r_x):
(makeSig_r_xx):
(defineWasmOpcode):
(assertTraps):
(Binary):
(Binary.prototype.ensure_space):
(Binary.prototype.trunc_buffer):
(Binary.prototype.reset):
(Binary.prototype.emit_u8):
(Binary.prototype.emit_u16):
(Binary.prototype.emit_u32):
(Binary.prototype.emit_leb_u):
(Binary.prototype.emit_u32v):
(Binary.prototype.emit_u64v):
(Binary.prototype.emit_bytes):
(Binary.prototype.emit_string):
(Binary.prototype.emit_heap_type):
(Binary.prototype.emit_type):
(Binary.prototype.emit_init_expr_recursive):
(Binary.prototype.emit_init_expr):
(Binary.prototype.emit_header):
(Binary.prototype.emit_section):
(WasmFunctionBuilder):
(WasmFunctionBuilder.prototype.numLocalNames):
(WasmFunctionBuilder.prototype.exportAs):
(WasmFunctionBuilder.prototype.exportFunc):
(WasmFunctionBuilder.prototype.setCompilationHint):
(WasmFunctionBuilder.prototype.addBody):
(WasmFunctionBuilder.prototype.addBodyWithEnd):
(WasmFunctionBuilder.prototype.getNumLocals):
(WasmFunctionBuilder.prototype.addLocals):
(WasmFunctionBuilder.prototype.end):
(WasmInitExpr.I32Const):
(WasmInitExpr.I64Const):
(WasmInitExpr.F32Const):
(WasmInitExpr.F64Const):
(WasmInitExpr.S128Const):
(WasmInitExpr.GlobalGet):
(WasmInitExpr.RefFunc):
(WasmInitExpr.RefNull):
(WasmInitExpr.StructNewWithRtt):
(WasmInitExpr.StructNew):
(WasmInitExpr.StructNewDefaultWithRtt):
(WasmInitExpr.StructNewDefault):
(WasmInitExpr.ArrayInit):
(WasmInitExpr.ArrayInitStatic):
(WasmInitExpr.RttCanon):
(WasmInitExpr.RttSub):
(WasmInitExpr.RttFreshSub):
(WasmInitExpr.defaultFor):
(WasmInitExpr):
(WasmGlobalBuilder):
(WasmGlobalBuilder.prototype.exportAs):
(WasmTableBuilder):
(WasmTableBuilder.prototype.exportAs):
(makeField):
(WasmStruct):
(WasmStructSubtype):
(WasmArray):
(WasmArraySubtype):
(WasmElemSegment):
(WasmElemSegment.prototype.is_active):
(WasmElemSegment.prototype.is_passive):
(WasmElemSegment.prototype.is_declarative):
(WasmElemSegment.prototype.expressions_as_elements):
(WasmModuleBuilder):
(WasmModuleBuilder.prototype.addStart):
(WasmModuleBuilder.prototype.addMemory):
(WasmModuleBuilder.prototype.addMemory64):
(WasmModuleBuilder.prototype.addExplicitSection):
(WasmModuleBuilder.prototype.stringToBytes):
(WasmModuleBuilder.prototype.createCustomSection):
(WasmModuleBuilder.prototype.addCustomSection):
(WasmModuleBuilder.prototype.addType):
(WasmModuleBuilder.prototype.addStruct):
(WasmModuleBuilder.prototype.addStructSubtype):
(WasmModuleBuilder.prototype.addArray):
(WasmModuleBuilder.prototype.addArraySubtype):
(WasmModuleBuilder.prototype.addGlobal):
(WasmModuleBuilder.prototype.addTable):
(WasmModuleBuilder.prototype.addTag):
(WasmModuleBuilder.prototype.addFunction):
(WasmModuleBuilder.prototype.addImport):
(WasmModuleBuilder.prototype.addImportedGlobal):
(WasmModuleBuilder.prototype.addImportedMemory):
(WasmModuleBuilder.prototype.addImportedTable):
(WasmModuleBuilder.prototype.addImportedTag):
(WasmModuleBuilder.prototype.addExport):
(WasmModuleBuilder.prototype.addExportOfKind):
(WasmModuleBuilder.prototype.setCompilationHint):
(WasmModuleBuilder.prototype.addDataSegment):
(WasmModuleBuilder.prototype.addPassiveDataSegment):
(WasmModuleBuilder.prototype.exportMemoryAs):
(WasmModuleBuilder.prototype.addActiveElementSegment):
(WasmModuleBuilder.prototype.addPassiveElementSegment):
(WasmModuleBuilder.prototype.addDeclarativeElementSegment):
(WasmModuleBuilder.prototype.appendToTable):
(WasmModuleBuilder.prototype.setTableBounds):
(WasmModuleBuilder.prototype.setName):
(WasmModuleBuilder.prototype.toBuffer):
(WasmModuleBuilder.prototype.toArray):
(WasmModuleBuilder.prototype.instantiate):
(WasmModuleBuilder.prototype.asyncInstantiate):
(WasmModuleBuilder.prototype.toModule):
(wasmSignedLeb):
(wasmUnsignedLeb):
(wasmI32Const):
(wasmI64Const):
(wasmF32Const):
(wasmF64Const):
(wasmS128Const):
(getOpcodeName):

  • wasm/wasm.json:

Source/JavaScriptCore:

Reviewed by Keith Miller.

Add support for the WebAssembly exception handling proposal, as per
the WIP spec: https://github.com/WebAssembly/exception-handling

The proposal includes 6 new instructions: try, catch, catch_all,
delegate, throw and rethrow. All the instructions are supported by
the LLInt and B3 generators, but not yet supported in Air. Any
functions use exceptions will use B3 in BBQ.

A few important notes about the implementation:

  • In B3, since we can now have multiple entrypoints (one for the

function entry + 1 for each catch/catch_all), we can no longer just
replace every value in the stack with a Phi when we find a new
entrypoint. This worked so far because of the assumption that any
block couldn't access its enclosing stack, and since the enclosing stack
would only be accessible when we exited the current block, we added Phis
at the end of each block when we had a new entrypoint. Now, since we have to capture all
live values at any point that might throw (calls, throw and rethrow),
we break that assumption. To simplify all the possible ways we might
have to merge the state from multiple entrypoints we now use B3
Variables to represent stack slots.

  • Some extra information is required to be able to properly restore

the state when catching an exception:

  • We added a field VM::calleeForWasmCatch. This field is necessary because whenever we throw, we might end up in JavaScript, which assumes the callee is a cell and uses it to get the VM and restore callee saves. The issue is when catching exceptions in wasm we still need the original callee, and if throwing and catching from the same frame, that call frame slot has now been overwritten, so we store its original value in the VM field.
  • We also need to store the current Wasm Instance into the call frame's slot for the this argument. The instance is used both by the unwinder, to check if the exception being thrown matches the exceptions handled by catch candidates, and by the catch implementation, which is necessary when throwing from a cross instance call where both the callee save or TLS will have the callee's instance.
  • We store the current opcode for the llint, or the call site index for B3, in the call frame slot for the argument count tag. The call site index is used by the unwinder to check if a given catch can handle the exception being thrown.
  • DerivedSources-input.xcfilelist:
  • DerivedSources-output.xcfilelist:
  • DerivedSources.make:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • Sources.txt:
  • bytecode/BytecodeList.rb:
  • bytecode/HandlerInfo.h:
  • bytecode/Instruction.h:

(JSC::BaseInstruction::name const):

  • interpreter/CallFrame.cpp:

(JSC::CallFrame::bytecodeIndex const):

  • interpreter/CallFrame.h:

(JSC::CallSiteIndex::CallSiteIndex):
(JSC::CallSiteIndex::hash const):
(JSC::CallSiteIndex::deletedValue):
(JSC::CallSiteIndex::isHashTableDeletedValue const):
(JSC::CallSiteIndexHash::hash):
(JSC::CallSiteIndexHash::equal):

  • interpreter/Interpreter.cpp:

(JSC::CatchInfo::CatchInfo):
(JSC::UnwindFunctor::UnwindFunctor):
(JSC::UnwindFunctor::operator() const):
(JSC::Interpreter::unwind):

  • interpreter/Interpreter.h:

(JSC::CatchInfo::CatchInfo):

  • interpreter/StackVisitor.cpp:

(JSC::StackVisitor::readNonInlinedFrame):

  • jit/AssemblyHelpers.cpp:

(JSC::AssemblyHelpers::restoreCalleeSavesFromEntryFrameCalleeSavesBuffer):
(JSC::AssemblyHelpers::restoreCalleeSavesFromVMEntryFrameCalleeSavesBuffer):
(JSC::AssemblyHelpers::restoreCalleeSavesFromVMEntryFrameCalleeSavesBufferImpl):

  • jit/AssemblyHelpers.h:
  • jit/JITExceptions.cpp:

(JSC::genericUnwind):

  • jit/JSInterfaceJIT.h:

(JSC::JSInterfaceJIT::convertCalleeToVM):

  • llint/LLIntData.h:

(JSC::LLInt::getCodeRef):
(JSC::LLInt::getWide16CodeRef):
(JSC::LLInt::getWide32CodeRef):

  • llint/LLIntExceptions.cpp:

(JSC::LLInt::wasmReturnToThrow):
(JSC::LLInt::handleWasmCatch):
(JSC::LLInt::handleWasmCatchAll):

  • llint/LLIntExceptions.h:
  • llint/LLIntOffsetsExtractor.cpp:
  • llint/WebAssembly.asm:
  • runtime/ErrorInstance.cpp:

(JSC::ErrorInstance::ErrorInstance):

  • runtime/ErrorInstance.h:

(JSC::ErrorInstance::setCatchableFromWasm):
(JSC::ErrorInstance::isCatchableFromWasm const):

  • runtime/JSGlobalObject.cpp:
  • runtime/JSGlobalObject.h:
  • runtime/OptionsList.h:
  • runtime/VM.cpp:

(JSC::VM::VM):

  • runtime/VM.h:

(JSC::VM::calleeForWasmCatchOffset):

  • wasm/WasmAirIRGenerator.cpp:

(JSC::Wasm::AirIRGenerator::ControlData::isTry):
(JSC::Wasm::AirIRGenerator::ControlData::isCatch):
(JSC::Wasm::AirIRGenerator::ControlData::isAnyCatch):
(JSC::Wasm::AirIRGenerator::ControlData::isLoop):
(JSC::Wasm::AirIRGenerator::ControlData::isBlock):
(JSC::Wasm::AirIRGenerator::ControlData::dump const):
(JSC::Wasm::AirIRGenerator::addTry):
(JSC::Wasm::AirIRGenerator::addCatch):
(JSC::Wasm::AirIRGenerator::addCatchToUnreachable):
(JSC::Wasm::AirIRGenerator::addCatchAll):
(JSC::Wasm::AirIRGenerator::addCatchAllToUnreachable):
(JSC::Wasm::AirIRGenerator::addDelegate):
(JSC::Wasm::AirIRGenerator::addDelegateToUnreachable):
(JSC::Wasm::AirIRGenerator::addThrow):
(JSC::Wasm::AirIRGenerator::addRethrow):

  • wasm/WasmB3IRGenerator.cpp:

(JSC::Wasm::B3IRGenerator::ControlData::ControlData):
(JSC::Wasm::B3IRGenerator::ControlData::isTry):
(JSC::Wasm::B3IRGenerator::ControlData::isAnyCatch):
(JSC::Wasm::B3IRGenerator::ControlData::isLoop):
(JSC::Wasm::B3IRGenerator::ControlData::isBlock):
(JSC::Wasm::B3IRGenerator::ControlData::isCatch):
(JSC::Wasm::B3IRGenerator::ControlData::dump const):
(JSC::Wasm::B3IRGenerator::ControlData::convertTryToCatch):
(JSC::Wasm::B3IRGenerator::ControlData::convertTryToCatchAll):
(JSC::Wasm::B3IRGenerator::ControlData::tryStart const):
(JSC::Wasm::B3IRGenerator::ControlData::tryEnd const):
(JSC::Wasm::B3IRGenerator::ControlData::tryDepth const):
(JSC::Wasm::B3IRGenerator::ControlData::catchKind const):
(JSC::Wasm::B3IRGenerator::ControlData::exception const):
(JSC::Wasm::B3IRGenerator::ControlData::stackSize const):
(JSC::Wasm::B3IRGenerator::didPopValueFromStack):
(JSC::Wasm::B3IRGenerator::addStackMap):
(JSC::Wasm::B3IRGenerator::takeStackmaps):
(JSC::Wasm::B3IRGenerator::takeExceptionHandlers):
(JSC::Wasm::B3IRGenerator::push):
(JSC::Wasm::B3IRGenerator::get):
(JSC::Wasm::B3IRGenerator::set):
(JSC::Wasm::PatchpointExceptionHandle::generate const):
(JSC::Wasm::B3IRGenerator::fixupPointerPlusOffset):
(JSC::Wasm::B3IRGenerator::B3IRGenerator):
(JSC::Wasm::B3IRGenerator::restoreWebAssemblyGlobalState):
(JSC::Wasm::B3IRGenerator::insertEntrySwitch):
(JSC::Wasm::B3IRGenerator::insertConstants):
(JSC::Wasm::B3IRGenerator::addRefIsNull):
(JSC::Wasm::B3IRGenerator::addTableGet):
(JSC::Wasm::B3IRGenerator::addTableSet):
(JSC::Wasm::B3IRGenerator::addRefFunc):
(JSC::Wasm::B3IRGenerator::addTableInit):
(JSC::Wasm::B3IRGenerator::addTableSize):
(JSC::Wasm::B3IRGenerator::addTableGrow):
(JSC::Wasm::B3IRGenerator::addTableFill):
(JSC::Wasm::B3IRGenerator::addTableCopy):
(JSC::Wasm::B3IRGenerator::getLocal):
(JSC::Wasm::B3IRGenerator::emitIndirectCall):
(JSC::Wasm::B3IRGenerator::addGrowMemory):
(JSC::Wasm::B3IRGenerator::addCurrentMemory):
(JSC::Wasm::B3IRGenerator::addMemoryFill):
(JSC::Wasm::B3IRGenerator::addMemoryInit):
(JSC::Wasm::B3IRGenerator::addMemoryCopy):
(JSC::Wasm::B3IRGenerator::setLocal):
(JSC::Wasm::B3IRGenerator::getGlobal):
(JSC::Wasm::B3IRGenerator::setGlobal):
(JSC::Wasm::B3IRGenerator::emitCheckAndPreparePointer):
(JSC::Wasm::B3IRGenerator::emitLoadOp):
(JSC::Wasm::B3IRGenerator::load):
(JSC::Wasm::B3IRGenerator::emitStoreOp):
(JSC::Wasm::B3IRGenerator::store):
(JSC::Wasm::B3IRGenerator::sanitizeAtomicResult):
(JSC::Wasm::B3IRGenerator::fixupPointerPlusOffsetForAtomicOps):
(JSC::Wasm::B3IRGenerator::emitAtomicLoadOp):
(JSC::Wasm::B3IRGenerator::atomicLoad):
(JSC::Wasm::B3IRGenerator::emitAtomicStoreOp):
(JSC::Wasm::B3IRGenerator::atomicStore):
(JSC::Wasm::B3IRGenerator::emitAtomicBinaryRMWOp):
(JSC::Wasm::B3IRGenerator::atomicBinaryRMW):
(JSC::Wasm::B3IRGenerator::emitAtomicCompareExchange):
(JSC::Wasm::B3IRGenerator::atomicCompareExchange):
(JSC::Wasm::B3IRGenerator::atomicWait):
(JSC::Wasm::B3IRGenerator::atomicNotify):
(JSC::Wasm::B3IRGenerator::truncSaturated):
(JSC::Wasm::B3IRGenerator::addSelect):
(JSC::Wasm::B3IRGenerator::addConstant):
(JSC::Wasm::B3IRGenerator::emitLoopTierUpCheck):
(JSC::Wasm::B3IRGenerator::loadFromScratchBuffer):
(JSC::Wasm::B3IRGenerator::connectControlEntry):
(JSC::Wasm::B3IRGenerator::addLoop):
(JSC::Wasm::B3IRGenerator::addTopLevel):
(JSC::Wasm::B3IRGenerator::addBlock):
(JSC::Wasm::B3IRGenerator::addIf):
(JSC::Wasm::B3IRGenerator::addElse):
(JSC::Wasm::B3IRGenerator::addElseToUnreachable):
(JSC::Wasm::B3IRGenerator::addTry):
(JSC::Wasm::B3IRGenerator::addCatch):
(JSC::Wasm::B3IRGenerator::preparePatchpointForExceptions):
(JSC::Wasm::B3IRGenerator::addCatchToUnreachable):
(JSC::Wasm::B3IRGenerator::addCatchAll):
(JSC::Wasm::B3IRGenerator::addCatchAllToUnreachable):
(JSC::Wasm::B3IRGenerator::emitCatchImpl):
(JSC::Wasm::B3IRGenerator::addDelegate):
(JSC::Wasm::B3IRGenerator::addDelegateToUnreachable):
(JSC::Wasm::B3IRGenerator::addThrow):
(JSC::Wasm::B3IRGenerator::addRethrow):
(JSC::Wasm::B3IRGenerator::addReturn):
(JSC::Wasm::B3IRGenerator::addBranch):
(JSC::Wasm::B3IRGenerator::addSwitch):
(JSC::Wasm::B3IRGenerator::endBlock):
(JSC::Wasm::B3IRGenerator::addEndToUnreachable):
(JSC::Wasm::B3IRGenerator::createCallPatchpoint):
(JSC::Wasm::B3IRGenerator::addCall):
(JSC::Wasm::B3IRGenerator::addCallIndirect):
(JSC::Wasm::B3IRGenerator::addCallRef):
(JSC::Wasm::B3IRGenerator::unify):
(JSC::Wasm::B3IRGenerator::unifyValuesWithBlock):
(JSC::Wasm::parseAndCompile):
(JSC::Wasm::computeExceptionHandlerLocations):
(JSC::Wasm::B3IRGenerator::emitChecksForModOrDiv):
(JSC::Wasm::B3IRGenerator::addOp<OpType::I32DivS>):
(JSC::Wasm::B3IRGenerator::addOp<OpType::I32RemS>):
(JSC::Wasm::B3IRGenerator::addOp<OpType::I32DivU>):
(JSC::Wasm::B3IRGenerator::addOp<OpType::I32RemU>):
(JSC::Wasm::B3IRGenerator::addOp<OpType::I64DivS>):
(JSC::Wasm::B3IRGenerator::addOp<OpType::I64RemS>):
(JSC::Wasm::B3IRGenerator::addOp<OpType::I64DivU>):
(JSC::Wasm::B3IRGenerator::addOp<OpType::I64RemU>):
(JSC::Wasm::B3IRGenerator::addOp<OpType::I32Ctz>):
(JSC::Wasm::B3IRGenerator::addOp<OpType::I64Ctz>):
(JSC::Wasm::B3IRGenerator::addOp<OpType::I32Popcnt>):
(JSC::Wasm::B3IRGenerator::addOp<OpType::I64Popcnt>):
(JSC::Wasm::B3IRGenerator::addOp<F64ConvertUI64>):
(JSC::Wasm::B3IRGenerator::addOp<OpType::F32ConvertUI64>):
(JSC::Wasm::B3IRGenerator::addOp<OpType::F64Nearest>):
(JSC::Wasm::B3IRGenerator::addOp<OpType::F32Nearest>):
(JSC::Wasm::B3IRGenerator::addOp<OpType::F64Trunc>):
(JSC::Wasm::B3IRGenerator::addOp<OpType::F32Trunc>):
(JSC::Wasm::B3IRGenerator::addOp<OpType::I32TruncSF64>):
(JSC::Wasm::B3IRGenerator::addOp<OpType::I32TruncSF32>):
(JSC::Wasm::B3IRGenerator::addOp<OpType::I32TruncUF64>):
(JSC::Wasm::B3IRGenerator::addOp<OpType::I32TruncUF32>):
(JSC::Wasm::B3IRGenerator::addOp<OpType::I64TruncSF64>):
(JSC::Wasm::B3IRGenerator::addOp<OpType::I64TruncUF64>):
(JSC::Wasm::B3IRGenerator::addOp<OpType::I64TruncSF32>):
(JSC::Wasm::B3IRGenerator::addOp<OpType::I64TruncUF32>):

  • wasm/WasmB3IRGenerator.h:
  • wasm/WasmBBQPlan.cpp:

(JSC::Wasm::BBQPlan::prepareImpl):
(JSC::Wasm::BBQPlan::work):
(JSC::Wasm::BBQPlan::compileFunction):
(JSC::Wasm::BBQPlan::didCompleteCompilation):
(JSC::Wasm::BBQPlan::initializeCallees):

  • wasm/WasmBBQPlan.h:
  • wasm/WasmCallee.cpp:

(JSC::Wasm::Callee::handlerForIndex):
(JSC::Wasm::LLIntCallee::LLIntCallee):
(JSC::Wasm::LLIntCallee::linkExceptionHandlers):
(JSC::Wasm::OptimizingJITCallee::linkExceptionHandlers):
(JSC::Wasm::OptimizingJITCallee::stackmap const):

  • wasm/WasmCallee.h:

(JSC::Wasm::Callee::hasExceptionHandlers const):
(JSC::Wasm::Callee::functionCodeBlock const):
(JSC::Wasm::OptimizingJITCallee::OptimizingJITCallee):

  • wasm/WasmCallingConvention.h:

(JSC::Wasm::WasmCallingConvention::callInformationFor const):

  • wasm/WasmFormat.h:

(JSC::Wasm::typeToString):
(JSC::Wasm::isValidExternalKind):
(JSC::Wasm::makeString):

  • wasm/WasmFunctionCodeBlock.h:

(JSC::Wasm::FunctionCodeBlock::numberOfExceptionHandlers const):
(JSC::Wasm::FunctionCodeBlock::exceptionHandler):
(JSC::Wasm::FunctionCodeBlock::addExceptionHandler):

  • wasm/WasmFunctionParser.h:

(JSC::Wasm::isTryOrCatch):
(JSC::Wasm::FunctionParser<Context>::parseExceptionIndex):
(JSC::Wasm::FunctionParser<Context>::parseExpression):
(JSC::Wasm::FunctionParser<Context>::parseUnreachableExpression):

  • wasm/WasmHandlerInfo.cpp: Added.

(JSC::Wasm::HandlerInfo::initialize):
(JSC::Wasm::HandlerInfo::handlerForIndex):

  • wasm/WasmHandlerInfo.h: Added.

(JSC::Wasm::UnlinkedHandlerInfo::UnlinkedHandlerInfo):
(JSC::Wasm::HandlerInfo::tag const):
(JSC::Wasm::HandlerInfo::delegateTarget const):

  • wasm/WasmInstance.cpp:

(JSC::Wasm::Instance::~Instance):

  • wasm/WasmInstance.h:

(JSC::Wasm::Instance::addTag):
(JSC::Wasm::Instance::tag const):

  • wasm/WasmLLIntGenerator.cpp:

(JSC::Wasm::LLIntGenerator::ControlType::try_):
(JSC::Wasm::LLIntGenerator::ControlType::catch_):
(JSC::Wasm::LLIntGenerator::ControlType::isLoop):
(JSC::Wasm::LLIntGenerator::ControlType::isBlock):
(JSC::Wasm::LLIntGenerator::ControlType::isIf):
(JSC::Wasm::LLIntGenerator::ControlType::isTry):
(JSC::Wasm::LLIntGenerator::ControlType::isAnyCatch):
(JSC::Wasm::LLIntGenerator::ControlType::isCatch):
(JSC::Wasm::LLIntGenerator::unifyValuesWithBlock):
(JSC::Wasm::LLIntGenerator::walkExpressionStack):
(JSC::Wasm::LLIntGenerator::materializeConstantsAndLocals):
(JSC::Wasm::parseAndCompileBytecode):
(JSC::Wasm::LLIntGenerator::LLIntGenerator):
(JSC::Wasm::LLIntGenerator::repatch):
(JSC::Wasm::LLIntGenerator::finalize):
(JSC::Wasm::LLIntGenerator::callInformationForCaller):
(JSC::Wasm::LLIntGenerator::callInformationForCallee):
(JSC::Wasm::LLIntGenerator::addArguments):
(JSC::Wasm::LLIntGenerator::addLoop):
(JSC::Wasm::LLIntGenerator::addTry):
(JSC::Wasm::LLIntGenerator::finalizePreviousBlockForCatch):
(JSC::Wasm::LLIntGenerator::addCatch):
(JSC::Wasm::LLIntGenerator::addCatchToUnreachable):
(JSC::Wasm::LLIntGenerator::addCatchAll):
(JSC::Wasm::LLIntGenerator::addCatchAllToUnreachable):
(JSC::Wasm::LLIntGenerator::addDelegate):
(JSC::Wasm::LLIntGenerator::addDelegateToUnreachable):
(JSC::Wasm::LLIntGenerator::addThrow):
(JSC::Wasm::LLIntGenerator::addRethrow):
(JSC::Wasm::LLIntGenerator::endBlock):
(JSC::Wasm::LLIntGenerator::addEndToUnreachable):

  • wasm/WasmLLIntGenerator.h:
  • wasm/WasmLimits.h:
  • wasm/WasmModuleInformation.cpp:
  • wasm/WasmModuleInformation.h:

(JSC::Wasm::ModuleInformation::exceptionIndexSpaceSize const):
(JSC::Wasm::ModuleInformation::isImportedExceptionFromExceptionIndexSpace const):
(JSC::Wasm::ModuleInformation::signatureIndexFromExceptionIndexSpace const):
(JSC::Wasm::ModuleInformation::importExceptionCount const):
(JSC::Wasm::ModuleInformation::isDeclaredException const):
(JSC::Wasm::ModuleInformation::addDeclaredException):

  • wasm/WasmOMGForOSREntryPlan.cpp:

(JSC::Wasm::OMGForOSREntryPlan::work):

  • wasm/WasmOMGPlan.cpp:

(JSC::Wasm::OMGPlan::work):

  • wasm/WasmOSREntryData.h:

(JSC::Wasm::OSREntryData::values):

  • wasm/WasmOperations.cpp:

(JSC::Wasm::loadValuesIntoBuffer):
(JSC::Wasm::doOSREntry):
(JSC::Wasm::JSC_DEFINE_JIT_OPERATION):

  • wasm/WasmOperations.h:
  • wasm/WasmSectionParser.cpp:

(JSC::Wasm::SectionParser::parseImport):
(JSC::Wasm::SectionParser::parseExport):
(JSC::Wasm::SectionParser::parseException):

  • wasm/WasmSections.h:

(JSC::Wasm::validateOrder):

  • wasm/WasmSignature.cpp:

(JSC::Wasm::SignatureInformation::SignatureInformation):
(JSC::Wasm::SignatureInformation::signatureFor):

  • wasm/WasmSlowPaths.cpp:

(JSC::LLInt::WASM_SLOW_PATH_DECL):

  • wasm/WasmSlowPaths.h:
  • wasm/WasmStreamingParser.cpp:

(JSC::Wasm::StreamingParser::parseCodeSectionSize):

  • wasm/WasmTag.cpp: Copied from Source/JavaScriptCore/wasm/js/JSWebAssemblyRuntimeError.h.
  • wasm/WasmTag.h: Copied from Source/JavaScriptCore/wasm/WasmLLIntGenerator.h.

(JSC::Wasm::Tag::create):
(JSC::Wasm::Tag::parameterCount const):
(JSC::Wasm::Tag::parameter const):
(JSC::Wasm::Tag::operator== const):
(JSC::Wasm::Tag::operator!= const):
(JSC::Wasm::Tag::signature const):
(JSC::Wasm::Tag::Tag):

  • wasm/WasmThunks.cpp:
  • wasm/WasmThunks.h:
  • wasm/generateWasmB3IRGeneratorInlinesHeader.py:

(CodeGenerator.generateOpcode):
(CodeGenerator.makeResult):
(CodeGenerator.generate):

  • wasm/generateWasmOpsHeader.py:

(typeMacroizer):

  • wasm/js/JSWebAssembly.cpp:
  • wasm/js/JSWebAssemblyException.cpp: Added.

(JSC::JSWebAssemblyException::JSWebAssemblyException):
(JSC::JSWebAssemblyException::finishCreation):
(JSC::JSWebAssemblyException::visitChildrenImpl):
(JSC::JSWebAssemblyException::destroy):
(JSC::JSWebAssemblyException::getArg const):

  • wasm/js/JSWebAssemblyException.h: Added.

(JSC::JSWebAssemblyException::subspaceFor):
(JSC::JSWebAssemblyException::createStructure):
(JSC::JSWebAssemblyException::create):
(JSC::JSWebAssemblyException::tag const):
(JSC::JSWebAssemblyException::payload const):

  • wasm/js/JSWebAssemblyHelpers.h:

(JSC::toJSValue):
(JSC::fromJSValue):

  • wasm/js/JSWebAssemblyInstance.cpp:

(JSC::JSWebAssemblyInstance::tryCreate):

  • wasm/js/JSWebAssemblyInstance.h:
  • wasm/js/JSWebAssemblyRuntimeError.cpp:

(JSC::createJSWebAssemblyRuntimeError):

  • wasm/js/JSWebAssemblyRuntimeError.h:
  • wasm/js/JSWebAssemblyTag.cpp: Copied from Source/JavaScriptCore/wasm/js/JSWebAssemblyRuntimeError.cpp.

(JSC::JSWebAssemblyTag::create):
(JSC::JSWebAssemblyTag::createStructure):
(JSC::JSWebAssemblyTag::JSWebAssemblyTag):

  • wasm/js/JSWebAssemblyTag.h: Copied from Source/JavaScriptCore/wasm/js/JSWebAssemblyRuntimeError.h.
  • wasm/js/WasmToJS.cpp:

(JSC::Wasm::wasmToJS):

  • wasm/js/WebAssemblyExceptionConstructor.cpp: Added.

(JSC::JSC_DEFINE_HOST_FUNCTION):
(JSC::WebAssemblyExceptionConstructor::create):
(JSC::WebAssemblyExceptionConstructor::createStructure):
(JSC::WebAssemblyExceptionConstructor::finishCreation):
(JSC::WebAssemblyExceptionConstructor::WebAssemblyExceptionConstructor):

  • wasm/js/WebAssemblyExceptionConstructor.h: Copied from Source/JavaScriptCore/wasm/js/JSWebAssemblyRuntimeError.h.
  • wasm/js/WebAssemblyExceptionPrototype.cpp: Added.

(JSC::WebAssemblyExceptionPrototype::create):
(JSC::WebAssemblyExceptionPrototype::createStructure):
(JSC::WebAssemblyExceptionPrototype::finishCreation):
(JSC::WebAssemblyExceptionPrototype::WebAssemblyExceptionPrototype):
(JSC::getException):
(JSC::getTag):
(JSC::JSC_DEFINE_HOST_FUNCTION):

  • wasm/js/WebAssemblyExceptionPrototype.h: Copied from Source/JavaScriptCore/wasm/js/JSWebAssemblyRuntimeError.h.
  • wasm/js/WebAssemblyFunction.cpp:

(JSC::JSC_DEFINE_HOST_FUNCTION):

  • wasm/js/WebAssemblyModuleRecord.cpp:

(JSC::WebAssemblyModuleRecord::linkImpl):

  • wasm/js/WebAssemblyTagConstructor.cpp: Added.

(JSC::JSC_DEFINE_HOST_FUNCTION):
(JSC::WebAssemblyTagConstructor::createTag):
(JSC::WebAssemblyTagConstructor::create):
(JSC::WebAssemblyTagConstructor::createStructure):
(JSC::WebAssemblyTagConstructor::finishCreation):
(JSC::WebAssemblyTagConstructor::WebAssemblyTagConstructor):

  • wasm/js/WebAssemblyTagConstructor.h: Copied from Source/JavaScriptCore/wasm/js/JSWebAssemblyRuntimeError.h.
  • wasm/js/WebAssemblyTagPrototype.cpp: Added.

(JSC::WebAssemblyTagPrototype::create):
(JSC::WebAssemblyTagPrototype::createStructure):
(JSC::WebAssemblyTagPrototype::finishCreation):
(JSC::WebAssemblyTagPrototype::WebAssemblyTagPrototype):
(JSC::getTag):
(JSC::JSC_DEFINE_HOST_FUNCTION):

  • wasm/js/WebAssemblyTagPrototype.h: Copied from Source/JavaScriptCore/wasm/js/JSWebAssemblyRuntimeError.h.
  • wasm/wasm.json:

Tools:

Reviewed by Keith Miller.

  • Scripts/run-jsc-stress-tests:
Location:
trunk
Files:
40 added
83 edited
8 copied

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r283841 r283852  
     12021-10-08  Tadeu Zagallo  <tzagallo@apple.com>
     2
     3        Implement the WebAssembly exception handling proposal
     4        https://bugs.webkit.org/show_bug.cgi?id=229681
     5        <rdar://81603387>
     6
     7        Reviewed by Keith Miller.
     8
     9        Add new tests for the exception handling and import a set of tests used by V8 into wasm/v8.
     10
     11        * wasm.yaml:
     12        * wasm/Builder.js:
     13        (const._importExceptionContinuation.type.Import.field):
     14        (export.default.Builder.prototype._registerSectionBuilders.const.section.in.WASM.description.section.switch.section.case.string_appeared_here.this.section):
     15        (const._exportFunctionContinuation.type.Export.field): Deleted.
     16        (const._exportFunctionContinuation): Deleted.
     17        * wasm/Builder_WebAssemblyBinary.js:
     18        (const.emitters.Import):
     19        (const.emitters.Export):
     20        (const.emitters.Exception):
     21        * wasm/assert.js:
     22        * wasm/self-test/test_BuilderJSON.js:
     23        (ImportBeforeTypeSections): Deleted.
     24        * wasm/stress/catch-with-delegate.js: Added.
     25        (import.Builder.from.string_appeared_here.import.as.assert.from.string_appeared_here.callback):
     26        (assert.throws):
     27        * wasm/stress/create-tag-from.js: Added.
     28        * wasm/stress/exception-cross-instance-2.js: Added.
     29        (test):
     30        (assert.eq):
     31        * wasm/stress/exception-cross-instance-3.js: Added.
     32        (test):
     33        (assert.eq):
     34        * wasm/stress/exception-cross-instance.js: Added.
     35        (test):
     36        (assert.throws):
     37        (instB.new.WebAssembly.Instance):
     38        * wasm/stress/exception-liveness-tier-up.js: Added.
     39        (import.Builder.from.string_appeared_here.import.as.assert.from.string_appeared_here.catch):
     40        (assert.eq.):
     41        (assert.eq):
     42        * wasm/stress/exception-multiple-instances.js: Added.
     43        (import.Builder.from.string_appeared_here.import.as.assert.from.string_appeared_here.const.module.new.WebAssembly.Module):
     44        (import.Builder.from.string_appeared_here.import.as.assert.from.string_appeared_here.inst.exports.throw):
     45        * wasm/stress/exception-simple-delegate.js: Added.
     46        (import.Builder.from.string_appeared_here.import.as.assert.from.string_appeared_here.testSimpleThrowDelegate):
     47        (testThrowDelegateSkip):
     48        (testDelegateCaller):
     49        (testSimpleDelegateMerge):
     50        * wasm/stress/exception-simple-throw-catch.js: Added.
     51        (import.Builder.from.string_appeared_here.import.as.assert.from.string_appeared_here.testSimpleTryCatch):
     52        (testSimpleTryCatchAll):
     53        (testCallTryCatch):
     54        (testCallTryCatchAll):
     55        (testSimpleTryCatchValue):
     56        (testCallTryCatchValue):
     57        (testStackTryCatch):
     58        (testLiveAfterTryCatch):
     59        (testLiveAfterTryCatchAll):
     60        (testUnifyTryCatchCatch):
     61        (testUnifyTryCatchCatchAll):
     62        (testUnifyTryNoThrow):
     63        (testUnifyTryNoCatch):
     64        (testNestedCatch):
     65        * wasm/stress/exception-thrown-from-js-to-wasm-catchall-rethrow.js: Added.
     66        (import.Builder.from.string_appeared_here.import.as.assert.from.string_appeared_here.callback):
     67        * wasm/stress/exception-thrown-from-js-to-wasm-catchall.js: Added.
     68        (import.Builder.from.string_appeared_here.import.as.assert.from.string_appeared_here.callback):
     69        * wasm/stress/exception-thrown-from-js-to-wasm.js: Added.
     70        (import.Builder.from.string_appeared_here.import.as.assert.from.string_appeared_here.callback):
     71        * wasm/stress/exception-thrown-out-of-wasm.js: Added.
     72        * wasm/stress/exception-thrown-over-wasm.js: Added.
     73        (import.Builder.from.string_appeared_here.import.as.assert.from.string_appeared_here.callback):
     74        * wasm/stress/exception-trap.js: Added.
     75        (import.Builder.from.string_appeared_here.import.as.assert.from.string_appeared_here.testCannotCatchUnreachable):
     76        (testCannotCatchOOB):
     77        (testWasmAPIThrow):
     78        (testJSCatchAndRethrow):
     79        * wasm/stress/rethrow-from-catch-to-catch.js: Added.
     80        (import.Builder.from.string_appeared_here.import.as.assert.from.string_appeared_here.callback):
     81        * wasm/stress/rethrow-to-catch.js: Added.
     82        (import.Builder.from.string_appeared_here.import.as.assert.from.string_appeared_here.callback):
     83        (assert.throws.callback):
     84        (assert.throws):
     85        * wasm/stress/rethrow-to-delegate-to-catch.js: Added.
     86        (import.Builder.from.string_appeared_here.import.as.assert.from.string_appeared_here):
     87        (assert.eq.exn.getArg):
     88        (assert.throws):
     89        (assert.throws.callback):
     90        (assert.eq):
     91        * wasm/stress/simple-export-exception.js: Added.
     92        * wasm/v8/LICENSE: Added.
     93        * wasm/v8/exceptions-api.js: Added.
     94        (TestImport):
     95        (TestImportExport):
     96        (TestExceptionConstructor):
     97        (TestExceptionConstructorWithPayload):
     98        (TestCatchJSException.js_func):
     99        (js_func):
     100        (TestCatchJS):
     101        (TestCatchJSExceptionWithPayload):
     102        (TestGetArg):
     103        * wasm/v8/exceptions-export.js: Added.
     104        (TestExportMultiple):
     105        (TestExportOutOfBounds):
     106        * wasm/v8/exceptions-externref.js: Added.
     107        (TestThrowRefNull):
     108        (TestThrowRefParam):
     109        * wasm/v8/exceptions-import.js: Added.
     110        (NewExportedTag):
     111        (TestImportSimple):
     112        (TestImportMissing):
     113        * wasm/v8/exceptions-rethrow.js: Added.
     114        (TestRethrowInCatch):
     115        (TestRethrowInCatchAll):
     116        (TestRethrowNested):
     117        (TestRethrowRecatch):
     118        * wasm/v8/exceptions-shared.js: Added.
     119        (NewExportedException):
     120        (TestSingleInstance.let.instance.builder.instantiate.):
     121        (TestSingleInstance):
     122        (TestMultiInstanceNonShared.let.instance2.builder.instantiate.):
     123        (TestMultiInstanceShared.let.instance2.builder.instantiate.):
     124        (TestMultiModuleShared.let.instance2.builder2.instantiate.):
     125        * wasm/v8/exceptions-type-reflection.js: Added.
     126        (TestExport):
     127        (TestImportExport):
     128        * wasm/v8/exceptions-utils.js: Added.
     129        (assertWasmThrows):
     130        * wasm/v8/exceptions.js: Added.
     131        (TestThrowSimple):
     132        (TestCatchSimple):
     133        (TestTrapNotCaught):
     134        (TestTrapViaJSNotCaught.js_import):
     135        (TestManuallyThrownRuntimeErrorCaught.throw_exc):
     136        (TestManuallyThrownRuntimeErrorCaught):
     137        (TestExnWithWasmProtoNotCaught.js_import):
     138        (TestExnWithWasmProtoNotCaught):
     139        (TestStackOverflowNotCaught.stack_overflow):
     140        (TestStackOverflowNotCaught):
     141        (TestThrowParamI):
     142        (TestThrowParamF):
     143        (TestThrowParamL):
     144        (TestThrowParamD):
     145        (TestCatchCrossFunctions.throw_value):
     146        (TestCatchCrossFunctions.throw_string):
     147        (TestCatchCrossFunctions.throw_undefined):
     148        (TestCatchCrossFunctions.throw_fp):
     149        (TestCatchCrossFunctions.throw_large):
     150        (TestDelegateNoThrow):
     151        (TestDelegateThrow):
     152        (TestDelegateThrowNoCatch):
     153        (TestDelegateMerge):
     154        (TestDelegate1):
     155        (TestDelegateUnreachable):
     156        (TestDelegateToCaller):
     157        (TestUnreachableInCatchAll):
     158        (TestThrowWithLocal):
     159        (TestCatchlessTry):
     160        * wasm/v8/mjsunit.js: Added.
     161        (MjsUnitAssertionError):
     162        (MjsUnitAssertionError.prototype.toString):
     163        (catch):
     164        (classOf):
     165        (ValueOf):
     166        (prettyPrinted):
     167        (prettyPrintedArrayElement):
     168        (failWithMessage):
     169        (formatFailureText):
     170        (fail):
     171        (deepObjectEquals):
     172        (deepEquals):
     173        (assertSame):
     174        (assertNotSame):
     175        (assertEquals):
     176        (assertNotEquals):
     177        (assertEqualsDelta):
     178        (assertArrayEquals):
     179        (assertPropertiesEqual):
     180        (assertToStringEquals):
     181        (assertTrue):
     182        (assertFalse):
     183        (assertNull):
     184        (assertNotNull):
     185        (executeCode):
     186        (checkException):
     187        (assertThrows):
     188        (assertThrowsEquals):
     189        (assertThrowsAsync):
     190        (assertInstanceof):
     191        (assertDoesNotThrow):
     192        (assertUnreachable):
     193        (assertContains):
     194        (assertMatches):
     195        (concatenateErrors):
     196        (assertPromiseResult):
     197        (OptimizationStatus):
     198        (assertUnoptimized):
     199        (assertOptimized):
     200        (isNeverOptimizeLiteMode):
     201        (isNeverOptimize):
     202        (isAlwaysOptimize):
     203        (isInterpreted):
     204        (isBaseline):
     205        (isUnoptimized):
     206        (isOptimized):
     207        (isTurboFanned):
     208        (MjsUnitAssertionError.prepareStackTrace):
     209        * wasm/v8/wasm-module-builder.js: Added.
     210        (bytes):
     211        (wasmOptRefType):
     212        (wasmRefType):
     213        (wasmRtt):
     214        (wasmRttNoDepth):
     215        (makeSig):
     216        (makeSig_v_x):
     217        (makeSig_x_v):
     218        (makeSig_v_xx):
     219        (makeSig_r_v):
     220        (makeSig_r_x):
     221        (makeSig_r_xx):
     222        (defineWasmOpcode):
     223        (assertTraps):
     224        (Binary):
     225        (Binary.prototype.ensure_space):
     226        (Binary.prototype.trunc_buffer):
     227        (Binary.prototype.reset):
     228        (Binary.prototype.emit_u8):
     229        (Binary.prototype.emit_u16):
     230        (Binary.prototype.emit_u32):
     231        (Binary.prototype.emit_leb_u):
     232        (Binary.prototype.emit_u32v):
     233        (Binary.prototype.emit_u64v):
     234        (Binary.prototype.emit_bytes):
     235        (Binary.prototype.emit_string):
     236        (Binary.prototype.emit_heap_type):
     237        (Binary.prototype.emit_type):
     238        (Binary.prototype.emit_init_expr_recursive):
     239        (Binary.prototype.emit_init_expr):
     240        (Binary.prototype.emit_header):
     241        (Binary.prototype.emit_section):
     242        (WasmFunctionBuilder):
     243        (WasmFunctionBuilder.prototype.numLocalNames):
     244        (WasmFunctionBuilder.prototype.exportAs):
     245        (WasmFunctionBuilder.prototype.exportFunc):
     246        (WasmFunctionBuilder.prototype.setCompilationHint):
     247        (WasmFunctionBuilder.prototype.addBody):
     248        (WasmFunctionBuilder.prototype.addBodyWithEnd):
     249        (WasmFunctionBuilder.prototype.getNumLocals):
     250        (WasmFunctionBuilder.prototype.addLocals):
     251        (WasmFunctionBuilder.prototype.end):
     252        (WasmInitExpr.I32Const):
     253        (WasmInitExpr.I64Const):
     254        (WasmInitExpr.F32Const):
     255        (WasmInitExpr.F64Const):
     256        (WasmInitExpr.S128Const):
     257        (WasmInitExpr.GlobalGet):
     258        (WasmInitExpr.RefFunc):
     259        (WasmInitExpr.RefNull):
     260        (WasmInitExpr.StructNewWithRtt):
     261        (WasmInitExpr.StructNew):
     262        (WasmInitExpr.StructNewDefaultWithRtt):
     263        (WasmInitExpr.StructNewDefault):
     264        (WasmInitExpr.ArrayInit):
     265        (WasmInitExpr.ArrayInitStatic):
     266        (WasmInitExpr.RttCanon):
     267        (WasmInitExpr.RttSub):
     268        (WasmInitExpr.RttFreshSub):
     269        (WasmInitExpr.defaultFor):
     270        (WasmInitExpr):
     271        (WasmGlobalBuilder):
     272        (WasmGlobalBuilder.prototype.exportAs):
     273        (WasmTableBuilder):
     274        (WasmTableBuilder.prototype.exportAs):
     275        (makeField):
     276        (WasmStruct):
     277        (WasmStructSubtype):
     278        (WasmArray):
     279        (WasmArraySubtype):
     280        (WasmElemSegment):
     281        (WasmElemSegment.prototype.is_active):
     282        (WasmElemSegment.prototype.is_passive):
     283        (WasmElemSegment.prototype.is_declarative):
     284        (WasmElemSegment.prototype.expressions_as_elements):
     285        (WasmModuleBuilder):
     286        (WasmModuleBuilder.prototype.addStart):
     287        (WasmModuleBuilder.prototype.addMemory):
     288        (WasmModuleBuilder.prototype.addMemory64):
     289        (WasmModuleBuilder.prototype.addExplicitSection):
     290        (WasmModuleBuilder.prototype.stringToBytes):
     291        (WasmModuleBuilder.prototype.createCustomSection):
     292        (WasmModuleBuilder.prototype.addCustomSection):
     293        (WasmModuleBuilder.prototype.addType):
     294        (WasmModuleBuilder.prototype.addStruct):
     295        (WasmModuleBuilder.prototype.addStructSubtype):
     296        (WasmModuleBuilder.prototype.addArray):
     297        (WasmModuleBuilder.prototype.addArraySubtype):
     298        (WasmModuleBuilder.prototype.addGlobal):
     299        (WasmModuleBuilder.prototype.addTable):
     300        (WasmModuleBuilder.prototype.addTag):
     301        (WasmModuleBuilder.prototype.addFunction):
     302        (WasmModuleBuilder.prototype.addImport):
     303        (WasmModuleBuilder.prototype.addImportedGlobal):
     304        (WasmModuleBuilder.prototype.addImportedMemory):
     305        (WasmModuleBuilder.prototype.addImportedTable):
     306        (WasmModuleBuilder.prototype.addImportedTag):
     307        (WasmModuleBuilder.prototype.addExport):
     308        (WasmModuleBuilder.prototype.addExportOfKind):
     309        (WasmModuleBuilder.prototype.setCompilationHint):
     310        (WasmModuleBuilder.prototype.addDataSegment):
     311        (WasmModuleBuilder.prototype.addPassiveDataSegment):
     312        (WasmModuleBuilder.prototype.exportMemoryAs):
     313        (WasmModuleBuilder.prototype.addActiveElementSegment):
     314        (WasmModuleBuilder.prototype.addPassiveElementSegment):
     315        (WasmModuleBuilder.prototype.addDeclarativeElementSegment):
     316        (WasmModuleBuilder.prototype.appendToTable):
     317        (WasmModuleBuilder.prototype.setTableBounds):
     318        (WasmModuleBuilder.prototype.setName):
     319        (WasmModuleBuilder.prototype.toBuffer):
     320        (WasmModuleBuilder.prototype.toArray):
     321        (WasmModuleBuilder.prototype.instantiate):
     322        (WasmModuleBuilder.prototype.asyncInstantiate):
     323        (WasmModuleBuilder.prototype.toModule):
     324        (wasmSignedLeb):
     325        (wasmUnsignedLeb):
     326        (wasmI32Const):
     327        (wasmI64Const):
     328        (wasmF32Const):
     329        (wasmF64Const):
     330        (wasmS128Const):
     331        (getOpcodeName):
     332        * wasm/wasm.json:
     333
    13342021-10-08  Yusuke Suzuki  <ysuzuki@apple.com>
    2335
  • trunk/JSTests/wasm.yaml

    r276896 r283852  
    4646- path: wasm/self-test/
    4747  cmd: runWebAssemblySuite unless parseRunCommands
     48- path: wasm/v8/
     49  cmd: runWebAssemblySuite(:no_module, "mjsunit.js") unless parseRunCommands
    4850
    4951- path: wasm/references-spec-tests/elem.wast.js
  • trunk/JSTests/wasm/Builder.js

    r270344 r283852  
    129129};
    130130
     131const _importExceptionContinuation = (builder, section, nextBuilder) => {
     132    return (module, field, type) => {
     133        assert.isString(module, `Import function module should be a string, got "${module}"`);
     134        assert.isString(field, `Import function field should be a string, got "${field}"`);
     135        const typeSection = builder._getSection("Type");
     136        type = _maybeRegisterType(builder, type);
     137        const tag = 0;
     138        section.data.push({ field, type, tag, kind: "Exception", module });
     139        return _errorHandlingProxyFor(nextBuilder);
     140    }
     141};
     142
    131143const _exportFunctionContinuation = (builder, section, nextBuilder) => {
    132144    return (field, index, type) => {
     
    212224        assert.isNumber(index, `Table exports only support number indices`);
    213225        section.data.push({field, kind: "Table", index});
     226        return _errorHandlingProxyFor(nextBuilder);
     227    }
     228};
     229
     230const _exportExceptionContinuation = (builder, section, nextBuilder) => {
     231    return (field, index) => {
     232        assert.isNumber(index, `Exception exports only support number indices`);
     233        section.data.push({field, kind: "Exception", index});
    214234        return _errorHandlingProxyFor(nextBuilder);
    215235    }
     
    308328        case "reserved": break; // improve checking https://bugs.webkit.org/show_bug.cgi?id=163421
    309329        case "table_index": break; // improve checking https://bugs.webkit.org/show_bug.cgi?id=163421
     330        case "exn": break;
    310331        case "reftype":
    311332            assert.truthy(WASM.isValidRefType(imms[idx]), `Invalid ref type on ${op}: "${imms[idx]}"`);
     
    336357                break;
    337358            case "End":
     359            case "Delegate":
    338360                nextBuilder = previousBuilder;
    339361                break;
     
    341363            case "Loop":
    342364            case "If":
     365            case "Try":
    343366                nextBuilder = _createFunctionBuilder(func, builder, functionBuilder);
    344367                break;
     
    489512                    importBuilder.Memory = _importMemoryContinuation(this, s, importBuilder);
    490513                    importBuilder.Table = _importTableContinuation(this, s, importBuilder);
     514                    importBuilder.Exception = _importExceptionContinuation(this, s, importBuilder);
    491515                    return _errorHandlingProxyFor(importBuilder);
    492516                };
     
    531555                };
    532556                break;
     557
     558            case "Exception": {
     559                this[section] = function() {
     560                    const s = this._addSection(section);
     561                    const dataBuilder = {
     562                        End: () => this,
     563                        Signature: (signature) => {
     564                            let type = _maybeRegisterType(this, signature);
     565                            s.data.push({ tag: 0, type });
     566                            return _errorHandlingProxyFor(dataBuilder);
     567                        },
     568                        // If we add tags with non-zero value then we can add a new member.
     569                    };
     570                    return _errorHandlingProxyFor(dataBuilder);
     571                };
     572                break;
     573            }
    533574
    534575            case "Global":
     
    570611                    exportBuilder.Memory = _exportMemoryContinuation(this, s, exportBuilder);
    571612                    exportBuilder.Table = _exportTableContinuation(this, s, exportBuilder);
     613                    exportBuilder.Exception = _exportExceptionContinuation(this, s, exportBuilder);
    572614                    return _errorHandlingProxyFor(exportBuilder);
    573615                };
     
    738780                if (number !== _unknownSectionId)
    739781                    assert.falsy(s.name === name && s.id === number, `Cannot have two sections with the same name "${name}" and ID ${number}`);
    740             // Check ordering.
    741             if ((number !== _unknownSectionId) && (this._sections.length !== 0)) {
    742                 for (let i = this._sections.length - 1; i >= 0; --i) {
    743                     if (this._sections[i].id === _unknownSectionId)
    744                         continue;
    745                     assert.le(this._sections[i].id, number, `Bad section ordering: "${this._sections[i].name}" cannot precede "${name}"`);
    746                     break;
    747                 }
    748             }
    749782        }
    750783        const s = Object.assign({ name: name, id: number, data: [] }, extraObject || {});
  • trunk/JSTests/wasm/Builder_WebAssemblyBinary.js

    r270344 r283852  
    144144                putGlobalType(bin, entry.globalDescription);
    145145                break;
     146            case "Exception":
     147                put(bin, "varuint32", entry.tag);
     148                put(bin, "varuint32", entry.type);
     149                break;
    146150            }
    147151        }
     
    186190            case "Memory":
    187191            case "Table":
     192            case "Exception":
    188193                put(bin, "varuint32", entry.index);
    189194                break;
     
    253258            for (const byte of datum.data)
    254259                put(bin, "uint8", byte);
     260        }
     261    },
     262
     263    Exception: (section, bin) => {
     264        put(bin, "varuint32", section.data.length);
     265        for (const exn of section.data) {
     266            put(bin, "varuint32", exn.tag);
     267            put(bin, "varuint32", exn.type);
    255268        }
    256269    },
  • trunk/JSTests/wasm/assert.js

    r262227 r283852  
    125125        func(...args);
    126126    } catch (e) {
    127         if (e instanceof type && e.message.indexOf(message) >= 0)
     127        if (e instanceof type && (typeof(e.message) == "undefined" || e.message.indexOf(message) >= 0))
    128128            return e;
    129129        _fail(`Expected to throw a ${type.name} with message "${message}", got ${e.name} with message "${e.message}"`);
  • trunk/JSTests/wasm/self-test/test_BuilderJSON.js

    r232970 r283852  
    139139    assert.eq(j.section[0].name, "Import");
    140140    assert.eq(j.section[0].data.length, 0);
    141 })();
    142 
    143 (function ImportBeforeTypeSections() {
    144     const b = (new Builder()).Import().End();
    145     assert.throws(() => b.Type(), Error, `Expected: "2" > "1": Bad section ordering: "Import" cannot precede "Type"`);
    146141})();
    147142
  • trunk/JSTests/wasm/wasm.json

    r279265 r283852  
    2424    "ref_type": ["funcref", "externref", "type_idx"],
    2525    "external_kind": {
    26         "Function": { "type": "uint8", "value": 0 },
    27         "Table":    { "type": "uint8", "value": 1 },
    28         "Memory":   { "type": "uint8", "value": 2 },
    29         "Global":   { "type": "uint8", "value": 3 }
     26        "Function":    { "type": "uint8", "value": 0 },
     27        "Table":       { "type": "uint8", "value": 1 },
     28        "Memory":      { "type": "uint8", "value": 2 },
     29        "Global":      { "type": "uint8", "value": 3 },
     30        "Exception":   { "type": "uint8", "value": 4 }
    3031    },
    3132    "section" : {
    32         "Type":     { "type": "varuint7", "value":  1, "description": "Function signature declarations" },
    33         "Import":   { "type": "varuint7", "value":  2, "description": "Import declarations" },
    34         "Function": { "type": "varuint7", "value":  3, "description": "Function declarations" },
    35         "Table":    { "type": "varuint7", "value":  4, "description": "Indirect function table and other tables" },
    36         "Memory":   { "type": "varuint7", "value":  5, "description": "Memory attributes" },
    37         "Global":   { "type": "varuint7", "value":  6, "description": "Global declarations" },
    38         "Export":   { "type": "varuint7", "value":  7, "description": "Exports" },
    39         "Start":    { "type": "varuint7", "value":  8, "description": "Start function declaration" },
    40         "Element":  { "type": "varuint7", "value":  9, "description": "Elements section" },
    41         "Code":     { "type": "varuint7", "value": 10, "description": "Function bodies (code)" },
    42         "Data":     { "type": "varuint7", "value": 11, "description": "Data segments" }
     33        "Type":      { "type": "varuint7", "value":  1, "description": "Function signature declarations" },
     34        "Import":    { "type": "varuint7", "value":  2, "description": "Import declarations" },
     35        "Function":  { "type": "varuint7", "value":  3, "description": "Function declarations" },
     36        "Table":     { "type": "varuint7", "value":  4, "description": "Indirect function table and other tables" },
     37        "Memory":    { "type": "varuint7", "value":  5, "description": "Memory attributes" },
     38        "Exception": { "type": "varuint7", "value": 13, "description": "Exception declarations" },
     39        "Global":    { "type": "varuint7", "value":  6, "description": "Global declarations" },
     40        "Export":    { "type": "varuint7", "value":  7, "description": "Exports" },
     41        "Start":     { "type": "varuint7", "value":  8, "description": "Start function declaration" },
     42        "Element":   { "type": "varuint7", "value":  9, "description": "Elements section" },
     43        "Code":      { "type": "varuint7", "value": 10, "description": "Function bodies (code)" },
     44        "Data":      { "type": "varuint7", "value": 11, "description": "Data segments" },
     45        "DataCount": { "type": "varuint7", "value": 12, "description": "Number of data segments" }
    4346    },
    4447    "opcode": {
    4548        "unreachable":         { "category": "control",    "value":   0, "return": [],                               "parameter": [],                             "immediate": [],                                                                                            "description": "trap immediately" },
     49        "nop":                 { "category": "control",    "value":   1, "return": [],                               "parameter": [],                             "immediate": [],                                                                                            "description": "no operation" },
    4650        "block":               { "category": "control",    "value":   2, "return": ["control"],                      "parameter": [],                             "immediate": [{"name": "sig", "type": "block_type"}],                                                       "description": "begin a sequence of expressions, yielding 0 or 1 values" },
    4751        "loop":                { "category": "control",    "value":   3, "return": ["control"],                      "parameter": [],                             "immediate": [{"name": "sig", "type": "block_type"}],                                                       "description": "begin a block which can also form control flow loops" },
    4852        "if":                  { "category": "control",    "value":   4, "return": ["control"],                      "parameter": ["bool"],                       "immediate": [{"name": "sig", "type": "block_type"}],                                                       "description": "begin if expression" },
    4953        "else":                { "category": "control",    "value":   5, "return": ["control"],                      "parameter": [],                             "immediate": [],                                                                                            "description": "begin else expression of if" },
    50         "select":              { "category": "control",    "value":  27, "return": ["prev"],                         "parameter": ["any", "prev", "bool"],        "immediate": [],                                                                                            "description": "select one of two values based on condition" },
    51         "annotated_select":    { "category": "control",    "value":  28, "return": ["prev"],                         "parameter": ["any", "prev", "bool"],        "immediate": [{"name": "target_types_count", "type": "varuint32",                                           "description": "number of entries in the target types vector"},
    52                                                                                                                                                                                 {"name": "target_types",       "type": "value_type*",                                         "description": "target types that indicate result of select instruction"}],
    53                                                                                                                                                                                                                                                                               "description": "the same as just select but with the annotation for result types" },
     54        "try":                 { "category": "control",    "value":   6, "return": ["control"],                      "parameter": [],                             "immediate": [{"name": "sig", "type": "block_type"}],                                                       "description": "begin try expression" },
     55        "catch":               { "category": "control",    "value":   7, "return": ["control"],                      "parameter": [],                             "immediate": [{"name": "exn", "type": "varuint32"}],                                                        "description": "begin catch expression of try" },
     56        "throw":               { "category": "control",    "value":   8, "return": ["control"],                      "parameter": [],                             "immediate": [{"name": "exn", "type": "varuint32"}],                                                        "description": "throw exception" },
     57        "rethrow":             { "category": "control",    "value":   9, "return": ["control"],                      "parameter": [],                             "immediate": [{"name": "relative_depth", "type": "varuint32"}],                                             "description": "rethrow the exception at the top of the stack" },
    5458        "br":                  { "category": "control",    "value":  12, "return": [],                               "parameter": [],                             "immediate": [{"name": "relative_depth", "type": "varuint32"}],                                             "description": "break that targets an outer nested block" },
    5559        "br_if":               { "category": "control",    "value":  13, "return": [],                               "parameter": [],                             "immediate": [{"name": "relative_depth", "type": "varuint32"}],                                             "description": "conditional break that targets an outer nested block" },
     
    5963                                                                                                                                                                                                                                                                              "description": "branch table control flow construct" },
    6064        "return":              { "category": "control",    "value":  15, "return": [],                               "parameter": [],                             "immediate": [],                                                                                            "description": "return zero or one value from this function" },
     65        "delegate":            { "category": "control",    "value":  24, "return": ["control"],                      "parameter": [],                             "immediate": [{"name": "relative_depth", "type": "varuint32"}],                                             "description": "delegate to a parent try block" },
     66        "catch_all":           { "category": "control",    "value":  25, "return": ["control"],                      "parameter": [],                             "immediate": [],                                                                                            "description": "catch exceptions regardless of tag" },
    6167        "drop":                { "category": "control",    "value":  26, "return": [],                               "parameter": ["any"],                        "immediate": [],                                                                                            "description": "ignore value" },
    62         "nop":                 { "category": "control",    "value":   1, "return": [],                               "parameter": [],                             "immediate": [],                                                                                            "description": "no operation" },
     68        "select":              { "category": "control",    "value":  27, "return": ["prev"],                         "parameter": ["any", "prev", "bool"],        "immediate": [],                                                                                            "description": "select one of two values based on condition" },
     69        "annotated_select":    { "category": "control",    "value":  28, "return": ["prev"],                         "parameter": ["any", "prev", "bool"],        "immediate": [{"name": "target_types_count", "type": "varuint32",                                           "description": "number of entries in the target types vector"},
     70                                                                                                                                                                                {"name": "target_types",       "type": "value_type*",                                         "description": "target types that indicate result of select instruction"}],
     71                                                                                                                                                                                                                                                                              "description": "the same as just select but with the annotation for result types" },
    6372        "end":                 { "category": "control",    "value":  11, "return": [],                               "parameter": [],                             "immediate": [],                                                                                            "description": "end a block, loop, or if" },
    6473        "i32.const":           { "category": "special",    "value":  65, "return": ["i32"],                          "parameter": [],                             "immediate": [{"name": "value",          "type": "varint32"}],                                              "description": "a constant value interpreted as i32" },
  • trunk/Source/JavaScriptCore/CMakeLists.txt

    r283851 r283852  
    123123    wasm/js/WebAssemblyCompileErrorConstructor.cpp
    124124    wasm/js/WebAssemblyCompileErrorPrototype.cpp
     125    wasm/js/WebAssemblyExceptionConstructor.cpp
     126    wasm/js/WebAssemblyExceptionPrototype.cpp
    125127    wasm/js/WebAssemblyGlobalConstructor.cpp
    126128    wasm/js/WebAssemblyGlobalPrototype.cpp
     
    137139    wasm/js/WebAssemblyTableConstructor.cpp
    138140    wasm/js/WebAssemblyTablePrototype.cpp
     141    wasm/js/WebAssemblyTagConstructor.cpp
     142    wasm/js/WebAssemblyTagPrototype.cpp
    139143)
    140144
     
    604608    b3/B3Common.h
    605609    b3/B3Type.h
     610    b3/B3ValueRep.h
    606611
    607612    bindings/ScriptFunctionCall.h
     
    12231228    wasm/WasmFormat.h
    12241229    wasm/WasmFunctionCodeBlock.h
     1230    wasm/WasmHandlerInfo.h
    12251231    wasm/WasmIndexOrName.h
    12261232    wasm/WasmLLIntTierUpCounter.h
     
    12311237    wasm/WasmName.h
    12321238    wasm/WasmNameSection.h
     1239    wasm/WasmOSREntryData.h
    12331240    wasm/WasmPageCount.h
    12341241    wasm/WasmSections.h
     
    12371244    wasm/WasmStreamingParser.h
    12381245    wasm/WasmTierUpCount.h
     1246    wasm/WasmValueLocation.h
    12391247
    12401248    wasm/js/JSWebAssembly.h
  • trunk/Source/JavaScriptCore/ChangeLog

    r283851 r283852  
     12021-10-08  Tadeu Zagallo  <tzagallo@apple.com> and Keith Miller  <keith_miller@apple.com>
     2
     3        Implement the WebAssembly exception handling proposal
     4        https://bugs.webkit.org/show_bug.cgi?id=229681
     5        <rdar://81603387>
     6
     7        Reviewed by Keith Miller.
     8
     9        Add support for the WebAssembly exception handling proposal, as per
     10        the WIP spec: https://github.com/WebAssembly/exception-handling
     11
     12        The proposal includes 6 new instructions: try, catch, catch_all,
     13        delegate, throw and rethrow. All the instructions are supported by
     14        the LLInt and B3 generators, but not yet supported in Air. Any
     15        functions use exceptions will use B3 in BBQ.
     16
     17        A few important notes about the implementation:
     18        - In B3, since we can now have multiple entrypoints (one for the
     19        function entry + 1 for each catch/catch_all), we can no longer just
     20        replace every value in the stack with a Phi when we find a new
     21        entrypoint. This worked so far because of the assumption that any
     22        block couldn't access its enclosing stack, and since the enclosing stack
     23        would only be accessible when we exited the current block, we added Phis
     24        at the end of each block when we had a new entrypoint. Now, since we have to capture all
     25        live values at any point that might throw (calls, throw and rethrow),
     26        we break that assumption. To simplify all the possible ways we might
     27        have to merge the state from multiple entrypoints we now use B3
     28        Variables to represent stack slots.
     29        - Some extra information is required to be able to properly restore
     30        the state when catching an exception:
     31            - We added a field VM::calleeForWasmCatch. This field is necessary
     32            because whenever we throw, we might end up in JavaScript, which
     33            assumes the callee is a cell and uses it to get the VM and restore
     34            callee saves. The issue is when catching exceptions in wasm we
     35            still need the original callee, and if throwing and catching from
     36            the same frame, that call frame slot has now been overwritten, so
     37            we store its original value in the VM field.
     38            - We also need to store the current Wasm Instance into the call
     39            frame's slot for the `this` argument. The instance is used both by
     40            the unwinder, to check if the exception being thrown matches the
     41            exceptions handled by catch candidates, and by the catch implementation,
     42            which is necessary when throwing from a cross instance call where both
     43            the callee save or TLS will have the callee's instance.
     44            - We store the current opcode for the llint, or the
     45            call site index for B3, in the call frame slot for the argument
     46            count tag. The call site index is used by the unwinder to check
     47            if a given catch can handle the exception being thrown.
     48
     49        * DerivedSources-input.xcfilelist:
     50        * DerivedSources-output.xcfilelist:
     51        * DerivedSources.make:
     52        * JavaScriptCore.xcodeproj/project.pbxproj:
     53        * Sources.txt:
     54        * bytecode/BytecodeList.rb:
     55        * bytecode/HandlerInfo.h:
     56        * bytecode/Instruction.h:
     57        (JSC::BaseInstruction::name const):
     58        * interpreter/CallFrame.cpp:
     59        (JSC::CallFrame::bytecodeIndex const):
     60        * interpreter/CallFrame.h:
     61        (JSC::CallSiteIndex::CallSiteIndex):
     62        (JSC::CallSiteIndex::hash const):
     63        (JSC::CallSiteIndex::deletedValue):
     64        (JSC::CallSiteIndex::isHashTableDeletedValue const):
     65        (JSC::CallSiteIndexHash::hash):
     66        (JSC::CallSiteIndexHash::equal):
     67        * interpreter/Interpreter.cpp:
     68        (JSC::CatchInfo::CatchInfo):
     69        (JSC::UnwindFunctor::UnwindFunctor):
     70        (JSC::UnwindFunctor::operator() const):
     71        (JSC::Interpreter::unwind):
     72        * interpreter/Interpreter.h:
     73        (JSC::CatchInfo::CatchInfo):
     74        * interpreter/StackVisitor.cpp:
     75        (JSC::StackVisitor::readNonInlinedFrame):
     76        * jit/AssemblyHelpers.cpp:
     77        (JSC::AssemblyHelpers::restoreCalleeSavesFromEntryFrameCalleeSavesBuffer):
     78        (JSC::AssemblyHelpers::restoreCalleeSavesFromVMEntryFrameCalleeSavesBuffer):
     79        (JSC::AssemblyHelpers::restoreCalleeSavesFromVMEntryFrameCalleeSavesBufferImpl):
     80        * jit/AssemblyHelpers.h:
     81        * jit/JITExceptions.cpp:
     82        (JSC::genericUnwind):
     83        * jit/JSInterfaceJIT.h:
     84        (JSC::JSInterfaceJIT::convertCalleeToVM):
     85        * llint/LLIntData.h:
     86        (JSC::LLInt::getCodeRef):
     87        (JSC::LLInt::getWide16CodeRef):
     88        (JSC::LLInt::getWide32CodeRef):
     89        * llint/LLIntExceptions.cpp:
     90        (JSC::LLInt::wasmReturnToThrow):
     91        (JSC::LLInt::handleWasmCatch):
     92        (JSC::LLInt::handleWasmCatchAll):
     93        * llint/LLIntExceptions.h:
     94        * llint/LLIntOffsetsExtractor.cpp:
     95        * llint/WebAssembly.asm:
     96        * runtime/ErrorInstance.cpp:
     97        (JSC::ErrorInstance::ErrorInstance):
     98        * runtime/ErrorInstance.h:
     99        (JSC::ErrorInstance::setCatchableFromWasm):
     100        (JSC::ErrorInstance::isCatchableFromWasm const):
     101        * runtime/JSGlobalObject.cpp:
     102        * runtime/JSGlobalObject.h:
     103        * runtime/OptionsList.h:
     104        * runtime/VM.cpp:
     105        (JSC::VM::VM):
     106        * runtime/VM.h:
     107        (JSC::VM::calleeForWasmCatchOffset):
     108        * wasm/WasmAirIRGenerator.cpp:
     109        (JSC::Wasm::AirIRGenerator::ControlData::isTry):
     110        (JSC::Wasm::AirIRGenerator::ControlData::isCatch):
     111        (JSC::Wasm::AirIRGenerator::ControlData::isAnyCatch):
     112        (JSC::Wasm::AirIRGenerator::ControlData::isLoop):
     113        (JSC::Wasm::AirIRGenerator::ControlData::isBlock):
     114        (JSC::Wasm::AirIRGenerator::ControlData::dump const):
     115        (JSC::Wasm::AirIRGenerator::addTry):
     116        (JSC::Wasm::AirIRGenerator::addCatch):
     117        (JSC::Wasm::AirIRGenerator::addCatchToUnreachable):
     118        (JSC::Wasm::AirIRGenerator::addCatchAll):
     119        (JSC::Wasm::AirIRGenerator::addCatchAllToUnreachable):
     120        (JSC::Wasm::AirIRGenerator::addDelegate):
     121        (JSC::Wasm::AirIRGenerator::addDelegateToUnreachable):
     122        (JSC::Wasm::AirIRGenerator::addThrow):
     123        (JSC::Wasm::AirIRGenerator::addRethrow):
     124        * wasm/WasmB3IRGenerator.cpp:
     125        (JSC::Wasm::B3IRGenerator::ControlData::ControlData):
     126        (JSC::Wasm::B3IRGenerator::ControlData::isTry):
     127        (JSC::Wasm::B3IRGenerator::ControlData::isAnyCatch):
     128        (JSC::Wasm::B3IRGenerator::ControlData::isLoop):
     129        (JSC::Wasm::B3IRGenerator::ControlData::isBlock):
     130        (JSC::Wasm::B3IRGenerator::ControlData::isCatch):
     131        (JSC::Wasm::B3IRGenerator::ControlData::dump const):
     132        (JSC::Wasm::B3IRGenerator::ControlData::convertTryToCatch):
     133        (JSC::Wasm::B3IRGenerator::ControlData::convertTryToCatchAll):
     134        (JSC::Wasm::B3IRGenerator::ControlData::tryStart const):
     135        (JSC::Wasm::B3IRGenerator::ControlData::tryEnd const):
     136        (JSC::Wasm::B3IRGenerator::ControlData::tryDepth const):
     137        (JSC::Wasm::B3IRGenerator::ControlData::catchKind const):
     138        (JSC::Wasm::B3IRGenerator::ControlData::exception const):
     139        (JSC::Wasm::B3IRGenerator::ControlData::stackSize const):
     140        (JSC::Wasm::B3IRGenerator::didPopValueFromStack):
     141        (JSC::Wasm::B3IRGenerator::addStackMap):
     142        (JSC::Wasm::B3IRGenerator::takeStackmaps):
     143        (JSC::Wasm::B3IRGenerator::takeExceptionHandlers):
     144        (JSC::Wasm::B3IRGenerator::push):
     145        (JSC::Wasm::B3IRGenerator::get):
     146        (JSC::Wasm::B3IRGenerator::set):
     147        (JSC::Wasm::PatchpointExceptionHandle::generate const):
     148        (JSC::Wasm::B3IRGenerator::fixupPointerPlusOffset):
     149        (JSC::Wasm::B3IRGenerator::B3IRGenerator):
     150        (JSC::Wasm::B3IRGenerator::restoreWebAssemblyGlobalState):
     151        (JSC::Wasm::B3IRGenerator::insertEntrySwitch):
     152        (JSC::Wasm::B3IRGenerator::insertConstants):
     153        (JSC::Wasm::B3IRGenerator::addRefIsNull):
     154        (JSC::Wasm::B3IRGenerator::addTableGet):
     155        (JSC::Wasm::B3IRGenerator::addTableSet):
     156        (JSC::Wasm::B3IRGenerator::addRefFunc):
     157        (JSC::Wasm::B3IRGenerator::addTableInit):
     158        (JSC::Wasm::B3IRGenerator::addTableSize):
     159        (JSC::Wasm::B3IRGenerator::addTableGrow):
     160        (JSC::Wasm::B3IRGenerator::addTableFill):
     161        (JSC::Wasm::B3IRGenerator::addTableCopy):
     162        (JSC::Wasm::B3IRGenerator::getLocal):
     163        (JSC::Wasm::B3IRGenerator::emitIndirectCall):
     164        (JSC::Wasm::B3IRGenerator::addGrowMemory):
     165        (JSC::Wasm::B3IRGenerator::addCurrentMemory):
     166        (JSC::Wasm::B3IRGenerator::addMemoryFill):
     167        (JSC::Wasm::B3IRGenerator::addMemoryInit):
     168        (JSC::Wasm::B3IRGenerator::addMemoryCopy):
     169        (JSC::Wasm::B3IRGenerator::setLocal):
     170        (JSC::Wasm::B3IRGenerator::getGlobal):
     171        (JSC::Wasm::B3IRGenerator::setGlobal):
     172        (JSC::Wasm::B3IRGenerator::emitCheckAndPreparePointer):
     173        (JSC::Wasm::B3IRGenerator::emitLoadOp):
     174        (JSC::Wasm::B3IRGenerator::load):
     175        (JSC::Wasm::B3IRGenerator::emitStoreOp):
     176        (JSC::Wasm::B3IRGenerator::store):
     177        (JSC::Wasm::B3IRGenerator::sanitizeAtomicResult):
     178        (JSC::Wasm::B3IRGenerator::fixupPointerPlusOffsetForAtomicOps):
     179        (JSC::Wasm::B3IRGenerator::emitAtomicLoadOp):
     180        (JSC::Wasm::B3IRGenerator::atomicLoad):
     181        (JSC::Wasm::B3IRGenerator::emitAtomicStoreOp):
     182        (JSC::Wasm::B3IRGenerator::atomicStore):
     183        (JSC::Wasm::B3IRGenerator::emitAtomicBinaryRMWOp):
     184        (JSC::Wasm::B3IRGenerator::atomicBinaryRMW):
     185        (JSC::Wasm::B3IRGenerator::emitAtomicCompareExchange):
     186        (JSC::Wasm::B3IRGenerator::atomicCompareExchange):
     187        (JSC::Wasm::B3IRGenerator::atomicWait):
     188        (JSC::Wasm::B3IRGenerator::atomicNotify):
     189        (JSC::Wasm::B3IRGenerator::truncSaturated):
     190        (JSC::Wasm::B3IRGenerator::addSelect):
     191        (JSC::Wasm::B3IRGenerator::addConstant):
     192        (JSC::Wasm::B3IRGenerator::emitLoopTierUpCheck):
     193        (JSC::Wasm::B3IRGenerator::loadFromScratchBuffer):
     194        (JSC::Wasm::B3IRGenerator::connectControlEntry):
     195        (JSC::Wasm::B3IRGenerator::addLoop):
     196        (JSC::Wasm::B3IRGenerator::addTopLevel):
     197        (JSC::Wasm::B3IRGenerator::addBlock):
     198        (JSC::Wasm::B3IRGenerator::addIf):
     199        (JSC::Wasm::B3IRGenerator::addElse):
     200        (JSC::Wasm::B3IRGenerator::addElseToUnreachable):
     201        (JSC::Wasm::B3IRGenerator::addTry):
     202        (JSC::Wasm::B3IRGenerator::addCatch):
     203        (JSC::Wasm::B3IRGenerator::preparePatchpointForExceptions):
     204        (JSC::Wasm::B3IRGenerator::addCatchToUnreachable):
     205        (JSC::Wasm::B3IRGenerator::addCatchAll):
     206        (JSC::Wasm::B3IRGenerator::addCatchAllToUnreachable):
     207        (JSC::Wasm::B3IRGenerator::emitCatchImpl):
     208        (JSC::Wasm::B3IRGenerator::addDelegate):
     209        (JSC::Wasm::B3IRGenerator::addDelegateToUnreachable):
     210        (JSC::Wasm::B3IRGenerator::addThrow):
     211        (JSC::Wasm::B3IRGenerator::addRethrow):
     212        (JSC::Wasm::B3IRGenerator::addReturn):
     213        (JSC::Wasm::B3IRGenerator::addBranch):
     214        (JSC::Wasm::B3IRGenerator::addSwitch):
     215        (JSC::Wasm::B3IRGenerator::endBlock):
     216        (JSC::Wasm::B3IRGenerator::addEndToUnreachable):
     217        (JSC::Wasm::B3IRGenerator::createCallPatchpoint):
     218        (JSC::Wasm::B3IRGenerator::addCall):
     219        (JSC::Wasm::B3IRGenerator::addCallIndirect):
     220        (JSC::Wasm::B3IRGenerator::addCallRef):
     221        (JSC::Wasm::B3IRGenerator::unify):
     222        (JSC::Wasm::B3IRGenerator::unifyValuesWithBlock):
     223        (JSC::Wasm::parseAndCompile):
     224        (JSC::Wasm::computeExceptionHandlerLocations):
     225        (JSC::Wasm::B3IRGenerator::emitChecksForModOrDiv):
     226        (JSC::Wasm::B3IRGenerator::addOp<OpType::I32DivS>):
     227        (JSC::Wasm::B3IRGenerator::addOp<OpType::I32RemS>):
     228        (JSC::Wasm::B3IRGenerator::addOp<OpType::I32DivU>):
     229        (JSC::Wasm::B3IRGenerator::addOp<OpType::I32RemU>):
     230        (JSC::Wasm::B3IRGenerator::addOp<OpType::I64DivS>):
     231        (JSC::Wasm::B3IRGenerator::addOp<OpType::I64RemS>):
     232        (JSC::Wasm::B3IRGenerator::addOp<OpType::I64DivU>):
     233        (JSC::Wasm::B3IRGenerator::addOp<OpType::I64RemU>):
     234        (JSC::Wasm::B3IRGenerator::addOp<OpType::I32Ctz>):
     235        (JSC::Wasm::B3IRGenerator::addOp<OpType::I64Ctz>):
     236        (JSC::Wasm::B3IRGenerator::addOp<OpType::I32Popcnt>):
     237        (JSC::Wasm::B3IRGenerator::addOp<OpType::I64Popcnt>):
     238        (JSC::Wasm::B3IRGenerator::addOp<F64ConvertUI64>):
     239        (JSC::Wasm::B3IRGenerator::addOp<OpType::F32ConvertUI64>):
     240        (JSC::Wasm::B3IRGenerator::addOp<OpType::F64Nearest>):
     241        (JSC::Wasm::B3IRGenerator::addOp<OpType::F32Nearest>):
     242        (JSC::Wasm::B3IRGenerator::addOp<OpType::F64Trunc>):
     243        (JSC::Wasm::B3IRGenerator::addOp<OpType::F32Trunc>):
     244        (JSC::Wasm::B3IRGenerator::addOp<OpType::I32TruncSF64>):
     245        (JSC::Wasm::B3IRGenerator::addOp<OpType::I32TruncSF32>):
     246        (JSC::Wasm::B3IRGenerator::addOp<OpType::I32TruncUF64>):
     247        (JSC::Wasm::B3IRGenerator::addOp<OpType::I32TruncUF32>):
     248        (JSC::Wasm::B3IRGenerator::addOp<OpType::I64TruncSF64>):
     249        (JSC::Wasm::B3IRGenerator::addOp<OpType::I64TruncUF64>):
     250        (JSC::Wasm::B3IRGenerator::addOp<OpType::I64TruncSF32>):
     251        (JSC::Wasm::B3IRGenerator::addOp<OpType::I64TruncUF32>):
     252        * wasm/WasmB3IRGenerator.h:
     253        * wasm/WasmBBQPlan.cpp:
     254        (JSC::Wasm::BBQPlan::prepareImpl):
     255        (JSC::Wasm::BBQPlan::work):
     256        (JSC::Wasm::BBQPlan::compileFunction):
     257        (JSC::Wasm::BBQPlan::didCompleteCompilation):
     258        (JSC::Wasm::BBQPlan::initializeCallees):
     259        * wasm/WasmBBQPlan.h:
     260        * wasm/WasmCallee.cpp:
     261        (JSC::Wasm::Callee::handlerForIndex):
     262        (JSC::Wasm::LLIntCallee::LLIntCallee):
     263        (JSC::Wasm::LLIntCallee::linkExceptionHandlers):
     264        (JSC::Wasm::OptimizingJITCallee::linkExceptionHandlers):
     265        (JSC::Wasm::OptimizingJITCallee::stackmap const):
     266        * wasm/WasmCallee.h:
     267        (JSC::Wasm::Callee::hasExceptionHandlers const):
     268        (JSC::Wasm::Callee::functionCodeBlock const):
     269        (JSC::Wasm::OptimizingJITCallee::OptimizingJITCallee):
     270        * wasm/WasmCallingConvention.h:
     271        (JSC::Wasm::WasmCallingConvention::callInformationFor const):
     272        * wasm/WasmFormat.h:
     273        (JSC::Wasm::typeToString):
     274        (JSC::Wasm::isValidExternalKind):
     275        (JSC::Wasm::makeString):
     276        * wasm/WasmFunctionCodeBlock.h:
     277        (JSC::Wasm::FunctionCodeBlock::numberOfExceptionHandlers const):
     278        (JSC::Wasm::FunctionCodeBlock::exceptionHandler):
     279        (JSC::Wasm::FunctionCodeBlock::addExceptionHandler):
     280        * wasm/WasmFunctionParser.h:
     281        (JSC::Wasm::isTryOrCatch):
     282        (JSC::Wasm::FunctionParser<Context>::parseExceptionIndex):
     283        (JSC::Wasm::FunctionParser<Context>::parseExpression):
     284        (JSC::Wasm::FunctionParser<Context>::parseUnreachableExpression):
     285        * wasm/WasmHandlerInfo.cpp: Added.
     286        (JSC::Wasm::HandlerInfo::initialize):
     287        (JSC::Wasm::HandlerInfo::handlerForIndex):
     288        * wasm/WasmHandlerInfo.h: Added.
     289        (JSC::Wasm::UnlinkedHandlerInfo::UnlinkedHandlerInfo):
     290        (JSC::Wasm::HandlerInfo::tag const):
     291        (JSC::Wasm::HandlerInfo::delegateTarget const):
     292        * wasm/WasmInstance.cpp:
     293        (JSC::Wasm::Instance::~Instance):
     294        * wasm/WasmInstance.h:
     295        (JSC::Wasm::Instance::addTag):
     296        (JSC::Wasm::Instance::tag const):
     297        * wasm/WasmLLIntGenerator.cpp:
     298        (JSC::Wasm::LLIntGenerator::ControlType::try_):
     299        (JSC::Wasm::LLIntGenerator::ControlType::catch_):
     300        (JSC::Wasm::LLIntGenerator::ControlType::isLoop):
     301        (JSC::Wasm::LLIntGenerator::ControlType::isBlock):
     302        (JSC::Wasm::LLIntGenerator::ControlType::isIf):
     303        (JSC::Wasm::LLIntGenerator::ControlType::isTry):
     304        (JSC::Wasm::LLIntGenerator::ControlType::isAnyCatch):
     305        (JSC::Wasm::LLIntGenerator::ControlType::isCatch):
     306        (JSC::Wasm::LLIntGenerator::unifyValuesWithBlock):
     307        (JSC::Wasm::LLIntGenerator::walkExpressionStack):
     308        (JSC::Wasm::LLIntGenerator::materializeConstantsAndLocals):
     309        (JSC::Wasm::parseAndCompileBytecode):
     310        (JSC::Wasm::LLIntGenerator::LLIntGenerator):
     311        (JSC::Wasm::LLIntGenerator::repatch):
     312        (JSC::Wasm::LLIntGenerator::finalize):
     313        (JSC::Wasm::LLIntGenerator::callInformationForCaller):
     314        (JSC::Wasm::LLIntGenerator::callInformationForCallee):
     315        (JSC::Wasm::LLIntGenerator::addArguments):
     316        (JSC::Wasm::LLIntGenerator::addLoop):
     317        (JSC::Wasm::LLIntGenerator::addTry):
     318        (JSC::Wasm::LLIntGenerator::finalizePreviousBlockForCatch):
     319        (JSC::Wasm::LLIntGenerator::addCatch):
     320        (JSC::Wasm::LLIntGenerator::addCatchToUnreachable):
     321        (JSC::Wasm::LLIntGenerator::addCatchAll):
     322        (JSC::Wasm::LLIntGenerator::addCatchAllToUnreachable):
     323        (JSC::Wasm::LLIntGenerator::addDelegate):
     324        (JSC::Wasm::LLIntGenerator::addDelegateToUnreachable):
     325        (JSC::Wasm::LLIntGenerator::addThrow):
     326        (JSC::Wasm::LLIntGenerator::addRethrow):
     327        (JSC::Wasm::LLIntGenerator::endBlock):
     328        (JSC::Wasm::LLIntGenerator::addEndToUnreachable):
     329        * wasm/WasmLLIntGenerator.h:
     330        * wasm/WasmLimits.h:
     331        * wasm/WasmModuleInformation.cpp:
     332        * wasm/WasmModuleInformation.h:
     333        (JSC::Wasm::ModuleInformation::exceptionIndexSpaceSize const):
     334        (JSC::Wasm::ModuleInformation::isImportedExceptionFromExceptionIndexSpace const):
     335        (JSC::Wasm::ModuleInformation::signatureIndexFromExceptionIndexSpace const):
     336        (JSC::Wasm::ModuleInformation::importExceptionCount const):
     337        (JSC::Wasm::ModuleInformation::isDeclaredException const):
     338        (JSC::Wasm::ModuleInformation::addDeclaredException):
     339        * wasm/WasmOMGForOSREntryPlan.cpp:
     340        (JSC::Wasm::OMGForOSREntryPlan::work):
     341        * wasm/WasmOMGPlan.cpp:
     342        (JSC::Wasm::OMGPlan::work):
     343        * wasm/WasmOSREntryData.h:
     344        (JSC::Wasm::OSREntryData::values):
     345        * wasm/WasmOperations.cpp:
     346        (JSC::Wasm::loadValuesIntoBuffer):
     347        (JSC::Wasm::doOSREntry):
     348        (JSC::Wasm::JSC_DEFINE_JIT_OPERATION):
     349        * wasm/WasmOperations.h:
     350        * wasm/WasmSectionParser.cpp:
     351        (JSC::Wasm::SectionParser::parseImport):
     352        (JSC::Wasm::SectionParser::parseExport):
     353        (JSC::Wasm::SectionParser::parseException):
     354        * wasm/WasmSections.h:
     355        (JSC::Wasm::validateOrder):
     356        * wasm/WasmSignature.cpp:
     357        (JSC::Wasm::SignatureInformation::SignatureInformation):
     358        (JSC::Wasm::SignatureInformation::signatureFor):
     359        * wasm/WasmSlowPaths.cpp:
     360        (JSC::LLInt::WASM_SLOW_PATH_DECL):
     361        * wasm/WasmSlowPaths.h:
     362        * wasm/WasmStreamingParser.cpp:
     363        (JSC::Wasm::StreamingParser::parseCodeSectionSize):
     364        * wasm/WasmTag.cpp: Copied from Source/JavaScriptCore/wasm/js/JSWebAssemblyRuntimeError.h.
     365        * wasm/WasmTag.h: Copied from Source/JavaScriptCore/wasm/WasmLLIntGenerator.h.
     366        (JSC::Wasm::Tag::create):
     367        (JSC::Wasm::Tag::parameterCount const):
     368        (JSC::Wasm::Tag::parameter const):
     369        (JSC::Wasm::Tag::operator== const):
     370        (JSC::Wasm::Tag::operator!= const):
     371        (JSC::Wasm::Tag::signature const):
     372        (JSC::Wasm::Tag::Tag):
     373        * wasm/WasmThunks.cpp:
     374        * wasm/WasmThunks.h:
     375        * wasm/generateWasmB3IRGeneratorInlinesHeader.py:
     376        (CodeGenerator.generateOpcode):
     377        (CodeGenerator.makeResult):
     378        (CodeGenerator.generate):
     379        * wasm/generateWasmOpsHeader.py:
     380        (typeMacroizer):
     381        * wasm/js/JSWebAssembly.cpp:
     382        * wasm/js/JSWebAssemblyException.cpp: Added.
     383        (JSC::JSWebAssemblyException::JSWebAssemblyException):
     384        (JSC::JSWebAssemblyException::finishCreation):
     385        (JSC::JSWebAssemblyException::visitChildrenImpl):
     386        (JSC::JSWebAssemblyException::destroy):
     387        (JSC::JSWebAssemblyException::getArg const):
     388        * wasm/js/JSWebAssemblyException.h: Added.
     389        (JSC::JSWebAssemblyException::subspaceFor):
     390        (JSC::JSWebAssemblyException::createStructure):
     391        (JSC::JSWebAssemblyException::create):
     392        (JSC::JSWebAssemblyException::tag const):
     393        (JSC::JSWebAssemblyException::payload const):
     394        * wasm/js/JSWebAssemblyHelpers.h:
     395        (JSC::toJSValue):
     396        (JSC::fromJSValue):
     397        * wasm/js/JSWebAssemblyInstance.cpp:
     398        (JSC::JSWebAssemblyInstance::tryCreate):
     399        * wasm/js/JSWebAssemblyInstance.h:
     400        * wasm/js/JSWebAssemblyRuntimeError.cpp:
     401        (JSC::createJSWebAssemblyRuntimeError):
     402        * wasm/js/JSWebAssemblyRuntimeError.h:
     403        * wasm/js/JSWebAssemblyTag.cpp: Copied from Source/JavaScriptCore/wasm/js/JSWebAssemblyRuntimeError.cpp.
     404        (JSC::JSWebAssemblyTag::create):
     405        (JSC::JSWebAssemblyTag::createStructure):
     406        (JSC::JSWebAssemblyTag::JSWebAssemblyTag):
     407        * wasm/js/JSWebAssemblyTag.h: Copied from Source/JavaScriptCore/wasm/js/JSWebAssemblyRuntimeError.h.
     408        * wasm/js/WasmToJS.cpp:
     409        (JSC::Wasm::wasmToJS):
     410        * wasm/js/WebAssemblyExceptionConstructor.cpp: Added.
     411        (JSC::JSC_DEFINE_HOST_FUNCTION):
     412        (JSC::WebAssemblyExceptionConstructor::create):
     413        (JSC::WebAssemblyExceptionConstructor::createStructure):
     414        (JSC::WebAssemblyExceptionConstructor::finishCreation):
     415        (JSC::WebAssemblyExceptionConstructor::WebAssemblyExceptionConstructor):
     416        * wasm/js/WebAssemblyExceptionConstructor.h: Copied from Source/JavaScriptCore/wasm/js/JSWebAssemblyRuntimeError.h.
     417        * wasm/js/WebAssemblyExceptionPrototype.cpp: Added.
     418        (JSC::WebAssemblyExceptionPrototype::create):
     419        (JSC::WebAssemblyExceptionPrototype::createStructure):
     420        (JSC::WebAssemblyExceptionPrototype::finishCreation):
     421        (JSC::WebAssemblyExceptionPrototype::WebAssemblyExceptionPrototype):
     422        (JSC::getException):
     423        (JSC::getTag):
     424        (JSC::JSC_DEFINE_HOST_FUNCTION):
     425        * wasm/js/WebAssemblyExceptionPrototype.h: Copied from Source/JavaScriptCore/wasm/js/JSWebAssemblyRuntimeError.h.
     426        * wasm/js/WebAssemblyFunction.cpp:
     427        (JSC::JSC_DEFINE_HOST_FUNCTION):
     428        * wasm/js/WebAssemblyModuleRecord.cpp:
     429        (JSC::WebAssemblyModuleRecord::linkImpl):
     430        * wasm/js/WebAssemblyTagConstructor.cpp: Added.
     431        (JSC::JSC_DEFINE_HOST_FUNCTION):
     432        (JSC::WebAssemblyTagConstructor::createTag):
     433        (JSC::WebAssemblyTagConstructor::create):
     434        (JSC::WebAssemblyTagConstructor::createStructure):
     435        (JSC::WebAssemblyTagConstructor::finishCreation):
     436        (JSC::WebAssemblyTagConstructor::WebAssemblyTagConstructor):
     437        * wasm/js/WebAssemblyTagConstructor.h: Copied from Source/JavaScriptCore/wasm/js/JSWebAssemblyRuntimeError.h.
     438        * wasm/js/WebAssemblyTagPrototype.cpp: Added.
     439        (JSC::WebAssemblyTagPrototype::create):
     440        (JSC::WebAssemblyTagPrototype::createStructure):
     441        (JSC::WebAssemblyTagPrototype::finishCreation):
     442        (JSC::WebAssemblyTagPrototype::WebAssemblyTagPrototype):
     443        (JSC::getTag):
     444        (JSC::JSC_DEFINE_HOST_FUNCTION):
     445        * wasm/js/WebAssemblyTagPrototype.h: Copied from Source/JavaScriptCore/wasm/js/JSWebAssemblyRuntimeError.h.
     446        * wasm/wasm.json:
     447
    14482021-10-08  Jer Noble  <jer.noble@apple.com>
    2449
  • trunk/Source/JavaScriptCore/DerivedSources-input.xcfilelist

    r282125 r283852  
    198198$(PROJECT_DIR)/wasm/js/WebAssemblyCompileErrorConstructor.cpp
    199199$(PROJECT_DIR)/wasm/js/WebAssemblyCompileErrorPrototype.cpp
     200$(PROJECT_DIR)/wasm/js/WebAssemblyExceptionConstructor.cpp
     201$(PROJECT_DIR)/wasm/js/WebAssemblyExceptionPrototype.cpp
    200202$(PROJECT_DIR)/wasm/js/WebAssemblyGlobalConstructor.cpp
    201203$(PROJECT_DIR)/wasm/js/WebAssemblyGlobalPrototype.cpp
     
    212214$(PROJECT_DIR)/wasm/js/WebAssemblyTableConstructor.cpp
    213215$(PROJECT_DIR)/wasm/js/WebAssemblyTablePrototype.cpp
     216$(PROJECT_DIR)/wasm/js/WebAssemblyTagConstructor.cpp
     217$(PROJECT_DIR)/wasm/js/WebAssemblyTagPrototype.cpp
    214218$(PROJECT_DIR)/wasm/wasm.json
    215219$(PROJECT_DIR)/yarr/create_regex_tables
  • trunk/Source/JavaScriptCore/DerivedSources-output.xcfilelist

    r282125 r283852  
    8383$(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/WebAssemblyCompileErrorConstructor.lut.h
    8484$(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/WebAssemblyCompileErrorPrototype.lut.h
     85$(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/WebAssemblyExceptionConstructor.lut.h
     86$(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/WebAssemblyExceptionPrototype.lut.h
    8587$(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/WebAssemblyGlobalConstructor.lut.h
    8688$(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/WebAssemblyGlobalPrototype.lut.h
     
    9799$(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/WebAssemblyTableConstructor.lut.h
    98100$(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/WebAssemblyTablePrototype.lut.h
     101$(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/WebAssemblyTagConstructor.lut.h
     102$(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/WebAssemblyTagPrototype.lut.h
    99103$(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/inspector/InspectorAlternateBackendDispatchers.h
    100104$(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/inspector/InspectorBackendCommands.js
  • trunk/Source/JavaScriptCore/DerivedSources.make

    r282125 r283852  
    204204    WebAssemblyCompileErrorConstructor.lut.h \
    205205    WebAssemblyCompileErrorPrototype.lut.h \
     206    WebAssemblyExceptionConstructor.lut.h \
     207    WebAssemblyExceptionPrototype.lut.h \
    206208    WebAssemblyGlobalConstructor.lut.h \
    207209    WebAssemblyGlobalPrototype.lut.h \
     
    218220    WebAssemblyTableConstructor.lut.h \
    219221    WebAssemblyTablePrototype.lut.h \
     222    WebAssemblyTagConstructor.lut.h \
     223    WebAssemblyTagPrototype.lut.h \
    220224#
    221225
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r283851 r283852  
    664664                0FEC85421BDACDAC0080FF74 /* B3Validate.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEC84F81BDACDAC0080FF74 /* B3Validate.h */; };
    665665                0FEC85441BDACDAC0080FF74 /* B3Value.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEC84FA1BDACDAC0080FF74 /* B3Value.h */; };
    666                 0FEC85471BDACDAC0080FF74 /* B3ValueRep.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEC84FD1BDACDAC0080FF74 /* B3ValueRep.h */; };
     666                0FEC85471BDACDAC0080FF74 /* B3ValueRep.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEC84FD1BDACDAC0080FF74 /* B3ValueRep.h */; settings = {ATTRIBUTES = (Private, ); }; };
    667667                0FEC856E1BDACDC70080FF74 /* AirAllocateStackByGraphColoring.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEC85491BDACDC70080FF74 /* AirAllocateStackByGraphColoring.h */; };
    668668                0FEC85701BDACDC70080FF74 /* AirArg.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEC854B1BDACDC70080FF74 /* AirArg.h */; };
     
    797797                147B83AC0E6DB8C9004775A4 /* BatchedTransitionOptimizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 147B83AA0E6DB8C9004775A4 /* BatchedTransitionOptimizer.h */; settings = {ATTRIBUTES = (Private, ); }; };
    798798                147B84630E6DE6B1004775A4 /* PutPropertySlot.h in Headers */ = {isa = PBXBuildFile; fileRef = 147B84620E6DE6B1004775A4 /* PutPropertySlot.h */; settings = {ATTRIBUTES = (Private, ); }; };
     799                148521D826EAEBFE00CC1D1A /* WasmHandlerInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 148521D726EAEBFE00CC1D1A /* WasmHandlerInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
    799800                1486A8C024ABED480073922D /* JSLockRefPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1486A8BF24ABED3C0073922D /* JSLockRefPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
    800801                14874AE615EBDE4A002E3587 /* JSScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 14874AE215EBDE4A002E3587 /* JSScope.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    828829                14CA958D16AB50FA00938A06 /* ObjectAllocationProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 14CA958C16AB50FA00938A06 /* ObjectAllocationProfile.h */; settings = {ATTRIBUTES = (Private, ); }; };
    829830                14D01A7721FB351F00BC54E9 /* JSScriptSourceProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 14D01A7621FB350300BC54E9 /* JSScriptSourceProvider.h */; };
     831                14D01BE626DEEF3800CAE0D0 /* WebAssemblyTagConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = 14D01BDA26DEEF3700CAE0D0 /* WebAssemblyTagConstructor.h */; };
     832                14D01BE726DEEF3800CAE0D0 /* WebAssemblyTagPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = 14D01BDB26DEEF3700CAE0D0 /* WebAssemblyTagPrototype.h */; };
     833                14D01BE926DEEF3800CAE0D0 /* WebAssemblyExceptionPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = 14D01BDD26DEEF3700CAE0D0 /* WebAssemblyExceptionPrototype.h */; };
     834                14D01BEC26DEEF3800CAE0D0 /* JSWebAssemblyTag.h in Headers */ = {isa = PBXBuildFile; fileRef = 14D01BE026DEEF3700CAE0D0 /* JSWebAssemblyTag.h */; };
     835                14D01BED26DEEF3800CAE0D0 /* JSWebAssemblyException.h in Headers */ = {isa = PBXBuildFile; fileRef = 14D01BE126DEEF3800CAE0D0 /* JSWebAssemblyException.h */; };
     836                14D01BEF26DEEF3800CAE0D0 /* WebAssemblyExceptionConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = 14D01BE326DEEF3800CAE0D0 /* WebAssemblyExceptionConstructor.h */; };
     837                14D01BF526DEEF5300CAE0D0 /* WasmTag.h in Headers */ = {isa = PBXBuildFile; fileRef = 14D01BF326DEEF5200CAE0D0 /* WasmTag.h */; };
    830838                14D2F3DB139F4BE200491031 /* MarkedSpace.h in Headers */ = {isa = PBXBuildFile; fileRef = 14D2F3D9139F4BE200491031 /* MarkedSpace.h */; settings = {ATTRIBUTES = (Private, ); }; };
    831839                14DF04DA16B3996D0016A513 /* StaticPropertyAnalysis.h in Headers */ = {isa = PBXBuildFile; fileRef = 14DF04D916B3996D0016A513 /* StaticPropertyAnalysis.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    12651273                86281EF425B61AF000367004 /* CheckPrivateBrandStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = 86281EF325B61AF000367004 /* CheckPrivateBrandStatus.h */; };
    12661274                863B23E00FC6118900703AA4 /* MacroAssemblerCodeRef.h in Headers */ = {isa = PBXBuildFile; fileRef = 863B23DF0FC60E6200703AA4 /* MacroAssemblerCodeRef.h */; settings = {ATTRIBUTES = (Private, ); }; };
    1267                 863FBC5A25B093B900F6C930 /* WasmValueLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 863FBC5825B093B900F6C930 /* WasmValueLocation.h */; };
     1275                863FBC5A25B093B900F6C930 /* WasmValueLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 863FBC5825B093B900F6C930 /* WasmValueLocation.h */; settings = {ATTRIBUTES = (Private, ); }; };
    12681276                865A30F1135007E100CDB49E /* JSCJSValueInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 865A30F0135007E100CDB49E /* JSCJSValueInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
    12691277                865DA0C525B8957400875772 /* SetPrivateBrandVariant.h in Headers */ = {isa = PBXBuildFile; fileRef = 865DA0C425B8957400875772 /* SetPrivateBrandVariant.h */; };
     
    19401948                E3BFD0BC1DAF808E0065DEA2 /* AccessCaseSnippetParams.h in Headers */ = {isa = PBXBuildFile; fileRef = E3BFD0BA1DAF807C0065DEA2 /* AccessCaseSnippetParams.h */; };
    19411949                E3C295DD1ED2CBDA00D3016F /* ObjectPropertyChangeAdaptiveWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = E3C295DC1ED2CBAA00D3016F /* ObjectPropertyChangeAdaptiveWatchpoint.h */; };
    1942                 E3C694B323026877006FBE42 /* WasmOSREntryData.h in Headers */ = {isa = PBXBuildFile; fileRef = E3C694B123026873006FBE42 /* WasmOSREntryData.h */; };
     1950                E3C694B323026877006FBE42 /* WasmOSREntryData.h in Headers */ = {isa = PBXBuildFile; fileRef = E3C694B123026873006FBE42 /* WasmOSREntryData.h */; settings = {ATTRIBUTES = (Private, ); }; };
    19431951                E3C73A9125BFA73B00EFE303 /* WasmStreamingPlan.h in Headers */ = {isa = PBXBuildFile; fileRef = E3C73A9025BFA73400EFE303 /* WasmStreamingPlan.h */; };
    19441952                E3C79CAB1DB9A4DC00D1ECA4 /* DOMJITEffect.h in Headers */ = {isa = PBXBuildFile; fileRef = E3C79CAA1DB9A4D600D1ECA4 /* DOMJITEffect.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    34643472                1482B7E10A43076000517CFC /* JSObjectRef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSObjectRef.h; sourceTree = "<group>"; };
    34653473                1482B7E20A43076000517CFC /* JSObjectRef.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSObjectRef.cpp; sourceTree = "<group>"; };
     3474                148521D526EAEBDF00CC1D1A /* WasmHandlerInfo.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WasmHandlerInfo.cpp; sourceTree = "<group>"; };
     3475                148521D726EAEBFE00CC1D1A /* WasmHandlerInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmHandlerInfo.h; sourceTree = "<group>"; };
    34663476                1486A8BE24ABED3B0073922D /* JSLockRef.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = JSLockRef.cpp; sourceTree = "<group>"; };
    34673477                1486A8BF24ABED3C0073922D /* JSLockRefPrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JSLockRefPrivate.h; sourceTree = "<group>"; };
     
    35473557                14D01A7521FB350300BC54E9 /* JSScriptSourceProvider.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = JSScriptSourceProvider.mm; sourceTree = "<group>"; };
    35483558                14D01A7621FB350300BC54E9 /* JSScriptSourceProvider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JSScriptSourceProvider.h; sourceTree = "<group>"; };
     3559                14D01BDA26DEEF3700CAE0D0 /* WebAssemblyTagConstructor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebAssemblyTagConstructor.h; path = js/WebAssemblyTagConstructor.h; sourceTree = "<group>"; };
     3560                14D01BDB26DEEF3700CAE0D0 /* WebAssemblyTagPrototype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebAssemblyTagPrototype.h; path = js/WebAssemblyTagPrototype.h; sourceTree = "<group>"; };
     3561                14D01BDC26DEEF3700CAE0D0 /* JSWebAssemblyException.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JSWebAssemblyException.cpp; path = js/JSWebAssemblyException.cpp; sourceTree = "<group>"; };
     3562                14D01BDD26DEEF3700CAE0D0 /* WebAssemblyExceptionPrototype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebAssemblyExceptionPrototype.h; path = js/WebAssemblyExceptionPrototype.h; sourceTree = "<group>"; };
     3563                14D01BDE26DEEF3700CAE0D0 /* WebAssemblyTagConstructor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebAssemblyTagConstructor.cpp; path = js/WebAssemblyTagConstructor.cpp; sourceTree = "<group>"; };
     3564                14D01BDF26DEEF3700CAE0D0 /* WebAssemblyTagPrototype.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebAssemblyTagPrototype.cpp; path = js/WebAssemblyTagPrototype.cpp; sourceTree = "<group>"; };
     3565                14D01BE026DEEF3700CAE0D0 /* JSWebAssemblyTag.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSWebAssemblyTag.h; path = js/JSWebAssemblyTag.h; sourceTree = "<group>"; };
     3566                14D01BE126DEEF3800CAE0D0 /* JSWebAssemblyException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSWebAssemblyException.h; path = js/JSWebAssemblyException.h; sourceTree = "<group>"; };
     3567                14D01BE226DEEF3800CAE0D0 /* WebAssemblyExceptionPrototype.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebAssemblyExceptionPrototype.cpp; path = js/WebAssemblyExceptionPrototype.cpp; sourceTree = "<group>"; };
     3568                14D01BE326DEEF3800CAE0D0 /* WebAssemblyExceptionConstructor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebAssemblyExceptionConstructor.h; path = js/WebAssemblyExceptionConstructor.h; sourceTree = "<group>"; };
     3569                14D01BE426DEEF3800CAE0D0 /* JSWebAssemblyTag.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JSWebAssemblyTag.cpp; path = js/JSWebAssemblyTag.cpp; sourceTree = "<group>"; };
     3570                14D01BE526DEEF3800CAE0D0 /* WebAssemblyExceptionConstructor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebAssemblyExceptionConstructor.cpp; path = js/WebAssemblyExceptionConstructor.cpp; sourceTree = "<group>"; };
     3571                14D01BF226DEEF5200CAE0D0 /* WasmTag.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmTag.cpp; sourceTree = "<group>"; };
     3572                14D01BF326DEEF5200CAE0D0 /* WasmTag.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmTag.h; sourceTree = "<group>"; };
    35493573                14D2F3D9139F4BE200491031 /* MarkedSpace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MarkedSpace.h; sourceTree = "<group>"; };
    35503574                14D792640DAA03FB001A9F05 /* CLoopStack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CLoopStack.h; sourceTree = "<group>"; };
     
    71627186                                E38350082390D9370036316D /* WasmGlobal.cpp */,
    71637187                                E38350092390D9370036316D /* WasmGlobal.h */,
     7188                                148521D526EAEBDF00CC1D1A /* WasmHandlerInfo.cpp */,
     7189                                148521D726EAEBFE00CC1D1A /* WasmHandlerInfo.h */,
    71647190                                AD8FF3961EB5BD850087FF82 /* WasmIndexOrName.cpp */,
    71657191                                AD8FF3951EB5BD850087FF82 /* WasmIndexOrName.h */,
     
    72197245                                AD5C36E31F69EC8B000BCAAF /* WasmTable.cpp */,
    72207246                                AD5C36E41F69EC8B000BCAAF /* WasmTable.h */,
     7247                                14D01BF226DEEF5200CAE0D0 /* WasmTag.cpp */,
     7248                                14D01BF326DEEF5200CAE0D0 /* WasmTag.h */,
    72217249                                5250D2CF1E8DA05A0029A932 /* WasmThunks.cpp */,
    72227250                                5250D2D01E8DA05A0029A932 /* WasmThunks.h */,
     
    91049132                                AD2FCBA61DB58DA400B3E736 /* JSWebAssemblyCompileError.cpp */,
    91059133                                AD2FCBA71DB58DA400B3E736 /* JSWebAssemblyCompileError.h */,
     9134                                14D01BDC26DEEF3700CAE0D0 /* JSWebAssemblyException.cpp */,
     9135                                14D01BE126DEEF3800CAE0D0 /* JSWebAssemblyException.h */,
    91069136                                E3BF3C4C2390D1E3008BC752 /* JSWebAssemblyGlobal.cpp */,
    91079137                                E3BF3C4B2390D1E2008BC752 /* JSWebAssemblyGlobal.h */,
     
    91199149                                AD2FCBAE1DB58DA400B3E736 /* JSWebAssemblyTable.cpp */,
    91209150                                AD2FCBAF1DB58DA400B3E736 /* JSWebAssemblyTable.h */,
     9151                                14D01BE426DEEF3800CAE0D0 /* JSWebAssemblyTag.cpp */,
     9152                                14D01BE026DEEF3700CAE0D0 /* JSWebAssemblyTag.h */,
    91219153                                ADD09AEF1F5F623F001313C2 /* WasmToJS.cpp */,
    91229154                                ADD09AEE1F5F623F001313C2 /* WasmToJS.h */,
     
    91259157                                AD2FCBB21DB58DA400B3E736 /* WebAssemblyCompileErrorPrototype.cpp */,
    91269158                                AD2FCBB31DB58DA400B3E736 /* WebAssemblyCompileErrorPrototype.h */,
     9159                                14D01BE526DEEF3800CAE0D0 /* WebAssemblyExceptionConstructor.cpp */,
     9160                                14D01BE326DEEF3800CAE0D0 /* WebAssemblyExceptionConstructor.h */,
     9161                                14D01BE226DEEF3800CAE0D0 /* WebAssemblyExceptionPrototype.cpp */,
     9162                                14D01BDD26DEEF3700CAE0D0 /* WebAssemblyExceptionPrototype.h */,
    91279163                                AD4937C91DDD27340077C807 /* WebAssemblyFunction.cpp */,
    91289164                                AD4937CA1DDD27340077C807 /* WebAssemblyFunction.h */,
     
    91599195                                AD2FCBC21DB58DA400B3E736 /* WebAssemblyTablePrototype.cpp */,
    91609196                                AD2FCBC31DB58DA400B3E736 /* WebAssemblyTablePrototype.h */,
     9197                                14D01BDE26DEEF3700CAE0D0 /* WebAssemblyTagConstructor.cpp */,
     9198                                14D01BDA26DEEF3700CAE0D0 /* WebAssemblyTagConstructor.h */,
     9199                                14D01BDF26DEEF3700CAE0D0 /* WebAssemblyTagPrototype.cpp */,
     9200                                14D01BDB26DEEF3700CAE0D0 /* WebAssemblyTagPrototype.h */,
    91619201                                52F6C35B1E71EB080081F4CC /* WebAssemblyWrapperFunction.cpp */,
    91629202                                52F6C35C1E71EB080081F4CC /* WebAssemblyWrapperFunction.h */,
     
    1041010450                                AD9E852F1E8A0C7C008DE39E /* JSWebAssemblyCodeBlock.h in Headers */,
    1041110451                                AD2FCBE31DB58DAD00B3E736 /* JSWebAssemblyCompileError.h in Headers */,
     10452                                14D01BED26DEEF3800CAE0D0 /* JSWebAssemblyException.h in Headers */,
    1041210453                                E3BF3C4D2390D1E8008BC752 /* JSWebAssemblyGlobal.h in Headers */,
    1041310454                                796FB43A1DFF8C3F0039C95D /* JSWebAssemblyHelpers.h in Headers */,
     
    1041810459                                AD2FCBE91DB58DAD00B3E736 /* JSWebAssemblyRuntimeError.h in Headers */,
    1041910460                                AD2FCBEB1DB58DAD00B3E736 /* JSWebAssemblyTable.h in Headers */,
     10461                                14D01BEC26DEEF3800CAE0D0 /* JSWebAssemblyTag.h in Headers */,
    1042010462                                1442566215EDE98D0066A49B /* JSWithScope.h in Headers */,
    1042110463                                86E3C619167BABEE006D760A /* JSWrapperMap.h in Headers */,
     
    1084610888                                53F40E8B1D5901BB0099A1B6 /* WasmFunctionParser.h in Headers */,
    1084710889                                E383500A2390D93B0036316D /* WasmGlobal.h in Headers */,
     10890                                148521D826EAEBFE00CC1D1A /* WasmHandlerInfo.h in Headers */,
    1084810891                                AD8FF3981EB5BDB20087FF82 /* WasmIndexOrName.h in Headers */,
    1084910892                                AD5C36E21F699EC0000BCAAF /* WasmInstance.h in Headers */,
     
    1087610919                                E3C73A9125BFA73B00EFE303 /* WasmStreamingPlan.h in Headers */,
    1087710920                                AD5C36E61F69EC91000BCAAF /* WasmTable.h in Headers */,
     10921                                14D01BF526DEEF5300CAE0D0 /* WasmTag.h in Headers */,
    1087810922                                5250D2D21E8DA05A0029A932 /* WasmThunks.h in Headers */,
    1087910923                                53E9E0AF1EAEC45700FEE251 /* WasmTierUpCount.h in Headers */,
     
    1090710951                                AD2FCBEF1DB58DAD00B3E736 /* WebAssemblyCompileErrorPrototype.h in Headers */,
    1090810952                                AD2FCC171DB59CB200B3E736 /* WebAssemblyCompileErrorPrototype.lut.h in Headers */,
     10953                                14D01BEF26DEEF3800CAE0D0 /* WebAssemblyExceptionConstructor.h in Headers */,
     10954                                14D01BE926DEEF3800CAE0D0 /* WebAssemblyExceptionPrototype.h in Headers */,
    1090910955                                AD4937D41DDD27DE0077C807 /* WebAssemblyFunction.h in Headers */,
    1091010956                                521322461ECBCE8200F65615 /* WebAssemblyFunctionBase.h in Headers */,
     
    1093410980                                AD2FCBFF1DB58DAD00B3E736 /* WebAssemblyTablePrototype.h in Headers */,
    1093510981                                AD2FCC211DB59CB200B3E736 /* WebAssemblyTablePrototype.lut.h in Headers */,
     10982                                14D01BE626DEEF3800CAE0D0 /* WebAssemblyTagConstructor.h in Headers */,
     10983                                14D01BE726DEEF3800CAE0D0 /* WebAssemblyTagPrototype.h in Headers */,
    1093610984                                52F6C35E1E71EB080081F4CC /* WebAssemblyWrapperFunction.h in Headers */,
    1093710985                                BC18C47A0E16F5CD00B34460 /* WebKitAvailability.h in Headers */,
  • trunk/Source/JavaScriptCore/Sources.txt

    r283139 r283852  
    10801080wasm/WasmFunctionCodeBlock.cpp
    10811081wasm/WasmGlobal.cpp
     1082wasm/WasmHandlerInfo.cpp
    10821083wasm/WasmIndexOrName.cpp
    10831084wasm/WasmInstance.cpp
     
    11061107wasm/WasmStreamingPlan.cpp
    11071108wasm/WasmTable.cpp
     1109wasm/WasmTag.cpp
    11081110wasm/WasmThunks.cpp
    11091111wasm/WasmTierUpCount.cpp
     
    11171119wasm/js/JSWebAssemblyCodeBlock.cpp
    11181120wasm/js/JSWebAssemblyCompileError.cpp
     1121wasm/js/JSWebAssemblyException.cpp
    11191122wasm/js/JSWebAssemblyGlobal.cpp
    11201123wasm/js/JSWebAssemblyInstance.cpp
     
    11241127wasm/js/JSWebAssemblyRuntimeError.cpp
    11251128wasm/js/JSWebAssemblyTable.cpp
     1129wasm/js/JSWebAssemblyTag.cpp
    11261130wasm/js/WasmToJS.cpp
    11271131wasm/js/WasmToJS.h
    11281132wasm/js/WebAssemblyCompileErrorConstructor.cpp
    11291133wasm/js/WebAssemblyCompileErrorPrototype.cpp
     1134wasm/js/WebAssemblyExceptionConstructor.cpp
     1135wasm/js/WebAssemblyExceptionPrototype.cpp
    11301136wasm/js/WebAssemblyFunction.cpp
    11311137wasm/js/WebAssemblyFunctionBase.cpp
     
    11451151wasm/js/WebAssemblyTableConstructor.cpp
    11461152wasm/js/WebAssemblyTablePrototype.cpp
     1153wasm/js/WebAssemblyTagConstructor.cpp
     1154wasm/js/WebAssemblyTagPrototype.cpp
    11471155wasm/js/WebAssemblyWrapperFunction.cpp
    11481156
  • trunk/Source/JavaScriptCore/bytecode/BytecodeList.rb

    r283168 r283852  
    18401840    }
    18411841
     1842op :throw,
     1843    args: {
     1844        exceptionIndex: unsigned,
     1845        firstValue: VirtualRegister,
     1846    }
     1847
     1848op :rethrow,
     1849    args: {
     1850        exception: VirtualRegister,
     1851    }
     1852
     1853op_group :Catch,
     1854    [
     1855        :catch,
     1856        :catch_no_tls,
     1857    ],
     1858    args: {
     1859        exceptionIndex: unsigned,
     1860        exception: VirtualRegister,
     1861        argumentCount: unsigned,
     1862        startOffset: unsigned,
     1863    }
     1864
     1865op_group :CatchAll,
     1866    [
     1867        :catch_all,
     1868        :catch_all_no_tls,
     1869    ],
     1870    args: {
     1871        exception: VirtualRegister,
     1872    }
     1873
    18421874end_section :Wasm
  • trunk/Source/JavaScriptCore/bytecode/HandlerInfo.h

    r255687 r283852  
    3131namespace JSC {
    3232
    33 enum class HandlerType {
     33enum class HandlerType : uint8_t {
    3434    Catch = 0,
    3535    Finally = 1,
  • trunk/Source/JavaScriptCore/bytecode/Instruction.h

    r281694 r283852  
    9090    const char* name() const
    9191    {
    92         return Traits::opcodeNames[opcodeID()];
     92        return Traits::opcodeNames[opcodeID<Traits>()];
    9393    }
    9494
  • trunk/Source/JavaScriptCore/interpreter/CallFrame.cpp

    r283410 r283852  
    131131BytecodeIndex CallFrame::bytecodeIndex() const
    132132{
    133     ASSERT(!callee().isWasm());
     133    if (callee().isWasm())
     134        return callSiteIndex().bytecodeIndex();
    134135    if (!codeBlock())
    135136        return BytecodeIndex(0);
  • trunk/Source/JavaScriptCore/interpreter/CallFrame.h

    r280858 r283852  
    4545    public:
    4646        CallSiteIndex() = default;
     47
     48        CallSiteIndex(WTF::HashTableDeletedValueType)
     49            : m_bits(deletedValue().bits())
     50        {
     51        }
    4752       
    4853        explicit CallSiteIndex(BytecodeIndex bytecodeIndex)
     
    5863        bool operator==(const CallSiteIndex& other) const { return m_bits == other.m_bits; }
    5964
     65        unsigned hash() const { return intHash(m_bits); }
     66        static CallSiteIndex deletedValue() { return fromBits(s_invalidIndex - 1); }
     67        bool isHashTableDeletedValue() const { return *this == deletedValue(); }
     68
    6069        uint32_t bits() const { return m_bits; }
    6170        static CallSiteIndex fromBits(uint32_t bits) { return CallSiteIndex(bits); }
     
    6473
    6574    private:
    66         uint32_t m_bits { BytecodeIndex().offset() };
     75        static constexpr uint32_t s_invalidIndex = std::numeric_limits<uint32_t>::max();
     76
     77        uint32_t m_bits { s_invalidIndex };
     78    };
     79
     80    struct CallSiteIndexHash {
     81        static unsigned hash(const CallSiteIndex& key) { return key.hash(); }
     82        static bool equal(const CallSiteIndex& a, const CallSiteIndex& b) { return a == b; }
     83        static constexpr bool safeToCompareToEmptyOrDeleted = true;
    6784    };
    6885
     
    333350
    334351} // namespace JSC
     352
     353namespace WTF {
     354
     355template<typename T> struct DefaultHash;
     356template<> struct DefaultHash<JSC::CallSiteIndex> : JSC::CallSiteIndexHash { };
     357
     358template<typename T> struct HashTraits;
     359template<> struct HashTraits<JSC::CallSiteIndex> : SimpleClassHashTraits<JSC::CallSiteIndex> {
     360    static constexpr bool emptyValueIsZero = false;
     361};
     362
     363} // namespace WTF
  • trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp

    r283566 r283852  
    5353#include "JSModuleRecord.h"
    5454#include "JSString.h"
     55#include "JSWebAssemblyException.h"
    5556#include "LLIntThunks.h"
    5657#include "LiteralParser.h"
     
    513514}
    514515
     516CatchInfo::CatchInfo(const HandlerInfo* handler, CodeBlock* codeBlock)
     517{
     518    m_valid = !!handler;
     519    if (m_valid) {
     520        m_type = handler->type();
     521#if ENABLE(JIT)
     522        m_nativeCode = handler->nativeCode;
     523#endif
     524
     525        // handler->target is meaningless for getting a code offset when catching
     526        // the exception in a DFG/FTL frame. This bytecode target offset could be
     527        // something that's in an inlined frame, which means an array access
     528        // with this bytecode offset in the machine frame is utterly meaningless
     529        // and can cause an overflow. OSR exit properly exits to handler->target
     530        // in the proper frame.
     531        if (!JITCode::isOptimizingJIT(codeBlock->jitType()))
     532            m_catchPCForInterpreter = codeBlock->instructions().at(handler->target).ptr();
     533        else
     534            m_catchPCForInterpreter = nullptr;
     535    }
     536}
     537
     538#if ENABLE(WEBASSEMBLY)
     539CatchInfo::CatchInfo(const Wasm::HandlerInfo* handler, const Wasm::Callee* callee)
     540{
     541    m_valid = !!handler;
     542    if (m_valid) {
     543        m_type = HandlerType::Catch;
     544        m_nativeCode = handler->m_nativeCode;
     545        if (const Wasm::FunctionCodeBlock* codeBlock = callee->functionCodeBlock())
     546            m_catchPCForInterpreter = codeBlock->instructions().at(handler->m_target).ptr();
     547        else
     548            m_catchPCForInterpreter = nullptr;
     549    }
     550}
     551#endif
     552
    515553class UnwindFunctor {
    516554public:
    517     UnwindFunctor(VM& vm, CallFrame*& callFrame, bool isTermination, CodeBlock*& codeBlock, HandlerInfo*& handler)
     555    UnwindFunctor(VM& vm, CallFrame*& callFrame, bool isTermination, JSValue thrownValue, CodeBlock*& codeBlock, CatchInfo& handler)
    518556        : m_vm(vm)
    519557        , m_callFrame(callFrame)
     
    522560        , m_handler(handler)
    523561    {
     562#if ENABLE(WEBASSEMBLY)
     563        if (!m_isTermination) {
     564            if (JSWebAssemblyException* wasmException = jsDynamicCast<JSWebAssemblyException*>(m_vm, thrownValue)) {
     565                m_catchableFromWasm = true;
     566                m_wasmTag = &wasmException->tag();
     567            } else if (ErrorInstance* error = jsDynamicCast<ErrorInstance*>(m_vm, thrownValue))
     568                m_catchableFromWasm = error->isCatchableFromWasm();
     569        }
     570#else
     571        UNUSED_PARAM(thrownValue);
     572#endif
    524573    }
    525574
     
    530579        m_codeBlock = visitor->codeBlock();
    531580
    532         m_handler = nullptr;
     581        m_handler.m_valid = false;
    533582        if (m_codeBlock) {
    534583            if (!m_isTermination) {
    535                 m_handler = findExceptionHandler(visitor, m_codeBlock, RequiredHandler::AnyHandler);
    536                 if (m_handler)
     584                m_handler = { findExceptionHandler(visitor, m_codeBlock, RequiredHandler::AnyHandler), m_codeBlock };
     585                if (m_handler.m_valid)
    537586                    return StackVisitor::Done;
    538587            }
     
    540589
    541590#if ENABLE(WEBASSEMBLY)
    542         if (visitor->callee().isCell()) {
    543             if (auto* jsToWasmICCallee = jsDynamicCast<JSToWasmICCallee*>(m_vm, visitor->callee().asCell()))
     591        CalleeBits callee = visitor->callee();
     592        if (callee.isCell()) {
     593            if (auto* jsToWasmICCallee = jsDynamicCast<JSToWasmICCallee*>(m_vm, callee.asCell()))
    544594                m_vm.wasmContext.store(jsToWasmICCallee->function()->previousInstance(m_callFrame), m_vm.softStackLimit());
     595
     596        }
     597
     598        if (m_catchableFromWasm && callee.isWasm()) {
     599            Wasm::Callee* wasmCallee = callee.asWasmCallee();
     600            if (wasmCallee->hasExceptionHandlers()) {
     601                JSWebAssemblyInstance* jsInstance = jsCast<JSWebAssemblyInstance*>(m_callFrame->thisValue());
     602                unsigned exceptionHandlerIndex = m_callFrame->callSiteIndex().bits();
     603                m_handler = { wasmCallee->handlerForIndex(jsInstance->instance(), exceptionHandlerIndex, m_wasmTag), wasmCallee };
     604                if (m_handler.m_valid)
     605                    return StackVisitor::Done;
     606            }
    545607        }
    546608#endif
     
    589651    bool m_isTermination;
    590652    CodeBlock*& m_codeBlock;
    591     HandlerInfo*& m_handler;
     653    CatchInfo& m_handler;
     654#if ENABLE(WEBASSEMBLY)
     655    const Wasm::Tag* m_wasmTag { nullptr };
     656    bool m_catchableFromWasm { false };
     657#endif
    592658};
    593659
    594 NEVER_INLINE HandlerInfo* Interpreter::unwind(VM& vm, CallFrame*& callFrame, Exception* exception)
     660NEVER_INLINE CatchInfo Interpreter::unwind(VM& vm, CallFrame*& callFrame, Exception* exception)
    595661{
    596662    auto scope = DECLARE_CATCH_SCOPE(vm);
     
    610676
    611677    // Calculate an exception handler vPC, unwinding call frames as necessary.
    612     HandlerInfo* handler = nullptr;
    613     UnwindFunctor functor(vm, callFrame, vm.isTerminationException(exception), codeBlock, handler);
     678    CatchInfo catchInfo;
     679    UnwindFunctor functor(vm, callFrame, vm.isTerminationException(exception), exceptionValue, codeBlock, catchInfo);
    614680    StackVisitor::visit<StackVisitor::TerminateIfTopEntryFrameIsEmpty>(callFrame, vm, functor);
    615681    if (vm.hasCheckpointOSRSideState())
    616682        vm.popAllCheckpointOSRSideStateUntil(callFrame);
    617683
    618     if (!handler)
    619         return nullptr;
    620 
    621     return handler;
     684    return catchInfo;
    622685}
    623686
  • trunk/Source/JavaScriptCore/interpreter/Interpreter.h

    r273225 r283852  
    4444namespace JSC {
    4545
     46#if ENABLE(WEBASSEMBLY)
     47namespace Wasm {
     48class Callee;
     49struct HandlerInfo;
     50}
     51#endif
     52
    4653    class CodeBlock;
    4754    class EvalExecutable;
     
    5966    class SourceCode;
    6067    class StackFrame;
     68    enum class HandlerType : uint8_t;
    6169    struct CallFrameClosure;
    6270    struct HandlerInfo;
     
    8290    };
    8391
     92    struct CatchInfo {
     93        CatchInfo()
     94            : m_valid(false)
     95        { }
     96
     97        CatchInfo(const HandlerInfo*, CodeBlock*);
     98#if ENABLE(WEBASSEMBLY)
     99        CatchInfo(const Wasm::HandlerInfo*, const Wasm::Callee*);
     100#endif
     101
     102        bool m_valid;
     103        HandlerType m_type;
     104#if ENABLE(JIT)
     105        MacroAssemblerCodePtr<ExceptionHandlerPtrTag> m_nativeCode;
     106#endif
     107        const Instruction* m_catchPCForInterpreter;
     108    };
     109
    84110    class Interpreter {
    85111        WTF_MAKE_FAST_ALLOCATED;
     
    113139        void getArgumentsData(CallFrame*, JSFunction*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc);
    114140
    115         NEVER_INLINE HandlerInfo* unwind(VM&, CallFrame*&, Exception*);
     141        NEVER_INLINE CatchInfo unwind(VM&, CallFrame*&, Exception*);
    116142        void notifyDebuggerOfExceptionToBeThrown(VM&, JSGlobalObject*, CallFrame*, Exception*);
    117143        NEVER_INLINE void debug(CallFrame*, DebugHookType);
  • trunk/Source/JavaScriptCore/interpreter/StackVisitor.cpp

    r278253 r283852  
    167167#endif
    168168
     169    m_frame.m_codeBlock = callFrame->codeBlock();
     170    m_frame.m_bytecodeIndex = !m_frame.codeBlock() ? BytecodeIndex(0)
     171        : codeOrigin ? codeOrigin->bytecodeIndex()
     172        : callFrame->bytecodeIndex();
     173
    169174#if ENABLE(WEBASSEMBLY)
    170175    if (callFrame->isAnyWasmCallee()) {
    171176        m_frame.m_isWasmFrame = true;
    172177        m_frame.m_codeBlock = nullptr;
    173         m_frame.m_bytecodeIndex = BytecodeIndex();
    174178
    175179        if (m_frame.m_callee.isWasm())
    176180            m_frame.m_wasmFunctionIndexOrName = m_frame.m_callee.asWasmCallee()->indexOrName();
    177 
    178         return;
    179     }
    180 #endif
    181     m_frame.m_codeBlock = callFrame->codeBlock();
    182     m_frame.m_bytecodeIndex = !m_frame.codeBlock() ? BytecodeIndex(0)
    183         : codeOrigin ? codeOrigin->bytecodeIndex()
    184         : callFrame->bytecodeIndex();
    185 
     181    }
     182#endif
    186183}
    187184
  • trunk/Source/JavaScriptCore/jit/AssemblyHelpers.cpp

    r283512 r283852  
    705705
    706706    loadPtr(&topEntryFrame, scratch);
    707     addPtr(TrustedImm32(EntryFrame::calleeSaveRegistersBufferOffset()), scratch);
    708 
    709     LoadRegSpooler spooler(*this, scratch);
    710 
    711     // Restore all callee saves except for the scratch.
    712     unsigned i = 0;
    713     for (; i < registerCount; i++) {
    714         RegisterAtOffset entry = allCalleeSaves->at(i);
    715         if (skipList.contains(entry.reg()))
    716             continue;
    717         if (!entry.reg().isGPR())
    718             break;
    719         spooler.loadGPR(entry);
    720     }
    721     spooler.finalizeGPR();
    722     for (; i < registerCount; i++) {
    723         RegisterAtOffset entry = allCalleeSaves->at(i);
    724         if (skipList.contains(entry.reg()))
    725             continue;
    726         ASSERT(!entry.reg().isGPR());
    727         spooler.loadFPR(entry);
    728     }
    729     spooler.finalizeFPR();
     707    restoreCalleeSavesFromVMEntryFrameCalleeSavesBufferImpl(scratch, skipList);
    730708
    731709    // Restore the callee save value of the scratch.
     
    746724#else
    747725    UNUSED_PARAM(topEntryFrame);
     726#endif // NUMBER_OF_CALLEE_SAVES_REGISTERS > 0
     727}
     728
     729void AssemblyHelpers::restoreCalleeSavesFromVMEntryFrameCalleeSavesBuffer(GPRReg vmGPR, GPRReg scratchGPR)
     730{
     731#if NUMBER_OF_CALLEE_SAVES_REGISTERS > 0
     732    loadPtr(Address(vmGPR, VM::topEntryFrameOffset()), scratchGPR);
     733    restoreCalleeSavesFromVMEntryFrameCalleeSavesBufferImpl(scratchGPR, RegisterSet::stackRegisters());
     734#else
     735    UNUSED_PARAM(vmGPR);
     736#endif // NUMBER_OF_CALLEE_SAVES_REGISTERS > 0
     737}
     738
     739void AssemblyHelpers::restoreCalleeSavesFromVMEntryFrameCalleeSavesBufferImpl(GPRReg entryFrameGPR, const RegisterSet& skipList)
     740{
     741#if NUMBER_OF_CALLEE_SAVES_REGISTERS > 0
     742    addPtr(TrustedImm32(EntryFrame::calleeSaveRegistersBufferOffset()), entryFrameGPR);
     743
     744    RegisterAtOffsetList* allCalleeSaves = RegisterSet::vmCalleeSaveRegisterOffsets();
     745    unsigned registerCount = allCalleeSaves->size();
     746
     747    LoadRegSpooler spooler(*this, entryFrameGPR);
     748
     749    // Restore all callee saves except for the scratch.
     750    unsigned i = 0;
     751    for (; i < registerCount; i++) {
     752        RegisterAtOffset entry = allCalleeSaves->at(i);
     753        if (skipList.contains(entry.reg()))
     754            continue;
     755        if (!entry.reg().isGPR())
     756            break;
     757        spooler.loadGPR(entry);
     758    }
     759    spooler.finalizeGPR();
     760    for (; i < registerCount; i++) {
     761        RegisterAtOffset entry = allCalleeSaves->at(i);
     762        if (skipList.contains(entry.reg()))
     763            continue;
     764        ASSERT(!entry.reg().isGPR());
     765        spooler.loadFPR(entry);
     766    }
     767    spooler.finalizeFPR();
     768
     769#else
     770    UNUSED_PARAM(vmGPR);
     771    UNUSED_PARAM(skipList);
    748772#endif // NUMBER_OF_CALLEE_SAVES_REGISTERS > 0
    749773}
  • trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h

    r283512 r283852  
    414414
    415415    void restoreCalleeSavesFromEntryFrameCalleeSavesBuffer(EntryFrame*&);
     416    void restoreCalleeSavesFromVMEntryFrameCalleeSavesBuffer(GPRReg vmGPR, GPRReg scratchGPR);
     417    void restoreCalleeSavesFromVMEntryFrameCalleeSavesBufferImpl(GPRReg entryFrame, const RegisterSet& skipList);
    416418
    417419    void copyLLIntBaselineCalleeSavesFromFrameOrRegisterToEntryFrameCalleeSavesBuffer(EntryFrame*&, const TempRegisterSet& usedRegisters = { RegisterSet::stubUnavailableRegisters() });
  • trunk/Source/JavaScriptCore/jit/JITExceptions.cpp

    r268247 r283852  
    5555    Exception* exception = scope.exception();
    5656    RELEASE_ASSERT(exception);
    57     HandlerInfo* handler = vm.interpreter->unwind(vm, callFrame, exception); // This may update callFrame.
     57    CatchInfo handler = vm.interpreter->unwind(vm, callFrame, exception); // This may update callFrame.
    5858
    5959    void* catchRoutine;
    6060    const Instruction* catchPCForInterpreter = nullptr;
    61     if (handler) {
    62         // handler->target is meaningless for getting a code offset when catching
    63         // the exception in a DFG/FTL frame. This bytecode target offset could be
    64         // something that's in an inlined frame, which means an array access
    65         // with this bytecode offset in the machine frame is utterly meaningless
    66         // and can cause an overflow. OSR exit properly exits to handler->target
    67         // in the proper frame.
    68         if (!JITCode::isOptimizingJIT(callFrame->codeBlock()->jitType()))
    69             catchPCForInterpreter = callFrame->codeBlock()->instructions().at(handler->target).ptr();
     61    if (handler.m_valid) {
     62        catchPCForInterpreter = handler.m_catchPCForInterpreter;
    7063#if ENABLE(JIT)
    71         catchRoutine = handler->nativeCode.executableAddress();
     64        catchRoutine = handler.m_nativeCode.executableAddress();
    7265#else
    7366        if (catchPCForInterpreter->isWide32())
  • trunk/Source/JavaScriptCore/jit/JSInterfaceJIT.h

    r263824 r283852  
    5858        void emitPutToCallFrameHeader(void* value, VirtualRegister entry);
    5959        void emitPutCellToCallFrameHeader(RegisterID from, VirtualRegister entry);
     60        void convertCalleeToVM(RegisterID callee);
    6061
    6162        VM* vm() const { return m_vm; }
     
    159160    }
    160161
     162    ALWAYS_INLINE void JSInterfaceJIT::convertCalleeToVM(RegisterID callee)
     163    {
     164        auto preciseAllocationCase = branchTestPtr(CCallHelpers::NonZero, callee, CCallHelpers::TrustedImm32(PreciseAllocation::halfAlignment));
     165        andPtr(CCallHelpers::TrustedImmPtr(MarkedBlock::blockMask), callee);
     166        loadPtr(CCallHelpers::Address(callee, MarkedBlock::offsetOfFooter + MarkedBlock::Footer::offsetOfVM()), callee);
     167        auto loadedCase = jump();
     168
     169        preciseAllocationCase.link(this);
     170        loadPtr(CCallHelpers::Address(callee, PreciseAllocation::offsetOfWeakSet() + WeakSet::offsetOfVM() - PreciseAllocation::headerSize()), callee);
     171
     172        loadedCase.link(this);
     173    }
     174
    161175} // namespace JSC
    162176
  • trunk/Source/JavaScriptCore/llint/LLIntData.h

    r281757 r283852  
    324324
    325325template<PtrTag tag>
     326ALWAYS_INLINE MacroAssemblerCodeRef<tag> getCodeRef(WasmOpcodeID opcodeID)
     327{
     328    return MacroAssemblerCodeRef<tag>::createSelfManagedCodeRef(getCodePtr<tag>(opcodeID));
     329}
     330
     331template<PtrTag tag>
     332ALWAYS_INLINE MacroAssemblerCodeRef<tag> getWide16CodeRef(WasmOpcodeID opcodeID)
     333{
     334    return MacroAssemblerCodeRef<tag>::createSelfManagedCodeRef(getWide16CodePtr<tag>(opcodeID));
     335}
     336
     337template<PtrTag tag>
     338ALWAYS_INLINE MacroAssemblerCodeRef<tag> getWide32CodeRef(WasmOpcodeID opcodeID)
     339{
     340    return MacroAssemblerCodeRef<tag>::createSelfManagedCodeRef(getWide32CodePtr<tag>(opcodeID));
     341}
     342
     343template<PtrTag tag>
    326344ALWAYS_INLINE LLIntCode getCodeFunctionPtr(WasmOpcodeID opcodeID)
    327345{
  • trunk/Source/JavaScriptCore/llint/LLIntExceptions.cpp

    r268485 r283852  
    3030#include "LLIntData.h"
    3131#include "LLIntThunks.h"
     32#include "WasmContext.h"
    3233
    3334#if LLINT_TRACING
     
    4849#endif
    4950    return LLInt::exceptionInstructions();
     51}
     52
     53Instruction* wasmReturnToThrow(VM& vm)
     54{
     55    UNUSED_PARAM(vm);
     56#if LLINT_TRACING
     57    if (UNLIKELY(Options::traceLLIntSlowPath())) {
     58        auto scope = DECLARE_CATCH_SCOPE(vm);
     59        dataLog("Throwing exception ", JSValue(scope.exception()), " (returnToThrow).\n");
     60    }
     61#endif
     62    return LLInt::wasmExceptionInstructions();
    5063}
    5164
     
    93106}
    94107
     108#if ENABLE(WEBASSEMBLY)
     109MacroAssemblerCodeRef<ExceptionHandlerPtrTag> handleWasmCatch(OpcodeSize size)
     110{
     111    WasmOpcodeID opcode = Wasm::Context::useFastTLS() ? wasm_catch : wasm_catch_no_tls;
     112    switch (size) {
     113    case OpcodeSize::Narrow:
     114        return LLInt::getCodeRef<ExceptionHandlerPtrTag>(opcode);
     115    case OpcodeSize::Wide16:
     116        return LLInt::getWide16CodeRef<ExceptionHandlerPtrTag>(opcode);
     117    case OpcodeSize::Wide32:
     118        return LLInt::getWide32CodeRef<ExceptionHandlerPtrTag>(opcode);
     119    }
     120    RELEASE_ASSERT_NOT_REACHED();
     121    return { };
     122}
     123
     124MacroAssemblerCodeRef<ExceptionHandlerPtrTag> handleWasmCatchAll(OpcodeSize size)
     125{
     126    WasmOpcodeID opcode = Wasm::Context::useFastTLS() ? wasm_catch_all : wasm_catch_all_no_tls;
     127    switch (size) {
     128    case OpcodeSize::Narrow:
     129        return LLInt::getCodeRef<ExceptionHandlerPtrTag>(opcode);
     130    case OpcodeSize::Wide16:
     131        return LLInt::getWide16CodeRef<ExceptionHandlerPtrTag>(opcode);
     132    case OpcodeSize::Wide32:
     133        return LLInt::getWide32CodeRef<ExceptionHandlerPtrTag>(opcode);
     134    }
     135    RELEASE_ASSERT_NOT_REACHED();
     136    return { };
     137}
     138#endif // ENABLE(WEBASSEMBLY)
     139
    95140} } // namespace JSC::LLInt
  • trunk/Source/JavaScriptCore/llint/LLIntExceptions.h

    r268485 r283852  
    4343// interpreter's exception handler.
    4444Instruction* returnToThrow(VM&);
     45Instruction* wasmReturnToThrow(VM&);
    4546
    4647// Use this when you're throwing to a call thunk.
     
    5051MacroAssemblerCodeRef<ExceptionHandlerPtrTag> handleCatch(OpcodeSize);
    5152
     53#if ENABLE(WEBASSEMBLY)
     54MacroAssemblerCodeRef<ExceptionHandlerPtrTag> handleWasmCatch(OpcodeSize);
     55MacroAssemblerCodeRef<ExceptionHandlerPtrTag> handleWasmCatchAll(OpcodeSize);
     56#endif // ENABLE(WEBASSEMBLY)
     57
    5258} } // namespace JSC::LLInt
  • trunk/Source/JavaScriptCore/llint/LLIntOffsetsExtractor.cpp

    r275542 r283852  
    5454#include "JSString.h"
    5555#include "JSTypeInfo.h"
     56#include "JSWebAssemblyInstance.h"
    5657#include "JumpTable.h"
    5758#include "LLIntData.h"
  • trunk/Source/JavaScriptCore/llint/WebAssembly.asm

    r276896 r283852  
    257257
    258258macro callWasmSlowPath(slowPath)
     259    storei PC, ArgumentCountIncludingThis + TagOffset[cfr]
    259260    prepareStateForCCall()
    260261    move cfr, a0
     
    275276end
    276277
     278macro restoreStackPointerAfterCall()
     279    loadp CodeBlock[cfr], ws1
     280    loadi Wasm::FunctionCodeBlock::m_numCalleeLocals[ws1], ws1
     281    lshiftp 3, ws1
     282    addp maxFrameExtentForSlowPathCall, ws1
     283    subp cfr, ws1, sp
     284end
     285
    277286macro wasmPrologue(codeBlockGetter, codeBlockSetter, loadWasmInstance)
    278287    # Set up the call frame and check if we should OSR.
     
    281290    loadWasmInstance()
    282291    reloadMemoryRegistersFromInstance(wasmInstance, ws0, ws1)
     292
     293    loadp Wasm::Instance::m_owner[wasmInstance], ws0
     294    storep ws0, ThisArgumentOffset[cfr]
    283295
    284296    codeBlockGetter(ws0)
     
    334346end
    335347
    336 # Less convenient, but required for opcodes that collide with reserved instructions (e.g. wasm_nop)
    337 macro unprefixedWasmOp(opcodeName, opcodeStruct, fn)
    338     commonOp(opcodeName, traceExecution, macro(size)
     348macro commonWasmOp(opcodeName, opcodeStruct, prologue, fn)
     349    commonOp(opcodeName, prologue, macro(size)
    339350        fn(macro(fn2)
    340351            fn2(opcodeName, opcodeStruct, size)
    341352        end)
    342353    end)
     354end
     355
     356# Less convenient, but required for opcodes that collide with reserved instructions (e.g. wasm_nop)
     357macro unprefixedWasmOp(opcodeName, opcodeStruct, fn)
     358    commonWasmOp(opcodeName, opcodeStruct, traceExecution, fn)
    343359end
    344360
     
    513529end)
    514530
    515 op(wasm_throw_from_slow_path_trampoline, macro ()
    516     loadp Wasm::Instance::m_pointerToTopEntryFrame[wasmInstance], t5
    517     loadp [t5], t5
    518     copyCalleeSavesToEntryFrameCalleeSavesBuffer(t5)
    519 
    520     move cfr, a0
    521     addp PB, PC, a1
    522     move wasmInstance, a2
    523     # Slow paths and the throwException macro store the exception code in the ArgumentCountIncludingThis slot
    524     loadi ArgumentCountIncludingThis + PayloadOffset[cfr], a3
    525     cCall4(_slow_path_wasm_throw_exception)
    526 
     531macro jumpToException()
    527532    if ARM64E
    528533        move r0, a0
     
    532537        jmp r0, ExceptionHandlerPtrTag
    533538    end
     539end
     540
     541op(wasm_throw_from_slow_path_trampoline, macro ()
     542    loadp Wasm::Instance::m_pointerToTopEntryFrame[wasmInstance], t5
     543    loadp [t5], t5
     544    copyCalleeSavesToEntryFrameCalleeSavesBuffer(t5)
     545
     546    move cfr, a0
     547    addp PB, PC, a1
     548    move wasmInstance, a2
     549    # Slow paths and the throwException macro store the exception code in the ArgumentCountIncludingThis slot
     550    loadi ArgumentCountIncludingThis + PayloadOffset[cfr], a3
     551    cCall4(_slow_path_wasm_throw_exception)
     552    jumpToException()
    534553end)
    535554
     
    544563    move cfr, a0
    545564    cCall4(_slow_path_wasm_throw_exception)
    546 
    547     if ARM64E
    548         move r0, a0
    549         leap JSCConfig + constexpr JSC::offsetOfJSCConfigGateMap + (constexpr Gate::exceptionHandler) * PtrSize, a1
    550         jmp [a1], NativeToJITGatePtrTag # ExceptionHandlerPtrTag
    551     else
    552         jmp r0, ExceptionHandlerPtrTag
    553     end
     565    jumpToException()
    554566end
    555567
     
    771783            # Load registers from stack
    772784            forEachArgumentGPR(macro (offset, gpr)
    773                 loadq CallFrameHeaderSize + offset[sp, ws1, 8], gpr
     785                loadq CallFrameHeaderSize + 8 + offset[sp, ws1, 8], gpr
    774786            end)
    775787
    776788            forEachArgumentFPR(macro (offset, fpr)
    777                 loadd CallFrameHeaderSize + offset[sp, ws1, 8], fpr
     789                loadd CallFrameHeaderSize + 8 + offset[sp, ws1, 8], fpr
    778790            end)
    779791
     
    812824            end)
    813825
    814             loadp CodeBlock[cfr], ws1
    815             loadi Wasm::FunctionCodeBlock::m_numCalleeLocals[ws1], ws1
    816             lshiftp 3, ws1
    817             addp maxFrameExtentForSlowPathCall, ws1
    818             subp cfr, ws1, sp
     826            restoreStackPointerAfterCall()
    819827
    820828            # We need to set PC to load information from the instruction stream, but we
     
    837845            move memoryBase, PC
    838846            forEachArgumentGPR(macro (offset, gpr)
    839                 storeq gpr, CallFrameHeaderSize + offset[ws1, ws0, 8]
     847                storeq gpr, CallFrameHeaderSize + 8 + offset[ws1, ws0, 8]
    840848            end)
    841849
    842850            forEachArgumentFPR(macro (offset, fpr)
    843                 stored fpr, CallFrameHeaderSize + offset[ws1, ws0, 8]
     851                stored fpr, CallFrameHeaderSize + 8 + offset[ws1, ws0, 8]
    844852            end)
    845853
     
    28052813    dispatch(ctx)
    28062814end)
     2815
     2816wasmOp(throw, WasmThrow, macro(ctx)
     2817    loadp Wasm::Instance::m_pointerToTopEntryFrame[wasmInstance], t5
     2818    loadp [t5], t5
     2819    copyCalleeSavesToEntryFrameCalleeSavesBuffer(t5)
     2820
     2821    callWasmSlowPath(_slow_path_wasm_throw)
     2822    jumpToException()
     2823end)
     2824
     2825wasmOp(rethrow, WasmRethrow, macro(ctx)
     2826    callWasmSlowPath(_slow_path_wasm_rethrow)
     2827    jumpToException()
     2828end)
     2829
     2830macro catchImpl(ctx, storeWasmInstance)
     2831    loadp Callee[cfr], t3
     2832    convertCalleeToVM(t3)
     2833    restoreCalleeSavesFromVMEntryFrameCalleeSavesBuffer(t3, t0)
     2834
     2835    loadp VM::calleeForWasmCatch[t3], ws1
     2836    storep 0, VM::calleeForWasmCatch[t3]
     2837    storep ws1, Callee[cfr]
     2838
     2839    loadp VM::callFrameForCatch[t3], cfr
     2840    storep 0, VM::callFrameForCatch[t3]
     2841
     2842    restoreStackPointerAfterCall()
     2843
     2844    loadp ThisArgumentOffset[cfr], wasmInstance
     2845    loadp JSWebAssemblyInstance::m_instance[wasmInstance], wasmInstance
     2846    storeWasmInstance(wasmInstance)
     2847    reloadMemoryRegistersFromInstance(wasmInstance, ws0, ws1)
     2848
     2849    loadp CodeBlock[cfr], PB
     2850    loadp Wasm::FunctionCodeBlock::m_instructionsRawPointer[PB], PB
     2851    loadp VM::targetInterpreterPCForThrow[t3], PC
     2852    subp PB, PC
     2853
     2854    callWasmSlowPath(_slow_path_wasm_retrieve_and_clear_exception)
     2855    move r1, t1
     2856
     2857    wgetu(ctx, m_startOffset, t2)
     2858    wgetu(ctx, m_argumentCount, t3)
     2859
     2860    lshifti 3, t2
     2861    subp cfr, t2, t2
     2862
     2863.copyLoop:
     2864    btiz t3, .done
     2865    loadq [t1], t6
     2866    storeq t6, [t2]
     2867    subi 1, t3
     2868    # FIXME: Use arm store-add/sub instructions in wasm LLInt catch
     2869    # https://bugs.webkit.org/show_bug.cgi?id=231210
     2870    subp 8, t2
     2871    addp 8, t1
     2872    jmp .copyLoop
     2873
     2874.done:
     2875    traceExecution()
     2876
     2877    dispatch(ctx)
     2878end
     2879
     2880commonWasmOp(wasm_catch, WasmCatch, macro() end, macro(ctx)
     2881    catchImpl(ctx, storeWasmInstanceToTLS)
     2882end)
     2883
     2884commonWasmOp(wasm_catch_no_tls, WasmCatch, macro() end, macro(ctx)
     2885    catchImpl(ctx, macro(instance) end)
     2886end)
     2887
     2888macro catchAllImpl(ctx, storeWasmInstance)
     2889    loadp Callee[cfr], t3
     2890    convertCalleeToVM(t3)
     2891    restoreCalleeSavesFromVMEntryFrameCalleeSavesBuffer(t3, t0)
     2892
     2893    loadp VM::calleeForWasmCatch[t3], ws1
     2894    storep 0, VM::calleeForWasmCatch[t3]
     2895    storep ws1, Callee[cfr]
     2896
     2897    loadp VM::callFrameForCatch[t3], cfr
     2898    storep 0, VM::callFrameForCatch[t3]
     2899
     2900    restoreStackPointerAfterCall()
     2901
     2902    loadp ThisArgumentOffset[cfr], wasmInstance
     2903    loadp JSWebAssemblyInstance::m_instance[wasmInstance], wasmInstance
     2904    storeWasmInstance(wasmInstance)
     2905    reloadMemoryRegistersFromInstance(wasmInstance, ws0, ws1)
     2906
     2907    loadp CodeBlock[cfr], PB
     2908    loadp Wasm::FunctionCodeBlock::m_instructionsRawPointer[PB], PB
     2909    loadp VM::targetInterpreterPCForThrow[t3], PC
     2910    subp PB, PC
     2911
     2912    callWasmSlowPath(_slow_path_wasm_retrieve_and_clear_exception)
     2913
     2914    traceExecution()
     2915
     2916    dispatch(ctx)
     2917end
     2918
     2919commonWasmOp(wasm_catch_all, WasmCatchAll, macro() end, macro(ctx)
     2920    catchAllImpl(ctx, storeWasmInstanceToTLS)
     2921end)
     2922
     2923commonWasmOp(wasm_catch_all_no_tls, WasmCatchAll, macro() end, macro(ctx)
     2924    catchAllImpl(ctx, macro(instance) end)
     2925end)
  • trunk/Source/JavaScriptCore/runtime/ErrorInstance.cpp

    r277967 r283852  
    4141    , m_errorInfoMaterialized(false)
    4242    , m_nativeGetterTypeError(false)
     43#if ENABLE(WEBASSEMBLY)
     44    , m_catchableFromWasm(true)
     45#endif // ENABLE(WEBASSEMBLY)
    4346{
    4447}
  • trunk/Source/JavaScriptCore/runtime/ErrorInstance.h

    r278589 r283852  
    8181    bool isNativeGetterTypeError() const { return m_nativeGetterTypeError; }
    8282
     83#if ENABLE(WEBASSEMBLY)
     84    void setCatchableFromWasm(bool flag) { m_catchableFromWasm = flag; }
     85    bool isCatchableFromWasm() const { return m_catchableFromWasm; }
     86#endif
     87
    8388    JS_EXPORT_PRIVATE String sanitizedToString(JSGlobalObject*);
    8489    JS_EXPORT_PRIVATE String sanitizedMessageString(JSGlobalObject*);
     
    117122    bool m_errorInfoMaterialized : 1;
    118123    bool m_nativeGetterTypeError : 1;
     124#if ENABLE(WEBASSEMBLY)
     125    bool m_catchableFromWasm : 1;
     126#endif
    119127};
    120128
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp

    r283566 r283852  
    154154#include "JSWebAssembly.h"
    155155#include "JSWebAssemblyCompileError.h"
     156#include "JSWebAssemblyException.h"
    156157#include "JSWebAssemblyGlobal.h"
    157158#include "JSWebAssemblyInstance.h"
     
    161162#include "JSWebAssemblyRuntimeError.h"
    162163#include "JSWebAssemblyTable.h"
     164#include "JSWebAssemblyTag.h"
    163165#include "JSWithScope.h"
    164166#include "LazyClassStructureInlines.h"
     
    221223#include "WebAssemblyCompileErrorConstructor.h"
    222224#include "WebAssemblyCompileErrorPrototype.h"
     225#include "WebAssemblyExceptionConstructor.h"
     226#include "WebAssemblyExceptionPrototype.h"
    223227#include "WebAssemblyFunction.h"
    224228#include "WebAssemblyGlobalConstructor.h"
     
    237241#include "WebAssemblyTableConstructor.h"
    238242#include "WebAssemblyTablePrototype.h"
     243#include "WebAssemblyTagConstructor.h"
     244#include "WebAssemblyTagPrototype.h"
    239245#include <wtf/RandomNumber.h>
    240246#include <wtf/SystemTracing.h>
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h

    r283566 r283852  
    170170#if ENABLE(WEBASSEMBLY)
    171171#define FOR_EACH_WEBASSEMBLY_CONSTRUCTOR_TYPE(macro) \
    172     macro(WebAssemblyCompileError, webAssemblyCompileError, webAssemblyCompileError, ErrorInstance,             CompileError, error, typeExposedByDefault) \
     172    macro(WebAssemblyCompileError, webAssemblyCompileError, webAssemblyCompileError, ErrorInstance,             CompileError, error,  typeExposedByDefault) \
     173    macro(WebAssemblyException,    webAssemblyException,    webAssemblyException,    JSWebAssemblyException,    Exception,    object, typeExposedByDefault) \
    173174    macro(WebAssemblyGlobal,       webAssemblyGlobal,       webAssemblyGlobal,       JSWebAssemblyGlobal,       Global,       object, typeExposedByDefault) \
    174175    macro(WebAssemblyInstance,     webAssemblyInstance,     webAssemblyInstance,     JSWebAssemblyInstance,     Instance,     object, typeExposedByDefault) \
    175     macro(WebAssemblyLinkError,    webAssemblyLinkError,    webAssemblyLinkError,    ErrorInstance,             LinkError,    error, typeExposedByDefault) \
     176    macro(WebAssemblyLinkError,    webAssemblyLinkError,    webAssemblyLinkError,    ErrorInstance,             LinkError,    error,  typeExposedByDefault) \
    176177    macro(WebAssemblyMemory,       webAssemblyMemory,       webAssemblyMemory,       JSWebAssemblyMemory,       Memory,       object, typeExposedByDefault) \
    177178    macro(WebAssemblyModule,       webAssemblyModule,       webAssemblyModule,       JSWebAssemblyModule,       Module,       object, typeExposedByDefault) \
    178     macro(WebAssemblyRuntimeError, webAssemblyRuntimeError, webAssemblyRuntimeError, ErrorInstance,             RuntimeError, error, typeExposedByDefault) \
    179     macro(WebAssemblyTable,        webAssemblyTable,        webAssemblyTable,        JSWebAssemblyTable,        Table,        object, typeExposedByDefault)
     179    macro(WebAssemblyRuntimeError, webAssemblyRuntimeError, webAssemblyRuntimeError, ErrorInstance,             RuntimeError, error,  typeExposedByDefault) \
     180    macro(WebAssemblyTable,        webAssemblyTable,        webAssemblyTable,        JSWebAssemblyTable,        Table,        object, typeExposedByDefault) \
     181    macro(WebAssemblyTag,          webAssemblyTag,          webAssemblyTag,          JSWebAssemblyTag,          Tag,          object, typeExposedByDefault)
    180182#else
    181183#define FOR_EACH_WEBASSEMBLY_CONSTRUCTOR_TYPE(macro)
  • trunk/Source/JavaScriptCore/runtime/OptionsList.h

    r283139 r283852  
    544544    v(Bool, useWebAssemblyThreading, true, Normal, "Allow instructions from the wasm threading spec.") \
    545545    v(Bool, useWebAssemblyTypedFunctionReferences, false, Normal, "Allow function types from the wasm typed function references spec.") \
     546    v(Bool, useWebAssemblyExceptions, true, Normal, "Allow the new section and instructions from the wasm exception handling spec.") \
    546547
    547548
  • trunk/Source/JavaScriptCore/runtime/VM.cpp

    r282860 r283852  
    130130#include "JSWeakSet.h"
    131131#include "JSWebAssemblyCodeBlock.h"
     132#include "JSWebAssemblyException.h"
    132133#include "JSWebAssemblyGlobal.h"
    133134#include "JSWebAssemblyInstance.h"
     
    135136#include "JSWebAssemblyModule.h"
    136137#include "JSWebAssemblyTable.h"
     138#include "JSWebAssemblyTag.h"
    137139#include "JSWithScope.h"
    138140#include "LLIntData.h"
     
    335337#if ENABLE(WEBASSEMBLY)
    336338    , webAssemblyCodeBlockHeapCellType(IsoHeapCellType::create<JSWebAssemblyCodeBlock>())
     339    , webAssemblyExceptionHeapCellType(IsoHeapCellType::create<JSWebAssemblyException>())
    337340    , webAssemblyFunctionHeapCellType(IsoHeapCellType::create<WebAssemblyFunction>())
    338341    , webAssemblyGlobalHeapCellType(IsoHeapCellType::create<JSWebAssemblyGlobal>())
     
    342345    , webAssemblyModuleRecordHeapCellType(IsoHeapCellType::create<WebAssemblyModuleRecord>())
    343346    , webAssemblyTableHeapCellType(IsoHeapCellType::create<JSWebAssemblyTable>())
     347    , webAssemblyTagHeapCellType(IsoHeapCellType::create<JSWebAssemblyTag>())
    344348#endif
    345349    , primitiveGigacageAuxiliarySpace("Primitive Gigacage Auxiliary", heap, auxiliaryHeapCellType.get(), primitiveGigacageAllocator.get()) // Hash:0x3e7cd762
     
    16301634DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(jsToWasmICCalleeSpace, cellHeapCellType.get(), JSToWasmICCallee)
    16311635DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(webAssemblyCodeBlockSpace, webAssemblyCodeBlockHeapCellType.get(), JSWebAssemblyCodeBlock) // Hash:0x9ad995cd
     1636DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(webAssemblyExceptionSpace, webAssemblyExceptionHeapCellType.get(), JSWebAssemblyException)
    16321637DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(webAssemblyFunctionSpace, webAssemblyFunctionHeapCellType.get(), WebAssemblyFunction) // Hash:0x8b7c32db
    16331638DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(webAssemblyGlobalSpace, webAssemblyGlobalHeapCellType.get(), JSWebAssemblyGlobal)
     
    16371642DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(webAssemblyModuleRecordSpace, webAssemblyModuleRecordHeapCellType.get(), WebAssemblyModuleRecord)
    16381643DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(webAssemblyTableSpace, webAssemblyTableHeapCellType.get(), JSWebAssemblyTable)
     1644DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(webAssemblyTagSpace, webAssemblyTagHeapCellType.get(), JSWebAssemblyTag)
    16391645DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(webAssemblyWrapperFunctionSpace, cellHeapCellType.get(), WebAssemblyWrapperFunction) // Hash:0xd4a5ff01
    16401646#endif
  • trunk/Source/JavaScriptCore/runtime/VM.h

    r282565 r283852  
    3030
    3131#include "CallData.h"
     32#include "CalleeBits.h"
    3233#include "CodeSpecializationKind.h"
    3334#include "CompleteSubspace.h"
     
    451452#if ENABLE(WEBASSEMBLY)
    452453    std::unique_ptr<IsoHeapCellType> webAssemblyCodeBlockHeapCellType;
     454    std::unique_ptr<IsoHeapCellType> webAssemblyExceptionHeapCellType;
    453455    std::unique_ptr<IsoHeapCellType> webAssemblyFunctionHeapCellType;
    454456    std::unique_ptr<IsoHeapCellType> webAssemblyGlobalHeapCellType;
     
    458460    std::unique_ptr<IsoHeapCellType> webAssemblyModuleRecordHeapCellType;
    459461    std::unique_ptr<IsoHeapCellType> webAssemblyTableHeapCellType;
     462    std::unique_ptr<IsoHeapCellType> webAssemblyTagHeapCellType;
    460463#endif
    461464
     
    627630    DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(jsToWasmICCalleeSpace)
    628631    DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(webAssemblyCodeBlockSpace)
     632    DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(webAssemblyExceptionSpace)
    629633    DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(webAssemblyFunctionSpace)
    630634    DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(webAssemblyGlobalSpace)
     
    634638    DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(webAssemblyModuleRecordSpace)
    635639    DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(webAssemblyTableSpace)
     640    DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(webAssemblyTagSpace)
    636641    DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(webAssemblyWrapperFunctionSpace)
    637642#endif
     
    897902    }
    898903
     904    static ptrdiff_t calleeForWasmCatchOffset()
     905    {
     906        return OBJECT_OFFSETOF(VM, calleeForWasmCatch);
     907    }
     908
    899909    static ptrdiff_t topEntryFrameOffset()
    900910    {
     
    9911001    CallFrame* newCallFrameReturnValue;
    9921002    CallFrame* callFrameForCatch;
     1003    CalleeBits calleeForWasmCatch;
    9931004    void* targetMachinePCForThrow;
    9941005    const Instruction* targetInterpreterPCForThrow;
  • trunk/Source/JavaScriptCore/wasm/WasmAirIRGenerator.cpp

    r280507 r283852  
    148148
    149149        static bool isIf(const ControlData& control) { return control.blockType() == BlockType::If; }
     150        static bool isTry(const ControlData& control) { return control.blockType() == BlockType::Try; }
     151        static bool isCatch(const ControlData& control) { return control.blockType() == BlockType::Catch; }
     152        static bool isAnyCatch(const ControlData& control) { return control.blockType() == BlockType::Catch; }
    150153        static bool isTopLevel(const ControlData& control) { return control.blockType() == BlockType::TopLevel; }
     154        static bool isLoop(const ControlData& control) { return control.blockType() == BlockType::Loop; }
     155        static bool isBlock(const ControlData& control) { return control.blockType() == BlockType::Block; }
    151156
    152157        void dump(PrintStream& out) const
     
    165170                out.print("TopLevel: ");
    166171                break;
     172            case BlockType::Try:
     173                out.print("Try: ");
     174                break;
     175            case BlockType::Catch:
     176                out.print("Catch: ");
     177                break;
    167178            }
    168179            out.print("Continuation: ", *continuation, ", Special: ");
     
    314325    PartialResult WARN_UNUSED_RETURN addElse(ControlData&, const Stack&);
    315326    PartialResult WARN_UNUSED_RETURN addElseToUnreachable(ControlData&);
     327
     328    PartialResult WARN_UNUSED_RETURN addTry(BlockSignature, Stack& enclosingStack, ControlType& result, Stack& newStack);
     329    PartialResult WARN_UNUSED_RETURN addCatch(unsigned exceptionIndex, const Signature&, Stack&, ControlType&, ResultList&);
     330    PartialResult WARN_UNUSED_RETURN addCatchToUnreachable(unsigned exceptionIndex, const Signature&, ControlType&, ResultList&);
     331    PartialResult WARN_UNUSED_RETURN addCatchAll(Stack&, ControlType&);
     332    PartialResult WARN_UNUSED_RETURN addCatchAllToUnreachable(ControlType&);
     333    PartialResult WARN_UNUSED_RETURN addDelegate(ControlType&, ControlType&);
     334    PartialResult WARN_UNUSED_RETURN addDelegateToUnreachable(ControlType&, ControlType&);
     335    PartialResult WARN_UNUSED_RETURN addThrow(unsigned exceptionIndex, Vector<ExpressionType>& args, Stack&);
     336    PartialResult WARN_UNUSED_RETURN addRethrow(unsigned, ControlType&);
    316337
    317338    PartialResult WARN_UNUSED_RETURN addReturn(const ControlData&, const Stack& returnValues);
     
    29833004}
    29843005
     3006// FIXME: Add support for Wasm exceptions in the Air generator
     3007// https://bugs.webkit.org/show_bug.cgi?id=231211
     3008auto AirIRGenerator::addTry(BlockSignature, Stack&, ControlType&, Stack&) -> PartialResult
     3009{
     3010    return { };
     3011}
     3012
     3013auto AirIRGenerator::addCatch(unsigned, const Signature&, Stack&, ControlType&, ResultList&) -> PartialResult
     3014{
     3015    RELEASE_ASSERT_NOT_REACHED();
     3016    return { };
     3017}
     3018
     3019auto AirIRGenerator::addCatchToUnreachable(unsigned, const Signature&, ControlType&, ResultList&) -> PartialResult
     3020{
     3021    RELEASE_ASSERT_NOT_REACHED();
     3022    return { };
     3023}
     3024
     3025auto AirIRGenerator::addCatchAll(Stack&, ControlType&) -> PartialResult
     3026{
     3027    RELEASE_ASSERT_NOT_REACHED();
     3028    return { };
     3029}
     3030
     3031auto AirIRGenerator::addCatchAllToUnreachable(ControlType&) -> PartialResult
     3032{
     3033    RELEASE_ASSERT_NOT_REACHED();
     3034    return { };
     3035}
     3036
     3037auto AirIRGenerator::addDelegate(ControlType&, ControlType&) -> PartialResult
     3038{
     3039    RELEASE_ASSERT_NOT_REACHED();
     3040    return { };
     3041}
     3042
     3043auto AirIRGenerator::addDelegateToUnreachable(ControlType&, ControlType&) -> PartialResult
     3044{
     3045    RELEASE_ASSERT_NOT_REACHED();
     3046    return { };
     3047}
     3048
     3049auto AirIRGenerator::addThrow(unsigned exceptionIndex, Vector<ExpressionType>&, Stack&) -> PartialResult
     3050{
     3051    UNUSED_PARAM(exceptionIndex);
     3052    return { };
     3053}
     3054
     3055auto AirIRGenerator::addRethrow(unsigned, ControlType&) -> PartialResult
     3056{
     3057    return { };
     3058}
     3059
    29853060auto AirIRGenerator::addReturn(const ControlData& data, const Stack& returnValues) -> PartialResult
    29863061{
  • trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp

    r280507 r283852  
    4949#include "JSCJSValueInlines.h"
    5050#include "JSWebAssemblyInstance.h"
     51#include "ProbeContext.h"
     52#include "ScratchRegisterAllocator.h"
    5153#include "ScratchRegisterAllocator.h"
    5254#include "WasmCallingConvention.h"
     
    8486}
    8587
     88class B3IRGenerator;
     89struct PatchpointExceptionHandle {
     90    void generate(CCallHelpers&, const B3::StackmapGenerationParams&, B3IRGenerator*) const;
     91
     92    static constexpr unsigned s_invalidCallSiteIndex =  std::numeric_limits<unsigned>::max();
     93
     94    unsigned m_callSiteIndex { s_invalidCallSiteIndex };
     95    unsigned m_offset;
     96};
     97
    8698class B3IRGenerator {
    8799public:
    88     using ExpressionType = Value*;
     100    using ExpressionType = Variable*;
    89101    using ResultList = Vector<ExpressionType, 8>;
    90102
    91103    struct ControlData {
    92         ControlData(Procedure& proc, Origin origin, BlockSignature signature, BlockType type, BasicBlock* continuation, BasicBlock* special = nullptr)
     104        ControlData(Procedure& proc, Origin origin, BlockSignature signature, BlockType type, unsigned stackSize, BasicBlock* continuation, BasicBlock* special = nullptr)
    93105            : controlBlockType(type)
    94106            , m_signature(signature)
     107            , m_stackSize(stackSize)
    95108            , continuation(continuation)
    96109            , special(special)
    97110        {
     111            ASSERT(type != BlockType::Try && type != BlockType::Catch);
     112            if (type != BlockType::TopLevel)
     113                m_stackSize -= signature->argumentCount();
     114
    98115            if (type == BlockType::Loop) {
    99116                for (unsigned i = 0; i < signature->argumentCount(); ++i)
     
    105122        }
    106123
     124        ControlData(Procedure& proc, Origin origin, BlockSignature signature, BlockType type, unsigned stackSize, BasicBlock* continuation, unsigned tryStart, unsigned tryDepth)
     125            : controlBlockType(type)
     126            , m_signature(signature)
     127            , m_stackSize(stackSize)
     128            , continuation(continuation)
     129            , special(nullptr)
     130            , m_tryStart(tryStart)
     131            , m_tryDepth(tryDepth)
     132        {
     133            UNUSED_PARAM(proc);
     134            UNUSED_PARAM(origin);
     135            for (unsigned i = 0; i < signature->returnCount(); ++i)
     136                phis.append(proc.add<Value>(Phi, toB3Type(signature->returnType(i)), origin));
     137        }
     138
    107139        ControlData()
    108140        {
     
    110142
    111143        static bool isIf(const ControlData& control) { return control.blockType() == BlockType::If; }
     144        static bool isTry(const ControlData& control) { return control.blockType() == BlockType::Try; }
     145        static bool isAnyCatch(const ControlData& control) { return control.blockType() == BlockType::Catch; }
    112146        static bool isTopLevel(const ControlData& control) { return control.blockType() == BlockType::TopLevel; }
     147        static bool isLoop(const ControlData& control) { return control.blockType() == BlockType::Loop; }
     148        static bool isBlock(const ControlData& control) { return control.blockType() == BlockType::Block; }
     149        static bool isCatch(const ControlData& control)
     150        {
     151            if (control.blockType() != BlockType::Catch)
     152                return false;
     153            return control.catchKind() == CatchKind::Catch;
     154        }
    113155
    114156        void dump(PrintStream& out) const
     
    127169                out.print("TopLevel: ");
    128170                break;
     171            case BlockType::Try:
     172                out.print("Try: ");
     173                break;
     174            case BlockType::Catch:
     175                out.print("Catch: ");
     176                break;
    129177            }
    130178            out.print("Continuation: ", *continuation, ", Special: ");
     
    155203        }
    156204
     205        void convertTryToCatch(unsigned tryEndCallSiteIndex, Variable* exception)
     206        {
     207            ASSERT(blockType() == BlockType::Try);
     208            controlBlockType = BlockType::Catch;
     209            m_catchKind = CatchKind::Catch;
     210            m_tryEnd = tryEndCallSiteIndex;
     211            m_exception = exception;
     212        }
     213
     214        void convertTryToCatchAll(unsigned tryEndCallSiteIndex, Variable* exception)
     215        {
     216            ASSERT(blockType() == BlockType::Try);
     217            controlBlockType = BlockType::Catch;
     218            m_catchKind = CatchKind::CatchAll;
     219            m_tryEnd = tryEndCallSiteIndex;
     220            m_exception = exception;
     221        }
     222
    157223        SignatureArgCount branchTargetArity() const
    158224        {
     
    170236        }
    171237
     238        unsigned tryStart() const
     239        {
     240            ASSERT(controlBlockType == BlockType::Try || controlBlockType == BlockType::Catch);
     241            return m_tryStart;
     242        }
     243
     244        unsigned tryEnd() const
     245        {
     246            ASSERT(controlBlockType == BlockType::Catch);
     247            return m_tryEnd;
     248        }
     249
     250        unsigned tryDepth() const
     251        {
     252            ASSERT(controlBlockType == BlockType::Try || controlBlockType == BlockType::Catch);
     253            return m_tryDepth;
     254        }
     255
     256        CatchKind catchKind() const
     257        {
     258            ASSERT(controlBlockType == BlockType::Catch);
     259            return m_catchKind;
     260        }
     261
     262        Variable* exception() const
     263        {
     264            ASSERT(controlBlockType == BlockType::Catch);
     265            return m_exception;
     266        }
     267
     268        unsigned stackSize() const { return m_stackSize; }
     269
    172270    private:
     271        // FIXME: Compress B3IRGenerator::ControlData fields using an union
     272        // https://bugs.webkit.org/show_bug.cgi?id=231212
    173273        friend class B3IRGenerator;
    174274        BlockType controlBlockType;
    175275        BlockSignature m_signature;
     276        unsigned m_stackSize;
    176277        BasicBlock* continuation;
    177278        BasicBlock* special;
    178         ResultList phis;
     279        Vector<Value*> phis;
     280        unsigned m_tryStart;
     281        unsigned m_tryEnd;
     282        unsigned m_tryDepth;
     283        CatchKind m_catchKind;
     284        Variable* m_exception;
    179285    };
    180286
     
    274380    PartialResult WARN_UNUSED_RETURN addElseToUnreachable(ControlData&);
    275381
     382    PartialResult WARN_UNUSED_RETURN addTry(BlockSignature, Stack& enclosingStack, ControlType& result, Stack& newStack);
     383    PartialResult WARN_UNUSED_RETURN addCatch(unsigned exceptionIndex, const Signature&, Stack&, ControlType&, ResultList&);
     384    PartialResult WARN_UNUSED_RETURN addCatchToUnreachable(unsigned exceptionIndex, const Signature&, ControlType&, ResultList&);
     385    PartialResult WARN_UNUSED_RETURN addCatchAll(Stack&, ControlType&);
     386    PartialResult WARN_UNUSED_RETURN addCatchAllToUnreachable(ControlType&);
     387    PartialResult WARN_UNUSED_RETURN addDelegate(ControlType&, ControlType&);
     388    PartialResult WARN_UNUSED_RETURN addDelegateToUnreachable(ControlType&, ControlType&);
     389    PartialResult WARN_UNUSED_RETURN addThrow(unsigned exceptionIndex, Vector<ExpressionType>& args, Stack&);
     390    PartialResult WARN_UNUSED_RETURN addRethrow(unsigned, ControlType&);
     391
    276392    PartialResult WARN_UNUSED_RETURN addReturn(const ControlData&, const Stack& returnValues);
    277393    PartialResult WARN_UNUSED_RETURN addBranch(ControlData&, ExpressionType condition, const Stack& returnValues);
     
    287403    PartialResult WARN_UNUSED_RETURN addCallRef(const Signature&, Vector<ExpressionType>& args, ResultList& results);
    288404    PartialResult WARN_UNUSED_RETURN addUnreachable();
    289     PartialResult WARN_UNUSED_RETURN emitIndirectCall(Value* calleeInstance, ExpressionType calleeCode, const Signature&, Vector<ExpressionType>& args, ResultList&);
     405    PartialResult WARN_UNUSED_RETURN emitIndirectCall(Value* calleeInstance, Value* calleeCode, const Signature&, Vector<ExpressionType>& args, ResultList&);
    290406    B3::Value* createCallPatchpoint(BasicBlock*, Origin, const Signature&, Vector<ExpressionType>& args, const ScopedLambda<void(PatchpointValue*)>& patchpointFunctor);
    291407
     
    293409    void setParser(FunctionParser<B3IRGenerator>* parser) { m_parser = parser; };
    294410    void didFinishParsingLocals() { }
    295     void didPopValueFromStack() { }
     411    void didPopValueFromStack() { --m_stackSize; }
    296412
    297413    Value* constant(B3::Type, uint64_t bits, std::optional<Origin> = std::nullopt);
    298414    Value* framePointer();
     415    void insertEntrySwitch();
    299416    void insertConstants();
    300417
    301418    B3::Type toB3ResultType(BlockSignature);
     419
     420    void addStackMap(unsigned callSiteIndex, StackMap&& stackmap)
     421    {
     422        m_stackmaps.add(CallSiteIndex(callSiteIndex), WTFMove(stackmap));
     423    }
     424
     425    StackMaps&& takeStackmaps()
     426    {
     427        return WTFMove(m_stackmaps);
     428    }
     429
     430    Vector<UnlinkedHandlerInfo>&& takeExceptionHandlers()
     431    {
     432        return WTFMove(m_exceptionHandlers);
     433    }
    302434
    303435private:
     
    308440
    309441    void emitWriteBarrierForJSWrapper();
    310     ExpressionType emitCheckAndPreparePointer(ExpressionType pointer, uint32_t offset, uint32_t sizeOfOp);
     442    Value* emitCheckAndPreparePointer(Value* pointer, uint32_t offset, uint32_t sizeOfOp);
    311443    B3::Kind memoryKind(B3::Opcode memoryOp);
    312     ExpressionType emitLoadOp(LoadOpType, ExpressionType pointer, uint32_t offset);
    313     void emitStoreOp(StoreOpType, ExpressionType pointer, ExpressionType value, uint32_t offset);
    314 
    315     ExpressionType sanitizeAtomicResult(ExtAtomicOpType, Type, ExpressionType result);
    316     ExpressionType emitAtomicLoadOp(ExtAtomicOpType, Type, ExpressionType pointer, uint32_t offset);
    317     void emitAtomicStoreOp(ExtAtomicOpType, Type, ExpressionType pointer, ExpressionType value, uint32_t offset);
    318     ExpressionType emitAtomicBinaryRMWOp(ExtAtomicOpType, Type, ExpressionType pointer, ExpressionType value, uint32_t offset);
    319     ExpressionType emitAtomicCompareExchange(ExtAtomicOpType, Type, ExpressionType pointer, ExpressionType expected, ExpressionType value, uint32_t offset);
    320 
    321     void unify(const ExpressionType phi, const ExpressionType source);
    322     void unifyValuesWithBlock(const Stack& resultStack, const ResultList& stack);
    323 
    324     void emitChecksForModOrDiv(B3::Opcode, ExpressionType left, ExpressionType right);
    325 
    326     int32_t WARN_UNUSED_RETURN fixupPointerPlusOffset(ExpressionType&, uint32_t);
    327     ExpressionType WARN_UNUSED_RETURN fixupPointerPlusOffsetForAtomicOps(ExtAtomicOpType, ExpressionType, uint32_t);
     444    Value* emitLoadOp(LoadOpType, Value* pointer, uint32_t offset);
     445    void emitStoreOp(StoreOpType, Value* pointer, Value*, uint32_t offset);
     446
     447    Value* sanitizeAtomicResult(ExtAtomicOpType, Type, Value* result);
     448    Value* emitAtomicLoadOp(ExtAtomicOpType, Type, Value* pointer, uint32_t offset);
     449    void emitAtomicStoreOp(ExtAtomicOpType, Type, Value* pointer, Value*, uint32_t offset);
     450    Value* emitAtomicBinaryRMWOp(ExtAtomicOpType, Type, Value* pointer, Value*, uint32_t offset);
     451    Value* emitAtomicCompareExchange(ExtAtomicOpType, Type, Value* pointer, Value* expected, Value*, uint32_t offset);
     452
     453    void unify(Value* phi, const ExpressionType source);
     454    void unifyValuesWithBlock(const Stack& resultStack, const ControlData& block);
     455
     456    void emitChecksForModOrDiv(B3::Opcode, Value* left, Value* right);
     457
     458    int32_t WARN_UNUSED_RETURN fixupPointerPlusOffset(Value*&, uint32_t);
     459    Value* WARN_UNUSED_RETURN fixupPointerPlusOffsetForAtomicOps(ExtAtomicOpType, Value*, uint32_t);
    328460
    329461    void restoreWasmContextInstance(Procedure&, BasicBlock*, Value*);
    330462    enum class RestoreCachedStackLimit { No, Yes };
    331     void restoreWebAssemblyGlobalState(RestoreCachedStackLimit, const MemoryInformation&, Value* instance, Procedure&, BasicBlock*);
     463    void restoreWebAssemblyGlobalState(RestoreCachedStackLimit, const MemoryInformation&, Value* instance, Procedure&, BasicBlock*, bool restoreInstance = true);
     464
     465    Value* loadFromScratchBuffer(unsigned& indexInBuffer, Value* pointer, B3::Type);
     466    void connectControlEntry(unsigned& indexInBuffer, Value* pointer, ControlData&, Stack& expressionStack, ControlData& currentData, bool fillLoopPhis = false);
     467    Value* emitCatchImpl(CatchKind, ControlType&, unsigned exceptionIndex = 0);
     468    PatchpointExceptionHandle preparePatchpointForExceptions(BasicBlock*, PatchpointValue*);
    332469
    333470    Origin origin();
     
    338475            return UINT32_MAX;
    339476        return m_outerLoops.last();
     477    }
     478
     479    ExpressionType push(Type type)
     480    {
     481        return push(toB3Type(type));
     482    }
     483
     484    ExpressionType push(B3::Type type)
     485    {
     486        ++m_stackSize;
     487        if (m_stackSize > m_maxStackSize) {
     488            m_maxStackSize = m_stackSize;
     489            Variable* var = m_proc.addVariable(type);
     490            m_stack.append(var);
     491            return var;
     492        }
     493
     494        Variable* var = m_stack[m_stackSize - 1];
     495        if (var->type() == type)
     496            return var;
     497
     498        var = m_proc.addVariable(type);
     499        m_stack[m_stackSize - 1] = var;
     500        return var;
     501    }
     502
     503    ExpressionType push(Value* value)
     504    {
     505        Variable* var = push(value->type());
     506        set(var, value);
     507        return var;
     508    }
     509
     510    Value* get(BasicBlock* block, Variable* variable)
     511    {
     512        return block->appendNew<VariableValue>(m_proc, B3::Get, origin(), variable);
     513    }
     514
     515    Value* get(Variable* variable)
     516    {
     517        return get(m_currentBlock, variable);
     518    }
     519
     520    Value* set(BasicBlock* block, Variable* dst, Value* src)
     521    {
     522        return block->appendNew<VariableValue>(m_proc, B3::Set, origin(), dst, src);
     523    }
     524
     525    Value* set(Variable* dst, Value* src)
     526    {
     527        return set(m_currentBlock, dst, src);
     528    }
     529
     530    Value* set(Variable* dst, Variable* src)
     531    {
     532        return set(dst, get(src));
    340533    }
    341534
     
    349542
    350543    Procedure& m_proc;
    351     BasicBlock* m_rootBlock { nullptr };
     544    Vector<BasicBlock*> m_rootBlocks;
     545    BasicBlock* m_topLevelBlock;
    352546    BasicBlock* m_currentBlock { nullptr };
    353547    Vector<uint32_t> m_outerLoops;
    354548    Vector<Variable*> m_locals;
     549    Vector<Variable*> m_stack;
    355550    Vector<UnlinkedWasmToWasmCall>& m_unlinkedWasmToWasmCalls; // List each call site and the function index whose address it should be patched with.
    356551    unsigned& m_osrEntryScratchBufferSize;
     
    366561    Value* m_instanceValue { nullptr }; // Always use the accessor below to ensure the instance value is materialized when used.
    367562    bool m_usesInstanceValue { false };
     563    bool m_hasCatch { false };
    368564    Value* instanceValue()
    369565    {
     
    374570    uint32_t m_maxNumJSCallArguments { 0 };
    375571    unsigned m_numImportFunctions;
     572
     573    Checked<unsigned> m_tryDepth { 0 };
     574    Checked<unsigned> m_callSiteIndex { 0 };
     575    Checked<unsigned> m_stackSize { 0 };
     576    Checked<unsigned> m_maxStackSize { 0 };
     577    StackMaps m_stackmaps;
     578    Vector<UnlinkedHandlerInfo> m_exceptionHandlers;
    376579};
    377580
     581void PatchpointExceptionHandle::generate(CCallHelpers& jit, const B3::StackmapGenerationParams& params, B3IRGenerator* generator) const
     582{
     583    if (m_callSiteIndex == s_invalidCallSiteIndex)
     584        return;
     585
     586    StackMap values;
     587    for (unsigned i = m_offset; i < params.value()->numChildren(); ++i)
     588        values.constructAndAppend(params[i], params.value()->child(i)->type());
     589    generator->addStackMap(m_callSiteIndex, WTFMove(values));
     590    jit.store32(CCallHelpers::TrustedImm32(m_callSiteIndex), CCallHelpers::tagFor(CallFrameSlot::argumentCountIncludingThis));
     591}
     592
    378593// Memory accesses in WebAssembly have unsigned 32-bit offsets, whereas they have signed 32-bit offsets in B3.
    379 int32_t B3IRGenerator::fixupPointerPlusOffset(ExpressionType& ptr, uint32_t offset)
     594int32_t B3IRGenerator::fixupPointerPlusOffset(Value*& ptr, uint32_t offset)
    380595{
    381596    if (static_cast<uint64_t>(offset) > static_cast<uint64_t>(std::numeric_limits<int32_t>::max())) {
     
    429644    , m_numImportFunctions(info.importFunctionCount())
    430645{
    431     m_rootBlock = m_proc.addBlock();
    432     m_currentBlock = m_rootBlock;
     646    m_topLevelBlock = m_proc.addBlock();
     647    m_rootBlocks.append(m_proc.addBlock());
     648    m_currentBlock = m_rootBlocks[0];
    433649
    434650    // FIXME we don't really need to pin registers here if there's no memory. It makes wasm -> wasm thunks simpler for now. https://bugs.webkit.org/show_bug.cgi?id=166623
     
    460676            this->emitExceptionCheck(jit, ExceptionType::OutOfBoundsMemoryAccess);
    461677        });
     678    }
     679
     680    {
     681        B3::PatchpointValue* getInstance = m_topLevelBlock->appendNew<B3::PatchpointValue>(m_proc, pointerType(), Origin());
     682        if (Context::useFastTLS())
     683            getInstance->clobber(RegisterSet::macroScratchRegisters());
     684        else {
     685            // FIXME: Because WasmToWasm call clobbers wasmContextInstance register and does not restore it, we need to restore it in the caller side.
     686            // This prevents us from using ArgumentReg to this (logically) immutable pinned register.
     687            getInstance->effects.writesPinned = false;
     688            getInstance->effects.readsPinned = true;
     689            getInstance->resultConstraints = { ValueRep::reg(m_wasmContextInstanceGPR) };
     690        }
     691        getInstance->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
     692            if (Context::useFastTLS()) {
     693                AllowMacroScratchRegisterUsageIf allowScratch(jit, CCallHelpers::loadWasmContextInstanceNeedsMacroScratchRegister());
     694                jit.loadWasmContextInstance(params[0].gpr());
     695            }
     696        });
     697        m_instanceValue = getInstance;
    462698    }
    463699
     
    495731
    496732    {
    497         B3::PatchpointValue* stackOverflowCheck = m_currentBlock->appendNew<B3::PatchpointValue>(m_proc, pointerType(), Origin());
    498         m_instanceValue = stackOverflowCheck;
     733        B3::PatchpointValue* stackOverflowCheck = m_currentBlock->appendNew<B3::PatchpointValue>(m_proc, Void, Origin());
     734        stackOverflowCheck->appendSomeRegister(instanceValue());
    499735        stackOverflowCheck->appendSomeRegister(framePointer());
    500736        stackOverflowCheck->clobber(RegisterSet::macroScratchRegisters());
    501         if (!Context::useFastTLS()) {
    502             // FIXME: Because WasmToWasm call clobbers wasmContextInstance register and does not restore it, we need to restore it in the caller side.
    503             // This prevents us from using ArgumentReg to this (logically) immutable pinned register.
    504             stackOverflowCheck->effects.writesPinned = false;
    505             stackOverflowCheck->effects.readsPinned = true;
    506             stackOverflowCheck->resultConstraints = { ValueRep::reg(m_wasmContextInstanceGPR) };
    507         }
    508737        stackOverflowCheck->numGPScratchRegisters = 2;
    509738        stackOverflowCheck->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
     
    527756            bool needsOverflowCheck = m_makesCalls || wasmFrameSize >= static_cast<int32_t>(minimumParentCheckSize) || needUnderflowCheck;
    528757
    529             GPRReg contextInstance = Context::useFastTLS() ? params[0].gpr() : m_wasmContextInstanceGPR;
    530 
    531758            // This allows leaf functions to not do stack checks if their frame size is within
    532759            // certain limits since their caller would have already done the check.
    533760            if (needsOverflowCheck) {
    534761                AllowMacroScratchRegisterUsage allowScratch(jit);
     762                GPRReg contextInstance = params[0].gpr();
    535763                GPRReg fp = params[1].gpr();
    536764                GPRReg scratch1 = params.gpScratch(0);
    537765                GPRReg scratch2 = params.gpScratch(1);
    538 
    539                 if (Context::useFastTLS())
    540                     jit.loadWasmContextInstance(contextInstance);
    541766
    542767                jit.loadPtr(CCallHelpers::Address(contextInstance, Instance::offsetOfCachedStackLimit()), scratch2);
     
    549774                    linkBuffer.link(overflow, CodeLocationLabel<JITThunkPtrTag>(Thunks::singleton().stub(throwStackOverflowFromWasmThunkGenerator).code()));
    550775                });
    551             } else if (m_usesInstanceValue && Context::useFastTLS()) {
    552                 // No overflow check is needed, but the instance values still needs to be correct.
    553                 AllowMacroScratchRegisterUsageIf allowScratch(jit, CCallHelpers::loadWasmContextInstanceNeedsMacroScratchRegister());
    554                 jit.loadWasmContextInstance(contextInstance);
    555             } else {
    556                 // We said we'd return a pointer. We don't actually need to because it isn't used, but the patchpoint conservatively said it had effects (potential stack check) which prevent it from getting removed.
    557776            }
    558777        });
     
    565784}
    566785
    567 void B3IRGenerator::restoreWebAssemblyGlobalState(RestoreCachedStackLimit restoreCachedStackLimit, const MemoryInformation& memory, Value* instance, Procedure& proc, BasicBlock* block)
    568 {
    569     restoreWasmContextInstance(proc, block, instance);
     786void B3IRGenerator::restoreWebAssemblyGlobalState(RestoreCachedStackLimit restoreCachedStackLimit, const MemoryInformation& memory, Value* instance, Procedure& proc, BasicBlock* block, bool restoreInstance)
     787{
     788    if (restoreInstance)
     789        restoreWasmContextInstance(proc, block, instance);
    570790
    571791    if (restoreCachedStackLimit == RestoreCachedStackLimit::Yes) {
     
    635855}
    636856
     857static void buildEntryBufferForCatch(Probe::Context& context)
     858{
     859    CallFrame* callFrame = context.fp<CallFrame*>();
     860    CallSiteIndex callSiteIndex = callFrame->callSiteIndex();
     861    OptimizingJITCallee* callee = bitwise_cast<OptimizingJITCallee*>(callFrame->callee().asWasmCallee());
     862    const StackMap& stackmap = callee->stackmap(callSiteIndex);
     863    VM* vm = context.gpr<VM*>(GPRInfo::regT0);
     864    uint64_t* buffer = vm->wasmContext.scratchBufferForSize(stackmap.size() * 8);
     865    loadValuesIntoBuffer(context, stackmap, buffer);
     866
     867    context.gpr(GPRInfo::argumentGPR0) = bitwise_cast<uintptr_t>(buffer);
     868}
     869
     870void B3IRGenerator::insertEntrySwitch()
     871{
     872    m_proc.setNumEntrypoints(m_rootBlocks.size());
     873
     874    Ref<B3::Air::PrologueGenerator> catchPrologueGenerator = createSharedTask<B3::Air::PrologueGeneratorFunction>([] (CCallHelpers& jit, B3::Air::Code& code) {
     875        AllowMacroScratchRegisterUsage allowScratch(jit);
     876
     877        jit.emitGetFromCallFrameHeaderPtr(CallFrameSlot::callee, GPRInfo::regT0);
     878        {
     879            // FIXME: Handling precise allocations in WasmB3IRGenerator catch entrypoints might be unnecessary
     880            // https://bugs.webkit.org/show_bug.cgi?id=231213
     881            auto preciseAllocationCase = jit.branchTestPtr(CCallHelpers::NonZero, GPRInfo::regT0, CCallHelpers::TrustedImm32(PreciseAllocation::halfAlignment));
     882            jit.andPtr(CCallHelpers::TrustedImmPtr(MarkedBlock::blockMask), GPRInfo::regT0);
     883            jit.loadPtr(CCallHelpers::Address(GPRInfo::regT0, MarkedBlock::offsetOfFooter + MarkedBlock::Footer::offsetOfVM()), GPRInfo::regT0);
     884            auto loadedCase = jit.jump();
     885
     886            preciseAllocationCase.link(&jit);
     887            jit.loadPtr(CCallHelpers::Address(GPRInfo::regT0, PreciseAllocation::offsetOfWeakSet() + WeakSet::offsetOfVM() - PreciseAllocation::headerSize()), GPRInfo::regT0);
     888
     889            loadedCase.link(&jit);
     890        }
     891        jit.restoreCalleeSavesFromVMEntryFrameCalleeSavesBuffer(GPRInfo::regT0, GPRInfo::regT3);
     892
     893        jit.loadPtr(CCallHelpers::Address(GPRInfo::regT0, VM::calleeForWasmCatchOffset()), GPRInfo::regT3);
     894        jit.storePtr(CCallHelpers::TrustedImmPtr(nullptr), CCallHelpers::Address(GPRInfo::regT0, VM::calleeForWasmCatchOffset()));
     895        jit.emitPutToCallFrameHeader(GPRInfo::regT3, CallFrameSlot::callee);
     896
     897        jit.load64(CCallHelpers::Address(GPRInfo::regT0, VM::callFrameForCatchOffset()), GPRInfo::callFrameRegister);
     898        jit.storePtr(CCallHelpers::TrustedImmPtr(nullptr), CCallHelpers::Address(GPRInfo::regT0, VM::callFrameForCatchOffset()));
     899
     900        jit.loadPtr(CCallHelpers::Address(GPRInfo::callFrameRegister, CallFrameSlot::thisArgument * sizeof(Register)), GPRInfo::regT3);
     901        jit.loadPtr(CCallHelpers::Address(GPRInfo::regT3, JSWebAssemblyInstance::offsetOfInstance()), GPRInfo::regT3);
     902        jit.storeWasmContextInstance(GPRInfo::regT3);
     903
     904        jit.probe(tagCFunction<JITProbePtrTag>(buildEntryBufferForCatch), nullptr);
     905
     906        jit.addPtr(CCallHelpers::TrustedImm32(-code.frameSize()), GPRInfo::callFrameRegister, CCallHelpers::stackPointerRegister);
     907    });
     908
     909    for (unsigned i = 1; i < m_rootBlocks.size(); ++i)
     910        m_proc.code().setPrologueForEntrypoint(i, catchPrologueGenerator.copyRef());
     911
     912    m_currentBlock = m_topLevelBlock;
     913    m_currentBlock->appendNew<Value>(m_proc, EntrySwitch, Origin());
     914    for (BasicBlock* block : m_rootBlocks)
     915        m_currentBlock->appendSuccessor(FrequentedBlock(block));
     916}
     917
    637918void B3IRGenerator::insertConstants()
    638919{
    639920    m_constantInsertionValues.execute(m_proc.at(0));
     921
     922    if (!m_hasCatch)
     923        return;
     924
     925    Value* jsInstance = m_proc.add<MemoryValue>(Load, pointerType(), Origin(), instanceValue(), safeCast<int32_t>(Instance::offsetOfOwner()));
     926    Value* store = m_proc.add<B3::MemoryValue>(B3::Store, Origin(), jsInstance, framePointer(), safeCast<int32_t>(CallFrameSlot::thisArgument * sizeof(Register)));
     927
     928    BasicBlock* block = m_rootBlocks[0];
     929    m_constantInsertionValues.insertValue(0, jsInstance);
     930    m_constantInsertionValues.insertValue(0, store);
     931    m_constantInsertionValues.execute(block);
    640932}
    641933
     
    706998auto B3IRGenerator::addRefIsNull(ExpressionType value, ExpressionType& result) -> PartialResult
    707999{
    708     result = m_currentBlock->appendNew<Value>(m_proc, B3::Equal, origin(), value, m_currentBlock->appendNew<Const64Value>(m_proc, origin(), JSValue::encode(jsNull())));
     1000    result = push(m_currentBlock->appendNew<Value>(m_proc, B3::Equal, origin(), get(value), m_currentBlock->appendNew<Const64Value>(m_proc, origin(), JSValue::encode(jsNull()))));
    7091001    return { };
    7101002}
     
    7131005{
    7141006    // FIXME: Emit this inline <https://bugs.webkit.org/show_bug.cgi?id=198506>.
    715     result = m_currentBlock->appendNew<CCallValue>(m_proc, toB3Type(Types::Externref), origin(),
     1007    Value* resultValue = m_currentBlock->appendNew<CCallValue>(m_proc, toB3Type(Types::Externref), origin(),
    7161008        m_currentBlock->appendNew<ConstPtrValue>(m_proc, origin(), tagCFunction<OperationPtrTag>(operationGetWasmTableElement)),
    717         instanceValue(), m_currentBlock->appendNew<Const32Value>(m_proc, origin(), tableIndex), index);
     1009        instanceValue(), m_currentBlock->appendNew<Const32Value>(m_proc, origin(), tableIndex), get(index));
    7181010
    7191011    {
     1012        result = push(resultValue);
    7201013        CheckValue* check = m_currentBlock->appendNew<CheckValue>(m_proc, Check, origin(),
    721             m_currentBlock->appendNew<Value>(m_proc, Equal, origin(), result, m_currentBlock->appendNew<Const64Value>(m_proc, origin(), 0)));
     1014            m_currentBlock->appendNew<Value>(m_proc, Equal, origin(), resultValue, m_currentBlock->appendNew<Const64Value>(m_proc, origin(), 0)));
    7221015
    7231016        check->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
     
    7341027    auto shouldThrow = m_currentBlock->appendNew<CCallValue>(m_proc, B3::Int32, origin(),
    7351028        m_currentBlock->appendNew<ConstPtrValue>(m_proc, origin(), tagCFunction<OperationPtrTag>(operationSetWasmTableElement)),
    736         instanceValue(), m_currentBlock->appendNew<Const32Value>(m_proc, origin(), tableIndex), index, value);
     1029        instanceValue(), m_currentBlock->appendNew<Const32Value>(m_proc, origin(), tableIndex), get(index), get(value));
    7371030
    7381031    {
     
    7521045    // FIXME: Emit this inline <https://bugs.webkit.org/show_bug.cgi?id=198506>.
    7531046
    754     result = m_currentBlock->appendNew<CCallValue>(m_proc, B3::Int64, origin(),
     1047    result = push(m_currentBlock->appendNew<CCallValue>(m_proc, B3::Int64, origin(),
    7551048        m_currentBlock->appendNew<ConstPtrValue>(m_proc, origin(), tagCFunction<OperationPtrTag>(operationWasmRefFunc)),
    756         instanceValue(), addConstant(Types::I32, index));
     1049        instanceValue(), constant(toB3Type(Types::I32), index)));
    7571050
    7581051    return { };
     
    7611054auto B3IRGenerator::addTableInit(unsigned elementIndex, unsigned tableIndex, ExpressionType dstOffset, ExpressionType srcOffset, ExpressionType length) -> PartialResult
    7621055{
    763     auto result = m_currentBlock->appendNew<CCallValue>(
     1056    Value* resultValue = m_currentBlock->appendNew<CCallValue>(
    7641057        m_proc, toB3Type(Types::I32), origin(),
    7651058        m_currentBlock->appendNew<ConstPtrValue>(m_proc, origin(), tagCFunction<OperationPtrTag>(operationWasmTableInit)),
     
    7671060        m_currentBlock->appendNew<Const32Value>(m_proc, origin(), elementIndex),
    7681061        m_currentBlock->appendNew<Const32Value>(m_proc, origin(), tableIndex),
    769         dstOffset, srcOffset, length);
     1062        get(dstOffset), get(srcOffset), get(length));
    7701063
    7711064    {
    7721065        CheckValue* check = m_currentBlock->appendNew<CheckValue>(m_proc, Check, origin(),
    773             m_currentBlock->appendNew<Value>(m_proc, Equal, origin(), result, m_currentBlock->appendNew<Const32Value>(m_proc, origin(), 0)));
     1066            m_currentBlock->appendNew<Value>(m_proc, Equal, origin(), resultValue, m_currentBlock->appendNew<Const32Value>(m_proc, origin(), 0)));
    7741067
    7751068        check->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
     
    7951088{
    7961089    // FIXME: Emit this inline <https://bugs.webkit.org/show_bug.cgi?id=198506>.
    797     result = m_currentBlock->appendNew<CCallValue>(m_proc, toB3Type(Types::I32), origin(),
     1090    result = push(m_currentBlock->appendNew<CCallValue>(m_proc, toB3Type(Types::I32), origin(),
    7981091        m_currentBlock->appendNew<ConstPtrValue>(m_proc, origin(), tagCFunction<OperationPtrTag>(operationGetWasmTableSize)),
    799         instanceValue(), m_currentBlock->appendNew<Const32Value>(m_proc, origin(), tableIndex));
     1092        instanceValue(), m_currentBlock->appendNew<Const32Value>(m_proc, origin(), tableIndex)));
    8001093
    8011094    return { };
     
    8041097auto B3IRGenerator::addTableGrow(unsigned tableIndex, ExpressionType fill, ExpressionType delta, ExpressionType& result) -> PartialResult
    8051098{
    806     result = m_currentBlock->appendNew<CCallValue>(m_proc, toB3Type(Types::I32), origin(),
     1099    result = push(m_currentBlock->appendNew<CCallValue>(m_proc, toB3Type(Types::I32), origin(),
    8071100        m_currentBlock->appendNew<ConstPtrValue>(m_proc, origin(), tagCFunction<OperationPtrTag>(operationWasmTableGrow)),
    808         instanceValue(), m_currentBlock->appendNew<Const32Value>(m_proc, origin(), tableIndex), fill, delta);
     1101        instanceValue(), m_currentBlock->appendNew<Const32Value>(m_proc, origin(), tableIndex), get(fill), get(delta)));
    8091102
    8101103    return { };
     
    8131106auto B3IRGenerator::addTableFill(unsigned tableIndex, ExpressionType offset, ExpressionType fill, ExpressionType count) -> PartialResult
    8141107{
    815     auto result = m_currentBlock->appendNew<CCallValue>(m_proc, toB3Type(Types::I32), origin(),
     1108    Value* resultValue = m_currentBlock->appendNew<CCallValue>(m_proc, toB3Type(Types::I32), origin(),
    8161109        m_currentBlock->appendNew<ConstPtrValue>(m_proc, origin(), tagCFunction<OperationPtrTag>(operationWasmTableFill)),
    817         instanceValue(), m_currentBlock->appendNew<Const32Value>(m_proc, origin(), tableIndex), offset, fill, count);
     1110        instanceValue(), m_currentBlock->appendNew<Const32Value>(m_proc, origin(), tableIndex), get(offset), get(fill), get(count));
    8181111
    8191112    {
    8201113        CheckValue* check = m_currentBlock->appendNew<CheckValue>(m_proc, Check, origin(),
    821             m_currentBlock->appendNew<Value>(m_proc, Equal, origin(), result, m_currentBlock->appendNew<Const32Value>(m_proc, origin(), 0)));
     1114            m_currentBlock->appendNew<Value>(m_proc, Equal, origin(), resultValue, m_currentBlock->appendNew<Const32Value>(m_proc, origin(), 0)));
    8221115
    8231116        check->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
     
    8311124auto B3IRGenerator::addTableCopy(unsigned dstTableIndex, unsigned srcTableIndex, ExpressionType dstOffset, ExpressionType srcOffset, ExpressionType length) -> PartialResult
    8321125{
    833     auto result = m_currentBlock->appendNew<CCallValue>(
     1126    Value* resultValue = m_currentBlock->appendNew<CCallValue>(
    8341127        m_proc, toB3Type(Types::I32), origin(),
    8351128        m_currentBlock->appendNew<ConstPtrValue>(m_proc, origin(), tagCFunction<OperationPtrTag>(operationWasmTableCopy)),
     
    8371130        m_currentBlock->appendNew<Const32Value>(m_proc, origin(), dstTableIndex),
    8381131        m_currentBlock->appendNew<Const32Value>(m_proc, origin(), srcTableIndex),
    839         dstOffset, srcOffset, length);
     1132        get(dstOffset), get(srcOffset), get(length));
    8401133
    8411134    {
    8421135        CheckValue* check = m_currentBlock->appendNew<CheckValue>(m_proc, Check, origin(),
    843             m_currentBlock->appendNew<Value>(m_proc, Equal, origin(), result, m_currentBlock->appendNew<Const32Value>(m_proc, origin(), 0)));
     1136            m_currentBlock->appendNew<Value>(m_proc, Equal, origin(), resultValue, m_currentBlock->appendNew<Const32Value>(m_proc, origin(), 0)));
    8441137
    8451138        check->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
     
    8541147{
    8551148    ASSERT(m_locals[index]);
    856     result = m_currentBlock->appendNew<VariableValue>(m_proc, B3::Get, origin(), m_locals[index]);
     1149    result = push(m_currentBlock->appendNew<VariableValue>(m_proc, B3::Get, origin(), m_locals[index]));
    8571150    return { };
    8581151}
     
    8681161}
    8691162
    870 auto B3IRGenerator::emitIndirectCall(Value* calleeInstance, ExpressionType calleeCode, const Signature& signature, Vector<ExpressionType>& args, ResultList& results) -> PartialResult
     1163auto B3IRGenerator::emitIndirectCall(Value* calleeInstance, Value* calleeCode, const Signature& signature, Vector<ExpressionType>& args, ResultList& results) -> PartialResult
    8711164{
    8721165    // Do a context switch if needed.
     
    9171210
    9181211    B3::Type returnType = toB3ResultType(&signature);
    919     ExpressionType callResult = createCallPatchpoint(m_currentBlock, origin(), signature, args,
     1212    Value* callResult = createCallPatchpoint(m_currentBlock, origin(), signature, args,
    9201213        scopedLambdaRef<void(PatchpointValue*)>([=] (PatchpointValue* patchpoint) -> void {
    9211214            patchpoint->effects.writesPinned = true;
     
    9291222
    9301223            patchpoint->append(calleeCode, ValueRep::SomeRegister);
     1224            PatchpointExceptionHandle handle = preparePatchpointForExceptions(m_currentBlock, patchpoint);
    9311225            patchpoint->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
    9321226                AllowMacroScratchRegisterUsage allowScratch(jit);
     1227                handle.generate(jit, params, this);
    9331228                jit.call(params[params.proc().resultCount(returnType)].gpr(), WasmEntryPtrTag);
    9341229            });
     
    9421237        const Vector<B3::Type>& tuple = m_proc.tupleForType(returnType);
    9431238        for (unsigned i = 0; i < signature.returnCount(); ++i)
    944             results.append(m_currentBlock->appendNew<ExtractValue>(m_proc, origin(), tuple[i], callResult, i));
     1239            results.append(push(m_currentBlock->appendNew<ExtractValue>(m_proc, origin(), tuple[i], callResult, i)));
    9451240        break;
    9461241    }
    9471242    default: {
    948         results.append(callResult);
     1243        results.append(push(callResult));
    9491244        break;
    9501245    }
     
    9591254auto B3IRGenerator::addGrowMemory(ExpressionType delta, ExpressionType& result) -> PartialResult
    9601255{
    961     result = m_currentBlock->appendNew<CCallValue>(m_proc, Int32, origin(),
     1256    result = push(m_currentBlock->appendNew<CCallValue>(m_proc, Int32, origin(),
    9621257        m_currentBlock->appendNew<ConstPtrValue>(m_proc, origin(), tagCFunction<OperationPtrTag>(operationGrowMemory)),
    963         framePointer(), instanceValue(), delta);
     1258        framePointer(), instanceValue(), get(delta)));
    9641259
    9651260    restoreWebAssemblyGlobalState(RestoreCachedStackLimit::No, m_info.memory, instanceValue(), m_proc, m_currentBlock);
     
    9811276        size, m_currentBlock->appendNew<Const32Value>(m_proc, origin(), shiftValue));
    9821277
    983     result = m_currentBlock->appendNew<Value>(m_proc, Trunc, origin(), numPages);
     1278    result = push(m_currentBlock->appendNew<Value>(m_proc, Trunc, origin(), numPages));
    9841279
    9851280    return { };
     
    9881283auto B3IRGenerator::addMemoryFill(ExpressionType dstAddress, ExpressionType targetValue, ExpressionType count) -> PartialResult
    9891284{
    990     auto result = m_currentBlock->appendNew<CCallValue>(
     1285    Value* resultValue = m_currentBlock->appendNew<CCallValue>(
    9911286        m_proc, toB3Type(Types::I32), origin(),
    9921287        m_currentBlock->appendNew<ConstPtrValue>(m_proc, origin(), tagCFunction<OperationPtrTag>(operationWasmMemoryFill)),
    9931288        instanceValue(),
    994         dstAddress, targetValue, count);
     1289        get(dstAddress), get(targetValue), get(count));
    9951290
    9961291    {
    9971292        CheckValue* check = m_currentBlock->appendNew<CheckValue>(m_proc, Check, origin(),
    998             m_currentBlock->appendNew<Value>(m_proc, Equal, origin(), result, m_currentBlock->appendNew<Const32Value>(m_proc, origin(), 0)));
     1293            m_currentBlock->appendNew<Value>(m_proc, Equal, origin(), resultValue, m_currentBlock->appendNew<Const32Value>(m_proc, origin(), 0)));
    9991294
    10001295        check->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
     
    10081303auto B3IRGenerator::addMemoryInit(unsigned dataSegmentIndex, ExpressionType dstAddress, ExpressionType srcAddress, ExpressionType length) -> PartialResult
    10091304{
    1010     auto result = m_currentBlock->appendNew<CCallValue>(
     1305    Value* resultValue = m_currentBlock->appendNew<CCallValue>(
    10111306        m_proc, toB3Type(Types::I32), origin(),
    10121307        m_currentBlock->appendNew<ConstPtrValue>(m_proc, origin(), tagCFunction<OperationPtrTag>(operationWasmMemoryInit)),
    10131308        instanceValue(),
    10141309        m_currentBlock->appendNew<Const32Value>(m_proc, origin(), dataSegmentIndex),
    1015         dstAddress, srcAddress, length);
     1310        get(dstAddress), get(srcAddress), get(length));
    10161311
    10171312    {
    10181313        CheckValue* check = m_currentBlock->appendNew<CheckValue>(m_proc, Check, origin(),
    1019             m_currentBlock->appendNew<Value>(m_proc, Equal, origin(), result, m_currentBlock->appendNew<Const32Value>(m_proc, origin(), 0)));
     1314            m_currentBlock->appendNew<Value>(m_proc, Equal, origin(), resultValue, m_currentBlock->appendNew<Const32Value>(m_proc, origin(), 0)));
    10201315
    10211316        check->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
     
    10291324auto B3IRGenerator::addMemoryCopy(ExpressionType dstAddress, ExpressionType srcAddress, ExpressionType count) -> PartialResult
    10301325{
    1031     auto result = m_currentBlock->appendNew<CCallValue>(
     1326    Value* resultValue = m_currentBlock->appendNew<CCallValue>(
    10321327        m_proc, toB3Type(Types::I32), origin(),
    10331328        m_currentBlock->appendNew<ConstPtrValue>(m_proc, origin(), tagCFunction<OperationPtrTag>(operationWasmMemoryCopy)),
    10341329        instanceValue(),
    1035         dstAddress, srcAddress, count);
     1330        get(dstAddress), get(srcAddress), get(count));
    10361331
    10371332    {
    10381333        CheckValue* check = m_currentBlock->appendNew<CheckValue>(m_proc, Check, origin(),
    1039             m_currentBlock->appendNew<Value>(m_proc, Equal, origin(), result, m_currentBlock->appendNew<Const32Value>(m_proc, origin(), 0)));
     1334            m_currentBlock->appendNew<Value>(m_proc, Equal, origin(), resultValue, m_currentBlock->appendNew<Const32Value>(m_proc, origin(), 0)));
    10401335
    10411336        check->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
     
    10611356{
    10621357    ASSERT(m_locals[index]);
    1063     m_currentBlock->appendNew<VariableValue>(m_proc, B3::Set, origin(), m_locals[index], value);
     1358    m_currentBlock->appendNew<VariableValue>(m_proc, B3::Set, origin(), m_locals[index], get(value));
    10641359    return { };
    10651360}
     
    10711366    switch (global.bindingMode) {
    10721367    case Wasm::GlobalInformation::BindingMode::EmbeddedInInstance:
    1073         result = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, toB3Type(global.type), origin(), globalsArray, safeCast<int32_t>(index * sizeof(Register)));
     1368        result = push(m_currentBlock->appendNew<MemoryValue>(m_proc, Load, toB3Type(global.type), origin(), globalsArray, safeCast<int32_t>(index * sizeof(Register))));
    10741369        break;
    10751370    case Wasm::GlobalInformation::BindingMode::Portable: {
    10761371        ASSERT(global.mutability == Wasm::GlobalInformation::Mutability::Mutable);
    10771372        Value* pointer = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, B3::Int64, origin(), globalsArray, safeCast<int32_t>(index * sizeof(Register)));
    1078         result = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, toB3Type(global.type), origin(), pointer);
     1373        result = push(m_currentBlock->appendNew<MemoryValue>(m_proc, Load, toB3Type(global.type), origin(), pointer));
    10791374        break;
    10801375    }
     
    10901385    switch (global.bindingMode) {
    10911386    case Wasm::GlobalInformation::BindingMode::EmbeddedInInstance:
    1092         m_currentBlock->appendNew<MemoryValue>(m_proc, Store, origin(), value, globalsArray, safeCast<int32_t>(index * sizeof(Register)));
     1387        m_currentBlock->appendNew<MemoryValue>(m_proc, Store, origin(), get(value), globalsArray, safeCast<int32_t>(index * sizeof(Register)));
    10931388        if (isRefType(global.type))
    10941389            emitWriteBarrierForJSWrapper();
     
    10971392        ASSERT(global.mutability == Wasm::GlobalInformation::Mutability::Mutable);
    10981393        Value* pointer = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, B3::Int64, origin(), globalsArray, safeCast<int32_t>(index * sizeof(Register)));
    1099         m_currentBlock->appendNew<MemoryValue>(m_proc, Store, origin(), value, pointer);
     1394        m_currentBlock->appendNew<MemoryValue>(m_proc, Store, origin(), get(value), pointer);
    11001395        // We emit a write-barrier onto JSWebAssemblyGlobal, not JSWebAssemblyInstance.
    11011396        if (isRefType(global.type)) {
     
    12001495}
    12011496
    1202 inline Value* B3IRGenerator::emitCheckAndPreparePointer(ExpressionType pointer, uint32_t offset, uint32_t sizeOfOperation)
     1497inline Value* B3IRGenerator::emitCheckAndPreparePointer(Value* pointer, uint32_t offset, uint32_t sizeOfOperation)
    12031498{
    12041499    ASSERT(m_memoryBaseGPR);
     
    12691564}
    12701565
    1271 inline Value* B3IRGenerator::emitLoadOp(LoadOpType op, ExpressionType pointer, uint32_t uoffset)
     1566inline Value* B3IRGenerator::emitLoadOp(LoadOpType op, Value* pointer, uint32_t uoffset)
    12721567{
    12731568    int32_t offset = fixupPointerPlusOffset(pointer, uoffset);
     
    13391634}
    13401635
    1341 auto B3IRGenerator::load(LoadOpType op, ExpressionType pointer, ExpressionType& result, uint32_t offset) -> PartialResult
    1342 {
     1636auto B3IRGenerator::load(LoadOpType op, ExpressionType pointerVar, ExpressionType& result, uint32_t offset) -> PartialResult
     1637{
     1638    Value* pointer = get(pointerVar);
    13431639    ASSERT(pointer->type() == Int32);
    13441640
     
    13571653        case LoadOpType::I32Load16U:
    13581654        case LoadOpType::I32Load8U:
    1359             result = constant(Int32, 0);
     1655            result = push(constant(Int32, 0));
    13601656            break;
    13611657        case LoadOpType::I64Load8S:
     
    13661662        case LoadOpType::I64Load:
    13671663        case LoadOpType::I64Load16U:
    1368             result = constant(Int64, 0);
     1664            result = push(constant(Int64, 0));
    13691665            break;
    13701666        case LoadOpType::F32Load:
    1371             result = constant(Float, 0);
     1667            result = push(constant(Float, 0));
    13721668            break;
    13731669        case LoadOpType::F64Load:
    1374             result = constant(Double, 0);
     1670            result = push(constant(Double, 0));
    13751671            break;
    13761672        }
    13771673
    13781674    } else
    1379         result = emitLoadOp(op, emitCheckAndPreparePointer(pointer, offset, sizeOfLoadOp(op)), offset);
     1675        result = push(emitLoadOp(op, emitCheckAndPreparePointer(pointer, offset, sizeOfLoadOp(op)), offset));
    13801676
    13811677    return { };
     
    14031699
    14041700
    1405 inline void B3IRGenerator::emitStoreOp(StoreOpType op, ExpressionType pointer, ExpressionType value, uint32_t uoffset)
     1701inline void B3IRGenerator::emitStoreOp(StoreOpType op, Value* pointer, Value* value, uint32_t uoffset)
    14061702{
    14071703    int32_t offset = fixupPointerPlusOffset(pointer, uoffset);
     
    14381734}
    14391735
    1440 auto B3IRGenerator::store(StoreOpType op, ExpressionType pointer, ExpressionType value, uint32_t offset) -> PartialResult
    1441 {
     1736auto B3IRGenerator::store(StoreOpType op, ExpressionType pointerVar, ExpressionType valueVar, uint32_t offset) -> PartialResult
     1737{
     1738    Value* pointer = get(pointerVar);
     1739    Value* value = get(valueVar);
    14421740    ASSERT(pointer->type() == Int32);
    14431741
     
    14651763}
    14661764
    1467 inline Value* B3IRGenerator::sanitizeAtomicResult(ExtAtomicOpType op, Type valueType, ExpressionType result)
    1468 {
    1469     auto sanitize32 = [&](ExpressionType result) {
     1765inline Value* B3IRGenerator::sanitizeAtomicResult(ExtAtomicOpType op, Type valueType, Value* result)
     1766{
     1767    auto sanitize32 = [&](Value* result) {
    14701768        switch (accessWidth(op)) {
    14711769        case B3::Width8:
     
    14921790}
    14931791
    1494 Value* B3IRGenerator::fixupPointerPlusOffsetForAtomicOps(ExtAtomicOpType op, ExpressionType ptr, uint32_t offset)
     1792Value* B3IRGenerator::fixupPointerPlusOffsetForAtomicOps(ExtAtomicOpType op, Value* ptr, uint32_t offset)
    14951793{
    14961794    auto pointer = m_currentBlock->appendNew<Value>(m_proc, Add, origin(), ptr, m_currentBlock->appendNew<Const64Value>(m_proc, origin(), offset));
     
    15051803}
    15061804
    1507 inline Value* B3IRGenerator::emitAtomicLoadOp(ExtAtomicOpType op, Type valueType, ExpressionType pointer, uint32_t uoffset)
     1805inline Value* B3IRGenerator::emitAtomicLoadOp(ExtAtomicOpType op, Type valueType, Value* pointer, uint32_t uoffset)
    15081806{
    15091807    pointer = fixupPointerPlusOffsetForAtomicOps(op, pointer, uoffset);
    15101808
    1511     ExpressionType value = nullptr;
     1809    Value* value = nullptr;
    15121810    switch (accessWidth(op)) {
    15131811    case B3::Width8:
     
    15381836        switch (valueType.kind) {
    15391837        case TypeKind::I32:
    1540             result = constant(Int32, 0);
     1838            result = push(constant(Int32, 0));
    15411839            break;
    15421840        case TypeKind::I64:
    1543             result = constant(Int64, 0);
     1841            result = push(constant(Int64, 0));
    15441842            break;
    15451843        default:
     
    15481846        }
    15491847    } else
    1550         result = emitAtomicLoadOp(op, valueType, emitCheckAndPreparePointer(pointer, offset, sizeOfAtomicOpMemoryAccess(op)), offset);
    1551 
    1552     return { };
    1553 }
    1554 
    1555 inline void B3IRGenerator::emitAtomicStoreOp(ExtAtomicOpType op, Type valueType, ExpressionType pointer, ExpressionType value, uint32_t uoffset)
     1848        result = push(emitAtomicLoadOp(op, valueType, emitCheckAndPreparePointer(get(pointer), offset, sizeOfAtomicOpMemoryAccess(op)), offset));
     1849
     1850    return { };
     1851}
     1852
     1853inline void B3IRGenerator::emitAtomicStoreOp(ExtAtomicOpType op, Type valueType, Value* pointer, Value* value, uint32_t uoffset)
    15561854{
    15571855    pointer = fixupPointerPlusOffsetForAtomicOps(op, pointer, uoffset);
     
    15741872        });
    15751873    } else
    1576         emitAtomicStoreOp(op, valueType, emitCheckAndPreparePointer(pointer, offset, sizeOfAtomicOpMemoryAccess(op)), value, offset);
    1577 
    1578     return { };
    1579 }
    1580 
    1581 inline Value* B3IRGenerator::emitAtomicBinaryRMWOp(ExtAtomicOpType op, Type valueType, ExpressionType pointer, ExpressionType value, uint32_t uoffset)
     1874        emitAtomicStoreOp(op, valueType, emitCheckAndPreparePointer(get(pointer), offset, sizeOfAtomicOpMemoryAccess(op)), get(value), offset);
     1875
     1876    return { };
     1877}
     1878
     1879inline Value* B3IRGenerator::emitAtomicBinaryRMWOp(ExtAtomicOpType op, Type valueType, Value* pointer, Value* value, uint32_t uoffset)
    15821880{
    15831881    pointer = fixupPointerPlusOffsetForAtomicOps(op, pointer, uoffset);
     
    16641962        switch (valueType.kind) {
    16651963        case TypeKind::I32:
    1666             result = constant(Int32, 0);
     1964            result = push(constant(Int32, 0));
    16671965            break;
    16681966        case TypeKind::I64:
    1669             result = constant(Int64, 0);
     1967            result = push(constant(Int64, 0));
    16701968            break;
    16711969        default:
     
    16741972        }
    16751973    } else
    1676         result = emitAtomicBinaryRMWOp(op, valueType, emitCheckAndPreparePointer(pointer, offset, sizeOfAtomicOpMemoryAccess(op)), value, offset);
    1677 
    1678     return { };
    1679 }
    1680 
    1681 Value* B3IRGenerator::emitAtomicCompareExchange(ExtAtomicOpType op, Type valueType, ExpressionType pointer, ExpressionType expected, ExpressionType value, uint32_t uoffset)
     1974        result = push(emitAtomicBinaryRMWOp(op, valueType, emitCheckAndPreparePointer(get(pointer), offset, sizeOfAtomicOpMemoryAccess(op)), get(value), offset));
     1975
     1976    return { };
     1977}
     1978
     1979Value* B3IRGenerator::emitAtomicCompareExchange(ExtAtomicOpType op, Type valueType, Value* pointer, Value* expected, Value* value, uint32_t uoffset)
    16821980{
    16831981    pointer = fixupPointerPlusOffsetForAtomicOps(op, pointer, uoffset);
     
    17892087        switch (valueType.kind) {
    17902088        case TypeKind::I32:
    1791             result = constant(Int32, 0);
     2089            result = push(constant(Int32, 0));
    17922090            break;
    17932091        case TypeKind::I64:
    1794             result = constant(Int64, 0);
     2092            result = push(constant(Int64, 0));
    17952093            break;
    17962094        default:
     
    17992097        }
    18002098    } else
    1801         result = emitAtomicCompareExchange(op, valueType, emitCheckAndPreparePointer(pointer, offset, sizeOfAtomicOpMemoryAccess(op)), expected, value, offset);
    1802 
    1803     return { };
    1804 }
    1805 
    1806 auto B3IRGenerator::atomicWait(ExtAtomicOpType op, ExpressionType pointer, ExpressionType value, ExpressionType timeout, ExpressionType& result, uint32_t offset) -> PartialResult
    1807 {
     2099        result = push(emitAtomicCompareExchange(op, valueType, emitCheckAndPreparePointer(get(pointer), offset, sizeOfAtomicOpMemoryAccess(op)), get(expected), get(value), offset));
     2100
     2101    return { };
     2102}
     2103
     2104auto B3IRGenerator::atomicWait(ExtAtomicOpType op, ExpressionType pointerVar, ExpressionType valueVar, ExpressionType timeoutVar, ExpressionType& result, uint32_t offset) -> PartialResult
     2105{
     2106    Value* pointer = get(pointerVar);
     2107    Value* value = get(valueVar);
     2108    Value* timeout = get(timeoutVar);
     2109    Value* resultValue = nullptr;
    18082110    if (op == ExtAtomicOpType::MemoryAtomicWait32) {
    1809         result = m_currentBlock->appendNew<CCallValue>(m_proc, Int32, origin(),
     2111        resultValue = m_currentBlock->appendNew<CCallValue>(m_proc, Int32, origin(),
    18102112            m_currentBlock->appendNew<ConstPtrValue>(m_proc, origin(), tagCFunction<OperationPtrTag>(operationMemoryAtomicWait32)),
    18112113            instanceValue(), pointer, m_currentBlock->appendNew<Const32Value>(m_proc, origin(), offset), value, timeout);
    18122114    } else {
    1813         result = m_currentBlock->appendNew<CCallValue>(m_proc, Int32, origin(),
     2115        resultValue = m_currentBlock->appendNew<CCallValue>(m_proc, Int32, origin(),
    18142116            m_currentBlock->appendNew<ConstPtrValue>(m_proc, origin(), tagCFunction<OperationPtrTag>(operationMemoryAtomicWait64)),
    18152117            instanceValue(), pointer, m_currentBlock->appendNew<Const32Value>(m_proc, origin(), offset), value, timeout);
     
    18172119
    18182120    {
     2121        result = push(resultValue);
    18192122        CheckValue* check = m_currentBlock->appendNew<CheckValue>(m_proc, Check, origin(),
    1820             m_currentBlock->appendNew<Value>(m_proc, LessThan, origin(), result, m_currentBlock->appendNew<Const32Value>(m_proc, origin(), 0)));
     2123            m_currentBlock->appendNew<Value>(m_proc, LessThan, origin(), resultValue, m_currentBlock->appendNew<Const32Value>(m_proc, origin(), 0)));
    18212124
    18222125        check->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
     
    18302133auto B3IRGenerator::atomicNotify(ExtAtomicOpType, ExpressionType pointer, ExpressionType count, ExpressionType& result, uint32_t offset) -> PartialResult
    18312134{
    1832     result = m_currentBlock->appendNew<CCallValue>(m_proc, Int32, origin(),
     2135    Value* resultValue = m_currentBlock->appendNew<CCallValue>(m_proc, Int32, origin(),
    18332136        m_currentBlock->appendNew<ConstPtrValue>(m_proc, origin(), tagCFunction<OperationPtrTag>(operationMemoryAtomicNotify)),
    1834         instanceValue(), pointer, m_currentBlock->appendNew<Const32Value>(m_proc, origin(), offset), count);
    1835 
     2137        instanceValue(), get(pointer), m_currentBlock->appendNew<Const32Value>(m_proc, origin(), offset), get(count));
    18362138    {
     2139        result = push(resultValue);
    18372140        CheckValue* check = m_currentBlock->appendNew<CheckValue>(m_proc, Check, origin(),
    1838             m_currentBlock->appendNew<Value>(m_proc, LessThan, origin(), result, m_currentBlock->appendNew<Const32Value>(m_proc, origin(), 0)));
     2141            m_currentBlock->appendNew<Value>(m_proc, LessThan, origin(), resultValue, m_currentBlock->appendNew<Const32Value>(m_proc, origin(), 0)));
    18392142
    18402143        check->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
     
    18522155}
    18532156
    1854 auto B3IRGenerator::truncSaturated(Ext1OpType op, ExpressionType arg, ExpressionType& result, Type returnType, Type) -> PartialResult
    1855 {
     2157auto B3IRGenerator::truncSaturated(Ext1OpType op, ExpressionType argVar, ExpressionType& result, Type returnType, Type) -> PartialResult
     2158{
     2159    Value* arg = get(argVar);
    18562160    Value* maxFloat = nullptr;
    18572161    Value* minFloat = nullptr;
     
    20032307    }
    20042308
    2005     result = m_currentBlock->appendNew<Value>(m_proc, B3::Select, origin(),
     2309    result = push(m_currentBlock->appendNew<Value>(m_proc, B3::Select, origin(),
    20062310        m_currentBlock->appendNew<Value>(m_proc, GreaterThan, origin(), arg, minFloat),
    20072311        m_currentBlock->appendNew<Value>(m_proc, B3::Select, origin(),
    20082312            m_currentBlock->appendNew<Value>(m_proc, LessThan, origin(), arg, maxFloat),
    20092313            patchpoint, maxResult),
    2010         requiresNaNCheck ? m_currentBlock->appendNew<Value>(m_proc, B3::Select, origin(), m_currentBlock->appendNew<Value>(m_proc, Equal, origin(), arg, arg), minResult, zero) : minResult);
     2314        requiresNaNCheck ? m_currentBlock->appendNew<Value>(m_proc, B3::Select, origin(), m_currentBlock->appendNew<Value>(m_proc, Equal, origin(), arg, arg), minResult, zero) : minResult));
    20112315
    20122316    return { };
     
    20152319auto B3IRGenerator::addSelect(ExpressionType condition, ExpressionType nonZero, ExpressionType zero, ExpressionType& result) -> PartialResult
    20162320{
    2017     result = m_currentBlock->appendNew<Value>(m_proc, B3::Select, origin(), condition, nonZero, zero);
     2321    result = push(m_currentBlock->appendNew<Value>(m_proc, B3::Select, origin(), get(condition), get(nonZero), get(zero)));
    20182322    return { };
    20192323}
     
    20222326{
    20232327
    2024     return constant(toB3Type(type), value);
     2328    return push(constant(toB3Type(type), value));
    20252329}
    20262330
     
    20832387    Value* countDownLocation = constant(pointerType(), bitwise_cast<uintptr_t>(&m_tierUp->m_counter), origin);
    20842388
    2085     Vector<ExpressionType> stackmap;
    2086     for (auto& local : m_locals) {
    2087         Value* result = m_currentBlock->appendNew<VariableValue>(m_proc, B3::Get, origin, local);
    2088         stackmap.append(result);
    2089     }
     2389    Vector<Value*> stackmap;
     2390    for (auto& local : m_locals)
     2391        stackmap.append(get(local));
    20902392    for (unsigned controlIndex = 0; controlIndex < m_parser->controlStack().size(); ++controlIndex) {
     2393        auto& data = m_parser->controlStack()[controlIndex].controlData;
    20912394        auto& expressionStack = m_parser->controlStack()[controlIndex].enclosedExpressionStack;
    20922395        for (TypedExpression value : expressionStack)
    2093             stackmap.append(value);
     2396            stackmap.append(get(value));
     2397        if (ControlType::isAnyCatch(data))
     2398            stackmap.append(get(data.exception()));
    20942399    }
    20952400    for (TypedExpression value : enclosingStack)
    2096         stackmap.append(value);
     2401        stackmap.append(get(value));
    20972402    for (TypedExpression value : newStack)
    2098         stackmap.append(value);
     2403        stackmap.append(get(value));
    20992404
    21002405    PatchpointValue* patch = m_currentBlock->appendNew<PatchpointValue>(m_proc, B3::Void, origin);
     
    21412446}
    21422447
     2448Value* B3IRGenerator::loadFromScratchBuffer(unsigned& indexInBuffer, Value* pointer, B3::Type type)
     2449{
     2450    size_t offset = sizeof(uint64_t) * indexInBuffer++;
     2451    RELEASE_ASSERT(type.isNumeric());
     2452    return m_currentBlock->appendNew<MemoryValue>(m_proc, Load, type, origin(), pointer, offset);
     2453}
     2454
     2455void B3IRGenerator::connectControlEntry(unsigned& indexInBuffer, Value* pointer, ControlData& data, Stack& expressionStack, ControlData& currentData, bool fillLoopPhis)
     2456{
     2457    // For each stack entry enclosed by this loop we need to replace the value with a phi so we can fill it on OSR entry.
     2458    for (unsigned i = 0; i < expressionStack.size(); i++) {
     2459        TypedExpression value = expressionStack[i];
     2460        auto* load = loadFromScratchBuffer(indexInBuffer, pointer, value->type());
     2461        if (fillLoopPhis)
     2462            m_currentBlock->appendNew<UpsilonValue>(m_proc, origin(), load, data.phis[i]);
     2463        else
     2464            m_currentBlock->appendNew<VariableValue>(m_proc, Set, origin(), value.value(), load);
     2465    }
     2466    if (ControlType::isAnyCatch(data) && &data != &currentData) {
     2467        auto* load = loadFromScratchBuffer(indexInBuffer, pointer, pointerType());
     2468        m_currentBlock->appendNew<VariableValue>(m_proc, Set, origin(), data.exception(), load);
     2469    }
     2470};
     2471
    21432472auto B3IRGenerator::addLoop(BlockSignature signature, Stack& enclosingStack, ControlType& block, Stack& newStack, uint32_t loopIndex) -> PartialResult
    21442473{
     
    21462475    BasicBlock* continuation = m_proc.addBlock();
    21472476
    2148     block = ControlData(m_proc, origin(), signature, BlockType::Loop, continuation, body);
     2477    block = ControlData(m_proc, origin(), signature, BlockType::Loop, m_stackSize, continuation, body);
     2478
    21492479    unsigned offset = enclosingStack.size() - signature->argumentCount();
    21502480    for (unsigned i = 0; i < signature->argumentCount(); ++i) {
    21512481        TypedExpression value = enclosingStack.at(offset + i);
    2152         auto* upsilon = m_currentBlock->appendNew<UpsilonValue>(m_proc, origin(), value);
    21532482        Value* phi = block.phis[i];
     2483        m_currentBlock->appendNew<UpsilonValue>(m_proc, origin(), get(value), phi);
    21542484        body->append(phi);
    2155         upsilon->setPhi(phi);
    2156         newStack.constructAndAppend(value.type(), phi);
    2157     }
     2485        set(body, value, phi);
     2486        newStack.append(value);
     2487    }
     2488    enclosingStack.shrink(offset);
    21582489
    21592490    m_currentBlock->appendNewControlValue(m_proc, Jump, origin(), body);
     
    21612492        dataLogLnIf(WasmB3IRGeneratorInternal::verbose, "Setting up for OSR entry");
    21622493
    2163         m_currentBlock = m_rootBlock;
    2164         Value* pointer = m_rootBlock->appendNew<ArgumentRegValue>(m_proc, Origin(), GPRInfo::argumentGPR0);
     2494        m_currentBlock = m_rootBlocks[0];
     2495        Value* pointer = m_rootBlocks[0]->appendNew<ArgumentRegValue>(m_proc, Origin(), GPRInfo::argumentGPR0);
    21652496
    21662497        unsigned indexInBuffer = 0;
    2167         auto loadFromScratchBuffer = [&] (B3::Type type) {
    2168             size_t offset = sizeof(uint64_t) * indexInBuffer++;
    2169             RELEASE_ASSERT(type.isNumeric());
    2170             return m_currentBlock->appendNew<MemoryValue>(m_proc, Load, type, origin(), pointer, offset);
    2171         };
    21722498
    21732499        for (auto& local : m_locals)
    2174             m_currentBlock->appendNew<VariableValue>(m_proc, Set, Origin(), local, loadFromScratchBuffer(local->type()));
    2175 
    2176         auto connectControlEntry = [&](const ControlData& data, Stack& expressionStack) {
    2177             // For each stack entry enclosed by this loop we need to replace the value with a phi so we can fill it on OSR entry.
    2178             BasicBlock* sourceBlock = nullptr;
    2179             unsigned blockIndex = 0;
    2180             B3::InsertionSet insertionSet(m_proc);
    2181             for (unsigned i = 0; i < expressionStack.size(); i++) {
    2182                 TypedExpression value = expressionStack[i];
    2183                 if (value->isConstant()) {
    2184                     ++indexInBuffer;
    2185                     continue;
    2186                 }
    2187 
    2188                 if (value->owner != sourceBlock) {
    2189                     if (sourceBlock)
    2190                         insertionSet.execute(sourceBlock);
    2191                     ASSERT(insertionSet.isEmpty());
    2192                     dataLogLnIf(WasmB3IRGeneratorInternal::verbose && sourceBlock, "Executed insertion set into: ", *sourceBlock);
    2193                     blockIndex = 0;
    2194                     sourceBlock = value->owner;
    2195                 }
    2196 
    2197                 while (sourceBlock->at(blockIndex++) != value)
    2198                     ASSERT(blockIndex < sourceBlock->size());
    2199                 ASSERT(sourceBlock->at(blockIndex - 1) == value);
    2200 
    2201                 auto* phi = data.continuation->appendNew<Value>(m_proc, Phi,  value->type(), value->origin());
    2202                 expressionStack[i] = TypedExpression { value.type(), phi };
    2203                 m_currentBlock->appendNew<UpsilonValue>(m_proc, value->origin(), loadFromScratchBuffer(value->type()), phi);
    2204 
    2205                 auto* sourceUpsilon = m_proc.add<UpsilonValue>(value->origin(), value, phi);
    2206                 insertionSet.insertValue(blockIndex, sourceUpsilon);
    2207             }
    2208             if (sourceBlock)
    2209                 insertionSet.execute(sourceBlock);
    2210         };
     2500            m_currentBlock->appendNew<VariableValue>(m_proc, Set, Origin(), local, loadFromScratchBuffer(indexInBuffer, pointer, local->type()));
    22112501
    22122502        for (unsigned controlIndex = 0; controlIndex < m_parser->controlStack().size(); ++controlIndex) {
    22132503            auto& data = m_parser->controlStack()[controlIndex].controlData;
    22142504            auto& expressionStack = m_parser->controlStack()[controlIndex].enclosedExpressionStack;
    2215             connectControlEntry(data, expressionStack);
    2216         }
    2217         for (unsigned i = 0; i < signature->argumentCount(); ++i) {
    2218             TypedExpression value = enclosingStack.at(offset + i);
    2219             Value* phi = block.phis[i];
    2220             m_currentBlock->appendNew<UpsilonValue>(m_proc, value->origin(), loadFromScratchBuffer(value->type()), phi);
    2221         }
    2222         enclosingStack.shrink(offset);
    2223         connectControlEntry(block, enclosingStack);
     2505            connectControlEntry(indexInBuffer, pointer, data, expressionStack, block);
     2506        }
     2507        connectControlEntry(indexInBuffer, pointer, block, enclosingStack, block);
     2508        connectControlEntry(indexInBuffer, pointer, block, newStack, block, true);
    22242509
    22252510        m_osrEntryScratchBufferSize = indexInBuffer;
    22262511        m_currentBlock->appendNewControlValue(m_proc, Jump, origin(), body);
    22272512        body->addPredecessor(m_currentBlock);
    2228     } else
    2229         enclosingStack.shrink(offset);
     2513    }
    22302514
    22312515    m_currentBlock = body;
     
    22362520B3IRGenerator::ControlData B3IRGenerator::addTopLevel(BlockSignature signature)
    22372521{
    2238     return ControlData(m_proc, Origin(), signature, BlockType::TopLevel, m_proc.addBlock());
     2522    return ControlData(m_proc, Origin(), signature, BlockType::TopLevel, m_stackSize, m_proc.addBlock());
    22392523}
    22402524
     
    22442528
    22452529    splitStack(signature, enclosingStack, newStack);
    2246     newBlock = ControlData(m_proc, origin(), signature, BlockType::Block, continuation);
     2530    newBlock = ControlData(m_proc, origin(), signature, BlockType::Block, m_stackSize, continuation);
    22472531    return { };
    22482532}
     
    22562540    BasicBlock* continuation = m_proc.addBlock();
    22572541
    2258     m_currentBlock->appendNew<Value>(m_proc, B3::Branch, origin(), condition);
     2542    m_currentBlock->appendNew<Value>(m_proc, B3::Branch, origin(), get(condition));
    22592543    m_currentBlock->setSuccessors(FrequentedBlock(taken), FrequentedBlock(notTaken));
    22602544    taken->addPredecessor(m_currentBlock);
     
    22632547    m_currentBlock = taken;
    22642548    splitStack(signature, enclosingStack, newStack);
    2265     result = ControlData(m_proc, origin(), signature, BlockType::If, continuation, notTaken);
     2549    result = ControlData(m_proc, origin(), signature, BlockType::If, m_stackSize, continuation, notTaken);
    22662550    return { };
    22672551}
     
    22692553auto B3IRGenerator::addElse(ControlData& data, const Stack& currentStack) -> PartialResult
    22702554{
    2271     unifyValuesWithBlock(currentStack, data.phis);
     2555    unifyValuesWithBlock(currentStack, data);
    22722556    m_currentBlock->appendNewControlValue(m_proc, Jump, origin(), data.continuation);
    22732557    return addElseToUnreachable(data);
     
    22772561{
    22782562    ASSERT(data.blockType() == BlockType::If);
     2563    m_stackSize = data.stackSize() + data.m_signature->argumentCount();
    22792564    m_currentBlock = data.special;
    22802565    data.convertIfToBlock();
     2566    return { };
     2567}
     2568
     2569auto B3IRGenerator::addTry(BlockSignature signature, Stack& enclosingStack, ControlType& result, Stack& newStack) -> PartialResult
     2570{
     2571    ++m_tryDepth;
     2572
     2573    BasicBlock* continuation = m_proc.addBlock();
     2574    splitStack(signature, enclosingStack, newStack);
     2575    result = ControlData(m_proc, origin(), signature, BlockType::Try, m_stackSize, continuation, ++m_callSiteIndex, m_tryDepth);
     2576    return { };
     2577}
     2578
     2579auto B3IRGenerator::addCatch(unsigned exceptionIndex, const Signature& signature, Stack& currentStack, ControlType& data, ResultList& results) -> PartialResult
     2580{
     2581    unifyValuesWithBlock(currentStack, data);
     2582    m_currentBlock->appendNewControlValue(m_proc, Jump, origin(), data.continuation);
     2583    return addCatchToUnreachable(exceptionIndex, signature, data, results);
     2584}
     2585
     2586PatchpointExceptionHandle B3IRGenerator::preparePatchpointForExceptions(BasicBlock* block, PatchpointValue* patch)
     2587{
     2588    ++m_callSiteIndex;
     2589    if (!m_tryDepth)
     2590        return { };
     2591
     2592    Vector<Value*> stackmap;
     2593    Origin origin = this->origin();
     2594    for (Variable* local : m_locals) {
     2595        Value* result = block->appendNew<VariableValue>(m_proc, B3::Get, origin, local);
     2596        stackmap.append(result);
     2597    }
     2598    for (unsigned controlIndex = 0; controlIndex < m_parser->controlStack().size(); ++controlIndex) {
     2599        ControlData& data = m_parser->controlStack()[controlIndex].controlData;
     2600        Stack& expressionStack = m_parser->controlStack()[controlIndex].enclosedExpressionStack;
     2601        for (Variable* value : expressionStack)
     2602            stackmap.append(get(block, value));
     2603        if (ControlType::isAnyCatch(data))
     2604            stackmap.append(get(block, data.exception()));
     2605    }
     2606
     2607    unsigned offset = patch->numChildren();
     2608    if (patch->type() != Void)
     2609        offset++;
     2610
     2611    patch->effects.exitsSideways = true;
     2612    patch->appendVectorWithRep(stackmap, ValueRep::LateColdAny);
     2613
     2614    return PatchpointExceptionHandle { m_callSiteIndex, offset };
     2615}
     2616
     2617auto B3IRGenerator::addCatchToUnreachable(unsigned exceptionIndex, const Signature& signature, ControlType& data, ResultList& results) -> PartialResult
     2618{
     2619    Value* operationResult = emitCatchImpl(CatchKind::Catch, data, exceptionIndex);
     2620    Value* payload = m_currentBlock->appendNew<ExtractValue>(m_proc, origin(), pointerType(), operationResult, 1);
     2621    for (unsigned i = 0; i < signature.argumentCount(); ++i) {
     2622        Type type = signature.argument(i);
     2623        Value* value = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, toB3Type(type), origin(), payload, i * sizeof(uint64_t));
     2624        results.append(push(value));
     2625    }
     2626    return { };
     2627}
     2628
     2629auto B3IRGenerator::addCatchAll(Stack& currentStack, ControlType& data) -> PartialResult
     2630{
     2631    unifyValuesWithBlock(currentStack, data);
     2632    m_currentBlock->appendNewControlValue(m_proc, Jump, origin(), data.continuation);
     2633    return addCatchAllToUnreachable(data);
     2634}
     2635
     2636auto B3IRGenerator::addCatchAllToUnreachable(ControlType& data) -> PartialResult
     2637{
     2638    emitCatchImpl(CatchKind::CatchAll, data);
     2639    return { };
     2640}
     2641
     2642Value* B3IRGenerator::emitCatchImpl(CatchKind kind, ControlType& data, unsigned exceptionIndex)
     2643{
     2644    m_hasCatch = true;
     2645    m_currentBlock = m_proc.addBlock();
     2646    m_rootBlocks.append(m_currentBlock);
     2647    m_stackSize = data.stackSize();
     2648
     2649    if (ControlType::isTry(data)) {
     2650        if (kind == CatchKind::Catch)
     2651            data.convertTryToCatch(++m_callSiteIndex, m_proc.addVariable(pointerType()));
     2652        else
     2653            data.convertTryToCatchAll(++m_callSiteIndex, m_proc.addVariable(pointerType()));
     2654    }
     2655
     2656    HandlerType handlerType = kind == CatchKind::Catch ? HandlerType::Catch : HandlerType::CatchAll;
     2657    m_exceptionHandlers.append({ handlerType, data.tryStart(), data.tryEnd(), 0, m_tryDepth, exceptionIndex });
     2658
     2659    restoreWebAssemblyGlobalState(RestoreCachedStackLimit::Yes, m_info.memory, instanceValue(), m_proc, m_currentBlock, false);
     2660
     2661    Value* pointer = m_currentBlock->appendNew<ArgumentRegValue>(m_proc, Origin(), GPRInfo::argumentGPR0);
     2662
     2663    unsigned indexInBuffer = 0;
     2664
     2665    for (auto& local : m_locals)
     2666        m_currentBlock->appendNew<VariableValue>(m_proc, Set, Origin(), local, loadFromScratchBuffer(indexInBuffer, pointer, local->type()));
     2667
     2668    for (unsigned controlIndex = 0; controlIndex < m_parser->controlStack().size(); ++controlIndex) {
     2669        auto& controlData = m_parser->controlStack()[controlIndex].controlData;
     2670        auto& expressionStack = m_parser->controlStack()[controlIndex].enclosedExpressionStack;
     2671        connectControlEntry(indexInBuffer, pointer, controlData, expressionStack, data);
     2672    }
     2673
     2674    PatchpointValue* result = m_currentBlock->appendNew<PatchpointValue>(m_proc, m_proc.addTuple({ pointerType(), pointerType() }), origin());
     2675    result->effects.exitsSideways = true;
     2676    result->clobber(RegisterSet::macroScratchRegisters());
     2677    RegisterSet clobberLate = RegisterSet::volatileRegistersForJSCall();
     2678    clobberLate.add(GPRInfo::argumentGPR0);
     2679    result->clobberLate(clobberLate);
     2680    result->append(instanceValue(), ValueRep::SomeRegister);
     2681    result->resultConstraints.append(ValueRep::reg(GPRInfo::returnValueGPR));
     2682    result->resultConstraints.append(ValueRep::reg(GPRInfo::returnValueGPR2));
     2683    result->setGenerator([=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
     2684        AllowMacroScratchRegisterUsage allowScratch(jit);
     2685        jit.move(params[2].gpr(), GPRInfo::argumentGPR0);
     2686        CCallHelpers::Call call = jit.call(OperationPtrTag);
     2687        jit.addLinkTask([call] (LinkBuffer& linkBuffer) {
     2688            linkBuffer.link(call, FunctionPtr<OperationPtrTag>(operationWasmRetrieveAndClearExceptionIfCatchable));
     2689        });
     2690    });
     2691
     2692    Value* exception = m_currentBlock->appendNew<ExtractValue>(m_proc, origin(), pointerType(), result, 0);
     2693    set(data.exception(), exception);
     2694
     2695    return result;
     2696}
     2697
     2698auto B3IRGenerator::addDelegate(ControlType& target, ControlType& data) -> PartialResult
     2699{
     2700    return addDelegateToUnreachable(target, data);
     2701}
     2702
     2703auto B3IRGenerator::addDelegateToUnreachable(ControlType& target, ControlType& data) -> PartialResult
     2704{
     2705    unsigned targetDepth = 0;
     2706    if (ControlType::isTry(target))
     2707        targetDepth = target.tryDepth();
     2708
     2709    m_exceptionHandlers.append({ HandlerType::Delegate, data.tryStart(), ++m_callSiteIndex, 0, m_tryDepth, targetDepth });
     2710    return { };
     2711}
     2712
     2713auto B3IRGenerator::addThrow(unsigned exceptionIndex, Vector<ExpressionType>& args, Stack&) -> PartialResult
     2714{
     2715    PatchpointValue* patch = m_proc.add<PatchpointValue>(B3::Void, origin());
     2716    patch->effects.terminal = true;
     2717    patch->append(instanceValue(), ValueRep::reg(GPRInfo::argumentGPR0));
     2718    patch->append(framePointer(), ValueRep::reg(GPRInfo::argumentGPR1));
     2719    for (unsigned i = 0; i < args.size(); ++i)
     2720        patch->append(get(args[i]), ValueRep::stackArgument(i * sizeof(EncodedJSValue)));
     2721    RegisterSet clobber = RegisterSet::macroScratchRegisters();
     2722    clobber.add(GPRInfo::argumentGPR2);
     2723    clobber.add(GPRInfo::argumentGPR3);
     2724    patch->clobber(clobber);
     2725    patch->clobberLate(RegisterSet::volatileRegistersForJSCall());
     2726    patch->numGPScratchRegisters = 1;
     2727    PatchpointExceptionHandle handle = preparePatchpointForExceptions(m_currentBlock, patch);
     2728    patch->setGenerator([this, exceptionIndex, handle] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
     2729        AllowMacroScratchRegisterUsage allowScratch(jit);
     2730        GPRReg scratch = params.gpScratch(0);
     2731        handle.generate(jit, params, this);
     2732
     2733        jit.loadPtr(CCallHelpers::Address(GPRInfo::argumentGPR0, Instance::offsetOfOwner()), scratch);
     2734        {
     2735            auto preciseAllocationCase = jit.branchTestPtr(CCallHelpers::NonZero, scratch, CCallHelpers::TrustedImm32(PreciseAllocation::halfAlignment));
     2736            jit.andPtr(CCallHelpers::TrustedImmPtr(MarkedBlock::blockMask), scratch);
     2737            jit.loadPtr(CCallHelpers::Address(scratch, MarkedBlock::offsetOfFooter + MarkedBlock::Footer::offsetOfVM()), scratch);
     2738            auto loadedCase = jit.jump();
     2739
     2740            preciseAllocationCase.link(&jit);
     2741            jit.loadPtr(CCallHelpers::Address(scratch, PreciseAllocation::offsetOfWeakSet() + WeakSet::offsetOfVM() - PreciseAllocation::headerSize()), scratch);
     2742
     2743            loadedCase.link(&jit);
     2744        }
     2745        jit.copyCalleeSavesToVMEntryFrameCalleeSavesBuffer(scratch);
     2746
     2747        jit.move(MacroAssembler::TrustedImm32(exceptionIndex), GPRInfo::argumentGPR2);
     2748        jit.move(MacroAssembler::stackPointerRegister, GPRInfo::argumentGPR3);
     2749        CCallHelpers::Call call = jit.call(OperationPtrTag);
     2750        jit.farJump(GPRInfo::returnValueGPR, ExceptionHandlerPtrTag);
     2751        jit.addLinkTask([call] (LinkBuffer& linkBuffer) {
     2752            linkBuffer.link(call, FunctionPtr<OperationPtrTag>(operationWasmThrow));
     2753        });
     2754    });
     2755    m_currentBlock->append(patch);
     2756
     2757    return { };
     2758}
     2759
     2760auto B3IRGenerator::addRethrow(unsigned, ControlType& data) -> PartialResult
     2761{
     2762    PatchpointValue* patch = m_proc.add<PatchpointValue>(B3::Void, origin());
     2763    patch->clobber(RegisterSet::macroScratchRegisters());
     2764    RegisterSet clobberLate;
     2765    clobberLate.add(GPRInfo::argumentGPR0);
     2766    clobberLate.add(GPRInfo::argumentGPR1);
     2767    clobberLate.add(GPRInfo::argumentGPR2);
     2768    patch->effects.terminal = true;
     2769    patch->append(instanceValue(), ValueRep::reg(GPRInfo::argumentGPR0));
     2770    patch->append(framePointer(), ValueRep::reg(GPRInfo::argumentGPR1));
     2771    patch->append(get(data.exception()), ValueRep::reg(GPRInfo::argumentGPR2));
     2772    patch->numGPScratchRegisters = 1;
     2773    PatchpointExceptionHandle handle = preparePatchpointForExceptions(m_currentBlock, patch);
     2774    patch->setGenerator([this, handle] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
     2775        AllowMacroScratchRegisterUsage allowScratch(jit);
     2776
     2777        GPRReg scratch = params.gpScratch(0);
     2778        jit.loadPtr(CCallHelpers::Address(GPRInfo::argumentGPR0, Instance::offsetOfOwner()), scratch);
     2779        {
     2780            auto preciseAllocationCase = jit.branchTestPtr(CCallHelpers::NonZero, scratch, CCallHelpers::TrustedImm32(PreciseAllocation::halfAlignment));
     2781            jit.andPtr(CCallHelpers::TrustedImmPtr(MarkedBlock::blockMask), scratch);
     2782            jit.loadPtr(CCallHelpers::Address(scratch, MarkedBlock::offsetOfFooter + MarkedBlock::Footer::offsetOfVM()), scratch);
     2783            auto loadedCase = jit.jump();
     2784
     2785            preciseAllocationCase.link(&jit);
     2786            jit.loadPtr(CCallHelpers::Address(scratch, PreciseAllocation::offsetOfWeakSet() + WeakSet::offsetOfVM() - PreciseAllocation::headerSize()), scratch);
     2787
     2788            loadedCase.link(&jit);
     2789        }
     2790        jit.copyCalleeSavesToVMEntryFrameCalleeSavesBuffer(scratch);
     2791
     2792        handle.generate(jit, params, this);
     2793        CCallHelpers::Call call = jit.call(OperationPtrTag);
     2794        jit.farJump(GPRInfo::returnValueGPR, ExceptionHandlerPtrTag);
     2795        jit.addLinkTask([call] (LinkBuffer& linkBuffer) {
     2796            linkBuffer.link(call, FunctionPtr<OperationPtrTag>(operationWasmRethrow));
     2797        });
     2798    });
     2799    m_currentBlock->append(patch);
     2800
    22812801    return { };
    22822802}
     
    23012821        if (rep.isStack()) {
    23022822            B3::Value* address = m_currentBlock->appendNew<B3::Value>(m_proc, B3::Add, Origin(), framePointer(), constant(pointerType(), rep.offsetFromFP()));
    2303             m_currentBlock->appendNew<B3::MemoryValue>(m_proc, B3::Store, Origin(), returnValues[offset + i], address);
     2823            m_currentBlock->appendNew<B3::MemoryValue>(m_proc, B3::Store, Origin(), get(returnValues[offset + i]), address);
    23042824        } else {
    23052825            ASSERT(rep.isReg());
    2306             patch->append(returnValues[offset + i], rep);
     2826            patch->append(get(returnValues[offset + i]), rep);
    23072827        }
    23082828    }
     
    23142834auto B3IRGenerator::addBranch(ControlData& data, ExpressionType condition, const Stack& returnValues) -> PartialResult
    23152835{
    2316     unifyValuesWithBlock(returnValues, data.phis);
     2836    unifyValuesWithBlock(returnValues, data);
    23172837
    23182838    BasicBlock* target = data.targetBlockForBranch();
    23192839    if (condition) {
    23202840        BasicBlock* continuation = m_proc.addBlock();
    2321         m_currentBlock->appendNew<Value>(m_proc, B3::Branch, origin(), condition);
     2841        m_currentBlock->appendNew<Value>(m_proc, B3::Branch, origin(), get(condition));
    23222842        m_currentBlock->setSuccessors(FrequentedBlock(target), FrequentedBlock(continuation));
    23232843        target->addPredecessor(m_currentBlock);
     
    23342854auto B3IRGenerator::addSwitch(ExpressionType condition, const Vector<ControlData*>& targets, ControlData& defaultTarget, const Stack& expressionStack) -> PartialResult
    23352855{
     2856    UNUSED_PARAM(expressionStack);
    23362857    for (size_t i = 0; i < targets.size(); ++i)
    2337         unifyValuesWithBlock(expressionStack, targets[i]->phis);
    2338     unifyValuesWithBlock(expressionStack, defaultTarget.phis);
    2339 
    2340     SwitchValue* switchValue = m_currentBlock->appendNew<SwitchValue>(m_proc, origin(), condition);
     2858        unifyValuesWithBlock(expressionStack, *targets[i]);
     2859    unifyValuesWithBlock(expressionStack, defaultTarget);
     2860
     2861    SwitchValue* switchValue = m_currentBlock->appendNew<SwitchValue>(m_proc, origin(), get(condition));
    23412862    switchValue->setFallThrough(FrequentedBlock(defaultTarget.targetBlockForBranch()));
    23422863    for (size_t i = 0; i < targets.size(); ++i)
     
    23522873    ASSERT(expressionStack.size() == data.signature()->returnCount());
    23532874    if (data.blockType() != BlockType::Loop)
    2354         unifyValuesWithBlock(expressionStack, data.phis);
     2875        unifyValuesWithBlock(expressionStack, data);
    23552876
    23562877    m_currentBlock->appendNewControlValue(m_proc, Jump, origin(), data.continuation);
     
    23642885    ControlData& data = entry.controlData;
    23652886    m_currentBlock = data.continuation;
     2887    m_stackSize = data.stackSize();
    23662888
    23672889    if (data.blockType() == BlockType::If) {
    23682890        data.special->appendNewControlValue(m_proc, Jump, origin(), m_currentBlock);
    23692891        m_currentBlock->addPredecessor(data.special);
    2370     }
     2892    } else if (data.blockType() == BlockType::Try || data.blockType() == BlockType::Catch)
     2893        --m_tryDepth;
    23712894
    23722895    if (data.blockType() != BlockType::Loop) {
     
    23742897            Value* result = data.phis[i];
    23752898            m_currentBlock->append(result);
    2376             entry.enclosedExpressionStack.constructAndAppend(data.signature()->returnType(i), result);
     2899            entry.enclosedExpressionStack.constructAndAppend(data.signature()->returnType(i), push(result));
    23772900        }
    23782901    } else {
    23792902        m_outerLoops.removeLast();
    23802903        for (unsigned i = 0; i < data.signature()->returnCount(); ++i) {
    2381             if (i < expressionStack.size())
     2904            if (i < expressionStack.size()) {
     2905                ++m_stackSize;
    23822906                entry.enclosedExpressionStack.append(expressionStack[i]);
    2383             else {
     2907            } else {
    23842908                Type returnType = data.signature()->returnType(i);
    2385                 entry.enclosedExpressionStack.constructAndAppend(returnType, constant(toB3Type(returnType), 0xbbadbeef));
     2909                entry.enclosedExpressionStack.constructAndAppend(returnType, push(constant(toB3Type(returnType), 0xbbadbeef)));
    23862910            }
    23872911        }
    23882912    }
     2913
    23892914
    23902915    // TopLevel does not have any code after this so we need to make sure we emit a return here.
     
    24012926    CallInformation wasmCallInfo = wasmCallingConvention().callInformationFor(signature);
    24022927    for (unsigned i = 0; i < args.size(); ++i)
    2403         constrainedArguments.append(B3::ConstrainedValue(args[i], wasmCallInfo.params[i]));
     2928        constrainedArguments.append(B3::ConstrainedValue(get(block, args[i]), wasmCallInfo.params[i]));
    24042929
    24052930    m_proc.requestCallArgAreaSizeInBytes(WTF::roundUpToMultipleOf(stackAlignmentBytes(), wasmCallInfo.headerAndArgumentStackSizeInBytes));
    24062931
    24072932    B3::Type returnType = toB3ResultType(&signature);
    2408     B3::PatchpointValue* patchpoint = block->appendNew<B3::PatchpointValue>(m_proc, returnType, origin);
     2933    PatchpointValue* patchpoint = m_proc.add<PatchpointValue>(returnType, origin);
    24092934    patchpoint->clobberEarly(RegisterSet::macroScratchRegisters());
    24102935    patchpoint->clobberLate(RegisterSet::volatileRegistersForJSCall());
     
    24182943        patchpoint->resultConstraints = WTFMove(resultConstraints);
    24192944    }
     2945    block->append(patchpoint);
    24202946    return patchpoint;
    24212947}
     
    24392965            ASSERT(signature.returnCount() == tuple.size());
    24402966            for (unsigned i = 0; i < signature.returnCount(); ++i)
    2441                 results.append(m_currentBlock->appendNew<ExtractValue>(m_proc, origin(), tuple[i], callResult, i));
     2967                results.append(push(m_currentBlock->appendNew<ExtractValue>(m_proc, origin(), tuple[i], callResult, i)));
    24422968            break;
    24432969        }
    24442970        default: {
    2445             results.append(callResult);
     2971            results.append(push(callResult));
    24462972            break;
    24472973        }
     
    24722998                // FIXME: We shouldn't have to do this: https://bugs.webkit.org/show_bug.cgi?id=172181
    24732999                patchpoint->clobberLate(PinnedRegisterInfo::get().toSave(MemoryMode::BoundsChecking));
    2474                 patchpoint->setGenerator([unlinkedWasmToWasmCalls, functionIndex] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
     3000                PatchpointExceptionHandle handle = preparePatchpointForExceptions(isWasmBlock, patchpoint);
     3001                patchpoint->setGenerator([this, handle, unlinkedWasmToWasmCalls, functionIndex] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
    24753002                    AllowMacroScratchRegisterUsage allowScratch(jit);
     3003                    handle.generate(jit, params, this);
    24763004                    CCallHelpers::Call call = jit.threadSafePatchableNearCall();
    24773005                    jit.addLinkTask([unlinkedWasmToWasmCalls, call, functionIndex] (LinkBuffer& linkBuffer) {
     
    24993027                // FIXME: We shouldn't have to do this: https://bugs.webkit.org/show_bug.cgi?id=172181
    25003028                patchpoint->clobberLate(PinnedRegisterInfo::get().toSave(MemoryMode::BoundsChecking));
    2501                 patchpoint->setGenerator([returnType] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
     3029                PatchpointExceptionHandle handle = preparePatchpointForExceptions(isEmbedderBlock, patchpoint);
     3030                patchpoint->setGenerator([this, handle, returnType] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
    25023031                    AllowMacroScratchRegisterUsage allowScratch(jit);
     3032                    handle.generate(jit, params, this);
    25033033                    jit.call(params[params.proc().resultCount(returnType)].gpr(), WasmEntryPtrTag);
    25043034                });
     
    25283058                if (m_mode == MemoryMode::Signaling || m_info.memory.isShared())
    25293059                    patchpoint->clobberLate(RegisterSet { PinnedRegisterInfo::get().boundsCheckingSizeRegister });
    2530                 patchpoint->setGenerator([unlinkedWasmToWasmCalls, functionIndex] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
     3060                PatchpointExceptionHandle handle = preparePatchpointForExceptions(m_currentBlock, patchpoint);
     3061                patchpoint->setGenerator([this, handle, unlinkedWasmToWasmCalls, functionIndex] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
    25313062                    AllowMacroScratchRegisterUsage allowScratch(jit);
     3063                    handle.generate(jit, params, this);
    25323064                    CCallHelpers::Call call = jit.threadSafePatchableNearCall();
    25333065                    jit.addLinkTask([unlinkedWasmToWasmCalls, call, functionIndex] (LinkBuffer& linkBuffer) {
     
    25443076auto B3IRGenerator::addCallIndirect(unsigned tableIndex, const Signature& signature, Vector<ExpressionType>& args, ResultList& results) -> PartialResult
    25453077{
    2546     ExpressionType calleeIndex = args.takeLast();
     3078    Value* calleeIndex = get(args.takeLast());
    25473079    ASSERT(signature.argumentCount() == args.size());
    25483080
     
    25533085    m_maxNumJSCallArguments = std::max(m_maxNumJSCallArguments, static_cast<uint32_t>(args.size()));
    25543086
    2555     ExpressionType callableFunctionBuffer;
    2556     ExpressionType instancesBuffer;
    2557     ExpressionType callableFunctionBufferLength;
     3087    Value* callableFunctionBuffer;
     3088    Value* instancesBuffer;
     3089    Value* callableFunctionBufferLength;
    25583090    {
    2559         ExpressionType table = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(),
     3091        Value* table = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(),
    25603092            instanceValue(), safeCast<int32_t>(Instance::offsetOfTablePtr(m_numImportFunctions, tableIndex)));
    25613093        callableFunctionBuffer = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(),
     
    25793111    calleeIndex = m_currentBlock->appendNew<Value>(m_proc, ZExt32, origin(), calleeIndex);
    25803112
    2581     ExpressionType callableFunction;
     3113    Value* callableFunction;
    25823114    {
    25833115        // Compute the offset in the table index space we are looking for.
    2584         ExpressionType offset = m_currentBlock->appendNew<Value>(m_proc, Mul, origin(),
     3116        Value* offset = m_currentBlock->appendNew<Value>(m_proc, Mul, origin(),
    25853117            calleeIndex, constant(pointerType(), sizeof(WasmToWasmImportableFunction)));
    25863118        callableFunction = m_currentBlock->appendNew<Value>(m_proc, Add, origin(), callableFunctionBuffer, offset);
     
    25893121        // FIXME: when we have trap handlers, we can just let the call fail because Signature::invalidIndex is 0. https://bugs.webkit.org/show_bug.cgi?id=177210
    25903122        static_assert(sizeof(WasmToWasmImportableFunction::signatureIndex) == sizeof(uint64_t), "Load codegen assumes i64");
    2591         ExpressionType calleeSignatureIndex = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, Int64, origin(), callableFunction, safeCast<int32_t>(WasmToWasmImportableFunction::offsetOfSignatureIndex()));
     3123        Value* calleeSignatureIndex = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, Int64, origin(), callableFunction, safeCast<int32_t>(WasmToWasmImportableFunction::offsetOfSignatureIndex()));
    25923124        {
    25933125            CheckValue* check = m_currentBlock->appendNew<CheckValue>(m_proc, Check, origin(),
     
    26033135        // Check the signature matches the value we expect.
    26043136        {
    2605             ExpressionType expectedSignatureIndex = m_currentBlock->appendNew<Const64Value>(m_proc, origin(), SignatureInformation::get(signature));
     3137            Value* expectedSignatureIndex = m_currentBlock->appendNew<Const64Value>(m_proc, origin(), SignatureInformation::get(signature));
    26063138            CheckValue* check = m_currentBlock->appendNew<CheckValue>(m_proc, Check, origin(),
    26073139                m_currentBlock->appendNew<Value>(m_proc, NotEqual, origin(), calleeSignatureIndex, expectedSignatureIndex));
     
    26173149    Value* calleeInstance = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(),
    26183150        m_currentBlock->appendNew<Value>(m_proc, Add, origin(), instancesBuffer, offset));
    2619     ExpressionType calleeCode = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(),
     3151    Value* calleeCode = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(),
    26203152        m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(), callableFunction,
    26213153            safeCast<int32_t>(WasmToWasmImportableFunction::offsetOfEntrypointLoadLocation())));
     
    26263158auto B3IRGenerator::addCallRef(const Signature& signature, Vector<ExpressionType>& args, ResultList& results) -> PartialResult
    26273159{
    2628     ExpressionType callee = args.takeLast();
     3160    Value* callee = get(args.takeLast());
    26293161    ASSERT(signature.argumentCount() == args.size());
    26303162    m_makesCalls = true;
     
    26433175        m_currentBlock->appendNew<Value>(m_proc, Add, origin(), jsCalleeInstance, instanceOffset));
    26443176
    2645     ExpressionType calleeCode = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(),
     3177    Value* calleeCode = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(),
    26463178        m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(), callee,
    26473179            safeCast<int32_t>(WebAssemblyFunctionBase::offsetOfEntrypointLoadLocation())));
     
    26503182}
    26513183
    2652 void B3IRGenerator::unify(const ExpressionType phi, const ExpressionType source)
    2653 {
    2654     m_currentBlock->appendNew<UpsilonValue>(m_proc, origin(), source, phi);
    2655 }
    2656 
    2657 void B3IRGenerator::unifyValuesWithBlock(const Stack& resultStack, const ResultList& result)
    2658 {
    2659     ASSERT(result.size() <= resultStack.size());
    2660 
    2661     for (size_t i = 0; i < result.size(); ++i)
    2662         unify(result[result.size() - 1 - i], resultStack.at(resultStack.size() - 1 - i));
     3184void B3IRGenerator::unify(Value* phi, const ExpressionType source)
     3185{
     3186    m_currentBlock->appendNew<UpsilonValue>(m_proc, origin(), get(source), phi);
     3187}
     3188
     3189void B3IRGenerator::unifyValuesWithBlock(const Stack& resultStack, const ControlData& block)
     3190{
     3191    const Vector<Value*>& phis = block.phis;
     3192    size_t resultSize = phis.size();
     3193
     3194    ASSERT(resultSize <= resultStack.size());
     3195
     3196    for (size_t i = 0; i < resultSize; ++i)
     3197        unify(phis[resultSize - 1 - i], resultStack.at(resultStack.size() - 1 - i));
    26633198}
    26643199
     
    27043239    compilationContext.embedderEntrypointJIT = makeUnique<CCallHelpers>();
    27053240    compilationContext.wasmEntrypointJIT = makeUnique<CCallHelpers>();
    2706 
    2707     Procedure procedure;
     3241    compilationContext.procedure = makeUnique<Procedure>();
     3242
     3243    Procedure& procedure = *compilationContext.procedure;
     3244
     3245    compilationContext.wasmEntrypointJIT = makeUnique<CCallHelpers>();
    27083246
    27093247    procedure.setOriginPrinter([] (PrintStream& out, Origin origin) {
     
    27263264    WASM_FAIL_IF_HELPER_FAILS(parser.parse());
    27273265
     3266    irGenerator.insertEntrySwitch();
    27283267    irGenerator.insertConstants();
    27293268
     
    27373276   
    27383277    {
     3278        if (shouldDumpDisassemblyFor(compilationMode))
     3279            procedure.code().setDisassembler(makeUnique<B3::Air::Disassembler>());
    27393280        B3::prepareForGeneration(procedure);
    27403281        B3::generate(procedure, *compilationContext.wasmEntrypointJIT);
     
    27433284    }
    27443285
     3286    result->stackmaps = irGenerator.takeStackmaps();
     3287    result->exceptionHandlers = irGenerator.takeExceptionHandlers();
     3288
    27453289    return result;
    27463290}
    27473291
     3292void computeExceptionHandlerLocations(Vector<CodeLocationLabel<ExceptionHandlerPtrTag>>& handlers, const InternalFunction* function, const CompilationContext& context, LinkBuffer& linkBuffer)
     3293{
     3294    if (!context.procedure)
     3295        return;
     3296
     3297    unsigned entrypointIndex = 0;
     3298    unsigned numEntrypoints = context.procedure->numEntrypoints();
     3299    for (const UnlinkedHandlerInfo& handlerInfo : function->exceptionHandlers) {
     3300        RELEASE_ASSERT(entrypointIndex < numEntrypoints);
     3301        if (handlerInfo.m_type == HandlerType::Delegate) {
     3302            handlers.append({ });
     3303            continue;
     3304        }
     3305
     3306        ++entrypointIndex;
     3307        handlers.append(linkBuffer.locationOf<ExceptionHandlerPtrTag>(context.procedure->code().entrypointLabel(entrypointIndex)));
     3308    }
     3309    RELEASE_ASSERT(entrypointIndex == numEntrypoints - 1);
     3310}
     3311
    27483312// Custom wasm ops. These are the ones too messy to do in wasm.json.
    27493313
    2750 void B3IRGenerator::emitChecksForModOrDiv(B3::Opcode operation, ExpressionType left, ExpressionType right)
     3314void B3IRGenerator::emitChecksForModOrDiv(B3::Opcode operation, Value* left, Value* right)
    27513315{
    27523316    ASSERT(operation == Div || operation == Mod || operation == UDiv || operation == UMod);
     
    27773341
    27783342template<>
    2779 auto B3IRGenerator::addOp<OpType::I32DivS>(ExpressionType left, ExpressionType right, ExpressionType& result) -> PartialResult
     3343auto B3IRGenerator::addOp<OpType::I32DivS>(ExpressionType leftVar, ExpressionType rightVar, ExpressionType& result) -> PartialResult
    27803344{
    27813345    const B3::Opcode op = Div;
     3346    Value* left = get(leftVar);
     3347    Value* right = get(rightVar);
    27823348    emitChecksForModOrDiv(op, left, right);
    2783     result = m_currentBlock->appendNew<Value>(m_proc, op, origin(), left, right);
     3349    result = push(m_currentBlock->appendNew<Value>(m_proc, op, origin(), left, right));
    27843350    return { };
    27853351}
    27863352
    27873353template<>
    2788 auto B3IRGenerator::addOp<OpType::I32RemS>(ExpressionType left, ExpressionType right, ExpressionType& result) -> PartialResult
     3354auto B3IRGenerator::addOp<OpType::I32RemS>(ExpressionType leftVar, ExpressionType rightVar, ExpressionType& result) -> PartialResult
    27893355{
    27903356    const B3::Opcode op = Mod;
     3357    Value* left = get(leftVar);
     3358    Value* right = get(rightVar);
    27913359    emitChecksForModOrDiv(op, left, right);
    2792     result = m_currentBlock->appendNew<Value>(m_proc, chill(op), origin(), left, right);
     3360    result = push(m_currentBlock->appendNew<Value>(m_proc, chill(op), origin(), left, right));
    27933361    return { };
    27943362}
    27953363
    27963364template<>
    2797 auto B3IRGenerator::addOp<OpType::I32DivU>(ExpressionType left, ExpressionType right, ExpressionType& result) -> PartialResult
     3365auto B3IRGenerator::addOp<OpType::I32DivU>(ExpressionType leftVar, ExpressionType rightVar, ExpressionType& result) -> PartialResult
    27983366{
    27993367    const B3::Opcode op = UDiv;
     3368    Value* left = get(leftVar);
     3369    Value* right = get(rightVar);
    28003370    emitChecksForModOrDiv(op, left, right);
    2801     result = m_currentBlock->appendNew<Value>(m_proc, op, origin(), left, right);
     3371    result = push(m_currentBlock->appendNew<Value>(m_proc, op, origin(), left, right));
    28023372    return { };
    28033373}
    28043374
    28053375template<>
    2806 auto B3IRGenerator::addOp<OpType::I32RemU>(ExpressionType left, ExpressionType right, ExpressionType& result) -> PartialResult
     3376auto B3IRGenerator::addOp<OpType::I32RemU>(ExpressionType leftVar, ExpressionType rightVar, ExpressionType& result) -> PartialResult
    28073377{
    28083378    const B3::Opcode op = UMod;
     3379    Value* left = get(leftVar);
     3380    Value* right = get(rightVar);
    28093381    emitChecksForModOrDiv(op, left, right);
    2810     result = m_currentBlock->appendNew<Value>(m_proc, op, origin(), left, right);
     3382    result = push(m_currentBlock->appendNew<Value>(m_proc, op, origin(), left, right));
    28113383    return { };
    28123384}
    28133385
    28143386template<>
    2815 auto B3IRGenerator::addOp<OpType::I64DivS>(ExpressionType left, ExpressionType right, ExpressionType& result) -> PartialResult
     3387auto B3IRGenerator::addOp<OpType::I64DivS>(ExpressionType leftVar, ExpressionType rightVar, ExpressionType& result) -> PartialResult
    28163388{
    28173389    const B3::Opcode op = Div;
     3390    Value* left = get(leftVar);
     3391    Value* right = get(rightVar);
    28183392    emitChecksForModOrDiv(op, left, right);
    2819     result = m_currentBlock->appendNew<Value>(m_proc, op, origin(), left, right);
     3393    result = push(m_currentBlock->appendNew<Value>(m_proc, op, origin(), left, right));
    28203394    return { };
    28213395}
    28223396
    28233397template<>
    2824 auto B3IRGenerator::addOp<OpType::I64RemS>(ExpressionType left, ExpressionType right, ExpressionType& result) -> PartialResult
     3398auto B3IRGenerator::addOp<OpType::I64RemS>(ExpressionType leftVar, ExpressionType rightVar, ExpressionType& result) -> PartialResult
    28253399{
    28263400    const B3::Opcode op = Mod;
     3401    Value* left = get(leftVar);
     3402    Value* right = get(rightVar);
    28273403    emitChecksForModOrDiv(op, left, right);
    2828     result = m_currentBlock->appendNew<Value>(m_proc, chill(op), origin(), left, right);
     3404    result = push(m_currentBlock->appendNew<Value>(m_proc, chill(op), origin(), left, right));
    28293405    return { };
    28303406}
    28313407
    28323408template<>
    2833 auto B3IRGenerator::addOp<OpType::I64DivU>(ExpressionType left, ExpressionType right, ExpressionType& result) -> PartialResult
     3409auto B3IRGenerator::addOp<OpType::I64DivU>(ExpressionType leftVar, ExpressionType rightVar, ExpressionType& result) -> PartialResult
    28343410{
    28353411    const B3::Opcode op = UDiv;
     3412    Value* left = get(leftVar);
     3413    Value* right = get(rightVar);
    28363414    emitChecksForModOrDiv(op, left, right);
    2837     result = m_currentBlock->appendNew<Value>(m_proc, op, origin(), left, right);
     3415    result = push(m_currentBlock->appendNew<Value>(m_proc, op, origin(), left, right));
    28383416    return { };
    28393417}
    28403418
    28413419template<>
    2842 auto B3IRGenerator::addOp<OpType::I64RemU>(ExpressionType left, ExpressionType right, ExpressionType& result) -> PartialResult
     3420auto B3IRGenerator::addOp<OpType::I64RemU>(ExpressionType leftVar, ExpressionType rightVar, ExpressionType& result) -> PartialResult
    28433421{
    28443422    const B3::Opcode op = UMod;
     3423    Value* left = get(leftVar);
     3424    Value* right = get(rightVar);
    28453425    emitChecksForModOrDiv(op, left, right);
    2846     result = m_currentBlock->appendNew<Value>(m_proc, op, origin(), left, right);
     3426    result = push(m_currentBlock->appendNew<Value>(m_proc, op, origin(), left, right));
    28473427    return { };
    28483428}
    28493429
    28503430template<>
    2851 auto B3IRGenerator::addOp<OpType::I32Ctz>(ExpressionType arg, ExpressionType& result) -> PartialResult
    2852 {
     3431auto B3IRGenerator::addOp<OpType::I32Ctz>(ExpressionType argVar, ExpressionType& result) -> PartialResult
     3432{
     3433    Value* arg = get(argVar);
    28533434    PatchpointValue* patchpoint = m_currentBlock->appendNew<PatchpointValue>(m_proc, Int32, origin());
    28543435    patchpoint->append(arg, ValueRep::SomeRegister);
     
    28573438    });
    28583439    patchpoint->effects = Effects::none();
    2859     result = patchpoint;
     3440    result = push(patchpoint);
    28603441    return { };
    28613442}
    28623443
    28633444template<>
    2864 auto B3IRGenerator::addOp<OpType::I64Ctz>(ExpressionType arg, ExpressionType& result) -> PartialResult
    2865 {
     3445auto B3IRGenerator::addOp<OpType::I64Ctz>(ExpressionType argVar, ExpressionType& result) -> PartialResult
     3446{
     3447    Value* arg = get(argVar);
    28663448    PatchpointValue* patchpoint = m_currentBlock->appendNew<PatchpointValue>(m_proc, Int64, origin());
    28673449    patchpoint->append(arg, ValueRep::SomeRegister);
     
    28703452    });
    28713453    patchpoint->effects = Effects::none();
    2872     result = patchpoint;
     3454    result = push(patchpoint);
    28733455    return { };
    28743456}
    28753457
    28763458template<>
    2877 auto B3IRGenerator::addOp<OpType::I32Popcnt>(ExpressionType arg, ExpressionType& result) -> PartialResult
    2878 {
     3459auto B3IRGenerator::addOp<OpType::I32Popcnt>(ExpressionType argVar, ExpressionType& result) -> PartialResult
     3460{
     3461    Value* arg = get(argVar);
    28793462#if CPU(X86_64)
    28803463    if (MacroAssembler::supportsCountPopulation()) {
     
    28853468        });
    28863469        patchpoint->effects = Effects::none();
    2887         result = patchpoint;
     3470        result = push(patchpoint);
    28883471        return { };
    28893472    }
     
    28913474
    28923475    Value* funcAddress = m_currentBlock->appendNew<ConstPtrValue>(m_proc, origin(), tagCFunction<OperationPtrTag>(operationPopcount32));
    2893     result = m_currentBlock->appendNew<CCallValue>(m_proc, Int32, origin(), Effects::none(), funcAddress, arg);
     3476    result = push(m_currentBlock->appendNew<CCallValue>(m_proc, Int32, origin(), Effects::none(), funcAddress, arg));
    28943477    return { };
    28953478}
    28963479
    28973480template<>
    2898 auto B3IRGenerator::addOp<OpType::I64Popcnt>(ExpressionType arg, ExpressionType& result) -> PartialResult
    2899 {
     3481auto B3IRGenerator::addOp<OpType::I64Popcnt>(ExpressionType argVar, ExpressionType& result) -> PartialResult
     3482{
     3483    Value* arg = get(argVar);
    29003484#if CPU(X86_64)
    29013485    if (MacroAssembler::supportsCountPopulation()) {
     
    29063490        });
    29073491        patchpoint->effects = Effects::none();
    2908         result = patchpoint;
     3492        result = push(patchpoint);
    29093493        return { };
    29103494    }
     
    29123496
    29133497    Value* funcAddress = m_currentBlock->appendNew<ConstPtrValue>(m_proc, origin(), tagCFunction<OperationPtrTag>(operationPopcount64));
    2914     result = m_currentBlock->appendNew<CCallValue>(m_proc, Int64, origin(), Effects::none(), funcAddress, arg);
     3498    result = push(m_currentBlock->appendNew<CCallValue>(m_proc, Int64, origin(), Effects::none(), funcAddress, arg));
    29153499    return { };
    29163500}
    29173501
    29183502template<>
    2919 auto B3IRGenerator::addOp<F64ConvertUI64>(ExpressionType arg, ExpressionType& result) -> PartialResult
    2920 {
     3503auto B3IRGenerator::addOp<F64ConvertUI64>(ExpressionType argVar, ExpressionType& result) -> PartialResult
     3504{
     3505    Value* arg = get(argVar);
    29213506    PatchpointValue* patchpoint = m_currentBlock->appendNew<PatchpointValue>(m_proc, Double, origin());
    29223507    if (isX86())
     
    29333518    });
    29343519    patchpoint->effects = Effects::none();
    2935     result = patchpoint;
     3520    result = push(patchpoint);
    29363521    return { };
    29373522}
    29383523
    29393524template<>
    2940 auto B3IRGenerator::addOp<OpType::F32ConvertUI64>(ExpressionType arg, ExpressionType& result) -> PartialResult
    2941 {
     3525auto B3IRGenerator::addOp<OpType::F32ConvertUI64>(ExpressionType argVar, ExpressionType& result) -> PartialResult
     3526{
     3527    Value* arg = get(argVar);
    29423528    PatchpointValue* patchpoint = m_currentBlock->appendNew<PatchpointValue>(m_proc, Float, origin());
    29433529    if (isX86())
     
    29543540    });
    29553541    patchpoint->effects = Effects::none();
    2956     result = patchpoint;
     3542    result = push(patchpoint);
    29573543    return { };
    29583544}
    29593545
    29603546template<>
    2961 auto B3IRGenerator::addOp<OpType::F64Nearest>(ExpressionType arg, ExpressionType& result) -> PartialResult
    2962 {
     3547auto B3IRGenerator::addOp<OpType::F64Nearest>(ExpressionType argVar, ExpressionType& result) -> PartialResult
     3548{
     3549    Value* arg = get(argVar);
    29633550    PatchpointValue* patchpoint = m_currentBlock->appendNew<PatchpointValue>(m_proc, Double, origin());
    29643551    patchpoint->append(arg, ValueRep::SomeRegister);
     
    29673554    });
    29683555    patchpoint->effects = Effects::none();
    2969     result = patchpoint;
     3556    result = push(patchpoint);
    29703557    return { };
    29713558}
    29723559
    29733560template<>
    2974 auto B3IRGenerator::addOp<OpType::F32Nearest>(ExpressionType arg, ExpressionType& result) -> PartialResult
    2975 {
     3561auto B3IRGenerator::addOp<OpType::F32Nearest>(ExpressionType argVar, ExpressionType& result) -> PartialResult
     3562{
     3563    Value* arg = get(argVar);
    29763564    PatchpointValue* patchpoint = m_currentBlock->appendNew<PatchpointValue>(m_proc, Float, origin());
    29773565    patchpoint->append(arg, ValueRep::SomeRegister);
     
    29803568    });
    29813569    patchpoint->effects = Effects::none();
    2982     result = patchpoint;
     3570    result = push(patchpoint);
    29833571    return { };
    29843572}
    29853573
    29863574template<>
    2987 auto B3IRGenerator::addOp<OpType::F64Trunc>(ExpressionType arg, ExpressionType& result) -> PartialResult
    2988 {
     3575auto B3IRGenerator::addOp<OpType::F64Trunc>(ExpressionType argVar, ExpressionType& result) -> PartialResult
     3576{
     3577    Value* arg = get(argVar);
    29893578    PatchpointValue* patchpoint = m_currentBlock->appendNew<PatchpointValue>(m_proc, Double, origin());
    29903579    patchpoint->append(arg, ValueRep::SomeRegister);
     
    29933582    });
    29943583    patchpoint->effects = Effects::none();
    2995     result = patchpoint;
     3584    result = push(patchpoint);
    29963585    return { };
    29973586}
    29983587
    29993588template<>
    3000 auto B3IRGenerator::addOp<OpType::F32Trunc>(ExpressionType arg, ExpressionType& result) -> PartialResult
    3001 {
     3589auto B3IRGenerator::addOp<OpType::F32Trunc>(ExpressionType argVar, ExpressionType& result) -> PartialResult
     3590{
     3591    Value* arg = get(argVar);
    30023592    PatchpointValue* patchpoint = m_currentBlock->appendNew<PatchpointValue>(m_proc, Float, origin());
    30033593    patchpoint->append(arg, ValueRep::SomeRegister);
     
    30063596    });
    30073597    patchpoint->effects = Effects::none();
    3008     result = patchpoint;
     3598    result = push(patchpoint);
    30093599    return { };
    30103600}
    30113601
    30123602template<>
    3013 auto B3IRGenerator::addOp<OpType::I32TruncSF64>(ExpressionType arg, ExpressionType& result) -> PartialResult
    3014 {
     3603auto B3IRGenerator::addOp<OpType::I32TruncSF64>(ExpressionType argVar, ExpressionType& result) -> PartialResult
     3604{
     3605    Value* arg = get(argVar);
    30153606    Value* max = constant(Double, bitwise_cast<uint64_t>(-static_cast<double>(std::numeric_limits<int32_t>::min())));
    30163607    Value* min = constant(Double, bitwise_cast<uint64_t>(static_cast<double>(std::numeric_limits<int32_t>::min()) - 1.0));
     
    30293620    });
    30303621    patchpoint->effects = Effects::none();
    3031     result = patchpoint;
     3622    result = push(patchpoint);
    30323623    return { };
    30333624}
    30343625
    30353626template<>
    3036 auto B3IRGenerator::addOp<OpType::I32TruncSF32>(ExpressionType arg, ExpressionType& result) -> PartialResult
    3037 {
     3627auto B3IRGenerator::addOp<OpType::I32TruncSF32>(ExpressionType argVar, ExpressionType& result) -> PartialResult
     3628{
     3629    Value* arg = get(argVar);
    30383630    Value* max = constant(Float, bitwise_cast<uint32_t>(-static_cast<float>(std::numeric_limits<int32_t>::min())));
    30393631    Value* min = constant(Float, bitwise_cast<uint32_t>(static_cast<float>(std::numeric_limits<int32_t>::min())));
     
    30523644    });
    30533645    patchpoint->effects = Effects::none();
    3054     result = patchpoint;
     3646    result = push(patchpoint);
    30553647    return { };
    30563648}
     
    30583650
    30593651template<>
    3060 auto B3IRGenerator::addOp<OpType::I32TruncUF64>(ExpressionType arg, ExpressionType& result) -> PartialResult
    3061 {
     3652auto B3IRGenerator::addOp<OpType::I32TruncUF64>(ExpressionType argVar, ExpressionType& result) -> PartialResult
     3653{
     3654    Value* arg = get(argVar);
    30623655    Value* max = constant(Double, bitwise_cast<uint64_t>(static_cast<double>(std::numeric_limits<int32_t>::min()) * -2.0));
    30633656    Value* min = constant(Double, bitwise_cast<uint64_t>(-1.0));
     
    30763669    });
    30773670    patchpoint->effects = Effects::none();
    3078     result = patchpoint;
     3671    result = push(patchpoint);
    30793672    return { };
    30803673}
    30813674
    30823675template<>
    3083 auto B3IRGenerator::addOp<OpType::I32TruncUF32>(ExpressionType arg, ExpressionType& result) -> PartialResult
    3084 {
     3676auto B3IRGenerator::addOp<OpType::I32TruncUF32>(ExpressionType argVar, ExpressionType& result) -> PartialResult
     3677{
     3678    Value* arg = get(argVar);
    30853679    Value* max = constant(Float, bitwise_cast<uint32_t>(static_cast<float>(std::numeric_limits<int32_t>::min()) * static_cast<float>(-2.0)));
    30863680    Value* min = constant(Float, bitwise_cast<uint32_t>(static_cast<float>(-1.0)));
     
    30993693    });
    31003694    patchpoint->effects = Effects::none();
    3101     result = patchpoint;
     3695    result = push(patchpoint);
    31023696    return { };
    31033697}
    31043698
    31053699template<>
    3106 auto B3IRGenerator::addOp<OpType::I64TruncSF64>(ExpressionType arg, ExpressionType& result) -> PartialResult
    3107 {
     3700auto B3IRGenerator::addOp<OpType::I64TruncSF64>(ExpressionType argVar, ExpressionType& result) -> PartialResult
     3701{
     3702    Value* arg = get(argVar);
    31083703    Value* max = constant(Double, bitwise_cast<uint64_t>(-static_cast<double>(std::numeric_limits<int64_t>::min())));
    31093704    Value* min = constant(Double, bitwise_cast<uint64_t>(static_cast<double>(std::numeric_limits<int64_t>::min())));
     
    31223717    });
    31233718    patchpoint->effects = Effects::none();
    3124     result = patchpoint;
     3719    result = push(patchpoint);
    31253720    return { };
    31263721}
    31273722
    31283723template<>
    3129 auto B3IRGenerator::addOp<OpType::I64TruncUF64>(ExpressionType arg, ExpressionType& result) -> PartialResult
    3130 {
     3724auto B3IRGenerator::addOp<OpType::I64TruncUF64>(ExpressionType argVar, ExpressionType& result) -> PartialResult
     3725{
     3726    Value* arg = get(argVar);
    31313727    Value* max = constant(Double, bitwise_cast<uint64_t>(static_cast<double>(std::numeric_limits<int64_t>::min()) * -2.0));
    31323728    Value* min = constant(Double, bitwise_cast<uint64_t>(-1.0));
     
    31653761    });
    31663762    patchpoint->effects = Effects::none();
    3167     result = patchpoint;
     3763    result = push(patchpoint);
    31683764    return { };
    31693765}
    31703766
    31713767template<>
    3172 auto B3IRGenerator::addOp<OpType::I64TruncSF32>(ExpressionType arg, ExpressionType& result) -> PartialResult
    3173 {
     3768auto B3IRGenerator::addOp<OpType::I64TruncSF32>(ExpressionType argVar, ExpressionType& result) -> PartialResult
     3769{
     3770    Value* arg = get(argVar);
    31743771    Value* max = constant(Float, bitwise_cast<uint32_t>(-static_cast<float>(std::numeric_limits<int64_t>::min())));
    31753772    Value* min = constant(Float, bitwise_cast<uint32_t>(static_cast<float>(std::numeric_limits<int64_t>::min())));
     
    31883785    });
    31893786    patchpoint->effects = Effects::none();
    3190     result = patchpoint;
     3787    result = push(patchpoint);
    31913788    return { };
    31923789}
    31933790
    31943791template<>
    3195 auto B3IRGenerator::addOp<OpType::I64TruncUF32>(ExpressionType arg, ExpressionType& result) -> PartialResult
    3196 {
     3792auto B3IRGenerator::addOp<OpType::I64TruncUF32>(ExpressionType argVar, ExpressionType& result) -> PartialResult
     3793{
     3794    Value* arg = get(argVar);
    31973795    Value* max = constant(Float, bitwise_cast<uint32_t>(static_cast<float>(std::numeric_limits<int64_t>::min()) * static_cast<float>(-2.0)));
    31983796    Value* min = constant(Float, bitwise_cast<uint32_t>(static_cast<float>(-1.0)));
     
    32313829    });
    32323830    patchpoint->effects = Effects::none();
    3233     result = patchpoint;
     3831    result = push(patchpoint);
    32343832    return { };
    32353833}
  • trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.h

    r271775 r283852  
    4141extern "C" void dumpProcedure(void*);
    4242
    43 namespace JSC { namespace Wasm {
     43namespace JSC {
     44
     45namespace B3 {
     46class Procedure;
     47}
     48
     49namespace Wasm {
    4450
    4551class MemoryInformation;
     
    4955    std::unique_ptr<CCallHelpers> wasmEntrypointJIT;
    5056    std::unique_ptr<OpaqueByproducts> wasmEntrypointByproducts;
     57    std::unique_ptr<B3::Procedure> procedure { nullptr };
    5158};
    5259
    5360Expected<std::unique_ptr<InternalFunction>, String> parseAndCompile(CompilationContext&, const FunctionData&, const Signature&, Vector<UnlinkedWasmToWasmCall>&, unsigned& osrEntryScratchBufferSize, const ModuleInformation&, MemoryMode, CompilationMode, uint32_t functionIndex, uint32_t loopIndexForOSREntry, TierUpCount* = nullptr);
    5461
     62void computeExceptionHandlerLocations(Vector<CodeLocationLabel<ExceptionHandlerPtrTag>>& handlers, const InternalFunction*, const CompilationContext&, LinkBuffer&);
     63
    5564} } // namespace JSC::Wasm
    5665
  • trunk/Source/JavaScriptCore/wasm/WasmBBQPlan.cpp

    r278093 r283852  
    6767
    6868    m_wasmInternalFunctions.resize(functions.size());
     69    m_exceptionHandlerLocations.resize(functions.size());
    6970    m_compilationContexts.resize(functions.size());
    7071    m_tierUpCounts.resize(functions.size());
     
    110111    }
    111112
     113    Vector<CodeLocationLabel<ExceptionHandlerPtrTag>> exceptionHandlerLocations;
     114    computeExceptionHandlerLocations(exceptionHandlerLocations, function.get(), context, linkBuffer);
     115
    112116    size_t functionIndexSpace = m_functionIndex + m_moduleInformation->importFunctionCount();
    113117    SignatureIndex signatureIndex = m_moduleInformation->internalFunctionSignatureIndices[m_functionIndex];
     
    119123    MacroAssemblerCodePtr<WasmEntryPtrTag> entrypoint;
    120124    {
    121         Ref<BBQCallee> callee = BBQCallee::create(WTFMove(function->entrypoint), functionIndexSpace, m_moduleInformation->nameSection->get(functionIndexSpace), WTFMove(tierUp), WTFMove(unlinkedWasmToWasmCalls));
     125        Ref<BBQCallee> callee = BBQCallee::create(WTFMove(function->entrypoint), functionIndexSpace, m_moduleInformation->nameSection->get(functionIndexSpace), WTFMove(tierUp), WTFMove(unlinkedWasmToWasmCalls), WTFMove(function->stackmaps), WTFMove(function->exceptionHandlers), WTFMove(exceptionHandlerLocations));
    122126        MacroAssembler::repatchPointer(function->calleeMoveLocation, CalleeBits::boxWasm(callee.ptr()));
    123127        ASSERT(!m_codeBlock->m_bbqCallees[m_functionIndex]);
     
    195199    if (Options::webAssemblyBBQAirModeThreshold() && m_moduleInformation->codeSectionSize >= Options::webAssemblyBBQAirModeThreshold())
    196200        forceUsingB3 = true;
    197 
    198     if (!forceUsingB3 && Options::wasmBBQUsesAir())
     201    else if (!m_moduleInformation->m_functionDoesNotUseExceptions.quickGet(functionIndex))
     202        forceUsingB3 = true;
     203    else if (!Options::wasmBBQUsesAir())
     204        forceUsingB3 = true;
     205
     206    if (forceUsingB3)
     207        parseAndCompileResult = parseAndCompile(context, function, signature, unlinkedWasmToWasmCalls, osrEntryScratchBufferSize, m_moduleInformation.get(), m_mode, CompilationMode::BBQMode, functionIndex, UINT32_MAX, tierUp);
     208    else
    199209        parseAndCompileResult = parseAndCompileAir(context, function, signature, unlinkedWasmToWasmCalls, m_moduleInformation.get(), m_mode, functionIndex, tierUp);
    200     else
    201         parseAndCompileResult = parseAndCompile(context, function, signature, unlinkedWasmToWasmCalls, osrEntryScratchBufferSize, m_moduleInformation.get(), m_mode, CompilationMode::BBQMode, functionIndex, UINT32_MAX, tierUp);
    202210
    203211    if (UNLIKELY(!parseAndCompileResult)) {
     
    223231        ASSERT(functionIndexSpace < m_moduleInformation->functionIndexSpaceSize());
    224232        {
     233            InternalFunction* function = m_wasmInternalFunctions[functionIndex].get();
    225234            LinkBuffer linkBuffer(*context.wasmEntrypointJIT, nullptr, LinkBuffer::Profile::Wasm, JITCompilationCanFail);
    226235            if (UNLIKELY(linkBuffer.didFailToAllocate())) {
     
    229238            }
    230239
    231             m_wasmInternalFunctions[functionIndex]->entrypoint.compilation = makeUnique<Compilation>(
     240            computeExceptionHandlerLocations(m_exceptionHandlerLocations[functionIndex], function, context, linkBuffer);
     241            function->entrypoint.compilation = makeUnique<Compilation>(
    232242                FINALIZE_CODE(linkBuffer, JITCompilationPtrTag, "WebAssembly BBQ function[%i] %s name %s", functionIndex, signature.toString().ascii().data(), makeString(IndexOrName(functionIndexSpace, m_moduleInformation->nameSection->get(functionIndexSpace))).ascii().data()),
    233243                WTFMove(context.wasmEntrypointByproducts));
     
    273283        InternalFunction* function = m_wasmInternalFunctions[internalFunctionIndex].get();
    274284        size_t functionIndexSpace = internalFunctionIndex + m_moduleInformation->importFunctionCount();
    275         Ref<BBQCallee> wasmEntrypointCallee = BBQCallee::create(WTFMove(function->entrypoint), functionIndexSpace, m_moduleInformation->nameSection->get(functionIndexSpace), WTFMove(m_tierUpCounts[internalFunctionIndex]), WTFMove(m_unlinkedWasmToWasmCalls[internalFunctionIndex]));
     285        Ref<BBQCallee> wasmEntrypointCallee = BBQCallee::create(WTFMove(function->entrypoint), functionIndexSpace, m_moduleInformation->nameSection->get(functionIndexSpace), WTFMove(m_tierUpCounts[internalFunctionIndex]), WTFMove(m_unlinkedWasmToWasmCalls[internalFunctionIndex]), WTFMove(function->stackmaps), WTFMove(function->exceptionHandlers), WTFMove(m_exceptionHandlerLocations[internalFunctionIndex]));
    276286        MacroAssembler::repatchPointer(function->calleeMoveLocation, CalleeBits::boxWasm(wasmEntrypointCallee.ptr()));
    277287
  • trunk/Source/JavaScriptCore/wasm/WasmBBQPlan.h

    r278093 r283852  
    8484
    8585    Vector<std::unique_ptr<InternalFunction>> m_wasmInternalFunctions;
     86    Vector<Vector<CodeLocationLabel<ExceptionHandlerPtrTag>>> m_exceptionHandlerLocations;
    8687    HashMap<uint32_t, std::unique_ptr<InternalFunction>, DefaultHash<uint32_t>, WTF::UnsignedWithZeroKeyHashTraits<uint32_t>> m_embedderToWasmInternalFunctions;
    8788    Vector<CompilationContext> m_compilationContexts;
  • trunk/Source/JavaScriptCore/wasm/WasmCallee.cpp

    r261755 r283852  
    2929#if ENABLE(WEBASSEMBLY)
    3030
     31#include "LLIntExceptions.h"
    3132#include "WasmCalleeRegistry.h"
    3233#include "WasmCallingConvention.h"
     
    5758}
    5859
     60const HandlerInfo* Callee::handlerForIndex(Instance& instance, unsigned index, const Tag* tag)
     61{
     62    ASSERT(hasExceptionHandlers());
     63    return HandlerInfo::handlerForIndex(instance, m_exceptionHandlers, index, tag);
     64}
     65
    5966JITCallee::JITCallee(Wasm::CompilationMode compilationMode, Entrypoint&& entrypoint)
    6067    : Callee(compilationMode)
     
    6875    , m_entrypoint(WTFMove(entrypoint))
    6976{
     77}
     78
     79LLIntCallee::LLIntCallee(std::unique_ptr<FunctionCodeBlock> codeBlock, size_t index, std::pair<const Name*, RefPtr<NameSection>>&& name)
     80    : Callee(Wasm::CompilationMode::LLIntMode, index, WTFMove(name))
     81    , m_codeBlock(WTFMove(codeBlock))
     82{
     83    linkExceptionHandlers();
     84}
     85
     86void LLIntCallee::linkExceptionHandlers()
     87{
     88    if (size_t count = m_codeBlock->numberOfExceptionHandlers()) {
     89        m_exceptionHandlers.resizeToFit(count);
     90        for (size_t i = 0; i < count; i++) {
     91            const UnlinkedHandlerInfo& unlinkedHandler = m_codeBlock->exceptionHandler(i);
     92            HandlerInfo& handler = m_exceptionHandlers[i];
     93            auto& instruction = *m_codeBlock->instructions().at(unlinkedHandler.m_target).ptr();
     94            CodeLocationLabel<ExceptionHandlerPtrTag> target;
     95            if (unlinkedHandler.m_type == HandlerType::Catch)
     96                target = CodeLocationLabel<ExceptionHandlerPtrTag>(LLInt::handleWasmCatch(instruction.width<WasmOpcodeTraits>()).code());
     97            else
     98                target = CodeLocationLabel<ExceptionHandlerPtrTag>(LLInt::handleWasmCatchAll(instruction.width<WasmOpcodeTraits>()).code());
     99
     100            handler.initialize(unlinkedHandler, target);
     101        }
     102    }
    70103}
    71104
     
    105138}
    106139
     140void OptimizingJITCallee::linkExceptionHandlers()
     141{
     142    size_t count = m_unlinkedExceptionHandlers.size();
     143    m_exceptionHandlers.resizeToFit(count);
     144    for (size_t i = 0; i < count; i++) {
     145        HandlerInfo& handler = m_exceptionHandlers[i];
     146        const UnlinkedHandlerInfo& unlinkedHandler = m_unlinkedExceptionHandlers[i];
     147        CodeLocationLabel<ExceptionHandlerPtrTag> location = m_exceptionHandlerLocations[i];
     148        handler.initialize(unlinkedHandler, location);
     149    }
     150    m_unlinkedExceptionHandlers.clear();
     151    m_exceptionHandlerLocations.clear();
     152}
     153
     154const Vector<OSREntryValue>& OptimizingJITCallee::stackmap(CallSiteIndex callSiteIndex) const
     155{
     156    auto iter = m_stackmaps.find(callSiteIndex);
     157    if (iter == m_stackmaps.end()) {
     158        for (auto pair : m_stackmaps) {
     159            dataLog(pair.key.bits(), ": ");
     160            for (auto value : pair.value)
     161                dataLog(value, ", ");
     162            dataLogLn("");
     163        }
     164    }
     165    RELEASE_ASSERT(iter != m_stackmaps.end());
     166    return iter->value;
     167}
     168
     169
    107170} } // namespace JSC::Wasm
    108171
  • trunk/Source/JavaScriptCore/wasm/WasmCallee.h

    r271775 r283852  
    3333#include "WasmFormat.h"
    3434#include "WasmFunctionCodeBlock.h"
     35#include "WasmHandlerInfo.h"
    3536#include "WasmIndexOrName.h"
     37#include "WasmLLIntTierUpCounter.h"
    3638#include "WasmTierUpCount.h"
    3739#include <wtf/ThreadSafeRefCounted.h>
     
    6062    virtual std::tuple<void*, void*> range() const = 0;
    6163
     64    const HandlerInfo* handlerForIndex(Instance&, unsigned, const Tag*);
     65
     66    bool hasExceptionHandlers() const { return !!m_exceptionHandlers.size(); }
     67
    6268#if ENABLE(WEBASSEMBLY_B3JIT)
    6369    virtual void setOSREntryCallee(Ref<OMGForOSREntryCallee>&&)
     
    6874
    6975    void dump(PrintStream&) const;
     76
     77    virtual FunctionCodeBlock* functionCodeBlock() const { return 0; }
    7078
    7179protected:
     
    7684    CompilationMode m_compilationMode;
    7785    IndexOrName m_indexOrName;
     86
     87protected:
     88    Vector<HandlerInfo> m_exceptionHandlers;
    7889};
    7990
     
    100111};
    101112
    102 #if ENABLE(WEBASSEMBLY_B3JIT)
    103 class OMGCallee final : public JITCallee {
    104 public:
    105     static Ref<OMGCallee> create(Wasm::Entrypoint&& entrypoint, size_t index, std::pair<const Name*, RefPtr<NameSection>>&& name, Vector<UnlinkedWasmToWasmCall>&& unlinkedCalls)
    106     {
    107         return adoptRef(*new OMGCallee(WTFMove(entrypoint), index, WTFMove(name), WTFMove(unlinkedCalls)));
    108     }
    109 
    110 private:
    111     OMGCallee(Wasm::Entrypoint&& entrypoint, size_t index, std::pair<const Name*, RefPtr<NameSection>>&& name, Vector<UnlinkedWasmToWasmCall>&& unlinkedCalls)
    112         : JITCallee(Wasm::CompilationMode::OMGMode, WTFMove(entrypoint), index, WTFMove(name), WTFMove(unlinkedCalls))
    113     {
    114     }
    115 };
    116 
    117 class OMGForOSREntryCallee final : public JITCallee {
    118 public:
    119     static Ref<OMGForOSREntryCallee> create(Wasm::Entrypoint&& entrypoint, size_t index, std::pair<const Name*, RefPtr<NameSection>>&& name, unsigned osrEntryScratchBufferSize, uint32_t loopIndex, Vector<UnlinkedWasmToWasmCall>&& unlinkedCalls)
    120     {
    121         return adoptRef(*new OMGForOSREntryCallee(WTFMove(entrypoint), index, WTFMove(name), osrEntryScratchBufferSize, loopIndex, WTFMove(unlinkedCalls)));
     113class EmbedderEntrypointCallee final : public JITCallee {
     114public:
     115    static Ref<EmbedderEntrypointCallee> create(Wasm::Entrypoint&& entrypoint)
     116    {
     117        return adoptRef(*new EmbedderEntrypointCallee(WTFMove(entrypoint)));
     118    }
     119
     120private:
     121    EmbedderEntrypointCallee(Wasm::Entrypoint&& entrypoint)
     122        : JITCallee(Wasm::CompilationMode::EmbedderEntrypointMode, WTFMove(entrypoint))
     123    {
     124    }
     125};
     126
     127
     128#if ENABLE(WEBASSEMBLY_B3JIT)
     129class OptimizingJITCallee : public JITCallee {
     130public:
     131    const Vector<OSREntryValue>& stackmap(CallSiteIndex) const;
     132
     133protected:
     134    OptimizingJITCallee(Wasm::CompilationMode mode, Wasm::Entrypoint&& entrypoint, size_t index, std::pair<const Name*, RefPtr<NameSection>>&& name, Vector<UnlinkedWasmToWasmCall>&& unlinkedCalls, HashMap<CallSiteIndex, Vector<OSREntryValue>>&& stackmaps, Vector<UnlinkedHandlerInfo>&& exceptionHandlers, Vector<CodeLocationLabel<ExceptionHandlerPtrTag>>&& exceptionHandlerLocations)
     135        : JITCallee(mode, WTFMove(entrypoint), index, WTFMove(name), WTFMove(unlinkedCalls))
     136        , m_stackmaps(WTFMove(stackmaps))
     137        , m_unlinkedExceptionHandlers(WTFMove(exceptionHandlers))
     138        , m_exceptionHandlerLocations(WTFMove(exceptionHandlerLocations))
     139    {
     140        RELEASE_ASSERT(m_unlinkedExceptionHandlers.size() == m_exceptionHandlerLocations.size());
     141        linkExceptionHandlers();
     142    }
     143
     144private:
     145    void linkExceptionHandlers();
     146
     147    HashMap<CallSiteIndex, Vector<OSREntryValue>> m_stackmaps;
     148    Vector<UnlinkedHandlerInfo> m_unlinkedExceptionHandlers;
     149    Vector<CodeLocationLabel<ExceptionHandlerPtrTag>> m_exceptionHandlerLocations;
     150};
     151
     152class OMGCallee final : public OptimizingJITCallee {
     153public:
     154    static Ref<OMGCallee> create(Wasm::Entrypoint&& entrypoint, size_t index, std::pair<const Name*, RefPtr<NameSection>>&& name, Vector<UnlinkedWasmToWasmCall>&& unlinkedCalls, HashMap<CallSiteIndex, Vector<OSREntryValue>>&& stackmaps, Vector<UnlinkedHandlerInfo>&& exceptionHandlers, Vector<CodeLocationLabel<ExceptionHandlerPtrTag>>&& exceptionHandlerLocations)
     155    {
     156        return adoptRef(*new OMGCallee(WTFMove(entrypoint), index, WTFMove(name), WTFMove(unlinkedCalls), WTFMove(stackmaps), WTFMove(exceptionHandlers), WTFMove(exceptionHandlerLocations)));
     157    }
     158
     159private:
     160    OMGCallee(Wasm::Entrypoint&& entrypoint, size_t index, std::pair<const Name*, RefPtr<NameSection>>&& name, Vector<UnlinkedWasmToWasmCall>&& unlinkedCalls, HashMap<CallSiteIndex, Vector<OSREntryValue>>&& stackmaps, Vector<UnlinkedHandlerInfo>&& exceptionHandlers, Vector<CodeLocationLabel<ExceptionHandlerPtrTag>>&& exceptionHandlerLocations)
     161        : OptimizingJITCallee(Wasm::CompilationMode::OMGMode, WTFMove(entrypoint), index, WTFMove(name), WTFMove(unlinkedCalls), WTFMove(stackmaps), WTFMove(exceptionHandlers), WTFMove(exceptionHandlerLocations))
     162    {
     163    }
     164};
     165
     166class OMGForOSREntryCallee final : public OptimizingJITCallee {
     167public:
     168    static Ref<OMGForOSREntryCallee> create(Wasm::Entrypoint&& entrypoint, size_t index, std::pair<const Name*, RefPtr<NameSection>>&& name, unsigned osrEntryScratchBufferSize, uint32_t loopIndex, Vector<UnlinkedWasmToWasmCall>&& unlinkedCalls, HashMap<CallSiteIndex, Vector<OSREntryValue>>&& stackmaps, Vector<UnlinkedHandlerInfo>&& exceptionHandlers, Vector<CodeLocationLabel<ExceptionHandlerPtrTag>>&& exceptionHandlerLocations)
     169    {
     170        return adoptRef(*new OMGForOSREntryCallee(WTFMove(entrypoint), index, WTFMove(name), osrEntryScratchBufferSize, loopIndex, WTFMove(unlinkedCalls), WTFMove(stackmaps), WTFMove(exceptionHandlers), WTFMove(exceptionHandlerLocations)));
    122171    }
    123172
     
    126175
    127176private:
    128     OMGForOSREntryCallee(Wasm::Entrypoint&& entrypoint, size_t index, std::pair<const Name*, RefPtr<NameSection>>&& name, unsigned osrEntryScratchBufferSize, uint32_t loopIndex, Vector<UnlinkedWasmToWasmCall>&& unlinkedCalls)
    129         : JITCallee(Wasm::CompilationMode::OMGForOSREntryMode, WTFMove(entrypoint), index, WTFMove(name), WTFMove(unlinkedCalls))
     177    OMGForOSREntryCallee(Wasm::Entrypoint&& entrypoint, size_t index, std::pair<const Name*, RefPtr<NameSection>>&& name, unsigned osrEntryScratchBufferSize, uint32_t loopIndex, Vector<UnlinkedWasmToWasmCall>&& unlinkedCalls, HashMap<CallSiteIndex, Vector<OSREntryValue>>&& stackmaps, Vector<UnlinkedHandlerInfo>&& exceptionHandlers, Vector<CodeLocationLabel<ExceptionHandlerPtrTag>>&& exceptionHandlerLocations)
     178        : OptimizingJITCallee(Wasm::CompilationMode::OMGForOSREntryMode, WTFMove(entrypoint), index, WTFMove(name), WTFMove(unlinkedCalls), WTFMove(stackmaps), WTFMove(exceptionHandlers), WTFMove(exceptionHandlerLocations))
    130179        , m_osrEntryScratchBufferSize(osrEntryScratchBufferSize)
    131180        , m_loopIndex(loopIndex)
     
    136185    uint32_t m_loopIndex;
    137186};
    138 #endif
    139 
    140 class EmbedderEntrypointCallee final : public JITCallee {
    141 public:
    142     static Ref<EmbedderEntrypointCallee> create(Wasm::Entrypoint&& entrypoint)
    143     {
    144         return adoptRef(*new EmbedderEntrypointCallee(WTFMove(entrypoint)));
    145     }
    146 
    147 private:
    148     EmbedderEntrypointCallee(Wasm::Entrypoint&& entrypoint)
    149         : JITCallee(Wasm::CompilationMode::EmbedderEntrypointMode, WTFMove(entrypoint))
    150     {
    151     }
    152 };
    153 
    154 #if ENABLE(WEBASSEMBLY_B3JIT)
    155 class BBQCallee final : public JITCallee {
    156 public:
    157     static Ref<BBQCallee> create(Wasm::Entrypoint&& entrypoint, size_t index, std::pair<const Name*, RefPtr<NameSection>>&& name, std::unique_ptr<TierUpCount>&& tierUpCount, Vector<UnlinkedWasmToWasmCall>&& unlinkedCalls)
    158     {
    159         return adoptRef(*new BBQCallee(WTFMove(entrypoint), index, WTFMove(name), WTFMove(tierUpCount), WTFMove(unlinkedCalls)));
     187
     188class BBQCallee final : public OptimizingJITCallee {
     189public:
     190    static Ref<BBQCallee> create(Wasm::Entrypoint&& entrypoint, size_t index, std::pair<const Name*, RefPtr<NameSection>>&& name, std::unique_ptr<TierUpCount>&& tierUpCount, Vector<UnlinkedWasmToWasmCall>&& unlinkedCalls, HashMap<CallSiteIndex, Vector<OSREntryValue>>&& stackmaps, Vector<UnlinkedHandlerInfo>&& exceptionHandlers, Vector<CodeLocationLabel<ExceptionHandlerPtrTag>>&& exceptionHandlerLocations)
     191    {
     192        return adoptRef(*new BBQCallee(WTFMove(entrypoint), index, WTFMove(name), WTFMove(tierUpCount), WTFMove(unlinkedCalls), WTFMove(stackmaps), WTFMove(exceptionHandlers), WTFMove(exceptionHandlerLocations)));
    160193    }
    161194
     
    178211
    179212private:
    180     BBQCallee(Wasm::Entrypoint&& entrypoint, size_t index, std::pair<const Name*, RefPtr<NameSection>>&& name, std::unique_ptr<TierUpCount>&& tierUpCount, Vector<UnlinkedWasmToWasmCall>&& unlinkedCalls)
    181         : JITCallee(Wasm::CompilationMode::BBQMode, WTFMove(entrypoint), index, WTFMove(name), WTFMove(unlinkedCalls))
     213    BBQCallee(Wasm::Entrypoint&& entrypoint, size_t index, std::pair<const Name*, RefPtr<NameSection>>&& name, std::unique_ptr<TierUpCount>&& tierUpCount, Vector<UnlinkedWasmToWasmCall>&& unlinkedCalls, HashMap<CallSiteIndex, Vector<OSREntryValue>>&& stackmaps, Vector<UnlinkedHandlerInfo>&& exceptionHandlers, Vector<CodeLocationLabel<ExceptionHandlerPtrTag>>&& exceptionHandlerLocations)
     214        : OptimizingJITCallee(Wasm::CompilationMode::BBQMode, WTFMove(entrypoint), index, WTFMove(name), WTFMove(unlinkedCalls), WTFMove(stackmaps), WTFMove(exceptionHandlers), WTFMove(exceptionHandlerLocations))
    182215        , m_tierUpCount(WTFMove(tierUpCount))
    183216    {
     
    219252
    220253    LLIntTierUpCounter& tierUpCounter() { return m_codeBlock->tierUpCounter(); }
    221 #endif
    222 
    223 private:
    224     LLIntCallee(std::unique_ptr<FunctionCodeBlock> codeBlock, size_t index, std::pair<const Name*, RefPtr<NameSection>>&& name)
    225         : Callee(Wasm::CompilationMode::LLIntMode, index, WTFMove(name))
    226         , m_codeBlock(WTFMove(codeBlock))
    227     {
    228         RELEASE_ASSERT(m_codeBlock);
    229     }
     254    FunctionCodeBlock* functionCodeBlock() const final { return m_codeBlock.get(); }
     255#endif
     256
     257private:
     258    LLIntCallee(std::unique_ptr<FunctionCodeBlock>, size_t index, std::pair<const Name*, RefPtr<NameSection>>&&);
     259
     260    void linkExceptionHandlers();
    230261
    231262#if ENABLE(WEBASSEMBLY_B3JIT)
  • trunk/Source/JavaScriptCore/wasm/WasmCallingConvention.h

    r279265 r283852  
    126126        size_t gpArgumentCount = 0;
    127127        size_t fpArgumentCount = 0;
    128         size_t argStackOffset = headerSizeInBytes;
     128        size_t argStackOffset = headerSizeInBytes + sizeof(Register);
    129129        if (role == CallRole::Caller)
    130130            argStackOffset -= sizeof(CallerFrameAndPC);
     
    137137        gpArgumentCount = 0;
    138138        fpArgumentCount = 0;
    139         size_t resultStackOffset = headerSizeInBytes;
     139        size_t resultStackOffset = headerSizeInBytes + sizeof(Register);
    140140        if (role == CallRole::Caller)
    141141            resultStackOffset -= sizeof(CallerFrameAndPC);
  • trunk/Source/JavaScriptCore/wasm/WasmFormat.h

    r281438 r283852  
    3030#include "CodeLocation.h"
    3131#include "Identifier.h"
     32#include "JSString.h"
    3233#include "MacroAssemblerCodeRef.h"
    3334#include "RegisterAtOffsetList.h"
     
    3536#include "WasmName.h"
    3637#include "WasmNameSection.h"
     38#include "WasmOSREntryData.h"
    3739#include "WasmOps.h"
    3840#include "WasmPageCount.h"
     
    5153struct CompilationContext;
    5254struct ModuleInformation;
     55struct UnlinkedHandlerInfo;
    5356
    5457using BlockSignature = const Signature*;
     
    7780}
    7881
     82inline JSString* typeToString(VM& vm, TypeKind type)
     83{
     84#define TYPE_CASE(macroName, value, b3, inc, wasmName) \
     85    case TypeKind::macroName: \
     86        return jsNontrivialString(vm, #wasmName); \
     87
     88    switch (type) {
     89        FOR_EACH_WASM_TYPE(TYPE_CASE)
     90    }
     91
     92#undef TYPE_CASE
     93}
     94
    7995inline bool isSubtype(Type sub, Type parent)
    8096{
     
    116132    Memory = 2,
    117133    Global = 3,
     134    Exception = 4,
    118135};
    119136
     
    126143    case static_cast<Int>(ExternalKind::Memory):
    127144    case static_cast<Int>(ExternalKind::Global):
     145    case static_cast<Int>(ExternalKind::Exception):
    128146        return true;
    129147    }
     
    135153static_assert(static_cast<int>(ExternalKind::Memory)   == 2, "Wasm needs Memory to have the value 2");
    136154static_assert(static_cast<int>(ExternalKind::Global)   == 3, "Wasm needs Global to have the value 3");
     155static_assert(static_cast<int>(ExternalKind::Exception)   == 4, "Wasm needs Exception to have the value 4");
    137156
    138157inline const char* makeString(ExternalKind kind)
     
    143162    case ExternalKind::Memory: return "memory";
    144163    case ExternalKind::Global: return "global";
     164    case ExternalKind::Exception: return "tag";
    145165    }
    146166    RELEASE_ASSERT_NOT_REACHED();
     
    373393    WTF_MAKE_STRUCT_FAST_ALLOCATED;
    374394    CodeLocationDataLabelPtr<WasmEntryPtrTag> calleeMoveLocation;
     395    StackMaps stackmaps;
     396    Vector<UnlinkedHandlerInfo> exceptionHandlers;
    375397    Entrypoint entrypoint;
    376398};
  • trunk/Source/JavaScriptCore/wasm/WasmFunctionCodeBlock.h

    r276609 r283852  
    11/*
    2  * Copyright (C) 2019 Apple Inc. All rights reserved.
     2 * Copyright (C) 2019-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2929
    3030#include "BytecodeConventions.h"
     31#include "HandlerInfo.h"
    3132#include "InstructionStream.h"
    3233#include "MacroAssemblerCodeRef.h"
     34#include "WasmHandlerInfo.h"
    3335#include "WasmLLIntTierUpCounter.h"
    3436#include "WasmOps.h"
     
    121123    unsigned numberOfJumpTables() const;
    122124
     125    size_t numberOfExceptionHandlers() const { return m_exceptionHandlers.size(); }
     126    UnlinkedHandlerInfo& exceptionHandler(int index) { return m_exceptionHandlers[index]; }
     127    void addExceptionHandler(const UnlinkedHandlerInfo& handler) { m_exceptionHandlers.append(handler); }
     128
    123129private:
    124130    using OutOfLineJumpTargets = HashMap<InstructionStream::Offset, int>;
     
    140146    LLIntTierUpCounter m_tierUpCounter;
    141147    Vector<JumpTable> m_jumpTables;
     148    Vector<UnlinkedHandlerInfo> m_exceptionHandlers;
    142149};
    143150
  • trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h

    r281438 r283852  
    3838    Block,
    3939    Loop,
    40     TopLevel
     40    TopLevel,
     41    Try,
     42    Catch,
     43};
     44
     45enum class CatchKind {
     46    Catch,
     47    CatchAll,
    4148};
    4249
     
    148155    PartialResult WARN_UNUSED_RETURN parseIndexForGlobal(uint32_t&);
    149156    PartialResult WARN_UNUSED_RETURN parseFunctionIndex(uint32_t&);
     157    PartialResult WARN_UNUSED_RETURN parseExceptionIndex(uint32_t&);
    150158    PartialResult WARN_UNUSED_RETURN parseBranchTarget(uint32_t&);
    151159
     
    211219    unsigned m_loopIndex { 0 };
    212220};
     221
     222template<typename ControlType>
     223static bool isTryOrCatch(ControlType& data)
     224{
     225    return ControlType::isTry(data) || ControlType::isCatch(data);
     226}
    213227
    214228template<typename Context>
     
    573587    WASM_PARSER_FAIL_IF(functionIndex >= m_info.functionIndexSpaceSize(), "function index ", functionIndex, " exceeds function index space ", m_info.functionIndexSpaceSize());
    574588    resultIndex = functionIndex;
     589    return { };
     590}
     591
     592template<typename Context>
     593auto FunctionParser<Context>::parseExceptionIndex(uint32_t& result) -> PartialResult
     594{
     595    uint32_t exceptionIndex;
     596    WASM_PARSER_FAIL_IF(!parseVarUInt32(exceptionIndex), "can't parse exception index");
     597    WASM_VALIDATOR_FAIL_IF(exceptionIndex >= m_info.exceptionIndexSpaceSize(), "exception index ", exceptionIndex, " is invalid, limit is ", m_info.exceptionIndexSpaceSize());
     598    result = exceptionIndex;
    575599    return { };
    576600}
     
    13341358    }
    13351359
     1360    case Try: {
     1361        WASM_PARSER_FAIL_IF(!Options::useWebAssemblyExceptions(), "wasm exceptions are not enabled");
     1362
     1363        BlockSignature inlineSignature;
     1364        WASM_PARSER_FAIL_IF(!parseBlockSignature(m_info, inlineSignature), "can't get try's signature");
     1365
     1366        WASM_VALIDATOR_FAIL_IF(m_expressionStack.size() < inlineSignature->argumentCount(), "Too few arguments on stack for try block. Trye expects ", inlineSignature->argumentCount(), ", but only ", m_expressionStack.size(), " were present. Try block has signature: ", inlineSignature->toString());
     1367        unsigned offset = m_expressionStack.size() - inlineSignature->argumentCount();
     1368        for (unsigned i = 0; i < inlineSignature->argumentCount(); ++i)
     1369            WASM_VALIDATOR_FAIL_IF(m_expressionStack[offset + i].type() != inlineSignature->argument(i), "Try expects the argument at index", i, " to be ", inlineSignature->argument(i).kind, " but argument has type ", m_expressionStack[i].type().kind);
     1370
     1371        int64_t oldSize = m_expressionStack.size();
     1372        Stack newStack;
     1373        ControlType control;
     1374        WASM_TRY_ADD_TO_CONTEXT(addTry(inlineSignature, m_expressionStack, control, newStack));
     1375        ASSERT_UNUSED(oldSize, oldSize - m_expressionStack.size() == inlineSignature->argumentCount());
     1376        ASSERT(newStack.size() == inlineSignature->argumentCount());
     1377
     1378        m_controlStack.append({ WTFMove(m_expressionStack), { }, WTFMove(control) });
     1379        m_expressionStack = WTFMove(newStack);
     1380        return { };
     1381    }
     1382
     1383    case Catch: {
     1384        WASM_PARSER_FAIL_IF(!Options::useWebAssemblyExceptions(), "wasm exceptions are not enabled");
     1385
     1386        WASM_PARSER_FAIL_IF(m_controlStack.size() == 1, "can't use catch block at the top-level of a function");
     1387
     1388        uint32_t exceptionIndex;
     1389        WASM_FAIL_IF_HELPER_FAILS(parseExceptionIndex(exceptionIndex));
     1390        SignatureIndex signatureIndex = m_info.signatureIndexFromExceptionIndexSpace(exceptionIndex);
     1391        const Signature& exceptionSignature = SignatureInformation::get(signatureIndex);
     1392
     1393        ControlEntry& controlEntry = m_controlStack.last();
     1394        WASM_VALIDATOR_FAIL_IF(!isTryOrCatch(controlEntry.controlData), "catch block isn't associated to a try");
     1395        WASM_FAIL_IF_HELPER_FAILS(unify(controlEntry.controlData));
     1396
     1397        ResultList results;
     1398        Stack preCatchStack;
     1399        m_expressionStack.swap(preCatchStack);
     1400        WASM_TRY_ADD_TO_CONTEXT(addCatch(exceptionIndex, exceptionSignature, preCatchStack, controlEntry.controlData, results));
     1401
     1402        RELEASE_ASSERT(exceptionSignature.argumentCount() == results.size());
     1403        for (unsigned i = 0; i < exceptionSignature.argumentCount(); ++i)
     1404            m_expressionStack.constructAndAppend(exceptionSignature.argument(i), results[i]);
     1405        return { };
     1406    }
     1407
     1408    case CatchAll: {
     1409        WASM_PARSER_FAIL_IF(!Options::useWebAssemblyExceptions(), "wasm exceptions are not enabled");
     1410
     1411        WASM_PARSER_FAIL_IF(m_controlStack.size() == 1, "can't use catch block at the top-level of a function");
     1412
     1413        ControlEntry& controlEntry = m_controlStack.last();
     1414
     1415        WASM_VALIDATOR_FAIL_IF(!isTryOrCatch(controlEntry.controlData), "catch block isn't associated to a try");
     1416        WASM_FAIL_IF_HELPER_FAILS(unify(controlEntry.controlData));
     1417
     1418        ResultList results;
     1419        Stack preCatchStack;
     1420        m_expressionStack.swap(preCatchStack);
     1421        WASM_TRY_ADD_TO_CONTEXT(addCatchAll(preCatchStack, controlEntry.controlData));
     1422        return { };
     1423    }
     1424
     1425    case Delegate: {
     1426        WASM_PARSER_FAIL_IF(!Options::useWebAssemblyExceptions(), "wasm exceptions are not enabled");
     1427
     1428        WASM_PARSER_FAIL_IF(m_controlStack.size() == 1, "can't use delegate at the top-level of a function");
     1429
     1430        uint32_t target;
     1431        WASM_FAIL_IF_HELPER_FAILS(parseBranchTarget(target));
     1432
     1433        ControlEntry controlEntry = m_controlStack.takeLast();
     1434        WASM_VALIDATOR_FAIL_IF(!ControlType::isTry(controlEntry.controlData), "delegate isn't associated to a try");
     1435
     1436        ControlType& targetData = m_controlStack[m_controlStack.size() - 1 - target].controlData;
     1437        WASM_VALIDATOR_FAIL_IF(!ControlType::isTry(targetData) && !ControlType::isTopLevel(targetData), "delegate target isn't a try or the top level block");
     1438
     1439        WASM_TRY_ADD_TO_CONTEXT(addDelegate(targetData, controlEntry.controlData));
     1440        WASM_FAIL_IF_HELPER_FAILS(unify(controlEntry.controlData));
     1441        WASM_TRY_ADD_TO_CONTEXT(endBlock(controlEntry, m_expressionStack));
     1442        m_expressionStack.swap(controlEntry.enclosedExpressionStack);
     1443        return { };
     1444    }
     1445
     1446    case Throw: {
     1447        WASM_PARSER_FAIL_IF(!Options::useWebAssemblyExceptions(), "wasm exceptions are not enabled");
     1448
     1449        uint32_t exceptionIndex;
     1450        WASM_FAIL_IF_HELPER_FAILS(parseExceptionIndex(exceptionIndex));
     1451        SignatureIndex signatureIndex = m_info.signatureIndexFromExceptionIndexSpace(exceptionIndex);
     1452        const Signature& exceptionSignature = SignatureInformation::get(signatureIndex);
     1453
     1454        WASM_VALIDATOR_FAIL_IF(m_expressionStack.size() < exceptionSignature.argumentCount(), "Too few arguments on stack for the exception being thrown. The exception expects ", exceptionSignature.argumentCount(), ", but only ", m_expressionStack.size(), " were present. Exception has signature: ", exceptionSignature.toString());
     1455        unsigned offset = m_expressionStack.size() - exceptionSignature.argumentCount();
     1456        Vector<ExpressionType> args;
     1457        WASM_PARSER_FAIL_IF(!args.tryReserveCapacity(exceptionSignature.argumentCount()), "can't allocate enough memory for throw's ", exceptionSignature.argumentCount(), " arguments");
     1458        for (unsigned i = 0; i < exceptionSignature.argumentCount(); ++i) {
     1459            TypedExpression arg = m_expressionStack.at(offset + i);
     1460            WASM_VALIDATOR_FAIL_IF(arg.type() != exceptionSignature.argument(i), "The exception being thrown expects the argument at index ", i, " to be ", exceptionSignature.argument(i).kind, " but argument has type ", arg.type().kind);
     1461            args.uncheckedAppend(arg);
     1462            m_context.didPopValueFromStack();
     1463        }
     1464        m_expressionStack.shrink(offset);
     1465
     1466        WASM_TRY_ADD_TO_CONTEXT(addThrow(exceptionIndex, args, m_expressionStack));
     1467        m_unreachableBlocks = 1;
     1468        return { };
     1469    }
     1470
     1471    case Rethrow: {
     1472        WASM_PARSER_FAIL_IF(!Options::useWebAssemblyExceptions(), "wasm exceptions are not enabled");
     1473
     1474        uint32_t target;
     1475        WASM_FAIL_IF_HELPER_FAILS(parseBranchTarget(target));
     1476
     1477        ControlType& data = m_controlStack[m_controlStack.size() - 1 - target].controlData;
     1478        WASM_VALIDATOR_FAIL_IF(!ControlType::isAnyCatch(data), "rethrow doesn't refer to a catch block");
     1479
     1480        WASM_TRY_ADD_TO_CONTEXT(addRethrow(target, data));
     1481        m_unreachableBlocks = 1;
     1482        return { };
     1483    }
     1484
    13361485    case Br:
    13371486    case BrIf: {
     
    14851634        WASM_TRY_ADD_TO_CONTEXT(addElseToUnreachable(data.controlData));
    14861635        m_expressionStack = WTFMove(data.elseBlockStack);
     1636        return { };
     1637    }
     1638
     1639    case Catch: {
     1640        WASM_PARSER_FAIL_IF(!Options::useWebAssemblyExceptions(), "wasm exceptions are not enabled");
     1641
     1642        uint32_t exceptionIndex;
     1643        WASM_FAIL_IF_HELPER_FAILS(parseExceptionIndex(exceptionIndex));
     1644        SignatureIndex signatureIndex = m_info.signatureIndexFromExceptionIndexSpace(exceptionIndex);
     1645        const Signature& exceptionSignature = SignatureInformation::get(signatureIndex);
     1646
     1647        if (m_unreachableBlocks > 1)
     1648            return { };
     1649
     1650        ControlEntry& data = m_controlStack.last();
     1651        WASM_VALIDATOR_FAIL_IF(!isTryOrCatch(data.controlData), "catch block isn't associated to a try");
     1652
     1653        m_unreachableBlocks = 0;
     1654        m_expressionStack = { };
     1655        ResultList results;
     1656        WASM_TRY_ADD_TO_CONTEXT(addCatchToUnreachable(exceptionIndex, exceptionSignature, data.controlData, results));
     1657
     1658        RELEASE_ASSERT(exceptionSignature.argumentCount() == results.size());
     1659        for (unsigned i = 0; i < exceptionSignature.argumentCount(); ++i)
     1660            m_expressionStack.constructAndAppend(exceptionSignature.argument(i), results[i]);
     1661        return { };
     1662    }
     1663
     1664    case CatchAll: {
     1665        WASM_PARSER_FAIL_IF(!Options::useWebAssemblyExceptions(), "wasm exceptions are not enabled");
     1666
     1667        if (m_unreachableBlocks > 1)
     1668            return { };
     1669
     1670        ControlEntry& data = m_controlStack.last();
     1671        m_unreachableBlocks = 0;
     1672        m_expressionStack = { };
     1673        WASM_VALIDATOR_FAIL_IF(!isTryOrCatch(data.controlData), "catch block isn't associated to a try");
     1674        WASM_TRY_ADD_TO_CONTEXT(addCatchAllToUnreachable(data.controlData));
     1675        return { };
     1676    }
     1677
     1678    case Delegate: {
     1679        WASM_PARSER_FAIL_IF(!Options::useWebAssemblyExceptions(), "wasm exceptions are not enabled");
     1680
     1681        WASM_PARSER_FAIL_IF(m_controlStack.size() == 1, "can't use delegate at the top-level of a function");
     1682
     1683        uint32_t target;
     1684        WASM_FAIL_IF_HELPER_FAILS(parseBranchTarget(target));
     1685
     1686        ControlEntry controlEntry = m_controlStack.takeLast();
     1687        WASM_VALIDATOR_FAIL_IF(!ControlType::isTry(controlEntry.controlData), "delegate isn't associated to a try");
     1688
     1689        ControlType& data = m_controlStack[m_controlStack.size() - 1 - target].controlData;
     1690        WASM_VALIDATOR_FAIL_IF(!ControlType::isTry(data) && !ControlType::isTopLevel(data), "delegate target isn't a try block");
     1691
     1692        WASM_TRY_ADD_TO_CONTEXT(addDelegateToUnreachable(data, controlEntry.controlData));
     1693        Stack emptyStack;
     1694        WASM_TRY_ADD_TO_CONTEXT(addEndToUnreachable(controlEntry, emptyStack));
     1695        m_expressionStack.swap(controlEntry.enclosedExpressionStack);
    14871696        return { };
    14881697    }
     
    14961705                WASM_FAIL_IF_HELPER_FAILS(unify(data.controlData));
    14971706                WASM_TRY_ADD_TO_CONTEXT(endBlock(data, m_expressionStack));
    1498             } else
    1499                 WASM_TRY_ADD_TO_CONTEXT(addEndToUnreachable(data));
     1707            } else {
     1708                Stack emptyStack;
     1709                WASM_TRY_ADD_TO_CONTEXT(addEndToUnreachable(data, emptyStack));
     1710            }
    15001711
    15011712            m_expressionStack.swap(data.enclosedExpressionStack);
     
    15041715        return { };
    15051716    }
     1717
     1718    case Try:
     1719        WASM_PARSER_FAIL_IF(!Options::useWebAssemblyExceptions(), "wasm exceptions are not enabled");
     1720        FALLTHROUGH;
    15061721
    15071722    case Loop:
     
    15771792    }
    15781793
     1794    case Rethrow: {
     1795        WASM_PARSER_FAIL_IF(!Options::useWebAssemblyExceptions(), "wasm exceptions are not enabled");
     1796        uint32_t target;
     1797        WASM_FAIL_IF_HELPER_FAILS(parseBranchTarget(target));
     1798
     1799        ControlType& data = m_controlStack[m_controlStack.size() - 1 - target].controlData;
     1800        WASM_VALIDATOR_FAIL_IF(!ControlType::isAnyCatch(data), "rethrow doesn't refer to a catch block");
     1801        return { };
     1802    }
     1803
    15791804    case Br:
    15801805    case BrIf: {
    15811806        uint32_t target;
    15821807        WASM_FAIL_IF_HELPER_FAILS(parseBranchTarget(target));
     1808        return { };
     1809    }
     1810
     1811    case Throw: {
     1812        WASM_PARSER_FAIL_IF(!Options::useWebAssemblyExceptions(), "wasm exceptions are not enabled");
     1813
     1814        uint32_t exceptionIndex;
     1815        WASM_FAIL_IF_HELPER_FAILS(parseExceptionIndex(exceptionIndex));
     1816
    15831817        return { };
    15841818    }
  • trunk/Source/JavaScriptCore/wasm/WasmInstance.cpp

    r278338 r283852  
    3535#include "WasmModuleInformation.h"
    3636#include "WasmSignatureInlines.h"
     37#include "WasmTag.h"
    3738#include <wtf/CheckedArithmetic.h>
    3839
     
    9192}
    9293
    93 Instance::~Instance() { }
     94Instance::~Instance()
     95{
     96}
    9497
    9598size_t Instance::extraMemoryAllocated() const
     
    298301}
    299302
     303void Instance::addTag(const Tag& tag)
     304{
     305    m_tags.append(Ref { tag });
     306}
     307
     308void Instance::addTag(Ref<Tag>&& tag)
     309{
     310    m_tags.append(WTFMove(tag));
     311}
     312
    300313} } // namespace JSC::Wasm
    301314
  • trunk/Source/JavaScriptCore/wasm/WasmInstance.h

    r278338 r283852  
    211211    }
    212212
     213    void addTag(const Tag&);
     214    void addTag(Ref<Tag>&&);
     215    const Tag& tag(unsigned i) const { return *m_tags[i]; }
     216
    213217private:
    214218    Instance(Context*, Ref<Module>&&, EntryFrame**, void**, StoreTopCallFrameCallback&&);
     
    238242    BitVector m_passiveElements;
    239243    BitVector m_passiveDataSegments;
     244    Vector<RefPtr<const Tag>> m_tags;
    240245};
    241246
  • trunk/Source/JavaScriptCore/wasm/WasmLLIntGenerator.cpp

    r280507 r283852  
    6363    };
    6464
    65     struct ControlType : public Variant<ControlLoop, ControlTopLevel, ControlBlock, ControlIf> {
    66         using Base = Variant<ControlLoop, ControlTopLevel, ControlBlock, ControlIf>;
     65    struct ControlTry {
     66        Ref<Label> m_try;
     67        unsigned m_tryDepth;
     68    };
     69
     70    struct ControlCatch {
     71        CatchKind m_kind;
     72        Ref<Label> m_tryStart;
     73        Ref<Label> m_tryEnd;
     74        unsigned m_tryDepth;
     75        VirtualRegister m_exception;
     76    };
     77
     78    struct CatchRewriteInfo {
     79        unsigned m_instructionOffset;
     80        unsigned m_tryDepth;
     81    };
     82
     83    struct ControlType : public Variant<ControlLoop, ControlTopLevel, ControlBlock, ControlIf, ControlTry, ControlCatch> {
     84        using Base = Variant<ControlLoop, ControlTopLevel, ControlBlock, ControlIf, ControlTry, ControlCatch>;
    6785
    6886        ControlType()
     
    91109        }
    92110
     111        static ControlType createTry(BlockSignature signature, unsigned stackSize, Ref<Label>&& tryLabel, RefPtr<Label>&& continuation, unsigned tryDepth)
     112        {
     113            return ControlType(signature, stackSize - signature->argumentCount(), WTFMove(continuation), ControlTry { WTFMove(tryLabel), tryDepth });
     114        }
     115
     116        static ControlType createCatch(BlockSignature signature, unsigned stackSize, Ref<Label>&& tryStart, RefPtr<Label>&& continuation, Ref<Label> tryEnd, unsigned tryDepth, VirtualRegister exception)
     117        {
     118            return ControlType(signature, stackSize - signature->argumentCount(), WTFMove(continuation), ControlCatch { CatchKind::Catch, WTFMove(tryStart), WTFMove(tryEnd), tryDepth, exception });
     119        }
     120
     121        static bool isLoop(const ControlType& control) { return WTF::holds_alternative<ControlLoop>(control); }
     122        static bool isTopLevel(const ControlType& control) { return WTF::holds_alternative<ControlTopLevel>(control); }
     123        static bool isBlock(const ControlType& control) { return WTF::holds_alternative<ControlBlock>(control); }
    93124        static bool isIf(const ControlType& control) { return WTF::holds_alternative<ControlIf>(control); }
    94         static bool isTopLevel(const ControlType& control) { return WTF::holds_alternative<ControlTopLevel>(control); }
     125        static bool isTry(const ControlType& control) { return WTF::holds_alternative<ControlTry>(control); }
     126        static bool isAnyCatch(const ControlType& control) { return WTF::holds_alternative<ControlCatch>(control); }
     127        static bool isCatch(const ControlType& control)
     128        {
     129            if (!WTF::holds_alternative<ControlCatch>(control))
     130                return false;
     131            ControlCatch catchData = WTF::get<ControlCatch>(control);
     132            return catchData.m_kind == CatchKind::Catch;
     133        }
    95134
    96135        unsigned stackSize() const { return m_stackSize; }
     
    153192    }
    154193
    155     LLIntGenerator(const ModuleInformation&, unsigned functionIndex, const Signature&);
     194    LLIntGenerator(ModuleInformation&, unsigned functionIndex, const Signature&);
    156195
    157196    std::unique_ptr<FunctionCodeBlock> finalize();
     197
     198    template<typename Opcode>
     199    void repatch(const CatchRewriteInfo&);
    158200
    159201    template<typename ExpressionListA, typename ExpressionListB>
     
    162204        ASSERT(destinations.size() <= values.size());
    163205        auto offset = values.size() - destinations.size();
    164         for (size_t i = 0; i < destinations.size(); ++i)
    165             WasmMov::emit(this, destinations[i], values[offset + i]);
     206        for (size_t i = 0; i < destinations.size(); ++i) {
     207            auto& src = values[offset + i];
     208            auto& dst = destinations[i];
     209            if ((VirtualRegister)src != (VirtualRegister)dst)
     210                WasmMov::emit(this, dst, src);
     211        }
    166212    }
    167213
     
    244290    PartialResult WARN_UNUSED_RETURN addElseToUnreachable(ControlType&);
    245291
     292    PartialResult WARN_UNUSED_RETURN addTry(BlockSignature, Stack& enclosingStack, ControlType& result, Stack& newStack);
     293    PartialResult WARN_UNUSED_RETURN addCatch(unsigned exceptionIndex, const Signature&, Stack&, ControlType&, ResultList&);
     294    PartialResult WARN_UNUSED_RETURN addCatchToUnreachable(unsigned exceptionIndex, const Signature&, ControlType&, ResultList&);
     295    PartialResult WARN_UNUSED_RETURN addCatchAll(Stack&, ControlType&);
     296    PartialResult WARN_UNUSED_RETURN addCatchAllToUnreachable(ControlType&);
     297    PartialResult WARN_UNUSED_RETURN addDelegate(ControlType&, ControlType&);
     298    PartialResult WARN_UNUSED_RETURN addDelegateToUnreachable(ControlType&, ControlType&);
     299    PartialResult WARN_UNUSED_RETURN addThrow(unsigned exceptionIndex, Vector<ExpressionType>& args, Stack&);
     300    PartialResult WARN_UNUSED_RETURN addRethrow(unsigned, ControlType&);
     301
    246302    PartialResult WARN_UNUSED_RETURN addReturn(const ControlType&, Stack& returnValues);
    247303    PartialResult WARN_UNUSED_RETURN addBranch(ControlType&, ExpressionType condition, Stack& returnValues);
    248304    PartialResult WARN_UNUSED_RETURN addSwitch(ExpressionType condition, const Vector<ControlType*>& targets, ControlType& defaultTargets, Stack& expressionStack);
    249305    PartialResult WARN_UNUSED_RETURN endBlock(ControlEntry&, Stack& expressionStack);
    250     PartialResult WARN_UNUSED_RETURN addEndToUnreachable(ControlEntry&, const Stack& expressionStack = { }, bool unreachable = true);
     306    PartialResult WARN_UNUSED_RETURN addEndToUnreachable(ControlEntry&, Stack& expressionStack, bool unreachable = true);
    251307    PartialResult WARN_UNUSED_RETURN endTopLevel(BlockSignature, const Stack&);
    252308
     
    338394    }
    339395
    340     template<typename Functor>
     396    template<typename Stack, typename Functor>
    341397    void walkExpressionStack(Stack& expressionStack, unsigned stackSize, const Functor& functor)
    342398    {
     
    347403    }
    348404
    349     template<typename Functor>
     405    template<typename Stack, typename Functor>
    350406    void walkExpressionStack(Stack& expressionStack, const Functor& functor)
    351407    {
     
    356412    void walkExpressionStack(ControlEntry& entry, const Functor& functor)
    357413    {
    358         walkExpressionStack(entry.enclosedExpressionStack, entry.controlData.stackSize(), functor);
     414        unsigned stackSize = entry.controlData.stackSize();
     415        walkExpressionStack(entry.enclosedExpressionStack, stackSize, functor);
    359416    }
    360417
     
    382439    void materializeConstantsAndLocals(Stack& expressionStack, NoConsistencyCheckTag)
    383440    {
    384         walkExpressionStack(expressionStack, [&](TypedExpression& expression, VirtualRegister slot) {
     441        walkExpressionStack(expressionStack, [&](auto& expression, VirtualRegister slot) {
    385442            ASSERT(expression.value() == slot || expression.value().isConstant() || expression.value().isArgument() || static_cast<unsigned>(expression.value().toLocal()) < m_codeBlock->m_numVars);
    386443            if (expression.value() == slot)
     
    418475    }
    419476
     477    void finalizePreviousBlockForCatch(ControlType&, Stack&);
     478
    420479    struct SwitchEntry {
    421480        InstructionStream::Offset offset;
     
    430489
    431490    FunctionParser<LLIntGenerator>* m_parser { nullptr };
    432     const ModuleInformation& m_info;
     491    ModuleInformation& m_info;
    433492    const unsigned m_functionIndex { UINT_MAX };
    434493    Vector<VirtualRegister> m_normalizedArguments;
     
    441500    Checked<unsigned> m_stackSize { 0 };
    442501    Checked<unsigned> m_maxStackSize { 0 };
     502    Checked<unsigned> m_tryDepth { 0 };
     503    Checked<unsigned> m_maxTryDepth { 0 };
     504    bool m_usesExceptions { false };
    443505};
    444506
    445 Expected<std::unique_ptr<FunctionCodeBlock>, String> parseAndCompileBytecode(const uint8_t* functionStart, size_t functionLength, const Signature& signature, const ModuleInformation& info, uint32_t functionIndex)
     507Expected<std::unique_ptr<FunctionCodeBlock>, String> parseAndCompileBytecode(const uint8_t* functionStart, size_t functionLength, const Signature& signature, ModuleInformation& info, uint32_t functionIndex)
    446508{
    447509    LLIntGenerator llintGenerator(info, functionIndex, signature);
     
    467529}
    468530
    469 LLIntGenerator::LLIntGenerator(const ModuleInformation& info, unsigned functionIndex, const Signature&)
     531LLIntGenerator::LLIntGenerator(ModuleInformation& info, unsigned functionIndex, const Signature&)
    470532    : BytecodeGeneratorBase(makeUnique<FunctionCodeBlock>(functionIndex), 0)
    471533    , m_info(info)
     
    486548}
    487549
     550template<typename Opcode>
     551void LLIntGenerator::repatch(const CatchRewriteInfo& info)
     552{
     553    auto ref = m_writer.ref(info.m_instructionOffset);
     554    Opcode* instruction = ref->cast<Opcode, WasmOpcodeTraits>();
     555    VirtualRegister exceptionRegister = virtualRegisterForLocal(m_maxStackSize + info.m_tryDepth - 1);
     556    instruction->setException(exceptionRegister, []() {
     557        RELEASE_ASSERT_NOT_REACHED();
     558        return VirtualRegister();
     559    });
     560}
     561
    488562std::unique_ptr<FunctionCodeBlock> LLIntGenerator::finalize()
    489563{
    490564    RELEASE_ASSERT(m_codeBlock);
     565
    491566    size_t numCalleeLocals = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), m_maxStackSize);
    492567    m_codeBlock->m_numCalleeLocals = numCalleeLocals;
     
    500575    RELEASE_ASSERT(usedBuffer.capacity() == oldCapacity);
    501576    *threadSpecific = WTFMove(usedBuffer);
     577
     578    if (!m_usesExceptions)
     579        m_info.m_functionDoesNotUseExceptions.quickSet(m_functionIndex);
    502580
    503581    return WTFMove(m_codeBlock);
     
    581659    // FIXME: we are allocating the extra space for the argument/return count in order to avoid interference, but we could do better
    582660    // NOTE: We increase arg count by 1 for the case of indirect calls
    583     m_stackSize += std::max(signature.argumentCount() + 1, signature.returnCount()) + gprCount + fprCount + stackCount + CallFrame::headerSizeInRegisters;
     661    m_stackSize += std::max(signature.argumentCount() + 1, signature.returnCount()) + gprCount + fprCount + stackCount + CallFrame::headerSizeInRegisters + 1;
    584662    if (m_stackSize.value() % stackAlignmentRegisters())
    585663        ++m_stackSize;
     
    592670
    593671    const unsigned stackOffset = m_stackSize;
    594     const unsigned base = stackOffset - CallFrame::headerSizeInRegisters;
     672    const unsigned base = stackOffset - CallFrame::headerSizeInRegisters - 1;
    595673
    596674    const uint32_t gprLimit = base - stackCount - gprCount;
     
    684762    uint32_t gprIndex = 0;
    685763    uint32_t fprIndex = gprCount;
    686     uint32_t stackIndex = 0;
     764    uint32_t stackIndex = 1;
    687765    const uint32_t maxGPRIndex = gprCount;
    688766    const uint32_t maxFPRIndex = maxGPRIndex + fprCount;
     
    732810    uint32_t gprIndex = 0;
    733811    uint32_t fprIndex = maxGPRIndex;
    734     uint32_t stackIndex = 0;
     812    uint32_t stackIndex = 1;
    735813
    736814    Vector<VirtualRegister> registerArguments(gprCount + fprCount);
     
    907985    block = ControlType::loop(signature, m_stackSize, WTFMove(body), WTFMove(continuation));
    908986
     987    Vector<unsigned> unresolvedOffsets;
    909988    Vector<VirtualRegister> osrEntryData;
    910989    for (uint32_t i = 0; i < m_codeBlock->m_numArguments; i++)
     
    917996        osrEntryData.append(virtualRegisterForLocal(i));
    918997    for (unsigned controlIndex = 0; controlIndex < m_parser->controlStack().size(); ++controlIndex) {
     998        ControlType& data = m_parser->controlStack()[controlIndex].controlData;
    919999        Stack& expressionStack = m_parser->controlStack()[controlIndex].enclosedExpressionStack;
    9201000        for (TypedExpression expression : expressionStack)
    9211001            osrEntryData.append(expression);
     1002        if (ControlType::isAnyCatch(data))
     1003            osrEntryData.append(WTF::get<ControlCatch>(data).m_exception);
    9221004    }
    9231005    for (TypedExpression expression : enclosingStack)
     
    9731055    emitLabel(control.m_alternate.get());
    9741056    data = ControlType::block(data.m_signature, m_stackSize, WTFMove(data.m_continuation));
     1057    return { };
     1058}
     1059
     1060auto LLIntGenerator::addTry(BlockSignature signature, Stack& enclosingStack, ControlType& result, Stack& newStack) -> PartialResult
     1061{
     1062    m_usesExceptions = true;
     1063    ++m_tryDepth;
     1064    if (m_maxTryDepth < m_tryDepth)
     1065        m_maxTryDepth = m_tryDepth;
     1066
     1067    splitStack(signature, enclosingStack, newStack);
     1068    Ref<Label> tryLabel = newEmittedLabel();
     1069    Ref<Label> continuation = newLabel();
     1070    result = ControlType::createTry(signature, m_stackSize, WTFMove(tryLabel), WTFMove(continuation), m_tryDepth);
     1071    return { };
     1072}
     1073
     1074void LLIntGenerator::finalizePreviousBlockForCatch(ControlType& data, Stack& expressionStack)
     1075{
     1076    if (!ControlType::isAnyCatch(data))
     1077        materializeConstantsAndLocals(expressionStack);
     1078    else {
     1079        checkConsistency();
     1080        VirtualRegister dst = virtualRegisterForLocal(data.stackSize());
     1081        for (TypedExpression& value : expressionStack) {
     1082            WasmMov::emit(this, dst, value);
     1083            value = TypedExpression { value.type(), dst };
     1084            dst -= 1;
     1085        }
     1086    }
     1087    WasmJmp::emit(this, data.m_continuation->bind(this));
     1088}
     1089
     1090auto LLIntGenerator::addCatch(unsigned exceptionIndex, const Signature& exceptionSignature, Stack& expressionStack, ControlType& data, ResultList& results) -> PartialResult
     1091{
     1092    finalizePreviousBlockForCatch(data, expressionStack);
     1093    return addCatchToUnreachable(exceptionIndex, exceptionSignature, data, results);
     1094}
     1095
     1096auto LLIntGenerator::addCatchToUnreachable(unsigned exceptionIndex, const Signature& exceptionSignature, ControlType& data, ResultList& results) -> PartialResult
     1097{
     1098    m_usesExceptions = true;
     1099    Ref<Label> catchLabel = newEmittedLabel();
     1100
     1101    m_stackSize = data.stackSize();
     1102    VirtualRegister exception = push();
     1103    if (WTF::holds_alternative<ControlTry>(data)) {
     1104        ControlTry& tryData = WTF::get<ControlTry>(data);
     1105        data = ControlType::createCatch(data.m_signature, data.stackSize(), WTFMove(tryData.m_try), WTFMove(data.m_continuation), catchLabel, tryData.m_tryDepth, exception);
     1106    }
     1107    for (unsigned i = 0; i < exceptionSignature.argumentCount(); ++i)
     1108        results.append(push());
     1109
     1110    if (Context::useFastTLS())
     1111        WasmCatch::emit(this, exceptionIndex, exception, exceptionSignature.argumentCount(), results.isEmpty() ? 0 : -results[0].offset());
     1112    else
     1113        WasmCatchNoTls::emit(this, exceptionIndex, exception, exceptionSignature.argumentCount(), results.isEmpty() ? 0 : -results[0].offset());
     1114
     1115    for (unsigned i = 0; i < exceptionSignature.argumentCount(); ++i) {
     1116        VirtualRegister dst = results[i];
     1117        Type type = exceptionSignature.argument(i);
     1118        switch (type.kind) {
     1119        case Wasm::TypeKind::F32:
     1120            WasmF32ReinterpretI32::emit(this, dst, dst);
     1121            break;
     1122        case Wasm::TypeKind::F64:
     1123            WasmF64ReinterpretI64::emit(this, dst, dst);
     1124            break;
     1125        case Wasm::TypeKind::I32:
     1126        case Wasm::TypeKind::I64:
     1127        case Wasm::TypeKind::Externref:
     1128        case Wasm::TypeKind::Funcref:
     1129            break;
     1130        default:
     1131            RELEASE_ASSERT_NOT_REACHED();
     1132            break;
     1133        }
     1134    }
     1135
     1136    ControlCatch& catchData = WTF::get<ControlCatch>(data);
     1137    catchData.m_kind = CatchKind::Catch;
     1138    m_codeBlock->addExceptionHandler({ HandlerType::Catch, catchData.m_tryStart->location(), catchData.m_tryEnd->location(), catchLabel->location(), m_tryDepth, exceptionIndex });
     1139
     1140    return { };
     1141}
     1142
     1143auto LLIntGenerator::addCatchAll(Stack& expressionStack, ControlType& data) -> PartialResult
     1144{
     1145    finalizePreviousBlockForCatch(data, expressionStack);
     1146    WasmJmp::emit(this, data.m_continuation->bind(this));
     1147    return addCatchAllToUnreachable(data);
     1148}
     1149
     1150auto LLIntGenerator::addCatchAllToUnreachable(ControlType& data) -> PartialResult
     1151{
     1152    m_usesExceptions = true;
     1153    Ref<Label> catchLabel = newEmittedLabel();
     1154    m_stackSize = data.stackSize();
     1155    VirtualRegister exception = push();
     1156    if (WTF::holds_alternative<ControlTry>(data)) {
     1157        ControlTry& tryData = WTF::get<ControlTry>(data);
     1158        data = ControlType::createCatch(data.m_signature, data.stackSize(), WTFMove(tryData.m_try), WTFMove(data.m_continuation), catchLabel, tryData.m_tryDepth, exception);
     1159    }
     1160    ControlCatch& catchData = WTF::get<ControlCatch>(data);
     1161    catchData.m_kind = CatchKind::CatchAll;
     1162
     1163    if (Context::useFastTLS())
     1164        WasmCatchAll::emit(this, exception);
     1165    else
     1166        WasmCatchAllNoTls::emit(this, exception);
     1167
     1168    m_codeBlock->addExceptionHandler({ HandlerType::CatchAll, catchData.m_tryStart->location(), catchData.m_tryEnd->location(), catchLabel->location(), m_tryDepth, 0 });
     1169    return { };
     1170}
     1171
     1172auto LLIntGenerator::addDelegate(ControlType& target, ControlType& data) -> PartialResult
     1173{
     1174    return addDelegateToUnreachable(target, data);
     1175}
     1176
     1177auto LLIntGenerator::addDelegateToUnreachable(ControlType& target, ControlType& data) -> PartialResult
     1178{
     1179    m_usesExceptions = true;
     1180    Ref<Label> delegateLabel = newEmittedLabel();
     1181
     1182    ASSERT(ControlType::isTry(target) || ControlType::isTopLevel(target));
     1183    unsigned targetDepth = ControlType::isTry(target) ? WTF::get<ControlTry>(target).m_tryDepth : 0;
     1184
     1185    ControlTry& tryData = WTF::get<ControlTry>(data);
     1186    m_codeBlock->addExceptionHandler({ HandlerType::Delegate, tryData.m_try->location(), delegateLabel->location(), 0, m_tryDepth, targetDepth });
     1187    checkConsistency();
     1188    return { };
     1189}
     1190
     1191auto LLIntGenerator::addThrow(unsigned exceptionIndex, Vector<ExpressionType>& args, Stack&) -> PartialResult
     1192{
     1193    m_usesExceptions = true;
     1194    walkExpressionStack(args, [&](VirtualRegister& arg, VirtualRegister slot) {
     1195        if (arg == slot)
     1196            return;
     1197        WasmMov::emit(this, slot, arg);
     1198        arg = slot;
     1199    });
     1200    WasmThrow::emit(this, exceptionIndex, args.isEmpty() ? virtualRegisterForLocal(0) : args[0]);
     1201    return { };
     1202}
     1203
     1204auto LLIntGenerator::addRethrow(unsigned, ControlType& data) -> PartialResult
     1205{
     1206    m_usesExceptions = true;
     1207    ASSERT(WTF::holds_alternative<ControlCatch>(data));
     1208    ControlCatch catchData = WTF::get<ControlCatch>(data);
     1209    WasmRethrow::emit(this, catchData.m_exception);
    9751210    return { };
    9761211}
     
    10501285    // FIXME: We only need to materialize constants here if there exists a jump to this label
    10511286    // https://bugs.webkit.org/show_bug.cgi?id=203657
    1052     materializeConstantsAndLocals(expressionStack);
     1287    finalizePreviousBlockForCatch(entry.controlData, expressionStack);
    10531288    return addEndToUnreachable(entry, expressionStack, false);
    10541289}
    10551290
    10561291
    1057 auto LLIntGenerator::addEndToUnreachable(ControlEntry& entry, const Stack& expressionStack, bool unreachable) -> PartialResult
     1292auto LLIntGenerator::addEndToUnreachable(ControlEntry& entry, Stack& expressionStack, bool unreachable) -> PartialResult
    10581293{
    10591294    ControlType& data = entry.controlData;
    10601295
    1061     RELEASE_ASSERT(unreachable || m_stackSize == data.stackSize() + data.m_signature->returnCount());
     1296    unsigned stackSize = data.stackSize();
     1297    if (ControlType::isAnyCatch(entry.controlData))
     1298        ++stackSize; // Account for the caught exception
     1299    RELEASE_ASSERT(unreachable || m_stackSize ==  stackSize + data.m_signature->returnCount());
    10621300
    10631301    m_stackSize = data.stackSize();
     1302
     1303    if (ControlType::isTry(data) || WTF::holds_alternative<ControlCatch>(data))
     1304        --m_tryDepth;
    10641305
    10651306    for (unsigned i = 0; i < data.m_signature->returnCount(); ++i) {
  • trunk/Source/JavaScriptCore/wasm/WasmLLIntGenerator.h

    r271775 r283852  
    3737struct ModuleInformation;
    3838
    39 Expected<std::unique_ptr<FunctionCodeBlock>, String> parseAndCompileBytecode(const uint8_t*, size_t, const Signature&, const ModuleInformation&, uint32_t functionIndex);
     39Expected<std::unique_ptr<FunctionCodeBlock>, String> parseAndCompileBytecode(const uint8_t*, size_t, const Signature&, ModuleInformation&, uint32_t functionIndex);
    4040
    4141} } // namespace JSC::Wasm
  • trunk/Source/JavaScriptCore/wasm/WasmLimits.h

    r246571 r283852  
    4242constexpr size_t maxImports = 100000;
    4343constexpr size_t maxExports = 100000;
     44constexpr size_t maxExceptions = 100000;
    4445constexpr size_t maxGlobals = 1000000;
    4546constexpr size_t maxDataSegments = 100000;
  • trunk/Source/JavaScriptCore/wasm/WasmModuleInformation.cpp

    r261755 r283852  
    3737{
    3838}
     39
    3940ModuleInformation::~ModuleInformation() { }
    4041
  • trunk/Source/JavaScriptCore/wasm/WasmModuleInformation.h

    r278340 r283852  
    5959    }
    6060
     61    size_t exceptionIndexSpaceSize() const { return importExceptionSignatureIndices.size() + internalExceptionSignatureIndices.size(); }
     62    bool isImportedExceptionFromExceptionIndexSpace(size_t exceptionIndex) const
     63    {
     64        ASSERT(exceptionIndex < exceptionIndexSpaceSize());
     65        return exceptionIndex < importExceptionSignatureIndices.size();
     66    }
     67    SignatureIndex signatureIndexFromExceptionIndexSpace(size_t exceptionIndex) const
     68    {
     69        return isImportedExceptionFromExceptionIndexSpace(exceptionIndex)
     70            ? importExceptionSignatureIndices[exceptionIndex]
     71            : internalExceptionSignatureIndices[exceptionIndex - importExceptionSignatureIndices.size()];
     72    }
     73
    6174    uint32_t importFunctionCount() const { return importFunctionSignatureIndices.size(); }
    6275    uint32_t internalFunctionCount() const { return internalFunctionSignatureIndices.size(); }
     76    uint32_t importExceptionCount() const { return importExceptionSignatureIndices.size(); }
    6377
    6478    // Currently, our wasm implementation allows only one memory and table.
     
    7791    void addDeclaredFunction(uint32_t index) { m_declaredFunctions.set(index); }
    7892
     93    bool isDeclaredException(uint32_t index) const { return m_declaredExceptions.contains(index); }
     94    void addDeclaredException(uint32_t index) { m_declaredExceptions.set(index); }
     95
    7996    Vector<Import> imports;
    8097    Vector<SignatureIndex> importFunctionSignatureIndices;
    8198    Vector<SignatureIndex> internalFunctionSignatureIndices;
     99    Vector<SignatureIndex> importExceptionSignatureIndices;
     100    Vector<SignatureIndex> internalExceptionSignatureIndices;
    82101    Vector<Ref<Signature>> usedSignatures;
    83102
     
    99118
    100119    BitVector m_declaredFunctions;
     120    BitVector m_declaredExceptions;
     121    BitVector m_functionDoesNotUseExceptions;
    101122    mutable BitVector m_referencedFunctions;
    102123};
  • trunk/Source/JavaScriptCore/wasm/WasmOMGForOSREntryPlan.cpp

    r282860 r283852  
    9292    }
    9393
     94    InternalFunction* internalFunction = parseAndCompileResult->get();
     95    Vector<CodeLocationLabel<ExceptionHandlerPtrTag>> exceptionHandlerLocations;
     96    computeExceptionHandlerLocations(exceptionHandlerLocations, internalFunction, context, linkBuffer);
     97
    9498    omgEntrypoint.compilation = makeUnique<Compilation>(
    9599        FINALIZE_WASM_CODE_FOR_MODE(CompilationMode::OMGForOSREntryMode, linkBuffer, JITCompilationPtrTag, "WebAssembly OMGForOSREntry function[%i] %s name %s", m_functionIndex, signature.toString().ascii().data(), makeString(IndexOrName(functionIndexSpace, m_moduleInformation->nameSection->get(functionIndexSpace))).ascii().data()),
    96100        WTFMove(context.wasmEntrypointByproducts));
    97101
    98     omgEntrypoint.calleeSaveRegisters = WTFMove(parseAndCompileResult.value()->entrypoint.calleeSaveRegisters);
     102    omgEntrypoint.calleeSaveRegisters = WTFMove(internalFunction->entrypoint.calleeSaveRegisters);
    99103
    100104    ASSERT(m_codeBlock.ptr() == m_module->codeBlockFor(mode()));
    101     Ref<OMGForOSREntryCallee> callee = OMGForOSREntryCallee::create(WTFMove(omgEntrypoint), functionIndexSpace, m_moduleInformation->nameSection->get(functionIndexSpace), osrEntryScratchBufferSize, m_loopIndex, WTFMove(unlinkedCalls));
     105    Ref<OMGForOSREntryCallee> callee = OMGForOSREntryCallee::create(WTFMove(omgEntrypoint), functionIndexSpace, m_moduleInformation->nameSection->get(functionIndexSpace), osrEntryScratchBufferSize, m_loopIndex, WTFMove(unlinkedCalls), WTFMove(internalFunction->stackmaps), WTFMove(internalFunction->exceptionHandlers), WTFMove(exceptionHandlerLocations));
    102106    {
    103         MacroAssembler::repatchPointer(parseAndCompileResult.value()->calleeMoveLocation, CalleeBits::boxWasm(callee.ptr()));
     107        MacroAssembler::repatchPointer(internalFunction->calleeMoveLocation, CalleeBits::boxWasm(callee.ptr()));
    104108
    105109        Locker locker { m_codeBlock->m_lock };
  • trunk/Source/JavaScriptCore/wasm/WasmOMGPlan.cpp

    r282860 r283852  
    8989    }
    9090
     91    InternalFunction* internalFunction = parseAndCompileResult->get();
     92    Vector<CodeLocationLabel<ExceptionHandlerPtrTag>> exceptionHandlerLocations;
     93    computeExceptionHandlerLocations(exceptionHandlerLocations, internalFunction, context, linkBuffer);
     94
    9195    omgEntrypoint.compilation = makeUnique<Compilation>(
    9296        FINALIZE_WASM_CODE_FOR_MODE(CompilationMode::OMGMode, linkBuffer, JITCompilationPtrTag, "WebAssembly OMG function[%i] %s name %s", m_functionIndex, signature.toString().ascii().data(), makeString(IndexOrName(functionIndexSpace, m_moduleInformation->nameSection->get(functionIndexSpace))).ascii().data()),
    9397        WTFMove(context.wasmEntrypointByproducts));
    9498
    95     omgEntrypoint.calleeSaveRegisters = WTFMove(parseAndCompileResult.value()->entrypoint.calleeSaveRegisters);
     99    omgEntrypoint.calleeSaveRegisters = WTFMove(internalFunction->entrypoint.calleeSaveRegisters);
    96100
    97101    MacroAssemblerCodePtr<WasmEntryPtrTag> entrypoint;
    98102    {
    99103        ASSERT(m_codeBlock.ptr() == m_module->codeBlockFor(mode()));
    100         Ref<OMGCallee> callee = OMGCallee::create(WTFMove(omgEntrypoint), functionIndexSpace, m_moduleInformation->nameSection->get(functionIndexSpace), WTFMove(unlinkedCalls));
    101         MacroAssembler::repatchPointer(parseAndCompileResult.value()->calleeMoveLocation, CalleeBits::boxWasm(callee.ptr()));
     104        Ref<OMGCallee> callee = OMGCallee::create(WTFMove(omgEntrypoint), functionIndexSpace, m_moduleInformation->nameSection->get(functionIndexSpace), WTFMove(unlinkedCalls), WTFMove(internalFunction->stackmaps), WTFMove(internalFunction->exceptionHandlers), WTFMove(exceptionHandlerLocations));
     105        MacroAssembler::repatchPointer(internalFunction->calleeMoveLocation, CalleeBits::boxWasm(callee.ptr()));
    102106        ASSERT(!m_codeBlock->m_omgCallees[m_functionIndex]);
    103107        entrypoint = callee->entrypoint();
  • trunk/Source/JavaScriptCore/wasm/WasmOSREntryData.h

    r271775 r283852  
    2828#if ENABLE(WEBASSEMBLY_B3JIT)
    2929
     30#include "B3Type.h"
    3031#include "B3ValueRep.h"
    31 #include "WasmFormat.h"
    3232#include <wtf/Vector.h>
    3333
     
    4848};
    4949
     50using StackMap = Vector<OSREntryValue>;
     51using StackMaps = HashMap<CallSiteIndex, StackMap>;
     52
    5053class OSREntryData {
    5154    WTF_MAKE_NONCOPYABLE(OSREntryData);
     
    6063    uint32_t functionIndex() const { return m_functionIndex; }
    6164    uint32_t loopIndex() const { return m_loopIndex; }
    62     Vector<OSREntryValue>& values() { return m_values; }
     65    StackMap& values() { return m_values; }
    6366
    6467private:
    6568    uint32_t m_functionIndex;
    6669    uint32_t m_loopIndex;
    67     Vector<OSREntryValue> m_values;
     70    StackMap m_values;
    6871};
    6972
  • trunk/Source/JavaScriptCore/wasm/WasmOperations.cpp

    r282701 r283852  
    11/*
    2  * Copyright (C) 2019-2020 Apple Inc. All rights reserved.
     2 * Copyright (C) 2019-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3535#include "JSCJSValueInlines.h"
    3636#include "JSGlobalObjectInlines.h"
     37#include "JSWebAssemblyException.h"
    3738#include "JSWebAssemblyHelpers.h"
    3839#include "JSWebAssemblyInstance.h"
     
    106107}
    107108
    108 SUPPRESS_ASAN
    109 static void doOSREntry(Instance* instance, Probe::Context& context, BBQCallee& callee, OMGForOSREntryCallee& osrEntryCallee, OSREntryData& osrEntryData)
    110 {
    111     auto returnWithoutOSREntry = [&] {
    112         context.gpr(GPRInfo::argumentGPR0) = 0;
    113     };
    114 
    115     RELEASE_ASSERT(osrEntryCallee.osrEntryScratchBufferSize() == osrEntryData.values().size());
    116 
    117     uint64_t* buffer = instance->context()->scratchBufferForSize(osrEntryCallee.osrEntryScratchBufferSize());
    118     if (!buffer)
    119         return returnWithoutOSREntry();
    120 
    121     dataLogLnIf(Options::verboseOSR(), osrEntryData.functionIndex(), ":OMG OSR entry: got entry callee ", RawPointer(&osrEntryCallee));
    122 
    123     // 1. Place required values in scratch buffer.
    124     for (unsigned index = 0; index < osrEntryData.values().size(); ++index) {
    125         const OSREntryValue& value = osrEntryData.values()[index];
     109void loadValuesIntoBuffer(Probe::Context& context, const StackMap& values, uint64_t* buffer)
     110{
     111    for (unsigned index = 0; index < values.size(); ++index) {
     112        const OSREntryValue& value = values[index];
    126113        dataLogLnIf(Options::verboseOSR(), "OMG OSR entry values[", index, "] ", value.type(), " ", value);
    127114        if (value.isGPR()) {
     
    165152                break;
    166153            }
    167         } else if (value.isStackArgument()) {
    168             switch (value.type().kind()) {
    169             case B3::Float:
    170                 *bitwise_cast<float*>(buffer + index) = *bitwise_cast<float*>(bitwise_cast<uint8_t*>(context.sp()) + value.offsetFromSP());
    171                 break;
    172             case B3::Double:
    173                 *bitwise_cast<double*>(buffer + index) = *bitwise_cast<double*>(bitwise_cast<uint8_t*>(context.sp()) + value.offsetFromSP());
    174                 break;
    175             default:
    176                 *bitwise_cast<uint64_t*>(buffer + index) = *bitwise_cast<uint64_t*>(bitwise_cast<uint8_t*>(context.sp()) + value.offsetFromSP());
    177                 break;
    178             }
    179154        } else
    180155            RELEASE_ASSERT_NOT_REACHED();
    181156    }
     157}
     158
     159SUPPRESS_ASAN
     160static void doOSREntry(Instance* instance, Probe::Context& context, BBQCallee& callee, OMGForOSREntryCallee& osrEntryCallee, OSREntryData& osrEntryData)
     161{
     162    auto returnWithoutOSREntry = [&] {
     163        context.gpr(GPRInfo::argumentGPR0) = 0;
     164    };
     165
     166    RELEASE_ASSERT(osrEntryCallee.osrEntryScratchBufferSize() == osrEntryData.values().size());
     167
     168    uint64_t* buffer = instance->context()->scratchBufferForSize(osrEntryCallee.osrEntryScratchBufferSize());
     169    if (!buffer)
     170        return returnWithoutOSREntry();
     171
     172    dataLogLnIf(Options::verboseOSR(), osrEntryData.functionIndex(), ":OMG OSR entry: got entry callee ", RawPointer(&osrEntryCallee));
     173
     174    // 1. Place required values in scratch buffer.
     175    loadValuesIntoBuffer(context, osrEntryData.values(), buffer);
    182176
    183177    // 2. Restore callee saves.
     
    659653}
    660654
    661 JSC_DEFINE_JIT_OPERATION(operationWasmMemoryFill, bool, (Instance* instance, uint32_t dstAddress, uint32_t targetValue, uint32_t count))
     655JSC_DEFINE_JIT_OPERATION(operationWasmMemoryFill, size_t, (Instance* instance, uint32_t dstAddress, uint32_t targetValue, uint32_t count))
    662656{
    663657    return instance->memory()->fill(dstAddress, static_cast<uint8_t>(targetValue), count);
    664658}
    665659
    666 JSC_DEFINE_JIT_OPERATION(operationWasmMemoryCopy, bool, (Instance* instance, uint32_t dstAddress, uint32_t srcAddress, uint32_t count))
     660JSC_DEFINE_JIT_OPERATION(operationWasmMemoryCopy, size_t, (Instance* instance, uint32_t dstAddress, uint32_t srcAddress, uint32_t count))
    667661{
    668662    return instance->memory()->copy(dstAddress, srcAddress, count);
     
    712706}
    713707
    714 JSC_DEFINE_JIT_OPERATION(operationSetWasmTableElement, bool, (Instance* instance, unsigned tableIndex, uint32_t signedIndex, EncodedJSValue encValue))
     708JSC_DEFINE_JIT_OPERATION(operationSetWasmTableElement, size_t, (Instance* instance, unsigned tableIndex, uint32_t signedIndex, EncodedJSValue encValue))
    715709{
    716710    return setWasmTableElement(instance, tableIndex, signedIndex, encValue);
    717711}
    718712
    719 JSC_DEFINE_JIT_OPERATION(operationWasmTableInit, bool, (Instance* instance, unsigned elementIndex, unsigned tableIndex, uint32_t dstOffset, uint32_t srcOffset, uint32_t length))
     713JSC_DEFINE_JIT_OPERATION(operationWasmTableInit, size_t, (Instance* instance, unsigned elementIndex, unsigned tableIndex, uint32_t dstOffset, uint32_t srcOffset, uint32_t length))
    720714{
    721715    ASSERT(elementIndex < instance->module().moduleInformation().elementCount());
     
    762756}
    763757
    764 JSC_DEFINE_JIT_OPERATION(operationWasmTableFill, bool, (Instance* instance, unsigned tableIndex, uint32_t offset, EncodedJSValue fill, uint32_t count))
     758JSC_DEFINE_JIT_OPERATION(operationWasmTableFill, size_t, (Instance* instance, unsigned tableIndex, uint32_t offset, EncodedJSValue fill, uint32_t count))
    765759{
    766760    ASSERT(tableIndex < instance->module().moduleInformation().tableCount());
     
    778772}
    779773
    780 JSC_DEFINE_JIT_OPERATION(operationWasmTableCopy, bool, (Instance* instance, unsigned dstTableIndex, unsigned srcTableIndex, int32_t dstOffset, int32_t srcOffset, int32_t length))
     774JSC_DEFINE_JIT_OPERATION(operationWasmTableCopy, size_t, (Instance* instance, unsigned dstTableIndex, unsigned srcTableIndex, int32_t dstOffset, int32_t srcOffset, int32_t length))
    781775{
    782776    ASSERT(dstTableIndex < instance->module().moduleInformation().tableCount());
     
    905899}
    906900
    907 JSC_DEFINE_JIT_OPERATION(operationWasmMemoryInit, bool, (Instance* instance, unsigned dataSegmentIndex, uint32_t dstAddress, uint32_t srcAddress, uint32_t length))
     901JSC_DEFINE_JIT_OPERATION(operationWasmMemoryInit, size_t, (Instance* instance, unsigned dataSegmentIndex, uint32_t dstAddress, uint32_t srcAddress, uint32_t length))
    908902{
    909903    ASSERT(dataSegmentIndex < instance->module().moduleInformation().dataSegmentsCount());
     
    917911}
    918912
    919 JSC_DEFINE_JIT_OPERATION(operationWasmToJSException, void*, (CallFrame* callFrame, Wasm::ExceptionType type, Instance* wasmInstance))
    920 {
    921     wasmInstance->storeTopCallFrame(callFrame);
    922     JSWebAssemblyInstance* instance = wasmInstance->owner<JSWebAssemblyInstance>();
    923     JSGlobalObject* globalObject = instance->globalObject();
    924 
    925     // Do not retrieve VM& from CallFrame since CallFrame's callee is not a JSCell.
     913JSC_DEFINE_JIT_OPERATION(operationWasmThrow, void*, (Instance* instance, CallFrame* callFrame, unsigned exceptionIndex, EncodedJSValue* arguments))
     914{
     915    instance->storeTopCallFrame(callFrame);
     916
     917    JSWebAssemblyInstance* jsInstance = instance->owner<JSWebAssemblyInstance>();
     918    JSGlobalObject* globalObject = jsInstance->globalObject();
    926919    VM& vm = globalObject->vm();
    927 
    928     {
    929         auto throwScope = DECLARE_THROW_SCOPE(vm);
    930 
    931         JSObject* error;
    932         if (type == ExceptionType::StackOverflow)
    933             error = createStackOverflowError(globalObject);
    934         else
    935             error = createJSWebAssemblyRuntimeError(globalObject, vm, Wasm::errorMessageForExceptionType(type));
    936         throwException(globalObject, throwScope, error);
    937     }
     920    auto throwScope = DECLARE_THROW_SCOPE(vm);
     921
     922    const Wasm::Tag& tag = instance->tag(exceptionIndex);
     923
     924    FixedVector<uint64_t> values(tag.parameterCount());
     925    for (unsigned i = 0; i < tag.parameterCount(); ++i)
     926        values[i] = arguments[i];
     927
     928    JSWebAssemblyException* exception = JSWebAssemblyException::create(vm, globalObject->webAssemblyExceptionStructure(), tag, WTFMove(values));
     929    throwException(globalObject, throwScope, exception);
    938930
    939931    genericUnwind(vm, callFrame);
     
    947939    // to the exception handler. If we did this, we could remove this terrible hack.
    948940    // https://bugs.webkit.org/show_bug.cgi?id=170440
     941    vm.calleeForWasmCatch = callFrame->callee();
     942    bitwise_cast<uint64_t*>(callFrame)[static_cast<int>(CallFrameSlot::callee)] = bitwise_cast<uint64_t>(jsInstance->module());
     943    return vm.targetMachinePCForThrow;
     944}
     945
     946JSC_DEFINE_JIT_OPERATION(operationWasmRethrow, void*, (Instance* instance, CallFrame* callFrame, EncodedJSValue thrownValue))
     947{
     948    instance->storeTopCallFrame(callFrame);
     949
     950    JSWebAssemblyInstance* jsInstance = instance->owner<JSWebAssemblyInstance>();
     951    JSGlobalObject* globalObject = jsInstance->globalObject();
     952    VM& vm = globalObject->vm();
     953    auto throwScope = DECLARE_THROW_SCOPE(vm);
     954
     955    throwException(globalObject, throwScope, JSValue::decode(thrownValue));
     956
     957    genericUnwind(vm, callFrame);
     958    ASSERT(!!vm.callFrameForCatch);
     959    ASSERT(!!vm.targetMachinePCForThrow);
     960    // FIXME: We could make this better:
     961    // This is a total hack, but the llint (both op_catch and llint_handle_uncaught_exception)
     962    // require a cell in the callee field to load the VM. (The baseline JIT does not require
     963    // this since it is compiled with a constant VM pointer.) We could make the calling convention
     964    // for exceptions first load callFrameForCatch info call frame register before jumping
     965    // to the exception handler. If we did this, we could remove this terrible hack.
     966    // https://bugs.webkit.org/show_bug.cgi?id=170440
     967    vm.calleeForWasmCatch = callFrame->callee();
     968    bitwise_cast<uint64_t*>(callFrame)[static_cast<int>(CallFrameSlot::callee)] = bitwise_cast<uint64_t>(jsInstance->module());
     969    return vm.targetMachinePCForThrow;
     970}
     971
     972JSC_DEFINE_JIT_OPERATION(operationWasmToJSException, void*, (CallFrame* callFrame, Wasm::ExceptionType type, Instance* wasmInstance))
     973{
     974    wasmInstance->storeTopCallFrame(callFrame);
     975    JSWebAssemblyInstance* instance = wasmInstance->owner<JSWebAssemblyInstance>();
     976    JSGlobalObject* globalObject = instance->globalObject();
     977
     978    // Do not retrieve VM& from CallFrame since CallFrame's callee is not a JSCell.
     979    VM& vm = globalObject->vm();
     980
     981    {
     982        auto throwScope = DECLARE_THROW_SCOPE(vm);
     983
     984        JSObject* error;
     985        if (type == ExceptionType::StackOverflow)
     986            error = createStackOverflowError(globalObject);
     987        else
     988            error = createJSWebAssemblyRuntimeError(globalObject, vm, type);
     989        throwException(globalObject, throwScope, error);
     990    }
     991
     992    genericUnwind(vm, callFrame);
     993    ASSERT(!!vm.callFrameForCatch);
     994    ASSERT(!!vm.targetMachinePCForThrow);
     995    // FIXME: We could make this better:
     996    // This is a total hack, but the llint (both op_catch and llint_handle_uncaught_exception)
     997    // require a cell in the callee field to load the VM. (The baseline JIT does not require
     998    // this since it is compiled with a constant VM pointer.) We could make the calling convention
     999    // for exceptions first load callFrameForCatch info call frame register before jumping
     1000    // to the exception handler. If we did this, we could remove this terrible hack.
     1001    // https://bugs.webkit.org/show_bug.cgi?id=170440
     1002    vm.calleeForWasmCatch = callFrame->callee();
    9491003    bitwise_cast<uint64_t*>(callFrame)[static_cast<int>(CallFrameSlot::callee)] = bitwise_cast<uint64_t>(instance->module());
    9501004    return vm.targetMachinePCForThrow;
    9511005}
    9521006
     1007JSC_DEFINE_JIT_OPERATION(operationWasmRetrieveAndClearExceptionIfCatchable, PointerPair, (Instance* instance))
     1008{
     1009    JSWebAssemblyInstance* jsInstance = instance->owner<JSWebAssemblyInstance>();
     1010    JSGlobalObject* globalObject = jsInstance->globalObject();
     1011    VM& vm = globalObject->vm();
     1012    auto throwScope = DECLARE_THROW_SCOPE(vm);
     1013
     1014    RELEASE_ASSERT(!!throwScope.exception());
     1015
     1016    Exception* exception = throwScope.exception();
     1017    JSValue thrownValue = exception->value();
     1018
     1019    // We want to clear the exception here rather than in the catch prologue
     1020    // JIT code because clearing it also entails clearing a bit in an Atomic
     1021    // bit field in VMTraps.
     1022    throwScope.clearException();
     1023
     1024    void* payload = nullptr;
     1025    if (JSWebAssemblyException* wasmException = jsDynamicCast<JSWebAssemblyException*>(vm, thrownValue))
     1026        payload = bitwise_cast<void*>(wasmException->payload().data());
     1027    return PointerPair { bitwise_cast<void*>(JSValue::encode(thrownValue)), payload };
     1028}
     1029
    9531030} } // namespace JSC::Wasm
    9541031
  • trunk/Source/JavaScriptCore/wasm/WasmOperations.h

    r282037 r283852  
    3333#include "SlowPathReturnType.h"
    3434#include "WasmExceptionType.h"
     35#include "WasmOSREntryData.h"
    3536
    3637namespace JSC {
     
    4647class Instance;
    4748class Signature;
     49
     50void loadValuesIntoBuffer(Probe::Context&, const StackMap&, uint64_t* buffer);
    4851
    4952#if ENABLE(WEBASSEMBLY_B3JIT)
     
    6770JSC_DECLARE_JIT_OPERATION(operationPopcount64, uint64_t, (int64_t));
    6871JSC_DECLARE_JIT_OPERATION(operationGrowMemory, int32_t, (void*, Instance*, int32_t));
    69 JSC_DECLARE_JIT_OPERATION(operationWasmMemoryFill, bool, (Instance*, uint32_t dstAddress, uint32_t targetValue, uint32_t count));
    70 JSC_DECLARE_JIT_OPERATION(operationWasmMemoryCopy, bool, (Instance*, uint32_t dstAddress, uint32_t srcAddress, uint32_t count));
     72JSC_DECLARE_JIT_OPERATION(operationWasmMemoryFill, size_t, (Instance*, uint32_t dstAddress, uint32_t targetValue, uint32_t count));
     73JSC_DECLARE_JIT_OPERATION(operationWasmMemoryCopy, size_t, (Instance*, uint32_t dstAddress, uint32_t srcAddress, uint32_t count));
    7174
    7275JSC_DECLARE_JIT_OPERATION(operationGetWasmTableElement, EncodedJSValue, (Instance*, unsigned, int32_t));
    73 JSC_DECLARE_JIT_OPERATION(operationSetWasmTableElement, bool, (Instance*, unsigned, uint32_t, EncodedJSValue encValue));
     76JSC_DECLARE_JIT_OPERATION(operationSetWasmTableElement, size_t, (Instance*, unsigned, uint32_t, EncodedJSValue encValue));
    7477JSC_DECLARE_JIT_OPERATION(operationWasmRefFunc, EncodedJSValue, (Instance*, uint32_t));
    75 JSC_DECLARE_JIT_OPERATION(operationWasmTableInit, bool, (Instance*, unsigned elementIndex, unsigned tableIndex, uint32_t dstOffset, uint32_t srcOffset, uint32_t length));
     78JSC_DECLARE_JIT_OPERATION(operationWasmTableInit, size_t, (Instance*, unsigned elementIndex, unsigned tableIndex, uint32_t dstOffset, uint32_t srcOffset, uint32_t length));
    7679JSC_DECLARE_JIT_OPERATION(operationWasmElemDrop, void, (Instance*, unsigned elementIndex));
    7780JSC_DECLARE_JIT_OPERATION(operationWasmTableGrow, int32_t, (Instance*, unsigned, EncodedJSValue fill, uint32_t delta));
    78 JSC_DECLARE_JIT_OPERATION(operationWasmTableFill, bool, (Instance*, unsigned, uint32_t offset, EncodedJSValue fill, uint32_t count));
    79 JSC_DECLARE_JIT_OPERATION(operationWasmTableCopy, bool, (Instance*, unsigned dstTableIndex, unsigned srcTableIndex, int32_t dstOffset, int32_t srcOffset, int32_t length));
     81JSC_DECLARE_JIT_OPERATION(operationWasmTableFill, size_t, (Instance*, unsigned, uint32_t offset, EncodedJSValue fill, uint32_t count));
     82JSC_DECLARE_JIT_OPERATION(operationWasmTableCopy, size_t, (Instance*, unsigned dstTableIndex, unsigned srcTableIndex, int32_t dstOffset, int32_t srcOffset, int32_t length));
    8083JSC_DECLARE_JIT_OPERATION(operationGetWasmTableSize, int32_t, (Instance*, unsigned));
    8184
     
    8386JSC_DECLARE_JIT_OPERATION(operationMemoryAtomicWait64, int32_t, (Instance* instance, unsigned base, unsigned offset, uint64_t value, int64_t timeout));
    8487JSC_DECLARE_JIT_OPERATION(operationMemoryAtomicNotify, int32_t, (Instance*, unsigned, unsigned, int32_t));
    85 JSC_DECLARE_JIT_OPERATION(operationWasmMemoryInit, bool, (Instance*, unsigned dataSegmentIndex, uint32_t dstAddress, uint32_t srcAddress, uint32_t length));
     88JSC_DECLARE_JIT_OPERATION(operationWasmMemoryInit, size_t, (Instance*, unsigned dataSegmentIndex, uint32_t dstAddress, uint32_t srcAddress, uint32_t length));
    8689JSC_DECLARE_JIT_OPERATION(operationWasmDataDrop, void, (Instance*, unsigned dataSegmentIndex));
    8790
     91JSC_DECLARE_JIT_OPERATION(operationWasmThrow, void*, (Instance*, CallFrame*, unsigned exceptionIndex, EncodedJSValue*));
     92JSC_DECLARE_JIT_OPERATION(operationWasmRethrow, void*, (Instance*, CallFrame*, EncodedJSValue thrownValue));
     93
    8894JSC_DECLARE_JIT_OPERATION(operationWasmToJSException, void*, (CallFrame*, Wasm::ExceptionType, Instance*));
     95struct PointerPair {
     96    void* first;
     97    void* second;
     98};
     99JSC_DECLARE_JIT_OPERATION(operationWasmRetrieveAndClearExceptionIfCatchable, PointerPair, (Instance*));
    89100
    90101} } // namespace JSC::Wasm
  • trunk/Source/JavaScriptCore/wasm/WasmSectionParser.cpp

    r281438 r283852  
    9292    WASM_PARSER_FAIL_IF(!m_info->imports.tryReserveCapacity(importCount), "can't allocate enough memory for ", importCount, " imports"); // FIXME this over-allocates when we fix the FIXMEs below.
    9393    WASM_PARSER_FAIL_IF(!m_info->importFunctionSignatureIndices.tryReserveCapacity(importCount), "can't allocate enough memory for ", importCount, " import function signatures"); // FIXME this over-allocates when we fix the FIXMEs below.
     94    if (Options::useWebAssemblyExceptions())
     95        WASM_PARSER_FAIL_IF(!m_info->importExceptionSignatureIndices.tryReserveCapacity(importCount), "can't allocate enough memory for ", importCount, " import exception signatures"); // FIXME this over-allocates when we fix the FIXMEs below.
    9496
    9597    for (uint32_t importNumber = 0; importNumber < importCount; ++importNumber) {
     
    141143            kindIndex = m_info->globals.size();
    142144            m_info->globals.uncheckedAppend(WTFMove(global));
     145            break;
     146        }
     147        case ExternalKind::Exception: {
     148            WASM_PARSER_FAIL_IF(!Options::useWebAssemblyExceptions(), "wasm exceptions are not enabled");
     149
     150            uint8_t tagType;
     151            WASM_PARSER_FAIL_IF(!parseUInt8(tagType), "can't get ", importNumber, "th Import exception's tag type");
     152            WASM_PARSER_FAIL_IF(tagType, importNumber, "th Import exception has tag type ", tagType, " but the only supported tag type is 0");
     153
     154            uint32_t exceptionSignatureIndex;
     155            WASM_PARSER_FAIL_IF(!parseVarUInt32(exceptionSignatureIndex), "can't get ", importNumber, "th Import's exception signature in module '", moduleString, "' field '", fieldString, "'");
     156            WASM_PARSER_FAIL_IF(exceptionSignatureIndex >= m_info->usedSignatures.size(), "invalid exception signature for ", importNumber, "th Import, ", exceptionSignatureIndex, " is out of range of ", m_info->usedSignatures.size(), " in module '", moduleString, "' field '", fieldString, "'");
     157            kindIndex = m_info->importExceptionSignatureIndices.size();
     158            SignatureIndex signatureIndex = SignatureInformation::get(m_info->usedSignatures[exceptionSignatureIndex]);
     159            m_info->importExceptionSignatureIndices.uncheckedAppend(signatureIndex);
    143160            break;
    144161        }
     
    359376            break;
    360377        }
     378        case ExternalKind::Exception: {
     379            WASM_PARSER_FAIL_IF(!Options::useWebAssemblyExceptions(), "wasm exceptions are not enabled");
     380
     381            WASM_PARSER_FAIL_IF(kindIndex >= m_info->exceptionIndexSpaceSize(), exportNumber, "th Export has invalid exception number ", kindIndex, " it exceeds the exception index space ", m_info->exceptionIndexSpaceSize(), ", named '", fieldString, "'");
     382            m_info->addDeclaredException(kindIndex);
     383            break;
     384        }
    361385        }
    362386
     
    818842}
    819843
     844auto SectionParser::parseException() -> PartialResult
     845{
     846    WASM_PARSER_FAIL_IF(!Options::useWebAssemblyExceptions(), "wasm exceptions are not enabled");
     847
     848    uint32_t exceptionCount;
     849    WASM_PARSER_FAIL_IF(!parseVarUInt32(exceptionCount), "can't get Exception section's count");
     850    WASM_PARSER_FAIL_IF(exceptionCount > maxExceptions, "Export section's count is too big ", exceptionCount, " maximum ", maxExceptions);
     851    WASM_PARSER_FAIL_IF(!m_info->internalExceptionSignatureIndices.tryReserveCapacity(exceptionCount), "can't allocate enough memory for ", exceptionCount, " exceptions");
     852
     853    for (uint32_t exceptionNumber = 0; exceptionNumber < exceptionCount; ++exceptionNumber) {
     854        uint8_t tagType;
     855        WASM_PARSER_FAIL_IF(!parseUInt8(tagType), "can't get ", exceptionNumber, "th Exception tag type");
     856        WASM_PARSER_FAIL_IF(tagType, exceptionNumber, "th Exception has tag type ", tagType, " but the only supported tag type is 0");
     857
     858        uint32_t typeNumber;
     859        WASM_PARSER_FAIL_IF(!parseVarUInt32(typeNumber), "can't get ", exceptionNumber, "th Exception's type number");
     860        WASM_PARSER_FAIL_IF(typeNumber >= m_info->usedSignatures.size(), exceptionNumber, "th Exception type number is invalid ", typeNumber);
     861        SignatureIndex signatureIndex = SignatureInformation::get(m_info->usedSignatures[typeNumber]);
     862        m_info->internalExceptionSignatureIndices.uncheckedAppend(signatureIndex);
     863    }
     864
     865    return { };
     866}
    820867auto SectionParser::parseCustom() -> PartialResult
    821868{
  • trunk/Source/JavaScriptCore/wasm/WasmSections.h

    r270948 r283852  
    4646    macro(Code,      10, "Function bodies (code)") \
    4747    macro(Data,      11, "Data segments") \
    48     macro(DataCount, 12, "Data count")
     48    macro(DataCount, 12, "Data count") \
     49    macro(Exception, 13, "Exception declarations") \
    4950
    5051enum class Section : uint8_t {
     
    9192    if (previousKnown == Section::DataCount && next == Section::Code)
    9293        return true;
     94    if (previousKnown == Section::Exception)
     95        return next >= Section::Global;
     96    if (next == Section::Exception)
     97        return previousKnown <= Section::Memory;
    9398    return static_cast<uint8_t>(previousKnown) < static_cast<uint8_t>(next);
    9499}
  • trunk/Source/JavaScriptCore/wasm/WasmSignature.cpp

    r282860 r283852  
    9797SignatureInformation::SignatureInformation()
    9898{
    99 #define MAKE_THUNK_SIGNATURE(type, enc, str, val)                          \
     99#define MAKE_THUNK_SIGNATURE(type, enc, str, val, _)                       \
    100100    do {                                                                   \
    101101        if (TypeKind::type != TypeKind::Void) {                            \
     
    166166RefPtr<Signature> SignatureInformation::signatureFor(const Vector<Type, 1>& results, const Vector<Type>& args)
    167167{
     168    if constexpr (ASSERT_ENABLED) {
     169        ASSERT(!results.contains(Wasm::Types::Void));
     170        ASSERT(!args.contains(Wasm::Types::Void));
     171    }
    168172    SignatureInformation& info = singleton();
    169173    Locker locker { info.m_lock };
  • trunk/Source/JavaScriptCore/wasm/WasmSlowPaths.cpp

    r282860 r283852  
    3030
    3131#include "BytecodeStructs.h"
     32#include "JITExceptions.h"
     33#include "JSWebAssemblyException.h"
    3234#include "JSWebAssemblyInstance.h"
    3335#include "LLIntData.h"
     
    587589}
    588590
     591WASM_SLOW_PATH_DECL(throw)
     592{
     593    instance->storeTopCallFrame(callFrame);
     594
     595    JSWebAssemblyInstance* jsInstance = instance->owner<JSWebAssemblyInstance>();
     596    JSGlobalObject* globalObject = jsInstance->globalObject();
     597    VM& vm = globalObject->vm();
     598    auto throwScope = DECLARE_THROW_SCOPE(vm);
     599
     600    auto instruction = pc->as<WasmThrow, WasmOpcodeTraits>();
     601    const Wasm::Tag& tag = instance->tag(instruction.m_exceptionIndex);
     602
     603    FixedVector<uint64_t> values(tag.parameterCount());
     604    for (unsigned i = 0; i < tag.parameterCount(); ++i)
     605        values[i] = READ((instruction.m_firstValue - i)).encodedJSValue();
     606
     607    JSWebAssemblyException* exception = JSWebAssemblyException::create(vm, globalObject->webAssemblyExceptionStructure(), tag, WTFMove(values));
     608    throwException(globalObject, throwScope, exception);
     609
     610    genericUnwind(vm, callFrame);
     611    ASSERT(!!vm.callFrameForCatch);
     612    ASSERT(!!vm.targetMachinePCForThrow);
     613    // FIXME: We could make this better:
     614    // This is a total hack, but the llint (both op_catch and llint_handle_uncaught_exception)
     615    // require a cell in the callee field to load the VM. (The baseline JIT does not require
     616    // this since it is compiled with a constant VM pointer.) We could make the calling convention
     617    // for exceptions first load callFrameForCatch info call frame register before jumping
     618    // to the exception handler. If we did this, we could remove this terrible hack.
     619    // https://bugs.webkit.org/show_bug.cgi?id=170440
     620    vm.calleeForWasmCatch = callFrame->callee();
     621    bitwise_cast<uint64_t*>(callFrame)[static_cast<int>(CallFrameSlot::callee)] = bitwise_cast<uint64_t>(jsInstance->module());
     622    WASM_RETURN_TWO(vm.targetMachinePCForThrow, nullptr);
     623}
     624
     625WASM_SLOW_PATH_DECL(rethrow)
     626{
     627    instance->storeTopCallFrame(callFrame);
     628
     629    JSWebAssemblyInstance* jsInstance = instance->owner<JSWebAssemblyInstance>();
     630    JSGlobalObject* globalObject = jsInstance->globalObject();
     631    VM& vm = globalObject->vm();
     632    auto throwScope = DECLARE_THROW_SCOPE(vm);
     633
     634    auto instruction = pc->as<WasmRethrow, WasmOpcodeTraits>();
     635    JSValue exception = READ(instruction.m_exception).jsValue();
     636    throwException(globalObject, throwScope, exception);
     637
     638    genericUnwind(vm, callFrame);
     639    ASSERT(!!vm.callFrameForCatch);
     640    ASSERT(!!vm.targetMachinePCForThrow);
     641    // FIXME: We could make this better:
     642    // This is a total hack, but the llint (both op_catch and llint_handle_uncaught_exception)
     643    // require a cell in the callee field to load the VM. (The baseline JIT does not require
     644    // this since it is compiled with a constant VM pointer.) We could make the calling convention
     645    // for exceptions first load callFrameForCatch info call frame register before jumping
     646    // to the exception handler. If we did this, we could remove this terrible hack.
     647    // https://bugs.webkit.org/show_bug.cgi?id=170440
     648    vm.calleeForWasmCatch = callFrame->callee();
     649    bitwise_cast<uint64_t*>(callFrame)[static_cast<int>(CallFrameSlot::callee)] = bitwise_cast<uint64_t>(jsInstance->module());
     650    WASM_RETURN_TWO(vm.targetMachinePCForThrow, nullptr);
     651}
     652
     653WASM_SLOW_PATH_DECL(retrieve_and_clear_exception)
     654{
     655    UNUSED_PARAM(callFrame);
     656    JSWebAssemblyInstance* jsInstance = instance->owner<JSWebAssemblyInstance>();
     657    JSGlobalObject* globalObject = jsInstance->globalObject();
     658    VM& vm = globalObject->vm();
     659    auto throwScope = DECLARE_THROW_SCOPE(vm);
     660
     661    RELEASE_ASSERT(!!throwScope.exception());
     662
     663    Exception* exception = throwScope.exception();
     664    JSValue thrownValue = exception->value();
     665    void* payload = nullptr;
     666
     667    const auto& handleCatchAll = [&](const auto& instruction) {
     668        callFrame->uncheckedR(instruction.m_exception) = thrownValue;
     669    };
     670
     671    const auto& handleCatch = [&](const auto& instruction) {
     672        JSWebAssemblyException* wasmException = jsDynamicCast<JSWebAssemblyException*>(vm, thrownValue);
     673        RELEASE_ASSERT(!!wasmException);
     674        payload = bitwise_cast<void*>(wasmException->payload().data());
     675        callFrame->uncheckedR(instruction.m_exception) = thrownValue;
     676    };
     677
     678    if (pc->is<WasmCatch, WasmOpcodeTraits>())
     679        handleCatch(pc->as<WasmCatch, WasmOpcodeTraits>());
     680    else if (pc->is<WasmCatchAll, WasmOpcodeTraits>())
     681        handleCatchAll(pc->as<WasmCatchAll, WasmOpcodeTraits>());
     682    else if (pc->is<WasmCatchNoTls, WasmOpcodeTraits>())
     683        handleCatch(pc->as<WasmCatchNoTls, WasmOpcodeTraits>());
     684    else if (pc->is<WasmCatchAllNoTls, WasmOpcodeTraits>())
     685        handleCatchAll(pc->as<WasmCatchAllNoTls, WasmOpcodeTraits>());
     686    else
     687        RELEASE_ASSERT_NOT_REACHED();
     688
     689    // We want to clear the exception here rather than in the catch prologue
     690    // JIT code because clearing it also entails clearing a bit in an Atomic
     691    // bit field in VMTraps.
     692    throwScope.clearException();
     693    WASM_RETURN_TWO(pc, payload);
     694}
     695
    589696extern "C" SlowPathReturnType slow_path_wasm_throw_exception(CallFrame* callFrame, const Instruction* pc, Wasm::Instance* instance, Wasm::ExceptionType exceptionType)
    590697{
  • trunk/Source/JavaScriptCore/wasm/WasmSlowPaths.h

    r280770 r283852  
    8484WASM_SLOW_PATH_HIDDEN_DECL(memory_atomic_wait64);
    8585WASM_SLOW_PATH_HIDDEN_DECL(memory_atomic_notify);
     86WASM_SLOW_PATH_HIDDEN_DECL(throw);
     87WASM_SLOW_PATH_HIDDEN_DECL(rethrow);
     88WASM_SLOW_PATH_HIDDEN_DECL(retrieve_and_clear_exception);
    8689
    8790extern "C" SlowPathReturnType slow_path_wasm_throw_exception(CallFrame*, const Instruction*, Wasm::Instance* instance, Wasm::ExceptionType) REFERENCED_FROM_ASM WTF_INTERNAL;
  • trunk/Source/JavaScriptCore/wasm/WasmStreamingParser.cpp

    r278340 r283852  
    118118    m_functionIndex = 0;
    119119    m_codeOffset = m_offset;
     120    m_info->m_functionDoesNotUseExceptions.ensureSize(functionCount);
    120121
    121122    WASM_PARSER_FAIL_IF(functionCount == std::numeric_limits<uint32_t>::max(), "Code section's count is too big ", functionCount);
  • trunk/Source/JavaScriptCore/wasm/WasmTag.cpp

    r283851 r283852  
    11/*
    2  * Copyright (C) 2016 Apple Inc. All rights reserved.
     2 * Copyright (C) 2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2424 */
    2525
    26 #pragma once
     26#include "config.h"
     27#include "WasmTag.h"
    2728
    2829#if ENABLE(WEBASSEMBLY)
    2930
    30 #include "ErrorInstance.h"
     31namespace JSC {
     32namespace Wasm {
    3133
    32 namespace JSC {
     34std::atomic<uint32_t> Tag::s_id = 0;
    3335
    34 JSObject* createJSWebAssemblyRuntimeError(JSGlobalObject*, VM&, const String&);
     36} } // namespace JSC::Wasm
    3537
    36 } // namespace JSC
    37 
    38 #endif // ENABLE(WEBASSEMBLY)
     38#endif
  • trunk/Source/JavaScriptCore/wasm/WasmTag.h

    r283851 r283852  
    11/*
    2  * Copyright (C) 2019 Apple Inc. All rights reserved.
     2 * Copyright (C) 2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2828#if ENABLE(WEBASSEMBLY)
    2929
    30 #include <wtf/Expected.h>
    31 #include <wtf/text/WTFString.h>
     30#include "WasmSignature.h"
    3231
    3332namespace JSC { namespace Wasm {
    3433
    35 class FunctionCodeBlock;
    36 class Signature;
    37 struct ModuleInformation;
     34class Tag : public ThreadSafeRefCounted<Tag> {
     35    WTF_MAKE_FAST_ALLOCATED;
     36    WTF_MAKE_NONCOPYABLE(Tag);
     37public:
     38    static Ref<Tag> create(const Signature& signature) { return adoptRef(*new Tag(signature)); }
    3839
    39 Expected<std::unique_ptr<FunctionCodeBlock>, String> parseAndCompileBytecode(const uint8_t*, size_t, const Signature&, const ModuleInformation&, uint32_t functionIndex);
     40    SignatureArgCount parameterCount() const { return m_signature->argumentCount(); }
     41    Type parameter(SignatureArgCount i) const { return m_signature->argument(i); }
     42
     43    bool operator==(const Tag& other) const { return m_id == other.m_id; }
     44    bool operator!=(const Tag& other) const { return m_id != other.m_id; }
     45
     46    const Signature& signature() const { return m_signature.get(); }
     47
     48private:
     49    Tag(const Signature& signature)
     50        : m_id(++s_id)
     51        , m_signature(Ref { signature })
     52    {
     53    }
     54
     55    static std::atomic<uint32_t> s_id;
     56    uint32_t m_id;
     57    Ref<const Signature> m_signature;
     58};
    4059
    4160} } // namespace JSC::Wasm
  • trunk/Source/JavaScriptCore/wasm/WasmThunks.cpp

    r277928 r283852  
    11/*
    2  * Copyright (C) 2017-2020 Apple Inc. All rights reserved.
     2 * Copyright (C) 2017-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2929#if ENABLE(WEBASSEMBLY)
    3030
     31#include "AllowMacroScratchRegisterUsage.h"
    3132#include "CCallHelpers.h"
     33#include "JSInterfaceJIT.h"
    3234#include "LinkBuffer.h"
     35#include "ProbeContext.h"
    3336#include "ScratchRegisterAllocator.h"
    3437#include "WasmExceptionType.h"
  • trunk/Source/JavaScriptCore/wasm/WasmThunks.h

    r278093 r283852  
    11/*
    2  * Copyright (C) 2017-2018 Apple Inc. All rights reserved.
     2 * Copyright (C) 2017-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
  • trunk/Source/JavaScriptCore/wasm/generateWasmB3IRGeneratorInlinesHeader.py

    r277853 r283852  
    145145            self.consume(")")
    146146        elif argumentRegex.match(self.token()):
    147             result = "arg" + self.token()[1:]
     147            result = "get(arg" + self.token()[1:] + ")"
    148148            self.advance()
    149149        else:
     
    157157        return result
    158158
     159    def makeResult(self, resultValue):
     160        return resultValue + ";\n" + "result = push(resultValue->type());\n" + "m_currentBlock->appendNew<VariableValue>(m_proc, Set, origin(), result, resultValue);"
     161
    159162    def generate(self, wasmOp):
    160163        if len(self.tokens) == 1:
    161             params = ["arg" + str(param) for param in range(len(wasmOp["parameter"]))]
    162             return "    result = m_currentBlock->appendNew<Value>(m_proc, B3::" + self.token() + ", origin(), " + ", ".join(params) + ")"
     164            params = ["get(arg" + str(param) + ")" for param in range(len(wasmOp["parameter"]))]
     165            return self.makeResult("    Value* resultValue = m_currentBlock->appendNew<Value>(m_proc, B3::" + self.token() + ", origin(), " + ", ".join(params) + ")")
    163166        result = self.generateOpcode()
    164         self.code.append("result = " + result)
    165         return "    " + "    \n".join(self.code)
     167        self.code.append("Value* resultValue = " + result)
     168        return self.makeResult("    " + "    \n".join(self.code))
    166169
    167170
     
    192195template<> auto B3IRGenerator::addOp<OpType::""" + wasm.toCpp(op["name"]) + ">(" + ", ".join(args) + """) -> PartialResult
    193196{
    194 """ + generateB3Code(opcode, b3op) + """;
     197""" + generateB3Code(opcode, b3op) + """
    195198    return { };
    196199}
  • trunk/Source/JavaScriptCore/wasm/generateWasmOpsHeader.py

    r282701 r283852  
    5454    inc = 0
    5555    for ty in wasm.types:
    56         yield cppMacro(ty, wasm.types[ty]["value"], wasm.types[ty]["b3type"], inc)
     56        yield cppMacro(ty, wasm.types[ty]["value"], wasm.types[ty]["b3type"], inc, ty)
    5757        inc += 1
    5858
  • trunk/Source/JavaScriptCore/wasm/js/JSWebAssembly.cpp

    r281438 r283852  
    7979@begin webAssemblyTable
    8080  CompileError    createWebAssemblyCompileError  DontEnum|PropertyCallback
     81  Exception       createWebAssemblyException     DontEnum|PropertyCallback
    8182  Global          createWebAssemblyGlobal        DontEnum|PropertyCallback
    8283  Instance        createWebAssemblyInstance      DontEnum|PropertyCallback
     
    8687  RuntimeError    createWebAssemblyRuntimeError  DontEnum|PropertyCallback
    8788  Table           createWebAssemblyTable         DontEnum|PropertyCallback
     89  Tag             createWebAssemblyTag           DontEnum|PropertyCallback
    8890  compile         webAssemblyCompileFunc         Function 1
    8991  instantiate     webAssemblyInstantiateFunc     Function 1
  • trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyHelpers.h

    r273813 r283852  
    3333#include "JSCJSValue.h"
    3434#include "JSSourceCode.h"
     35#include "JSWebAssemblyRuntimeError.h"
    3536#include "WasmFormat.h"
    3637#include "WebAssemblyFunction.h"
     
    145146}
    146147
     148ALWAYS_INLINE JSValue toJSValue(JSGlobalObject* globalObject, const Wasm::Type type, uint64_t bits)
     149{
     150    switch (type.kind) {
     151    case Wasm::TypeKind::Void:
     152        return jsUndefined();
     153    case Wasm::TypeKind::I32:
     154        return jsNumber(static_cast<int32_t>(bits));
     155    case Wasm::TypeKind::F32:
     156        return jsNumber(bitwise_cast<float>(static_cast<int32_t>(bits)));
     157    case Wasm::TypeKind::F64:
     158        return jsNumber(bitwise_cast<double>(bits));
     159    case Wasm::TypeKind::I64:
     160        return JSBigInt::createFrom(globalObject, static_cast<int64_t>(bits));
     161    case Wasm::TypeKind::Externref:
     162    case Wasm::TypeKind::Funcref:
     163        return bitwise_cast<JSValue>(bits);
     164    default:
     165        break;
     166    }
     167    RELEASE_ASSERT_NOT_REACHED();
     168    return JSValue();
     169}
     170
     171ALWAYS_INLINE uint64_t fromJSValue(JSGlobalObject* globalObject, const Wasm::Type type, JSValue value)
     172{
     173    VM& vm = globalObject->vm();
     174    auto scope = DECLARE_THROW_SCOPE(vm);
     175    switch (type.kind) {
     176    case Wasm::TypeKind::TypeIdx:
     177    case Wasm::TypeKind::Funcref: {
     178        bool isNullable = type.isNullable();
     179        WebAssemblyFunction* wasmFunction = nullptr;
     180        WebAssemblyWrapperFunction* wasmWrapperFunction = nullptr;
     181        if (!isWebAssemblyHostFunction(vm, value, wasmFunction, wasmWrapperFunction) && (!isNullable || !value.isNull()))
     182            return throwVMException(globalObject, scope, createJSWebAssemblyRuntimeError(globalObject, vm, "Funcref must be an exported wasm function"));
     183        if (type.kind == Wasm::TypeKind::TypeIdx && (wasmFunction || wasmWrapperFunction)) {
     184            Wasm::SignatureIndex paramIndex = type.index;
     185            Wasm::SignatureIndex argIndex;
     186            if (wasmFunction)
     187                argIndex = wasmFunction->signatureIndex();
     188            else
     189                argIndex = wasmWrapperFunction->signatureIndex();
     190            if (paramIndex != argIndex)
     191                return throwVMException(globalObject, scope, createJSWebAssemblyRuntimeError(globalObject, vm, "Argument function did not match the reference type"));
     192        }
     193        break;
     194    }
     195    case Wasm::TypeKind::Externref:
     196        if (!type.isNullable() && value.isNull())
     197            return throwVMException(globalObject, scope, createJSWebAssemblyRuntimeError(globalObject, vm, "Non-null Externref cannot be null"));
     198        break;
     199    case Wasm::TypeKind::I32:
     200        RELEASE_AND_RETURN(scope, value.toInt32(globalObject));
     201    case Wasm::TypeKind::I64:
     202        RELEASE_AND_RETURN(scope, bitwise_cast<uint64_t>(value.toBigInt64(globalObject)));
     203    case Wasm::TypeKind::F32:
     204        RELEASE_AND_RETURN(scope, bitwise_cast<uint32_t>(value.toFloat(globalObject)));
     205    case Wasm::TypeKind::F64:
     206        RELEASE_AND_RETURN(scope, bitwise_cast<uint64_t>(value.toNumber(globalObject)));
     207    case Wasm::TypeKind::Void:
     208    case Wasm::TypeKind::Func:
     209    case Wasm::TypeKind::RefNull:
     210    case Wasm::TypeKind::Ref:
     211        RELEASE_ASSERT_NOT_REACHED();
     212    }
     213
     214    RELEASE_AND_RETURN(scope, JSValue::encode(value));
     215}
     216
    147217} // namespace JSC
    148218
  • trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp

    r277909 r283852  
    217217        case Wasm::ExternalKind::Global:
    218218        case Wasm::ExternalKind::Table:
     219        case Wasm::ExternalKind::Exception:
    219220            continue;
    220221        case Wasm::ExternalKind::Memory:
     
    243244        case Wasm::ExternalKind::Global:
    244245        case Wasm::ExternalKind::Table:
     246        case Wasm::ExternalKind::Exception:
    245247            break;
    246248
  • trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h

    r282860 r283852  
    4949
    5050class JSWebAssemblyInstance final : public JSNonFinalObject {
     51    friend class LLIntOffsetsExtractor;
     52
    5153public:
    5254    using Base = JSNonFinalObject;
  • trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyRuntimeError.cpp

    r277238 r283852  
    11/*
    2  * Copyright (C) 2016 Apple Inc. All rights reserved.
     2 * Copyright (C) 2016-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3838    return ErrorInstance::create(globalObject, vm, globalObject->webAssemblyRuntimeErrorStructure(), message, JSValue(), defaultSourceAppender, TypeNothing, ErrorType::Error, true);
    3939}
     40
     41JSObject* createJSWebAssemblyRuntimeError(JSGlobalObject* globalObject, VM& vm, Wasm::ExceptionType type)
     42{
     43    ErrorInstance* error = ErrorInstance::create(globalObject, vm, globalObject->webAssemblyRuntimeErrorStructure(), Wasm::errorMessageForExceptionType(type), JSValue(), defaultSourceAppender, TypeNothing, ErrorType::Error, true);
     44    error->setCatchableFromWasm(false);
     45    return error;
     46}
    4047   
    4148} // namespace JSC
  • trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyRuntimeError.h

    r274609 r283852  
    11/*
    2  * Copyright (C) 2016 Apple Inc. All rights reserved.
     2 * Copyright (C) 2016-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2929
    3030#include "ErrorInstance.h"
     31#include "WasmExceptionType.h"
    3132
    3233namespace JSC {
    3334
    3435JSObject* createJSWebAssemblyRuntimeError(JSGlobalObject*, VM&, const String&);
     36JSObject* createJSWebAssemblyRuntimeError(JSGlobalObject*, VM&, Wasm::ExceptionType);
    3537
    3638} // namespace JSC
  • trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyTag.cpp

    r283851 r283852  
    11/*
    2  * Copyright (C) 2016 Apple Inc. All rights reserved.
     2 * Copyright (C) 2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2525
    2626#include "config.h"
    27 #include "JSWebAssemblyRuntimeError.h"
     27#include "JSWebAssemblyTag.h"
    2828
    2929#if ENABLE(WEBASSEMBLY)
    3030
    31 #include "JSCJSValueInlines.h"
     31#include "WasmTag.h"
    3232
    3333namespace JSC {
    3434
    35 JSObject* createJSWebAssemblyRuntimeError(JSGlobalObject* globalObject, VM& vm, const String& message)
     35const ClassInfo JSWebAssemblyTag::s_info = { "WebAssembly.Tag", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSWebAssemblyTag) };
     36
     37JSWebAssemblyTag* JSWebAssemblyTag::create(VM& vm, JSGlobalObject* globalObject, Structure* structure, const Wasm::Tag& tag)
    3638{
    37     ASSERT(!message.isEmpty());
    38     return ErrorInstance::create(globalObject, vm, globalObject->webAssemblyRuntimeErrorStructure(), message, JSValue(), defaultSourceAppender, TypeNothing, ErrorType::Error, true);
     39    UNUSED_PARAM(globalObject);
     40    auto* jsTag = new (NotNull, allocateCell<JSWebAssemblyTag>(vm.heap)) JSWebAssemblyTag(vm, structure, tag);
     41    jsTag->finishCreation(vm);
     42    return jsTag;
    3943}
    40    
     44
     45Structure* JSWebAssemblyTag::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
     46{
     47    return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
     48}
     49
     50JSWebAssemblyTag::JSWebAssemblyTag(VM& vm, Structure* structure, const Wasm::Tag& tag)
     51    : Base(vm, structure)
     52    , m_tag(Ref { tag })
     53{
     54}
     55
     56void JSWebAssemblyTag::destroy(JSCell* cell)
     57{
     58    static_cast<JSWebAssemblyTag*>(cell)->JSWebAssemblyTag::~JSWebAssemblyTag();
     59}
     60
    4161} // namespace JSC
    4262
  • trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyTag.h

    r283851 r283852  
    11/*
    2  * Copyright (C) 2016 Apple Inc. All rights reserved.
     2 * Copyright (C) 2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2828#if ENABLE(WEBASSEMBLY)
    2929
    30 #include "ErrorInstance.h"
     30#include "WasmTag.h"
    3131
    3232namespace JSC {
    3333
    34 JSObject* createJSWebAssemblyRuntimeError(JSGlobalObject*, VM&, const String&);
     34class JSWebAssemblyTag final : public JSNonFinalObject {
     35public:
     36    using Base = JSNonFinalObject;
     37    static constexpr bool needsDestruction = true;
     38
     39    static void destroy(JSCell*);
     40
     41    template<typename CellType, SubspaceAccess mode>
     42    static IsoSubspace* subspaceFor(VM& vm)
     43    {
     44        return vm.webAssemblyTagSpace<mode>();
     45    }
     46
     47    DECLARE_EXPORT_INFO;
     48
     49    JS_EXPORT_PRIVATE static JSWebAssemblyTag* create(VM&, JSGlobalObject*, Structure*, const Wasm::Tag&);
     50    static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
     51
     52    const Wasm::Tag& tag() const { return m_tag; }
     53    const Wasm::Signature& signature() const { return tag().signature(); }
     54
     55private:
     56    JSWebAssemblyTag(VM&, Structure*, const Wasm::Tag&);
     57
     58    const Ref<const Wasm::Tag> m_tag;
     59};
    3560
    3661} // namespace JSC
  • trunk/Source/JavaScriptCore/wasm/js/WasmToJS.cpp

    r279265 r283852  
    9999        unsigned marshalledFPRs = 0;
    100100        unsigned calleeFrameOffset = CallFrameSlot::firstArgument * static_cast<int>(sizeof(Register));
    101         unsigned frOffset = CallFrame::headerSizeInRegisters * static_cast<int>(sizeof(Register));
     101        unsigned frOffset = CallFrameSlot::firstArgument * static_cast<int>(sizeof(Register));
    102102        for (unsigned argNum = 0; argNum < argCount; ++argNum) {
    103103            Type argType = signature.argument(argNum);
     
    163163        unsigned marshalledFPRs = 0;
    164164        unsigned calleeFrameOffset = CallFrameSlot::firstArgument * static_cast<int>(sizeof(Register));
    165         unsigned frOffset = CallFrame::headerSizeInRegisters * static_cast<int>(sizeof(Register));
     165        unsigned frOffset = CallFrameSlot::firstArgument * static_cast<int>(sizeof(Register));
    166166
    167167        auto marshallFPR = [&] (FPRReg fprReg) {
  • trunk/Source/JavaScriptCore/wasm/js/WebAssemblyExceptionConstructor.h

    r283851 r283852  
    11/*
    2  * Copyright (C) 2016 Apple Inc. All rights reserved.
     2 * Copyright (C) 2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2828#if ENABLE(WEBASSEMBLY)
    2929
    30 #include "ErrorInstance.h"
     30#include "InternalFunction.h"
     31#include "JSObject.h"
    3132
    3233namespace JSC {
    3334
    34 JSObject* createJSWebAssemblyRuntimeError(JSGlobalObject*, VM&, const String&);
     35class WebAssemblyExceptionPrototype;
     36
     37class WebAssemblyExceptionConstructor final : public InternalFunction {
     38public:
     39    using Base = InternalFunction;
     40    static constexpr unsigned StructureFlags = Base::StructureFlags | HasStaticPropertyTable;
     41
     42    static WebAssemblyExceptionConstructor* create(VM&, Structure*, WebAssemblyExceptionPrototype*);
     43    static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
     44
     45    DECLARE_INFO;
     46
     47private:
     48    WebAssemblyExceptionConstructor(VM&, Structure*);
     49    void finishCreation(VM&, WebAssemblyExceptionPrototype*);
     50};
     51STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(WebAssemblyExceptionConstructor, InternalFunction);
    3552
    3653} // namespace JSC
  • trunk/Source/JavaScriptCore/wasm/js/WebAssemblyExceptionPrototype.h

    r283851 r283852  
    11/*
    2  * Copyright (C) 2016 Apple Inc. All rights reserved.
     2 * Copyright (C) 2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2828#if ENABLE(WEBASSEMBLY)
    2929
    30 #include "ErrorInstance.h"
     30#include "JSDestructibleObject.h"
     31#include "JSObject.h"
    3132
    3233namespace JSC {
    3334
    34 JSObject* createJSWebAssemblyRuntimeError(JSGlobalObject*, VM&, const String&);
     35class WebAssemblyExceptionPrototype final : public JSNonFinalObject {
     36public:
     37    using Base = JSNonFinalObject;
     38    static constexpr unsigned StructureFlags = Base::StructureFlags | HasStaticPropertyTable;
     39
     40    template<typename CellType, SubspaceAccess>
     41    static IsoSubspace* subspaceFor(VM& vm)
     42    {
     43        STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(WebAssemblyExceptionPrototype, Base);
     44        return &vm.plainObjectSpace;
     45    }
     46
     47    static WebAssemblyExceptionPrototype* create(VM&, JSGlobalObject*, Structure*);
     48    static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
     49
     50    DECLARE_INFO;
     51
     52private:
     53    WebAssemblyExceptionPrototype(VM&, Structure*);
     54    void finishCreation(VM&);
     55};
    3556
    3657} // namespace JSC
  • trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp

    r279265 r283852  
    7979
    8080    for (unsigned argIndex = 0; argIndex < signature.argumentCount(); ++argIndex) {
    81         JSValue arg = callFrame->argument(argIndex);
    82         switch (signature.argument(argIndex).kind) {
    83         case Wasm::TypeKind::I32:
    84             arg = JSValue::decode(arg.toInt32(globalObject));
    85             break;
    86         case Wasm::TypeKind::TypeIdx:
    87         case Wasm::TypeKind::Funcref: {
    88             bool isNullable = signature.argument(argIndex).isNullable();
    89             WebAssemblyFunction* wasmFunction = nullptr;
    90             WebAssemblyWrapperFunction* wasmWrapperFunction = nullptr;
    91             if (!isWebAssemblyHostFunction(vm, arg, wasmFunction, wasmWrapperFunction) && (!isNullable || !arg.isNull()))
    92                 return JSValue::encode(throwException(globalObject, scope, createJSWebAssemblyRuntimeError(globalObject, vm, "Funcref must be an exported wasm function")));
    93             if (signature.argument(argIndex).kind == Wasm::TypeKind::TypeIdx && (wasmFunction || wasmWrapperFunction)) {
    94                 Wasm::SignatureIndex paramIndex = signature.argument(argIndex).index;
    95                 Wasm::SignatureIndex argIndex;
    96                 if (wasmFunction)
    97                     argIndex = wasmFunction->signatureIndex();
    98                 else
    99                     argIndex = wasmWrapperFunction->signatureIndex();
    100                 if (paramIndex != argIndex)
    101                     return JSValue::encode(throwException(globalObject, scope, createJSWebAssemblyRuntimeError(globalObject, vm, "Argument function did not match the reference type")));
    102             }
    103             break;
    104         }
    105         case Wasm::TypeKind::Externref:
    106             if (!signature.argument(argIndex).isNullable() && arg.isNull())
    107                 return JSValue::encode(throwException(globalObject, scope, createJSWebAssemblyRuntimeError(globalObject, vm, "Non-null Externref cannot be null")));
    108             break;
    109         case Wasm::TypeKind::I64:
    110             arg = JSValue::decode(bitwise_cast<uint64_t>(arg.toBigInt64(globalObject)));
    111             break;
    112         case Wasm::TypeKind::F32:
    113             arg = JSValue::decode(bitwise_cast<uint32_t>(arg.toFloat(globalObject)));
    114             break;
    115         case Wasm::TypeKind::F64:
    116             arg = JSValue::decode(bitwise_cast<uint64_t>(arg.toNumber(globalObject)));
    117             break;
    118         case Wasm::TypeKind::Void:
    119         case Wasm::TypeKind::Func:
    120         case Wasm::TypeKind::RefNull:
    121         case Wasm::TypeKind::Ref:
    122             RELEASE_ASSERT_NOT_REACHED();
    123         }
     81        uint64_t value = fromJSValue(globalObject, signature.argument(argIndex), callFrame->argument(argIndex));
    12482        RETURN_IF_EXCEPTION(scope, encodedJSValue());
    125         boxedArgs.append(arg);
     83        boxedArgs.append(JSValue::decode(value));
    12684    }
    12785
     
    153111    ASSERT(&wasmFunction->instance()->instance() == vm.wasmContext.load());
    154112    EncodedJSValue rawResult = vmEntryToWasm(wasmFunction->jsEntrypoint(MustCheckArity).executableAddress(), &vm, &protoCallFrame);
    155     // We need to make sure this is in a register or on the stack since it's stored in Vector<JSValue>.
    156     // This probably isn't strictly necessary, since the WebAssemblyFunction* should keep the instance
    157     // alive. But it's good hygiene.
    158     instance->use();
    159113    if (prevWasmInstance != wasmInstance) {
    160114        // This is just for some extra safety instead of leaving a cached
     
    168122    vm.wasmContext.store(prevWasmInstance, vm.softStackLimit());
    169123    RETURN_IF_EXCEPTION(scope, { });
     124
     125    // We need to make sure this is in a register or on the stack since it's stored in Vector<JSValue>.
     126    // This probably isn't strictly necessary, since the WebAssemblyFunction* should keep the instance
     127    // alive. But it's good hygiene.
     128    instance->use();
    170129
    171130    return rawResult;
  • trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp

    r279265 r283852  
    3838#include "JSWebAssemblyLinkError.h"
    3939#include "JSWebAssemblyModule.h"
     40#include "JSWebAssemblyTag.h"
    4041#include "ObjectConstructor.h"
    4142#include "WasmSignatureInlines.h"
     
    131132        case Wasm::ExternalKind::Global:
    132133        case Wasm::ExternalKind::Table:
     134        case Wasm::ExternalKind::Exception:
    133135            break;
    134136        case Wasm::ExternalKind::Memory:
     
    364366
    365367        case Wasm::ExternalKind::Table: {
    366             // 7. Otherwise (i is a table import):
     368            // 7. If i is a table import:
    367369            JSWebAssemblyTable* table = jsDynamicCast<JSWebAssemblyTable*>(vm, value);
    368370            // i. If v is not a WebAssembly.Table object, throw a WebAssembly.LinkError.
     
    392394            m_instance->setTable(vm, import.kindIndex, table);
    393395            RETURN_IF_EXCEPTION(scope, void());
     396            break;
     397        }
     398
     399        case Wasm::ExternalKind::Exception: {
     400            JSWebAssemblyTag* tag = jsDynamicCast<JSWebAssemblyTag*>(vm, value);
     401            if (!tag)
     402                return exception(createJSWebAssemblyLinkError(globalObject, vm, importFailMessage(import, "Tag import", "is not an instance of WebAssembly.Tag")));
     403
     404            Wasm::SignatureIndex expectedSignatureIndex = moduleInformation.importExceptionSignatureIndices[import.kindIndex];
     405
     406            if (expectedSignatureIndex != tag->tag().signature().index())
     407                return exception(createJSWebAssemblyLinkError(globalObject, vm, importFailMessage(import, "imported Tag", "signature doesn't match the imported WebAssembly Tag's signature")));
     408
     409            m_instance->instance().addTag(tag->tag());
    394410            break;
    395411        }
     
    421437        }
    422438    }
     439
     440    for (Wasm::SignatureIndex signatureIndex : moduleInformation.internalExceptionSignatureIndices)
     441        m_instance->instance().addTag(Wasm::Tag::create(Wasm::SignatureInformation::get(signatureIndex)));
    423442
    424443    unsigned functionImportCount = codeBlock->functionImportCount();
     
    558577            break;
    559578        }
     579        case Wasm::ExternalKind::Exception: {
     580            exportedValue = JSWebAssemblyTag::create(vm, globalObject, globalObject->m_webAssemblyTagStructure.get(globalObject), m_instance->instance().tag(exp.kindIndex));
     581            break;
     582        }
    560583        }
    561584
  • trunk/Source/JavaScriptCore/wasm/js/WebAssemblyTagConstructor.h

    r283851 r283852  
    11/*
    2  * Copyright (C) 2016 Apple Inc. All rights reserved.
     2 * Copyright (C) 2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2828#if ENABLE(WEBASSEMBLY)
    2929
    30 #include "ErrorInstance.h"
     30#include "InternalFunction.h"
     31#include "WasmOps.h"
    3132
    3233namespace JSC {
    3334
    34 JSObject* createJSWebAssemblyRuntimeError(JSGlobalObject*, VM&, const String&);
     35class JSWebAssemblyTag;
     36class WebAssemblyTagPrototype;
     37
     38namespace Wasm {
     39class Tag;
     40}
     41
     42class WebAssemblyTagConstructor final : public InternalFunction {
     43public:
     44    using Base = InternalFunction;
     45
     46    static WebAssemblyTagConstructor* create(VM&, Structure*, WebAssemblyTagPrototype*);
     47    static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
     48
     49    DECLARE_INFO;
     50
     51private:
     52    WebAssemblyTagConstructor(VM&, Structure*);
     53    void finishCreation(VM&, WebAssemblyTagPrototype*);
     54};
     55STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(WebAssemblyTagConstructor, InternalFunction);
    3556
    3657} // namespace JSC
  • trunk/Source/JavaScriptCore/wasm/js/WebAssemblyTagPrototype.h

    r283851 r283852  
    11/*
    2  * Copyright (C) 2016 Apple Inc. All rights reserved.
     2 * Copyright (C) 2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2828#if ENABLE(WEBASSEMBLY)
    2929
    30 #include "ErrorInstance.h"
     30#include "JSObject.h"
    3131
    3232namespace JSC {
    3333
    34 JSObject* createJSWebAssemblyRuntimeError(JSGlobalObject*, VM&, const String&);
     34class WebAssemblyTagPrototype final : public JSNonFinalObject {
     35public:
     36    using Base = JSNonFinalObject;
     37    static constexpr unsigned StructureFlags = Base::StructureFlags | HasStaticPropertyTable;
     38
     39    template<typename CellType, SubspaceAccess>
     40    static IsoSubspace* subspaceFor(VM& vm)
     41    {
     42        STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(WebAssemblyTagPrototype, Base);
     43        return &vm.plainObjectSpace;
     44    }
     45
     46    static WebAssemblyTagPrototype* create(VM&, JSGlobalObject*, Structure*);
     47    static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
     48
     49    DECLARE_INFO;
     50
     51private:
     52    WebAssemblyTagPrototype(VM&, Structure*);
     53    void finishCreation(VM&);
     54};
    3555
    3656} // namespace JSC
  • trunk/Source/JavaScriptCore/wasm/wasm.json

    r279265 r283852  
    2424    "ref_type": ["funcref", "externref", "type_idx"],
    2525    "external_kind": {
    26         "Function": { "type": "uint8", "value": 0 },
    27         "Table":    { "type": "uint8", "value": 1 },
    28         "Memory":   { "type": "uint8", "value": 2 },
    29         "Global":   { "type": "uint8", "value": 3 }
     26        "Function":    { "type": "uint8", "value": 0 },
     27        "Table":       { "type": "uint8", "value": 1 },
     28        "Memory":      { "type": "uint8", "value": 2 },
     29        "Global":      { "type": "uint8", "value": 3 },
     30        "Exception":   { "type": "uint8", "value": 4 }
    3031    },
    3132    "section" : {
    32         "Type":     { "type": "varuint7", "value":  1, "description": "Function signature declarations" },
    33         "Import":   { "type": "varuint7", "value":  2, "description": "Import declarations" },
    34         "Function": { "type": "varuint7", "value":  3, "description": "Function declarations" },
    35         "Table":    { "type": "varuint7", "value":  4, "description": "Indirect function table and other tables" },
    36         "Memory":   { "type": "varuint7", "value":  5, "description": "Memory attributes" },
    37         "Global":   { "type": "varuint7", "value":  6, "description": "Global declarations" },
    38         "Export":   { "type": "varuint7", "value":  7, "description": "Exports" },
    39         "Start":    { "type": "varuint7", "value":  8, "description": "Start function declaration" },
    40         "Element":  { "type": "varuint7", "value":  9, "description": "Elements section" },
    41         "Code":     { "type": "varuint7", "value": 10, "description": "Function bodies (code)" },
    42         "Data":     { "type": "varuint7", "value": 11, "description": "Data segments" }
     33        "Type":      { "type": "varuint7", "value":  1, "description": "Function signature declarations" },
     34        "Import":    { "type": "varuint7", "value":  2, "description": "Import declarations" },
     35        "Function":  { "type": "varuint7", "value":  3, "description": "Function declarations" },
     36        "Table":     { "type": "varuint7", "value":  4, "description": "Indirect function table and other tables" },
     37        "Memory":    { "type": "varuint7", "value":  5, "description": "Memory attributes" },
     38        "Exception": { "type": "varuint7", "value": 13, "description": "Exception declarations" },
     39        "Global":    { "type": "varuint7", "value":  6, "description": "Global declarations" },
     40        "Export":    { "type": "varuint7", "value":  7, "description": "Exports" },
     41        "Start":     { "type": "varuint7", "value":  8, "description": "Start function declaration" },
     42        "Element":   { "type": "varuint7", "value":  9, "description": "Elements section" },
     43        "Code":      { "type": "varuint7", "value": 10, "description": "Function bodies (code)" },
     44        "Data":      { "type": "varuint7", "value": 11, "description": "Data segments" },
     45        "DataCount": { "type": "varuint7", "value": 12, "description": "Number of data segments" }
    4346    },
    4447    "opcode": {
    4548        "unreachable":         { "category": "control",    "value":   0, "return": [],                               "parameter": [],                             "immediate": [],                                                                                            "description": "trap immediately" },
     49        "nop":                 { "category": "control",    "value":   1, "return": [],                               "parameter": [],                             "immediate": [],                                                                                            "description": "no operation" },
    4650        "block":               { "category": "control",    "value":   2, "return": ["control"],                      "parameter": [],                             "immediate": [{"name": "sig", "type": "block_type"}],                                                       "description": "begin a sequence of expressions, yielding 0 or 1 values" },
    4751        "loop":                { "category": "control",    "value":   3, "return": ["control"],                      "parameter": [],                             "immediate": [{"name": "sig", "type": "block_type"}],                                                       "description": "begin a block which can also form control flow loops" },
    4852        "if":                  { "category": "control",    "value":   4, "return": ["control"],                      "parameter": ["bool"],                       "immediate": [{"name": "sig", "type": "block_type"}],                                                       "description": "begin if expression" },
    4953        "else":                { "category": "control",    "value":   5, "return": ["control"],                      "parameter": [],                             "immediate": [],                                                                                            "description": "begin else expression of if" },
    50         "select":              { "category": "control",    "value":  27, "return": ["prev"],                         "parameter": ["any", "prev", "bool"],        "immediate": [],                                                                                            "description": "select one of two values based on condition" },
    51         "annotated_select":    { "category": "control",    "value":  28, "return": ["prev"],                         "parameter": ["any", "prev", "bool"],        "immediate": [{"name": "target_types_count", "type": "varuint32",                                           "description": "number of entries in the target types vector"},
    52                                                                                                                                                                                 {"name": "target_types",       "type": "value_type*",                                         "description": "target types that indicate result of select instruction"}],
    53                                                                                                                                                                                                                                                                               "description": "the same as just select but with the annotation for result types" },
     54        "try":                 { "category": "control",    "value":   6, "return": ["control"],                      "parameter": [],                             "immediate": [{"name": "sig", "type": "block_type"}],                                                       "description": "begin try expression" },
     55        "catch":               { "category": "control",    "value":   7, "return": ["control"],                      "parameter": [],                             "immediate": [{"name": "exn", "type": "varuint32"}],                                                        "description": "begin catch expression of try" },
     56        "throw":               { "category": "control",    "value":   8, "return": ["control"],                      "parameter": [],                             "immediate": [{"name": "exn", "type": "varuint32"}],                                                        "description": "throw exception" },
     57        "rethrow":             { "category": "control",    "value":   9, "return": ["control"],                      "parameter": [],                             "immediate": [{"name": "relative_depth", "type": "varuint32"}],                                             "description": "rethrow the exception at the top of the stack" },
    5458        "br":                  { "category": "control",    "value":  12, "return": [],                               "parameter": [],                             "immediate": [{"name": "relative_depth", "type": "varuint32"}],                                             "description": "break that targets an outer nested block" },
    5559        "br_if":               { "category": "control",    "value":  13, "return": [],                               "parameter": [],                             "immediate": [{"name": "relative_depth", "type": "varuint32"}],                                             "description": "conditional break that targets an outer nested block" },
     
    5963                                                                                                                                                                                                                                                                              "description": "branch table control flow construct" },
    6064        "return":              { "category": "control",    "value":  15, "return": [],                               "parameter": [],                             "immediate": [],                                                                                            "description": "return zero or one value from this function" },
     65        "delegate":            { "category": "control",    "value":  24, "return": ["control"],                      "parameter": [],                             "immediate": [{"name": "relative_depth", "type": "varuint32"}],                                             "description": "delegate to a parent try block" },
     66        "catch_all":           { "category": "control",    "value":  25, "return": ["control"],                      "parameter": [],                             "immediate": [],                                                                                            "description": "catch exceptions regardless of tag" },
    6167        "drop":                { "category": "control",    "value":  26, "return": [],                               "parameter": ["any"],                        "immediate": [],                                                                                            "description": "ignore value" },
    62         "nop":                 { "category": "control",    "value":   1, "return": [],                               "parameter": [],                             "immediate": [],                                                                                            "description": "no operation" },
     68        "select":              { "category": "control",    "value":  27, "return": ["prev"],                         "parameter": ["any", "prev", "bool"],        "immediate": [],                                                                                            "description": "select one of two values based on condition" },
     69        "annotated_select":    { "category": "control",    "value":  28, "return": ["prev"],                         "parameter": ["any", "prev", "bool"],        "immediate": [{"name": "target_types_count", "type": "varuint32",                                           "description": "number of entries in the target types vector"},
     70                                                                                                                                                                                {"name": "target_types",       "type": "value_type*",                                         "description": "target types that indicate result of select instruction"}],
     71                                                                                                                                                                                                                                                                              "description": "the same as just select but with the annotation for result types" },
    6372        "end":                 { "category": "control",    "value":  11, "return": [],                               "parameter": [],                             "immediate": [],                                                                                            "description": "end a block, loop, or if" },
    6473        "i32.const":           { "category": "special",    "value":  65, "return": ["i32"],                          "parameter": [],                             "immediate": [{"name": "value",          "type": "varint32"}],                                              "description": "a constant value interpreted as i32" },
  • trunk/Tools/ChangeLog

    r283851 r283852  
     12021-10-08  Tadeu Zagallo  <tzagallo@apple.com>
     2
     3        Implement the WebAssembly exception handling proposal
     4        https://bugs.webkit.org/show_bug.cgi?id=229681
     5        <rdar://81603387>
     6
     7        Reviewed by Keith Miller.
     8
     9        * Scripts/run-jsc-stress-tests:
     10
    1112021-10-08  Jer Noble  <jer.noble@apple.com>
    212
  • trunk/Tools/Scripts/run-jsc-stress-tests

    r283745 r283852  
    12281228    prepareExtraAbsoluteFiles(WASMTESTS_PATH, ["wasm.json"])
    12291229    prepareExtraRelativeFiles(modules.map { |f| "../" + f }, $collection)
    1230     run("default-wasm", "-m", *(FTL_OPTIONS + optionalTestSpecificOptions))
     1230    if optionalTestSpecificOptions[0] == :no_module
     1231      optionalTestSpecificOptions.shift
     1232    else
     1233      optionalTestSpecificOptions.unshift "-m"
     1234    end
     1235    run("default-wasm", *(FTL_OPTIONS + optionalTestSpecificOptions))
    12311236    if $mode != "quick"
    1232         run("wasm-no-cjit-yes-tls-context", "-m", "--useFastTLSForWasmContext=true", *(FTL_OPTIONS + NO_CJIT_OPTIONS + optionalTestSpecificOptions))
    1233         run("wasm-eager", "-m", *(FTL_OPTIONS + EAGER_OPTIONS + optionalTestSpecificOptions))
    1234         run("wasm-eager-jettison", "-m", "--forceCodeBlockToJettisonDueToOldAge=true", "--useRandomizingExecutableIslandAllocation=true", "--verifyGC=true", *(FTL_OPTIONS + optionalTestSpecificOptions))
    1235         run("wasm-no-tls-context", "-m", "--useFastTLSForWasmContext=false", *(FTL_OPTIONS + optionalTestSpecificOptions))
    1236         run("wasm-slow-memory", "-m", "--useWebAssemblyFastMemory=false", *(FTL_OPTIONS + optionalTestSpecificOptions))
    1237         run("wasm-b3", "-m", "--useWasmLLInt=false", "--wasmBBQUsesAir=false", *(FTL_OPTIONS + optionalTestSpecificOptions))
    1238         run("wasm-air", "-m", "--useWasmLLInt=false", "--useRandomizingExecutableIslandAllocation=true", *(FTL_OPTIONS + optionalTestSpecificOptions))
    1239         run("wasm-collect-continuously", "-m", "--collectContinuously=true", "--verifyGC=true", *(FTL_OPTIONS + optionalTestSpecificOptions)) if shouldCollectContinuously?
     1237        run("wasm-no-cjit-yes-tls-context", "--useFastTLSForWasmContext=true", *(FTL_OPTIONS + NO_CJIT_OPTIONS + optionalTestSpecificOptions))
     1238        run("wasm-eager", *(FTL_OPTIONS + EAGER_OPTIONS + optionalTestSpecificOptions))
     1239        run("wasm-eager-jettison", "--forceCodeBlockToJettisonDueToOldAge=true", "--useRandomizingExecutableIslandAllocation=true", "--verifyGC=true", *(FTL_OPTIONS + optionalTestSpecificOptions))
     1240        run("wasm-no-tls-context", "--useFastTLSForWasmContext=false", *(FTL_OPTIONS + optionalTestSpecificOptions))
     1241        run("wasm-slow-memory", "--useWebAssemblyFastMemory=false", *(FTL_OPTIONS + optionalTestSpecificOptions))
     1242        run("wasm-b3", "--useWasmLLInt=false", "--wasmBBQUsesAir=false", *(FTL_OPTIONS + optionalTestSpecificOptions))
     1243        run("wasm-air", "--useWasmLLInt=false", "--useRandomizingExecutableIslandAllocation=true", *(FTL_OPTIONS + optionalTestSpecificOptions))
     1244        run("wasm-collect-continuously", "--collectContinuously=true", "--verifyGC=true", *(FTL_OPTIONS + optionalTestSpecificOptions)) if shouldCollectContinuously?
    12401245    end
    12411246end
Note: See TracChangeset for help on using the changeset viewer.