Diff
Modified: trunk/JSTests/ChangeLog (249660 => 249661)
--- trunk/JSTests/ChangeLog 2019-09-09 20:32:26 UTC (rev 249660)
+++ trunk/JSTests/ChangeLog 2019-09-09 20:32:56 UTC (rev 249661)
@@ -1,3 +1,27 @@
+2019-09-07 Keith Miller <[email protected]>
+
+ OSR entry into wasm misses some contexts
+ https://bugs.webkit.org/show_bug.cgi?id=201569
+
+ Reviewed by Yusuke Suzuki.
+
+ Add a new harness and wast and the generated wasm file for
+ testing. The idea long term is to make it easy to test by creating
+ a C file and converting it to a wast then modify that to produce a
+ test.
+
+ * wasm.yaml:
+ * wasm/wast-tests/harness.js: Added.
+ (async.runWasmFile):
+ * wasm/wast-tests/osr-entry-inner-loop-branch-above-no-consts.wasm: Added.
+ * wasm/wast-tests/osr-entry-inner-loop-branch-above-no-consts.wast: Added.
+ * wasm/wast-tests/osr-entry-inner-loop-branch-above.wasm: Added.
+ * wasm/wast-tests/osr-entry-inner-loop-branch-above.wast: Added.
+ * wasm/wast-tests/osr-entry-inner-loop.wasm: Added.
+ * wasm/wast-tests/osr-entry-inner-loop.wast: Added.
+ * wasm/wast-tests/osr-entry-multiple-enclosed-contexts.wasm: Added.
+ * wasm/wast-tests/osr-entry-multiple-enclosed-contexts.wast: Added.
+
2019-09-09 Yusuke Suzuki <[email protected]>
[JSC] Promise resolve/reject functions should be created more efficiently
Added: trunk/JSTests/wasm/wast-tests/harness.js (0 => 249661)
--- trunk/JSTests/wasm/wast-tests/harness.js (rev 0)
+++ trunk/JSTests/wasm/wast-tests/harness.js 2019-09-09 20:32:56 UTC (rev 249661)
@@ -0,0 +1,22 @@
+asyncTestStart(1);
+let context = {
+ env: globalThis,
+};
+
+globalThis.__linear_memory = new WebAssembly.Memory({ initial: 1 });
+
+async function runWasmFile(filePath) {
+ let blob = readFile(filePath, "binary");
+ let compiled;
+ try {
+ compiled = await WebAssembly.instantiate(blob, context);
+ compiled.instance.exports.test();
+ } catch (e) {
+ print(e);
+ throw e;
+ }
+ asyncTestPassed();
+}
+
+for (wasmFile of arguments)
+ runWasmFile(wasmFile);
Added: trunk/JSTests/wasm/wast-tests/osr-entry-inner-loop-branch-above-no-consts.wasm (0 => 249661)
--- trunk/JSTests/wasm/wast-tests/osr-entry-inner-loop-branch-above-no-consts.wasm (rev 0)
+++ trunk/JSTests/wasm/wast-tests/osr-entry-inner-loop-branch-above-no-consts.wasm 2019-09-09 20:32:56 UTC (rev 249661)
@@ -0,0 +1,6 @@
+��asm������
+``��2env__linear_memory����envcallerIsOMGCompiled����test��
+pn �� ��(��!A!A��!@A��! @��+��A��!@ �� ��(��Al6�� Aj!��E+��j! ��(��! Aj"AG+�� jj j
\ No newline at end of file
Added: trunk/JSTests/wasm/wast-tests/osr-entry-inner-loop-branch-above-no-consts.wast (0 => 249661)
--- trunk/JSTests/wasm/wast-tests/osr-entry-inner-loop-branch-above-no-consts.wast (rev 0)
+++ trunk/JSTests/wasm/wast-tests/osr-entry-inner-loop-branch-above-no-consts.wast 2019-09-09 20:32:56 UTC (rev 249661)
@@ -0,0 +1,65 @@
+(module
+ (type (;0;) (func (param i32) (result i32)))
+ (type (;1;) (func (result i32)))
+ (import "env" "__linear_memory" (memory (;0;) 0))
+ (import "env" "callerIsOMGCompiled" (func (;0;) (type 1)))
+ (func (export "test") (type 0) (param i32) (result i32)
+ (local i32 i32 i32 i32)
+ get_local 0
+ get_local 0
+ i32.load
+ set_local 1
+ i32.const 2
+ set_local 2
+ i32.const 0
+ set_local 3
+ loop ;; label = @1
+ i32.const 0
+ set_local 4
+ get_local 1
+ get_local 2
+ if i32
+ get_local 2
+ else
+ get_local 2
+ end
+ block ;; label = @2
+ call 0
+ br_if 0 (;@2;)
+ i32.const 0
+ set_local 4
+ loop ;; label = @3
+ get_local 0
+ get_local 0
+ i32.load
+ i32.const 3
+ i32.mul
+ i32.store
+ get_local 4
+ i32.const 1
+ i32.add
+ set_local 4
+ call 0
+ i32.eqz
+ br_if 0 (;@3;)
+ end
+ end
+ i32.add
+ set_local 2
+ get_local 0
+ i32.load
+ set_local 1
+ get_local 3
+ i32.const 1
+ i32.add
+ tee_local 3
+ i32.const 20
+ i32.ne
+ br_if 0 (;@1;)
+ end
+ get_local 1
+ get_local 2
+ i32.add
+ i32.add
+ get_local 4
+ i32.add))
Added: trunk/JSTests/wasm/wast-tests/osr-entry-inner-loop-branch-above.wasm (0 => 249661)
--- trunk/JSTests/wasm/wast-tests/osr-entry-inner-loop-branch-above.wasm (rev 0)
+++ trunk/JSTests/wasm/wast-tests/osr-entry-inner-loop-branch-above.wasm 2019-09-09 20:32:56 UTC (rev 249661)
@@ -0,0 +1,6 @@
+��asm������
+``��2env__linear_memory����envcallerIsOMGCompiled����test��
+\x83\x80 �� ��(��!A!A��!@A C����@@ BA��! @��+��A��!@ �� ��(��Al6�� Aj!��E+��j! ��(��! Aj"AG+�� jj j
\ No newline at end of file
Added: trunk/JSTests/wasm/wast-tests/osr-entry-inner-loop-branch-above.wast (0 => 249661)
--- trunk/JSTests/wasm/wast-tests/osr-entry-inner-loop-branch-above.wast (rev 0)
+++ trunk/JSTests/wasm/wast-tests/osr-entry-inner-loop-branch-above.wast 2019-09-09 20:32:56 UTC (rev 249661)
@@ -0,0 +1,80 @@
+(module
+ (type (;0;) (func (param i32) (result i32)))
+ (type (;1;) (func (result i32)))
+ (import "env" "__linear_memory" (memory (;0;) 0))
+ (import "env" "callerIsOMGCompiled" (func (;0;) (type 1)))
+ (func (export "test") (type 0) (param i32) (result i32)
+ (local i32 i32 i32 i32)
+ get_local 0
+ get_local 0
+ i32.load
+ set_local 1
+ i32.const 2
+ set_local 2
+ i32.const 0
+ set_local 3
+ loop ;; label = @1
+ ;; add a bunch of values so there is a bigger stack here than in the if block.
+ i32.const 1
+ get_local 1
+ f32.const 3
+ get_local 3
+ i64.const 4
+
+ ;; real program
+ i32.const 0
+ set_local 4
+ get_local 1
+ get_local 2
+ if i32
+ get_local 2
+ else
+ get_local 2
+ end
+ block ;; label = @2
+ call 0
+ br_if 0 (;@2;)
+ i32.const 0
+ set_local 4
+ loop ;; label = @3
+ get_local 0
+ get_local 0
+ i32.load
+ i32.const 3
+ i32.mul
+ i32.store
+ get_local 4
+ i32.const 1
+ i32.add
+ set_local 4
+ call 0
+ i32.eqz
+ br_if 0 (;@3;)
+ end
+ end
+ i32.add
+ set_local 2
+ get_local 0
+ i32.load
+ set_local 1
+ get_local 3
+ i32.const 1
+ i32.add
+ tee_local 3
+ i32.const 20
+ i32.ne
+ br_if 0 (;@1;)
+
+ ;; drop our extra values so we can compile
+ drop
+ drop
+ drop
+ drop
+ drop
+ end
+ get_local 1
+ get_local 2
+ i32.add
+ i32.add
+ get_local 4
+ i32.add))
Added: trunk/JSTests/wasm/wast-tests/osr-entry-inner-loop.wasm (0 => 249661)
--- trunk/JSTests/wasm/wast-tests/osr-entry-inner-loop.wasm (rev 0)
+++ trunk/JSTests/wasm/wast-tests/osr-entry-inner-loop.wasm 2019-09-09 20:32:56 UTC (rev 249661)
@@ -0,0 +1,6 @@
+��asm������
+``��2env__linear_memory����envcallerIsOMGCompiled����test��
+hf �� ��(��!A!A��!@A��! @��+��A��!@ �� ��(��Al6�� Aj!��E+��j! ��(��! Aj"AG+�� jj j
\ No newline at end of file
Added: trunk/JSTests/wasm/wast-tests/osr-entry-inner-loop.wast (0 => 249661)
--- trunk/JSTests/wasm/wast-tests/osr-entry-inner-loop.wast (rev 0)
+++ trunk/JSTests/wasm/wast-tests/osr-entry-inner-loop.wast 2019-09-09 20:32:56 UTC (rev 249661)
@@ -0,0 +1,60 @@
+(module
+ (type (;0;) (func (param i32) (result i32)))
+ (type (;1;) (func (result i32)))
+ (import "env" "__linear_memory" (memory (;0;) 0))
+ (import "env" "callerIsOMGCompiled" (func (;0;) (type 1)))
+ (func (export "test") (type 0) (param i32) (result i32)
+ (local i32 i32 i32 i32)
+ get_local 0
+ get_local 0
+ i32.load
+ set_local 1
+ i32.const 2
+ set_local 2
+ i32.const 0
+ set_local 3
+ loop ;; label = @1
+ i32.const 0
+ set_local 4
+ get_local 1
+ get_local 2
+ block ;; label = @2
+ call 0
+ br_if 0 (;@2;)
+ i32.const 0
+ set_local 4
+ loop ;; label = @3
+ get_local 0
+ get_local 0
+ i32.load
+ i32.const 3
+ i32.mul
+ i32.store
+ get_local 4
+ i32.const 1
+ i32.add
+ set_local 4
+ call 0
+ i32.eqz
+ br_if 0 (;@3;)
+ end
+ end
+ i32.add
+ set_local 2
+ get_local 0
+ i32.load
+ set_local 1
+ get_local 3
+ i32.const 1
+ i32.add
+ tee_local 3
+ i32.const 20
+ i32.ne
+ br_if 0 (;@1;)
+ end
+ get_local 1
+ get_local 2
+ i32.add
+ i32.add
+ get_local 4
+ i32.add))
Added: trunk/JSTests/wasm/wast-tests/osr-entry-multiple-enclosed-contexts.wasm (0 => 249661)
--- trunk/JSTests/wasm/wast-tests/osr-entry-multiple-enclosed-contexts.wasm (rev 0)
+++ trunk/JSTests/wasm/wast-tests/osr-entry-multiple-enclosed-contexts.wasm 2019-09-09 20:32:56 UTC (rev 249661)
@@ -0,0 +1,5 @@
+��asm������
+``��2env__linear_memory����envcallerIsOMGCompiled����test��
+RP ��(��Aj��! ��(��!A��!@ +��A��!@ �� Al6�� Aj!��! ��(��! E+�� j j
\ No newline at end of file
Added: trunk/JSTests/wasm/wast-tests/osr-entry-multiple-enclosed-contexts.wast (0 => 249661)
--- trunk/JSTests/wasm/wast-tests/osr-entry-multiple-enclosed-contexts.wast (rev 0)
+++ trunk/JSTests/wasm/wast-tests/osr-entry-multiple-enclosed-contexts.wast 2019-09-09 20:32:56 UTC (rev 249661)
@@ -0,0 +1,47 @@
+(module
+ (type (;0;) (func (param i32) (result i32)))
+ (type (;1;) (func (result i32)))
+ (import "env" "__linear_memory" (memory (;0;) 0))
+ (import "env" "callerIsOMGCompiled" (func (;0;) (type 1)))
+ (func (export "test") (type 0) (param i32) (result i32)
+ (local i32 i32 i32 i32)
+ get_local 0
+ i32.load
+ i32.const 2
+ i32.add
+ call 0
+ set_local 2
+ get_local 0
+ i32.load
+ set_local 3
+ i32.const 0
+ set_local 4
+ block ;; label = @1
+ get_local 2
+ br_if 0 (;@1;)
+ i32.const 0
+ set_local 4
+ loop ;; label = @2
+ get_local 0
+ get_local 3
+ i32.const 3
+ i32.mul
+ i32.store
+ get_local 4
+ i32.const 1
+ i32.add
+ set_local 4
+ call 0
+ set_local 2
+ get_local 0
+ i32.load
+ set_local 3
+ get_local 2
+ i32.eqz
+ br_if 0 (;@2;)
+ end
+ end
+ get_local 4
+ i32.add
+ get_local 3
+ i32.add))
Modified: trunk/JSTests/wasm.yaml (249660 => 249661)
--- trunk/JSTests/wasm.yaml 2019-09-09 20:32:26 UTC (rev 249660)
+++ trunk/JSTests/wasm.yaml 2019-09-09 20:32:56 UTC (rev 249661)
@@ -21,8 +21,8 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-- path: wasm/self-test/
- cmd: runWebAssemblySuite unless parseRunCommands
+- path: wasm/wast-tests/
+ cmd: runWebAssemblyWithHarness
- path: wasm/js-api/
cmd: runWebAssemblySuite unless parseRunCommands
- path: wasm/noJIT/
@@ -43,6 +43,8 @@
cmd: runWebAssemblySuite unless parseRunCommands
- path: wasm/modules/
cmd: runWebAssembly unless parseRunCommands
+- path: wasm/self-test/
+ cmd: runWebAssemblySuite unless parseRunCommands
- path: wasm/spec-tests/address.wast.js
cmd: runWebAssemblySpecTest :normal
@@ -185,3 +187,4 @@
- path: wasm/modules/run-from-wasm.wasm
cmd: runWebAssembly
+
Modified: trunk/Source/_javascript_Core/ChangeLog (249660 => 249661)
--- trunk/Source/_javascript_Core/ChangeLog 2019-09-09 20:32:26 UTC (rev 249660)
+++ trunk/Source/_javascript_Core/ChangeLog 2019-09-09 20:32:56 UTC (rev 249661)
@@ -1,3 +1,54 @@
+2019-09-07 Keith Miller <[email protected]>
+
+ OSR entry into wasm misses some contexts
+ https://bugs.webkit.org/show_bug.cgi?id=201569
+
+ Reviewed by Yusuke Suzuki.
+
+ This patch fixes an issue where we could fail to capture some of
+ our contexts when OSR entering into wasm code. Before we would
+ only capture the state of the block immediately surrounding the
+ entrance loop block header. We actually need to capture all
+ enclosed stacks.
+
+ Additionally, we don't need to use variables for all the captured
+ values. We can use a Phi and insert an upsilon just below the
+ captured value.
+
+ * interpreter/CallFrame.h:
+ * jsc.cpp:
+ (GlobalObject::finishCreation):
+ (functionCallerIsOMGCompiled):
+ * wasm/WasmAirIRGenerator.cpp:
+ (JSC::Wasm::AirIRGenerator::AirIRGenerator):
+ (JSC::Wasm::AirIRGenerator::emitEntryTierUpCheck):
+ (JSC::Wasm::AirIRGenerator::emitLoopTierUpCheck):
+ (JSC::Wasm::AirIRGenerator::addLoop):
+ * wasm/WasmB3IRGenerator.cpp:
+ (JSC::Wasm::B3IRGenerator::createStack):
+ (JSC::Wasm::B3IRGenerator::B3IRGenerator):
+ (JSC::Wasm::B3IRGenerator::addConstant):
+ (JSC::Wasm::B3IRGenerator::emitEntryTierUpCheck):
+ (JSC::Wasm::B3IRGenerator::emitLoopTierUpCheck):
+ (JSC::Wasm::B3IRGenerator::addLoop):
+ (JSC::Wasm::B3IRGenerator::addEndToUnreachable):
+ (JSC::Wasm::dumpExpressionStack):
+ (JSC::Wasm::B3IRGenerator::dump):
+ (JSC::Wasm::B3IRGenerator::Stack::Stack): Deleted.
+ (JSC::Wasm::B3IRGenerator::Stack::append): Deleted.
+ (JSC::Wasm::B3IRGenerator::Stack::takeLast): Deleted.
+ (JSC::Wasm::B3IRGenerator::Stack::last): Deleted.
+ (JSC::Wasm::B3IRGenerator::Stack::size const): Deleted.
+ (JSC::Wasm::B3IRGenerator::Stack::isEmpty const): Deleted.
+ (JSC::Wasm::B3IRGenerator::Stack::convertToExpressionList): Deleted.
+ (JSC::Wasm::B3IRGenerator::Stack::at const): Deleted.
+ (JSC::Wasm::B3IRGenerator::Stack::variableAt const): Deleted.
+ (JSC::Wasm::B3IRGenerator::Stack::shrink): Deleted.
+ (JSC::Wasm::B3IRGenerator::Stack::swap): Deleted.
+ (JSC::Wasm::B3IRGenerator::Stack::dump const): Deleted.
+ * wasm/WasmFunctionParser.h:
+ (JSC::Wasm::FunctionParser::controlStack):
+
2019-09-09 Yusuke Suzuki <[email protected]>
[JSC] Promise resolve/reject functions should be created more efficiently
Modified: trunk/Source/_javascript_Core/interpreter/CallFrame.h (249660 => 249661)
--- trunk/Source/_javascript_Core/interpreter/CallFrame.h 2019-09-09 20:32:26 UTC (rev 249660)
+++ trunk/Source/_javascript_Core/interpreter/CallFrame.h 2019-09-09 20:32:56 UTC (rev 249661)
@@ -132,7 +132,7 @@
JSGlobalObject* wasmAwareLexicalGlobalObject(VM&);
- bool isAnyWasmCallee();
+ JS_EXPORT_PRIVATE bool isAnyWasmCallee();
// Global object in which the currently executing code was defined.
// Differs from VM::vmEntryGlobalObject() during function calls across web browser frames.
Modified: trunk/Source/_javascript_Core/jsc.cpp (249660 => 249661)
--- trunk/Source/_javascript_Core/jsc.cpp 2019-09-09 20:32:26 UTC (rev 249660)
+++ trunk/Source/_javascript_Core/jsc.cpp 2019-09-09 20:32:56 UTC (rev 249661)
@@ -27,6 +27,7 @@
#include "BuiltinNames.h"
#include "ButterflyInlines.h"
#include "BytecodeCacheError.h"
+#include "CallFrameInlines.h"
#include "CatchScope.h"
#include "CodeBlock.h"
#include "CodeCache.h"
@@ -320,6 +321,7 @@
static EncodedJSValue JSC_HOST_CALL functionNoOSRExitFuzzing(ExecState*);
static EncodedJSValue JSC_HOST_CALL functionOptimizeNextInvocation(ExecState*);
static EncodedJSValue JSC_HOST_CALL functionNumberOfDFGCompiles(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionCallerIsOMGCompiled(ExecState*);
static EncodedJSValue JSC_HOST_CALL functionJSCOptions(ExecState*);
static EncodedJSValue JSC_HOST_CALL functionReoptimizationRetryCount(ExecState*);
static EncodedJSValue JSC_HOST_CALL functionTransferArrayBuffer(ExecState*);
@@ -541,6 +543,7 @@
addFunction(vm, "noFTL", functionNoFTL, 1);
addFunction(vm, "noOSRExitFuzzing", functionNoOSRExitFuzzing, 1);
addFunction(vm, "numberOfDFGCompiles", functionNumberOfDFGCompiles, 1);
+ addFunction(vm, "callerIsOMGCompiled", functionCallerIsOMGCompiled, 0);
addFunction(vm, "jscOptions", functionJSCOptions, 0);
addFunction(vm, "optimizeNextInvocation", functionOptimizeNextInvocation, 1);
addFunction(vm, "reoptimizationRetryCount", functionReoptimizationRetryCount, 1);
@@ -1727,6 +1730,31 @@
return JSValue::encode(numberOfDFGCompiles(exec));
}
+EncodedJSValue JSC_HOST_CALL functionCallerIsOMGCompiled(ExecState* exec)
+{
+ VM& vm = exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (!Options::useBBQTierUpChecks())
+ return JSValue::encode(jsBoolean(true));
+
+ CallerFunctor wasmToJSFrame;
+ StackVisitor::visit(exec, &vm, wasmToJSFrame);
+ if (!wasmToJSFrame.callerFrame()->isAnyWasmCallee())
+ return throwVMError(exec, scope, "caller is not a wasm->js import function");
+
+ // We have a wrapper frame that we generate for imports. If we ever can direct call from wasm we would need to change this.
+ ASSERT(!wasmToJSFrame.callerFrame()->callee().isWasm());
+ CallerFunctor wasmFrame;
+ StackVisitor::visit(wasmToJSFrame.callerFrame(), &vm, wasmFrame);
+ ASSERT(wasmFrame.callerFrame()->callee().isWasm());
+#if ENABLE(WEBASSEMBLY)
+ auto mode = wasmFrame.callerFrame()->callee().asWasmCallee()->compilationMode();
+ return JSValue::encode(jsBoolean(mode == Wasm::CompilationMode::OMGMode || mode == Wasm::CompilationMode::OMGForOSREntryMode));
+#endif
+ RELEASE_ASSERT_NOT_REACHED();
+}
+
Message::Message(ArrayBufferContents&& contents, int32_t index)
: m_contents(WTFMove(contents))
, m_index(index)
Modified: trunk/Source/_javascript_Core/wasm/WasmAirIRGenerator.cpp (249660 => 249661)
--- trunk/Source/_javascript_Core/wasm/WasmAirIRGenerator.cpp 2019-09-09 20:32:26 UTC (rev 249660)
+++ trunk/Source/_javascript_Core/wasm/WasmAirIRGenerator.cpp 2019-09-09 20:32:56 UTC (rev 249661)
@@ -591,8 +591,8 @@
void emitThrowException(CCallHelpers&, ExceptionType);
- void emitEntryTierUpCheck(int32_t incrementCount, B3::Origin);
- void emitLoopTierUpCheck(int32_t incrementCount, const Stack&, uint32_t, uint32_t, B3::Origin);
+ void emitEntryTierUpCheck();
+ void emitLoopTierUpCheck(uint32_t loopIndex);
void emitWriteBarrierForJSWrapper();
ExpressionType emitCheckAndPreparePointer(ExpressionType pointer, uint32_t offset, uint32_t sizeOfOp);
@@ -852,7 +852,7 @@
}
});
- emitEntryTierUpCheck(TierUpCount::functionEntryIncrement(), B3::Origin());
+ emitEntryTierUpCheck();
}
void AirIRGenerator::restoreWebAssemblyGlobalState(RestoreCachedStackLimit restoreCachedStackLimit, const MemoryInformation& memory, TypedTmp instance, BasicBlock* block)
@@ -1603,10 +1603,8 @@
return { };
}
-void AirIRGenerator::emitEntryTierUpCheck(int32_t incrementCount, B3::Origin origin)
+void AirIRGenerator::emitEntryTierUpCheck()
{
- UNUSED_PARAM(origin);
-
if (!m_tierUp)
return;
@@ -1624,7 +1622,7 @@
patch->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
AllowMacroScratchRegisterUsage allowScratch(jit);
- CCallHelpers::Jump tierUp = jit.branchAdd32(CCallHelpers::PositiveOrZero, CCallHelpers::TrustedImm32(incrementCount), CCallHelpers::Address(params[0].gpr()));
+ CCallHelpers::Jump tierUp = jit.branchAdd32(CCallHelpers::PositiveOrZero, CCallHelpers::TrustedImm32(TierUpCount::functionEntryIncrement()), CCallHelpers::Address(params[0].gpr()));
CCallHelpers::Label tierUpResume = jit.label();
params.addLatePath([=] (CCallHelpers& jit) {
@@ -1650,9 +1648,10 @@
emitPatchpoint(patch, Tmp(), countdownPtr);
}
-void AirIRGenerator::emitLoopTierUpCheck(int32_t incrementCount, const Stack& expressionStack, uint32_t loopIndex, uint32_t outerLoopIndex, B3::Origin origin)
+void AirIRGenerator::emitLoopTierUpCheck(uint32_t loopIndex)
{
- UNUSED_PARAM(origin);
+ uint32_t outerLoopIndex = this->outerLoopIndex();
+ m_outerLoops.append(loopIndex);
if (!m_tierUp)
return;
@@ -1680,15 +1679,17 @@
Vector<ConstrainedTmp> patchArgs;
patchArgs.append(countdownPtr);
- Vector<B3::Type> types;
- for (auto& local : m_locals) {
+ for (auto& local : m_locals)
patchArgs.append(ConstrainedTmp(local, B3::ValueRep::ColdAny));
- types.append(toB3Type(local.type()));
+ for (unsigned controlIndex = 0; controlIndex < m_parser->controlStack().size(); ++controlIndex) {
+ ExpressionList& expressionStack = m_parser->controlStack()[controlIndex].enclosedExpressionStack;
+ for (auto& value : expressionStack)
+ patchArgs.append(ConstrainedTmp(value, B3::ValueRep::ColdAny));
+
+ const auto& results = m_parser->controlStack()[controlIndex].controlData.result;
+ for (auto& value : results)
+ patchArgs.append(ConstrainedTmp(value, B3::ValueRep::ColdAny));
}
- for (auto& _expression_ : expressionStack) {
- patchArgs.append(ConstrainedTmp(_expression_, B3::ValueRep::ColdAny));
- types.append(toB3Type(_expression_.type()));
- }
TierUpCount::TriggerReason* forceEntryTrigger = &(m_tierUp->osrEntryTriggers().last());
static_assert(!static_cast<uint8_t>(TierUpCount::TriggerReason::DontTrigger), "the JIT code assumes non-zero means 'enter'");
@@ -1696,12 +1697,13 @@
patch->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
AllowMacroScratchRegisterUsage allowScratch(jit);
CCallHelpers::Jump forceOSREntry = jit.branchTest8(CCallHelpers::NonZero, CCallHelpers::AbsoluteAddress(forceEntryTrigger));
- CCallHelpers::Jump tierUp = jit.branchAdd32(CCallHelpers::PositiveOrZero, CCallHelpers::TrustedImm32(incrementCount), CCallHelpers::Address(params[0].gpr()));
+ CCallHelpers::Jump tierUp = jit.branchAdd32(CCallHelpers::PositiveOrZero, CCallHelpers::TrustedImm32(TierUpCount::loopIncrement()), CCallHelpers::Address(params[0].gpr()));
MacroAssembler::Label tierUpResume = jit.label();
OSREntryData& osrEntryData = m_tierUp->addOSREntryData(m_functionIndex, loopIndex);
- for (unsigned index = 0; index < types.size(); ++index)
- osrEntryData.values().constructAndAppend(params[index + 1], types[index]);
+ // First argument is the countdown location.
+ for (unsigned index = 1; index < params.value()->numChildren(); ++index)
+ osrEntryData.values().constructAndAppend(params[index], params.value()->child(index)->type());
OSREntryData* osrEntryDataPtr = &osrEntryData;
params.addLatePath([=] (CCallHelpers& jit) {
@@ -1718,7 +1720,7 @@
emitPatchpoint(patch, Tmp(), WTFMove(patchArgs));
}
-AirIRGenerator::ControlData AirIRGenerator::addLoop(Type signature, const Stack& expressionStack, uint32_t loopIndex)
+AirIRGenerator::ControlData AirIRGenerator::addLoop(Type signature, const Stack&, uint32_t loopIndex)
{
BasicBlock* body = m_code.addBlock();
BasicBlock* continuation = m_code.addBlock();
@@ -1726,10 +1728,8 @@
append(Jump);
m_currentBlock->setSuccessors(body);
- uint32_t outerLoopIndex = this->outerLoopIndex();
- m_outerLoops.append(loopIndex);
m_currentBlock = body;
- emitLoopTierUpCheck(TierUpCount::loopIncrement(), expressionStack, loopIndex, outerLoopIndex, origin());
+ emitLoopTierUpCheck(loopIndex);
return ControlData(origin(), signature, tmpForType(signature), BlockType::Loop, continuation, body);
}
Modified: trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp (249660 => 249661)
--- trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp 2019-09-09 20:32:26 UTC (rev 249660)
+++ trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp 2019-09-09 20:32:56 UTC (rev 249661)
@@ -161,108 +161,9 @@
typedef Value* ExpressionType;
typedef Vector<ExpressionType, 1> ExpressionList;
- friend class Stack;
- class Stack {
- public:
- Stack(B3IRGenerator* generator)
- : m_generator(generator)
- {
- }
+ using Stack = ExpressionList;
+ Stack createStack() { return { }; }
- void append(ExpressionType _expression_)
- {
- if (m_generator->m_compilationMode == CompilationMode::OMGForOSREntryMode) {
- Variable* variable = m_generator->m_proc.addVariable(_expression_->type());
- m_generator->m_currentBlock->appendNew<VariableValue>(m_generator->m_proc, Set, m_generator->origin(), variable, _expression_);
- m_stack.append(variable);
- return;
- }
- m_data.append(_expression_);
- }
-
- ExpressionType takeLast()
- {
- if (m_generator->m_compilationMode == CompilationMode::OMGForOSREntryMode)
- return m_generator->m_currentBlock->appendNew<VariableValue>(m_generator->m_proc, B3::Get, m_generator->origin(), m_stack.takeLast());
- return m_data.takeLast();
- }
-
- ExpressionType last()
- {
- if (m_generator->m_compilationMode == CompilationMode::OMGForOSREntryMode)
- return m_generator->m_currentBlock->appendNew<VariableValue>(m_generator->m_proc, B3::Get, m_generator->origin(), m_stack.last());
- return m_data.last();
- }
-
- unsigned size() const
- {
- if (m_generator->m_compilationMode == CompilationMode::OMGForOSREntryMode)
- return m_stack.size();
- return m_data.size();
- }
- bool isEmpty() const { return size() == 0; }
-
- ExpressionList convertToExpressionList()
- {
- if (m_generator->m_compilationMode == CompilationMode::OMGForOSREntryMode) {
- ExpressionList results;
- for (unsigned i = 0; i < m_stack.size(); ++i)
- results.append(at(i));
- return results;
- }
- return m_data;
- }
-
- ExpressionType at(unsigned i) const
- {
- if (m_generator->m_compilationMode == CompilationMode::OMGForOSREntryMode)
- return m_generator->m_currentBlock->appendNew<VariableValue>(m_generator->m_proc, B3::Get, m_generator->origin(), m_stack.at(i));
- return m_data.at(i);
- }
-
- Variable* variableAt(unsigned i) const
- {
- if (m_generator->m_compilationMode == CompilationMode::OMGForOSREntryMode)
- return m_stack.at(i);
- return nullptr;
- }
-
- void shrink(unsigned i)
- {
- if (m_generator->m_compilationMode == CompilationMode::OMGForOSREntryMode) {
- m_stack.shrink(i);
- return;
- }
- m_data.shrink(i);
- }
-
- void swap(Stack& stack)
- {
- std::swap(m_generator, stack.m_generator);
- m_data.swap(stack.m_data);
- m_stack.swap(stack.m_stack);
- }
-
- void dump() const
- {
- CommaPrinter comma(", ", "");
- dataLog(comma, "ExpressionStack:");
- if (m_generator->m_compilationMode == CompilationMode::OMGForOSREntryMode) {
- for (const auto& variable : m_stack)
- dataLog(comma, *variable);
- return;
- }
- for (const auto& _expression_ : m_data)
- dataLog(comma, *_expression_);
- }
-
- private:
- B3IRGenerator* m_generator { nullptr };
- ExpressionList m_data;
- Vector<Variable*> m_stack;
- };
- Stack createStack() { return Stack(this); }
-
using ControlType = ControlData;
using ResultList = ControlData::ResultList;
using ControlEntry = FunctionParser<B3IRGenerator>::ControlEntry;
@@ -351,8 +252,8 @@
private:
void emitExceptionCheck(CCallHelpers&, ExceptionType);
- void emitEntryTierUpCheck(int32_t incrementCount, B3::Origin);
- void emitLoopTierUpCheck(int32_t incrementCount, const Stack&, uint32_t, uint32_t, B3::Origin);
+ void emitEntryTierUpCheck();
+ void emitLoopTierUpCheck(uint32_t loopIndex);
void emitWriteBarrierForJSWrapper();
ExpressionType emitCheckAndPreparePointer(ExpressionType pointer, uint32_t offset, uint32_t sizeOfOp);
@@ -584,7 +485,7 @@
});
}
- emitEntryTierUpCheck(TierUpCount::functionEntryIncrement(), Origin());
+ emitEntryTierUpCheck();
if (m_compilationMode == CompilationMode::OMGForOSREntryMode)
m_currentBlock = m_proc.addBlock();
@@ -1187,18 +1088,19 @@
B3IRGenerator::ExpressionType B3IRGenerator::addConstant(Type type, uint64_t value)
{
+
return constant(toB3Type(type), value);
}
-void B3IRGenerator::emitEntryTierUpCheck(int32_t incrementCount, Origin origin)
+void B3IRGenerator::emitEntryTierUpCheck()
{
if (!m_tierUp)
return;
ASSERT(m_tierUp);
- Value* countDownLocation = constant(pointerType(), reinterpret_cast<uint64_t>(&m_tierUp->m_counter), origin);
+ Value* countDownLocation = constant(pointerType(), reinterpret_cast<uint64_t>(&m_tierUp->m_counter), Origin());
- PatchpointValue* patch = m_currentBlock->appendNew<PatchpointValue>(m_proc, B3::Void, origin);
+ PatchpointValue* patch = m_currentBlock->appendNew<PatchpointValue>(m_proc, B3::Void, Origin());
Effects effects = Effects::none();
// FIXME: we should have a more precise heap range for the tier up count.
effects.reads = B3::HeapRange::top();
@@ -1209,7 +1111,7 @@
patch->append(countDownLocation, ValueRep::SomeRegister);
patch->setGenerator([=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
AllowMacroScratchRegisterUsage allowScratch(jit);
- CCallHelpers::Jump tierUp = jit.branchAdd32(CCallHelpers::PositiveOrZero, CCallHelpers::TrustedImm32(incrementCount), CCallHelpers::Address(params[0].gpr()));
+ CCallHelpers::Jump tierUp = jit.branchAdd32(CCallHelpers::PositiveOrZero, CCallHelpers::TrustedImm32(TierUpCount::functionEntryIncrement()), CCallHelpers::Address(params[0].gpr()));
CCallHelpers::Label tierUpResume = jit.label();
params.addLatePath([=] (CCallHelpers& jit) {
@@ -1233,13 +1135,15 @@
});
}
-void B3IRGenerator::emitLoopTierUpCheck(int32_t incrementCount, const Stack& expressionStack, uint32_t loopIndex, uint32_t outerLoopIndex, B3::Origin origin)
+void B3IRGenerator::emitLoopTierUpCheck(uint32_t loopIndex)
{
+ uint32_t outerLoopIndex = this->outerLoopIndex();
+ m_outerLoops.append(loopIndex);
+
if (!m_tierUp)
return;
- ASSERT(m_tierUp);
-
+ Origin origin = this->origin();
ASSERT(m_tierUp->osrEntryTriggers().size() == loopIndex);
m_tierUp->osrEntryTriggers().append(TierUpCount::TriggerReason::DontTrigger);
m_tierUp->outerLoops().append(outerLoopIndex);
@@ -1247,16 +1151,14 @@
Value* countDownLocation = constant(pointerType(), reinterpret_cast<uint64_t>(&m_tierUp->m_counter), origin);
Vector<ExpressionType> stackmap;
- Vector<B3::Type> types;
for (auto& local : m_locals) {
ExpressionType result = m_currentBlock->appendNew<VariableValue>(m_proc, B3::Get, origin, local);
stackmap.append(result);
- types.append(result->type());
}
- for (unsigned i = 0; i < expressionStack.size(); ++i) {
- ExpressionType result = expressionStack.at(i);
- stackmap.append(result);
- types.append(result->type());
+ for (unsigned controlIndex = 0; controlIndex < m_parser->controlStack().size(); ++controlIndex) {
+ auto& expressionStack = m_parser->controlStack()[controlIndex].enclosedExpressionStack;
+ for (Value* value : expressionStack)
+ stackmap.append(value);
}
PatchpointValue* patch = m_currentBlock->appendNew<PatchpointValue>(m_proc, B3::Void, origin);
@@ -1281,12 +1183,13 @@
patch->setGenerator([=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
AllowMacroScratchRegisterUsage allowScratch(jit);
CCallHelpers::Jump forceOSREntry = jit.branchTest8(CCallHelpers::NonZero, CCallHelpers::AbsoluteAddress(forceEntryTrigger));
- CCallHelpers::Jump tierUp = jit.branchAdd32(CCallHelpers::PositiveOrZero, CCallHelpers::TrustedImm32(incrementCount), CCallHelpers::Address(params[0].gpr()));
+ CCallHelpers::Jump tierUp = jit.branchAdd32(CCallHelpers::PositiveOrZero, CCallHelpers::TrustedImm32(TierUpCount::loopIncrement()), CCallHelpers::Address(params[0].gpr()));
MacroAssembler::Label tierUpResume = jit.label();
OSREntryData& osrEntryData = m_tierUp->addOSREntryData(m_functionIndex, loopIndex);
- for (unsigned index = 0; index < types.size(); ++index)
- osrEntryData.values().constructAndAppend(params[index + 1], types[index]);
+ // First argument is the countdown location.
+ for (unsigned i = 1; i < params.value()->numChildren(); ++i)
+ osrEntryData.values().constructAndAppend(params[i], params.value()->child(i)->type());
OSREntryData* osrEntryDataPtr = &osrEntryData;
params.addLatePath([=] (CCallHelpers& jit) {
@@ -1301,7 +1204,7 @@
});
}
-B3IRGenerator::ControlData B3IRGenerator::addLoop(Type signature, const Stack& stack, uint32_t loopIndex)
+B3IRGenerator::ControlData B3IRGenerator::addLoop(Type signature, const Stack&, uint32_t loopIndex)
{
BasicBlock* body = m_proc.addBlock();
BasicBlock* continuation = m_proc.addBlock();
@@ -1308,42 +1211,62 @@
m_currentBlock->appendNewControlValue(m_proc, Jump, origin(), body);
if (loopIndex == m_loopIndexForOSREntry) {
+ dataLogLnIf(WasmB3IRGeneratorInternal::verbose, "Setting up for OSR entry");
m_currentBlock = m_rootBlock;
- m_osrEntryScratchBufferSize = m_locals.size() + stack.size();
Value* pointer = m_rootBlock->appendNew<ArgumentRegValue>(m_proc, Origin(), GPRInfo::argumentGPR0);
- auto loadFromScratchBuffer = [&] (B3::Type type, unsigned index) {
- size_t offset = sizeof(uint64_t) * index;
- switch (type.kind()) {
- case B3::Int32:
- return m_currentBlock->appendNew<MemoryValue>(m_proc, Load, Int32, origin(), pointer, offset);
- case B3::Int64:
- return m_currentBlock->appendNew<MemoryValue>(m_proc, Load, B3::Int64, origin(), pointer, offset);
- case B3::Float:
- return m_currentBlock->appendNew<MemoryValue>(m_proc, Load, B3::Float, origin(), pointer, offset);
- case B3::Double:
- return m_currentBlock->appendNew<MemoryValue>(m_proc, Load, B3::Double, origin(), pointer, offset);
- default:
- RELEASE_ASSERT_NOT_REACHED();
- break;
- }
+ unsigned indexInBuffer = 0;
+ auto loadFromScratchBuffer = [&] (B3::Type type) {
+ size_t offset = sizeof(uint64_t) * indexInBuffer++;
+ RELEASE_ASSERT(type.isNumeric());
+ return m_currentBlock->appendNew<MemoryValue>(m_proc, Load, type, origin(), pointer, offset);
};
- unsigned indexInBuffer = 0;
for (auto& local : m_locals)
- m_currentBlock->appendNew<VariableValue>(m_proc, Set, Origin(), local, loadFromScratchBuffer(local->type(), indexInBuffer++));
- for (unsigned i = 0; i < stack.size(); ++i) {
- auto* variable = stack.variableAt(i);
- m_currentBlock->appendNew<VariableValue>(m_proc, Set, Origin(), variable, loadFromScratchBuffer(variable->type(), indexInBuffer++));
+ m_currentBlock->appendNew<VariableValue>(m_proc, Set, Origin(), local, loadFromScratchBuffer(local->type()));
+
+ for (unsigned controlIndex = 0; controlIndex < m_parser->controlStack().size(); ++controlIndex) {
+ const auto& data = ""
+ auto& expressionStack = m_parser->controlStack()[controlIndex].enclosedExpressionStack;
+
+ // 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.
+ BasicBlock* sourceBlock = nullptr;
+ unsigned blockIndex = 0;
+ B3::InsertionSet insertionSet(m_proc);
+ for (unsigned i = 0; i < expressionStack.size(); i++) {
+ auto* value = expressionStack[i];
+ if (value->isConstant())
+ continue;
+
+ if (value->owner != sourceBlock) {
+ insertionSet.execute(sourceBlock);
+ ASSERT(insertionSet.isEmpty());
+ dataLogLnIf(WasmB3IRGeneratorInternal::verbose && sourceBlock, "Executed insertion set into: ", *sourceBlock);
+ blockIndex = 0;
+ sourceBlock = value->owner;
+ }
+
+ while (sourceBlock->at(blockIndex++) != value)
+ ASSERT(blockIndex < sourceBlock->size());
+ ASSERT(sourceBlock->at(blockIndex - 1) == value);
+
+ auto* phi = data.continuation->appendNew<Value>(m_proc, Phi, value->type(), value->origin());
+ expressionStack[i] = phi;
+ m_currentBlock->appendNew<UpsilonValue>(m_proc, value->origin(), loadFromScratchBuffer(value->type()), phi);
+
+ auto* sourceUpsilon = m_proc.add<UpsilonValue>(value->origin(), value, phi);
+ insertionSet.insertValue(blockIndex, sourceUpsilon);
+ }
+ insertionSet.execute(sourceBlock);
}
+
+ m_osrEntryScratchBufferSize = indexInBuffer;
m_currentBlock->appendNewControlValue(m_proc, Jump, origin(), body);
body->addPredecessor(m_currentBlock);
}
- uint32_t outerLoopIndex = this->outerLoopIndex();
- m_outerLoops.append(loopIndex);
m_currentBlock = body;
- emitLoopTierUpCheck(TierUpCount::loopIncrement(), stack, loopIndex, outerLoopIndex, origin());
+ emitLoopTierUpCheck(loopIndex);
return ControlData(m_proc, origin(), signature, BlockType::Loop, continuation, body);
}
@@ -1467,7 +1390,7 @@
// TopLevel does not have any code after this so we need to make sure we emit a return here.
if (data.type() == BlockType::TopLevel)
- return addReturn(entry.controlData, entry.enclosedExpressionStack.convertToExpressionList());
+ return addReturn(entry.controlData, entry.enclosedExpressionStack);
return { };
}
@@ -1739,6 +1662,13 @@
unify(result[result.size() - 1 - i], resultStack.at(resultStack.size() - 1 - i));
}
+static void dumpExpressionStack(const CommaPrinter& comma, const B3IRGenerator::ExpressionList& expressionStack)
+{
+ dataLog(comma, "ExpressionStack:");
+ for (const auto& _expression_ : expressionStack)
+ dataLog(comma, *_expression_);
+}
+
void B3IRGenerator::dump(const Vector<ControlEntry>& controlStack, const Stack* expressionStack)
{
dataLogLn("Constants:");
@@ -1752,7 +1682,8 @@
ASSERT(controlStack.size());
for (size_t i = controlStack.size(); i--;) {
dataLog(" ", controlStack[i].controlData, ": ");
- expressionStack->dump();
+ CommaPrinter comma(", ", "");
+ dumpExpressionStack(comma, *expressionStack);
expressionStack = &controlStack[i].enclosedExpressionStack;
dataLogLn();
}
Modified: trunk/Source/_javascript_Core/wasm/WasmFunctionParser.h (249660 => 249661)
--- trunk/Source/_javascript_Core/wasm/WasmFunctionParser.h 2019-09-09 20:32:26 UTC (rev 249660)
+++ trunk/Source/_javascript_Core/wasm/WasmFunctionParser.h 2019-09-09 20:32:56 UTC (rev 249661)
@@ -60,6 +60,8 @@
OpType currentOpcode() const { return m_currentOpcode; }
size_t currentOpcodeStartingOffset() const { return m_currentOpcodeStartingOffset; }
+ Vector<ControlEntry>& controlStack() { return m_controlStack; }
+
private:
static const bool verbose = false;
Modified: trunk/Source/_javascript_Core/wasm/WasmOpcodeOrigin.cpp (249660 => 249661)
--- trunk/Source/_javascript_Core/wasm/WasmOpcodeOrigin.cpp 2019-09-09 20:32:26 UTC (rev 249660)
+++ trunk/Source/_javascript_Core/wasm/WasmOpcodeOrigin.cpp 2019-09-09 20:32:56 UTC (rev 249661)
@@ -32,7 +32,7 @@
void OpcodeOrigin::dump(PrintStream& out) const
{
- out.print("{opcode: ", makeString(opcode()), ", location: ", location(), "}");
+ out.print("{opcode: ", makeString(opcode()), ", location: ", RawPointer(reinterpret_cast<void*>(location())), "}");
}
} } // namespace JSC::Wasm
Modified: trunk/Tools/ChangeLog (249660 => 249661)
--- trunk/Tools/ChangeLog 2019-09-09 20:32:26 UTC (rev 249660)
+++ trunk/Tools/ChangeLog 2019-09-09 20:32:56 UTC (rev 249661)
@@ -1,3 +1,14 @@
+2019-09-07 Keith Miller <[email protected]>
+
+ OSR entry into wasm misses some contexts
+ https://bugs.webkit.org/show_bug.cgi?id=201569
+
+ Reviewed by Yusuke Suzuki.
+
+ Add new test harness mode for tests created from wast files.
+
+ * Scripts/run-jsc-stress-tests:
+
2019-09-09 Daniel Bates <[email protected]>
Remove all selection view animations before dumping results
Modified: trunk/Tools/Scripts/run-jsc-stress-tests (249660 => 249661)
--- trunk/Tools/Scripts/run-jsc-stress-tests 2019-09-09 20:32:26 UTC (rev 249660)
+++ trunk/Tools/Scripts/run-jsc-stress-tests 2019-09-09 20:32:56 UTC (rev 249661)
@@ -1114,6 +1114,36 @@
end
end
+def runHarnessTest(kind, *options)
+ wasmFiles = allWasmFiles($collection)
+ wasmFiles.each {
+ | file |
+ basename = file.basename.to_s
+ addRunCommand("(" + basename + ")-" + kind, [pathToVM.to_s] + $testSpecificRequiredOptions + options + [$benchmark.to_s, "--", basename], silentOutputHandler, simpleErrorHandler)
+ }
+end
+
+def runWebAssemblyWithHarness(*optionalTestSpecificOptions)
+ raise unless $benchmark.to_s =~ /harness\.m?js/
+ return if !$jitTests
+ return if !$isFTLPlatform
+
+ wasmFiles = allWasmFiles($collection)
+ prepareExtraRelativeFiles(wasmFiles.map { |f| f.basename }, $collection)
+
+ runHarnessTest("default-wasm", *(FTL_OPTIONS + optionalTestSpecificOptions))
+ if $mode != "quick"
+ runHarnessTest("wasm-no-cjit-yes-tls-context", "--useFastTLSForWasmContext=true", *(FTL_OPTIONS + NO_CJIT_OPTIONS + optionalTestSpecificOptions))
+ runHarnessTest("wasm-eager", *(FTL_OPTIONS + EAGER_OPTIONS + optionalTestSpecificOptions))
+ runHarnessTest("wasm-eager-jettison", "--forceCodeBlockToJettisonDueToOldAge=true", *(FTL_OPTIONS + optionalTestSpecificOptions))
+ runHarnessTest("wasm-no-call-ic", "--useCallICsForWebAssemblyToJSCalls=false", *(FTL_OPTIONS + optionalTestSpecificOptions))
+ runHarnessTest("wasm-no-tls-context", "--useFastTLSForWasmContext=false", *(FTL_OPTIONS + optionalTestSpecificOptions))
+ runHarnessTest("wasm-slow-memory", "--useWebAssemblyFastMemory=false", *(FTL_OPTIONS + optionalTestSpecificOptions))
+ runHarnessTest("wasm-no-air", "--wasmBBQUsesAir=false", *(FTL_OPTIONS + optionalTestSpecificOptions))
+ runHarnessTest("wasm-collect-continuously", "--collectContinuously=true", *(FTL_OPTIONS + optionalTestSpecificOptions)) if shouldCollectContinuously?
+ end
+end
+
def runWebAssemblyEmscripten(mode)
case mode
when :skip
@@ -1483,6 +1513,21 @@
puts "Skipping #{$collectionName}/#{$benchmark}"
end
+def allWasmFiles(path)
+ if path.file?
+ [path]
+ else
+ result = []
+ Dir.foreach(path) {
+ | filename |
+ next unless filename =~ /\.m?wasm$/
+ next unless (path + filename).file?
+ result << path + filename
+ }
+ result
+ end
+end
+
def allJSFiles(path)
if path.file?
[path]