diff --git a/src/compiler/wasm-compiler.cc b/src/compiler/wasm-compiler.cc
index 7c9a01db7b..205e387941 100644
--- a/src/compiler/wasm-compiler.cc
+++ b/src/compiler/wasm-compiler.cc
@@ -3065,8 +3065,7 @@ Node* WasmGraphBuilder::CurrentMemoryPages() {
Node* WasmGraphBuilder::BuildLoadBuiltinFromInstance(int builtin_index) {
DCHECK(Builtins::IsBuiltinId(builtin_index));
- Node* isolate_root =
- LOAD_INSTANCE_FIELD(IsolateRoot, MachineType::TaggedPointer());
+ Node* isolate_root = LOAD_INSTANCE_FIELD(IsolateRoot, MachineType::Pointer());
return LOAD_TAGGED_POINTER(isolate_root,
IsolateData::builtin_slot_offset(builtin_index));
}
@@ -4540,14 +4539,13 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
void BuildModifyThreadInWasmFlag(bool new_value) {
if (!trap_handler::IsTrapHandlerEnabled()) return;
- Node* thread_in_wasm_flag_address_address =
- graph()->NewNode(mcgraph()->common()->ExternalConstant(
- ExternalReference::wasm_thread_in_wasm_flag_address_address(
- isolate_)));
- Node* thread_in_wasm_flag_address = SetEffect(graph()->NewNode(
- mcgraph()->machine()->Load(LoadRepresentation(MachineType::Pointer())),
- thread_in_wasm_flag_address_address, mcgraph()->Int32Constant(0),
- Effect(), Control()));
+ Node* isolate_root =
+ LOAD_INSTANCE_FIELD(IsolateRoot, MachineType::Pointer());
+
+ Node* thread_in_wasm_flag_address =
+ LOAD_RAW(isolate_root, Isolate::thread_in_wasm_flag_address_offset(),
+ MachineType::Pointer());
+
SetEffect(graph()->NewNode(
mcgraph()->machine()->Store(StoreRepresentation(
MachineRepresentation::kWord32, kNoWriteBarrier)),
diff --git a/src/external-reference.cc b/src/external-reference.cc
index e13b204d8a..95ed54a952 100644
--- a/src/external-reference.cc
+++ b/src/external-reference.cc
@@ -826,12 +826,6 @@ ExternalReference ExternalReference::debug_restart_fp_address(
return ExternalReference(isolate->debug()->restart_fp_address());
}
-ExternalReference ExternalReference::wasm_thread_in_wasm_flag_address_address(
- Isolate* isolate) {
- return ExternalReference(reinterpret_cast
(
- &isolate->thread_local_top()->thread_in_wasm_flag_address_));
-}
-
ExternalReference ExternalReference::fast_c_call_caller_fp_address(
Isolate* isolate) {
return ExternalReference(
diff --git a/src/external-reference.h b/src/external-reference.h
index 63ee1b19ad..2fef99c8b2 100644
--- a/src/external-reference.h
+++ b/src/external-reference.h
@@ -70,8 +70,6 @@ class StatsCounter;
V(debug_suspended_generator_address, \
"Debug::step_suspended_generator_address()") \
V(debug_restart_fp_address, "Debug::restart_fp_address()") \
- V(wasm_thread_in_wasm_flag_address_address, \
- "&Isolate::thread_in_wasm_flag_address") \
V(fast_c_call_caller_fp_address, \
"IsolateData::fast_c_call_caller_fp_address") \
V(fast_c_call_caller_pc_address, \
diff --git a/src/isolate.h b/src/isolate.h
index f4a64a6a9d..743ae03e54 100644
--- a/src/isolate.h
+++ b/src/isolate.h
@@ -1030,6 +1030,18 @@ class Isolate final : private HiddenFactory {
deoptimizer_lazy_throw_ = value;
}
ThreadLocalTop* thread_local_top() { return &thread_local_top_; }
+
+ static uint32_t thread_in_wasm_flag_address_offset() {
+ // For WebAssembly trap handlers there is a flag in thread-local storage
+ // which indicates that the executing thread executes WebAssembly code. To
+ // access this flag directly from generated code, we store a pointer to the
+ // flag in ThreadLocalTop in thread_in_wasm_flag_address_. This function
+ // here returns the offset of that member from {isolate_root()}.
+ return static_cast(
+ OFFSET_OF(Isolate, thread_local_top_.thread_in_wasm_flag_address_) -
+ isolate_root_bias());
+ }
+
MaterializedObjectStore* materialized_object_store() {
return materialized_object_store_;
}
diff --git a/src/runtime/runtime-test.cc b/src/runtime/runtime-test.cc
index 6cc3f9e4cf..c8432211e3 100644
--- a/src/runtime/runtime-test.cc
+++ b/src/runtime/runtime-test.cc
@@ -843,6 +843,12 @@ RUNTIME_FUNCTION(Runtime_IsWasmTrapHandlerEnabled) {
return isolate->heap()->ToBoolean(trap_handler::IsTrapHandlerEnabled());
}
+RUNTIME_FUNCTION(Runtime_IsThreadInWasm) {
+ DisallowHeapAllocation no_gc;
+ DCHECK_EQ(0, args.length());
+ return isolate->heap()->ToBoolean(trap_handler::IsThreadInWasm());
+}
+
RUNTIME_FUNCTION(Runtime_GetWasmRecoveredTrapCount) {
HandleScope scope(isolate);
DCHECK_EQ(0, args.length());
diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h
index af4c143585..fc8820ec80 100644
--- a/src/runtime/runtime.h
+++ b/src/runtime/runtime.h
@@ -491,6 +491,7 @@ namespace internal {
F(IsLiftoffFunction, 1, 1) \
F(IsWasmCode, 1, 1) \
F(IsWasmTrapHandlerEnabled, 0, 1) \
+ F(IsThreadInWasm, 0, 1) \
F(NeverOptimizeFunction, 1, 1) \
F(NotifyContextDisposed, 0, 1) \
F(OptimizeFunctionOnNextCall, -1, 1) \
diff --git a/test/mjsunit/regress/wasm/regress-8533.js b/test/mjsunit/regress/wasm/regress-8533.js
new file mode 100644
index 0000000000..5d782b747c
--- /dev/null
+++ b/test/mjsunit/regress/wasm/regress-8533.js
@@ -0,0 +1,85 @@
+// Copyright 2018 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --wasm-shared-engine --no-wasm-disable-structured-cloning --allow-natives-syntax --experimental-wasm-threads
+
+load('test/mjsunit/wasm/wasm-constants.js');
+load('test/mjsunit/wasm/wasm-module-builder.js');
+
+
+// In this test we start a worker which enters wasm and stays there in a loop.
+// The main thread stays in JS and checks that its thread-in-wasm flag is not
+// set. The main thread calls setTimeout after every check to give the worker a
+// chance to be scheculed.
+const sync_address = 12;
+(function TestPostModule() {
+ let builder = new WasmModuleBuilder();
+ let sig_index = builder.addType(kSig_v_v);
+ let import_id = builder.addImport('m', 'func', sig_index);
+ builder.addFunction('wait', kSig_v_v)
+ .addBody([
+ // Calling the imported function sets the thread-in-wasm flag of the
+ // main thread.
+ kExprCallFunction, import_id, // --
+ kExprLoop, kWasmStmt, // --
+ kExprI32Const, sync_address, // --
+ kExprI32LoadMem, 0, 0, // --
+ kExprI32Eqz,
+ kExprBrIf, 0, // --
+ kExprEnd,
+ ])
+ .exportFunc();
+
+ builder.addFunction('signal', kSig_v_v)
+ .addBody([
+ kExprI32Const, sync_address, // --
+ kExprI32Const, 1, // --
+ kExprI32StoreMem, 0, 0, // --
+ ])
+ .exportFunc();
+ builder.addImportedMemory("m", "imported_mem", 0, 1, "shared");
+
+ let module = builder.toModule();
+ let memory = new WebAssembly.Memory({initial: 1, maximum: 1, shared: true});
+
+ let workerScript = `
+ onmessage = function(msg) {
+ try {
+ let worker_instance = new WebAssembly.Instance(msg.module,
+ {m: {imported_mem: msg.memory,
+ func: _ => 5}});
+ postMessage("start running");
+ worker_instance.exports.wait();
+ postMessage("finished");
+ } catch(e) {
+ postMessage('ERROR: ' + e);
+ }
+ }
+ `;
+
+ let worker = new Worker(workerScript, {type: 'string'});
+ worker.postMessage({module: module, memory: memory});
+
+ let main_instance = new WebAssembly.Instance(
+ module, {m: {imported_mem: memory, func: _ => 7}});
+
+ let counter = 0;
+ function CheckThreadNotInWasm() {
+ // We check the thread-in-wasm flag many times and reschedule ourselves in
+ // between to increase the chance that we read the flag set by the worker.
+ assertFalse(%IsThreadInWasm());
+ counter++;
+ if (counter < 100) {
+ setTimeout(CheckThreadNotInWasm, 0);
+ } else {
+ main_instance.exports.signal(sync_address);
+ assertEquals('finished', worker.getMessage());
+ worker.terminate();
+ }
+ }
+
+ assertFalse(%IsThreadInWasm());
+ assertEquals('start running', worker.getMessage());
+ CheckThreadNotInWasm();
+})();
diff --git a/test/unittests/wasm/trap-handler-x64-unittest.cc b/test/unittests/wasm/trap-handler-x64-unittest.cc
index f7f5d20c57..680c92fa4d 100644
--- a/test/unittests/wasm/trap-handler-x64-unittest.cc
+++ b/test/unittests/wasm/trap-handler-x64-unittest.cc
@@ -215,17 +215,15 @@ class TrapHandlerTest : public TestWithIsolate,
void GenerateSetThreadInWasmFlagCode(MacroAssembler* masm) {
masm->Move(scratch,
- ExternalReference::wasm_thread_in_wasm_flag_address_address(
- i_isolate()));
- masm->movp(scratch, MemOperand(scratch, 0));
+ i_isolate()->thread_local_top()->thread_in_wasm_flag_address_,
+ RelocInfo::NONE);
masm->movl(MemOperand(scratch, 0), Immediate(1));
}
void GenerateResetThreadInWasmFlagCode(MacroAssembler* masm) {
masm->Move(scratch,
- ExternalReference::wasm_thread_in_wasm_flag_address_address(
- i_isolate()));
- masm->movp(scratch, MemOperand(scratch, 0));
+ i_isolate()->thread_local_top()->thread_in_wasm_flag_address_,
+ RelocInfo::NONE);
masm->movl(MemOperand(scratch, 0), Immediate(0));
}
@@ -240,13 +238,17 @@ class TrapHandlerTest : public TestWithIsolate,
GeneratedCode::FromAddress(i_isolate(),
reinterpret_cast(buffer.start()))
.Call();
+ CHECK(!g_test_handler_executed);
}
// Execute the code in buffer. We expect a crash which we recover from in the
// test handler.
void ExecuteExpectCrash(Vector buffer, bool check_wasm_flag = true) {
CHECK(!g_test_handler_executed);
- ExecuteBuffer(buffer);
+ MakeAssemblerBufferExecutable(buffer.start(), buffer.size());
+ GeneratedCode::FromAddress(i_isolate(),
+ reinterpret_cast(buffer.start()))
+ .Call();
CHECK(g_test_handler_executed);
g_test_handler_executed = false;
if (check_wasm_flag) CHECK(!GetThreadInWasmFlag());