Title: [214384] trunk/Source
Revision
214384
Author
[email protected]
Date
2017-03-24 16:25:16 -0700 (Fri, 24 Mar 2017)

Log Message

WebAssembly: store state in TLS instead of on VM
https://bugs.webkit.org/show_bug.cgi?id=169611

Reviewed by Filip Pizlo.

Source/_javascript_Core:

Using thread-local storage instead of VM makes code more position
independent. We used to store the WebAssembly top Instance (the
latest one in the call stack) on VM, now we instead store it in
TLS. This top Instance is used to access a bunch of state such as
Memory location, size, table (for call_indirect), etc.

Instead of calling it "top", which is confusing, we now just call
it WasmContext.

Making the code PIC means future patches will be able to
postMessage and structured clone into IDB without having to
recompile the code. This wasn't possible before because we
hard-coded the address of VM at compilation time. That doesn't
work between workers, and doesn't work across reloads (which IDB
is intended to do).

It'll also potentially make code faster once we start tuning
what's in TLS, what's in which of the 4 free slots, and what's in
pinned registers. I'm leaving this tuning for later because
there's lower lying fruit for us to pick.

* CMakeLists.txt:
* _javascript_Core.xcodeproj/project.pbxproj:
* assembler/AbstractMacroAssembler.h:
* assembler/AllowMacroScratchRegisterUsageIf.h: Copied from assembler/AllowMacroScratchRegisterUsage.h.
(JSC::AllowMacroScratchRegisterUsageIf::AllowMacroScratchRegisterUsageIf):
(JSC::AllowMacroScratchRegisterUsageIf::~AllowMacroScratchRegisterUsageIf):
* assembler/MacroAssembler.h:
(JSC::MacroAssembler::storeToTLSPtr): we previously didn't have
the code required to store to TLS, only to load
* assembler/MacroAssemblerARM64.h:
(JSC::MacroAssemblerARM64::loadFromTLSPtrNeedsMacroScratchRegister):
(JSC::MacroAssemblerARM64::storeToTLS32):
(JSC::MacroAssemblerARM64::storeToTLS64):
(JSC::MacroAssemblerARM64::storeToTLSPtrNeedsMacroScratchRegister):
* assembler/MacroAssemblerX86Common.h:
(JSC::MacroAssemblerX86Common::loadFromTLSPtrNeedsMacroScratchRegister):
(JSC::MacroAssemblerX86Common::storeToTLS32):
(JSC::MacroAssemblerX86Common::storeToTLSPtrNeedsMacroScratchRegister):
* assembler/MacroAssemblerX86_64.h:
(JSC::MacroAssemblerX86_64::loadFromTLS64): was loading 32-bit instead of 64-bit
(JSC::MacroAssemblerX86_64::storeToTLS64):
* assembler/X86Assembler.h:
(JSC::X86Assembler::movl_rm):
(JSC::X86Assembler::movq_rm):
* b3/testb3.cpp:
(JSC::B3::testFastTLSLoad):
(JSC::B3::testFastTLSStore):
(JSC::B3::run):
* jit/AssemblyHelpers.h:
(JSC::AssemblyHelpers::loadWasmContext):
(JSC::AssemblyHelpers::storeWasmContext):
(JSC::AssemblyHelpers::loadWasmContextNeedsMacroScratchRegister):
(JSC::AssemblyHelpers::storeWasmContextNeedsMacroScratchRegister):
* jit/Repatch.cpp:
(JSC::webAssemblyOwner):
* jit/ThunkGenerators.cpp:
(JSC::throwExceptionFromWasmThunkGenerator):
* runtime/Options.h:
* runtime/VM.cpp:
(JSC::VM::VM):
* runtime/VM.h:
* wasm/WasmB3IRGenerator.cpp:
(JSC::Wasm::loadWasmContext):
(JSC::Wasm::storeWasmContext):
(JSC::Wasm::B3IRGenerator::B3IRGenerator):
(JSC::Wasm::getMemoryBaseAndSize):
(JSC::Wasm::restoreWebAssemblyGlobalState):
(JSC::Wasm::createJSToWasmWrapper):
(JSC::Wasm::parseAndCompile):
* wasm/WasmBinding.cpp:
(JSC::Wasm::materializeImportJSCell):
(JSC::Wasm::wasmToJs):
(JSC::Wasm::wasmToWasm):
* wasm/WasmContext.cpp: Added.
(JSC::loadWasmContext):
(JSC::storeWasmContext):
* wasm/WasmContext.h: Added. Replaces "top" JSWebAssemblyInstance.
* wasm/js/WebAssemblyFunction.cpp:
(JSC::callWebAssemblyFunction):
* wasm/js/WebAssemblyInstanceConstructor.h:

Source/WTF:

* wtf/FastTLS.h: reserve one key for WebAssembly, delete a bunch
of dead code which clang couldn't compile (it's valid GCC assembly
which LLVM dislikes).

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/CMakeLists.txt (214383 => 214384)


--- trunk/Source/_javascript_Core/CMakeLists.txt	2017-03-24 23:16:52 UTC (rev 214383)
+++ trunk/Source/_javascript_Core/CMakeLists.txt	2017-03-24 23:25:16 UTC (rev 214384)
@@ -932,6 +932,7 @@
     wasm/WasmB3IRGenerator.cpp
     wasm/WasmBinding.cpp
     wasm/WasmCallingConvention.cpp
+    wasm/WasmContext.cpp
     wasm/WasmFaultSignalHandler.cpp
     wasm/WasmFormat.cpp
     wasm/WasmMemory.cpp

Modified: trunk/Source/_javascript_Core/ChangeLog (214383 => 214384)


--- trunk/Source/_javascript_Core/ChangeLog	2017-03-24 23:16:52 UTC (rev 214383)
+++ trunk/Source/_javascript_Core/ChangeLog	2017-03-24 23:25:16 UTC (rev 214384)
@@ -1,5 +1,94 @@
 2017-03-24  JF Bastien  <[email protected]>
 
+        WebAssembly: store state in TLS instead of on VM
+        https://bugs.webkit.org/show_bug.cgi?id=169611
+
+        Reviewed by Filip Pizlo.
+
+        Using thread-local storage instead of VM makes code more position
+        independent. We used to store the WebAssembly top Instance (the
+        latest one in the call stack) on VM, now we instead store it in
+        TLS. This top Instance is used to access a bunch of state such as
+        Memory location, size, table (for call_indirect), etc.
+
+        Instead of calling it "top", which is confusing, we now just call
+        it WasmContext.
+
+        Making the code PIC means future patches will be able to
+        postMessage and structured clone into IDB without having to
+        recompile the code. This wasn't possible before because we
+        hard-coded the address of VM at compilation time. That doesn't
+        work between workers, and doesn't work across reloads (which IDB
+        is intended to do).
+
+        It'll also potentially make code faster once we start tuning
+        what's in TLS, what's in which of the 4 free slots, and what's in
+        pinned registers. I'm leaving this tuning for later because
+        there's lower lying fruit for us to pick.
+
+        * CMakeLists.txt:
+        * _javascript_Core.xcodeproj/project.pbxproj:
+        * assembler/AbstractMacroAssembler.h:
+        * assembler/AllowMacroScratchRegisterUsageIf.h: Copied from assembler/AllowMacroScratchRegisterUsage.h.
+        (JSC::AllowMacroScratchRegisterUsageIf::AllowMacroScratchRegisterUsageIf):
+        (JSC::AllowMacroScratchRegisterUsageIf::~AllowMacroScratchRegisterUsageIf):
+        * assembler/MacroAssembler.h:
+        (JSC::MacroAssembler::storeToTLSPtr): we previously didn't have
+        the code required to store to TLS, only to load
+        * assembler/MacroAssemblerARM64.h:
+        (JSC::MacroAssemblerARM64::loadFromTLSPtrNeedsMacroScratchRegister):
+        (JSC::MacroAssemblerARM64::storeToTLS32):
+        (JSC::MacroAssemblerARM64::storeToTLS64):
+        (JSC::MacroAssemblerARM64::storeToTLSPtrNeedsMacroScratchRegister):
+        * assembler/MacroAssemblerX86Common.h:
+        (JSC::MacroAssemblerX86Common::loadFromTLSPtrNeedsMacroScratchRegister):
+        (JSC::MacroAssemblerX86Common::storeToTLS32):
+        (JSC::MacroAssemblerX86Common::storeToTLSPtrNeedsMacroScratchRegister):
+        * assembler/MacroAssemblerX86_64.h:
+        (JSC::MacroAssemblerX86_64::loadFromTLS64): was loading 32-bit instead of 64-bit
+        (JSC::MacroAssemblerX86_64::storeToTLS64):
+        * assembler/X86Assembler.h:
+        (JSC::X86Assembler::movl_rm):
+        (JSC::X86Assembler::movq_rm):
+        * b3/testb3.cpp:
+        (JSC::B3::testFastTLSLoad):
+        (JSC::B3::testFastTLSStore):
+        (JSC::B3::run):
+        * jit/AssemblyHelpers.h:
+        (JSC::AssemblyHelpers::loadWasmContext):
+        (JSC::AssemblyHelpers::storeWasmContext):
+        (JSC::AssemblyHelpers::loadWasmContextNeedsMacroScratchRegister):
+        (JSC::AssemblyHelpers::storeWasmContextNeedsMacroScratchRegister):
+        * jit/Repatch.cpp:
+        (JSC::webAssemblyOwner):
+        * jit/ThunkGenerators.cpp:
+        (JSC::throwExceptionFromWasmThunkGenerator):
+        * runtime/Options.h:
+        * runtime/VM.cpp:
+        (JSC::VM::VM):
+        * runtime/VM.h:
+        * wasm/WasmB3IRGenerator.cpp:
+        (JSC::Wasm::loadWasmContext):
+        (JSC::Wasm::storeWasmContext):
+        (JSC::Wasm::B3IRGenerator::B3IRGenerator):
+        (JSC::Wasm::getMemoryBaseAndSize):
+        (JSC::Wasm::restoreWebAssemblyGlobalState):
+        (JSC::Wasm::createJSToWasmWrapper):
+        (JSC::Wasm::parseAndCompile):
+        * wasm/WasmBinding.cpp:
+        (JSC::Wasm::materializeImportJSCell):
+        (JSC::Wasm::wasmToJs):
+        (JSC::Wasm::wasmToWasm):
+        * wasm/WasmContext.cpp: Added.
+        (JSC::loadWasmContext):
+        (JSC::storeWasmContext):
+        * wasm/WasmContext.h: Added. Replaces "top" JSWebAssemblyInstance.
+        * wasm/js/WebAssemblyFunction.cpp:
+        (JSC::callWebAssemblyFunction):
+        * wasm/js/WebAssemblyInstanceConstructor.h:
+
+2017-03-24  JF Bastien  <[email protected]>
+
         WebAssembly: spec-tests/memory.wast.js fails in debug
         https://bugs.webkit.org/show_bug.cgi?id=169794
 

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (214383 => 214384)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2017-03-24 23:16:52 UTC (rev 214383)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2017-03-24 23:25:16 UTC (rev 214384)
@@ -349,7 +349,7 @@
 		0F37308C1C0BD29100052BFA /* B3PhiChildren.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F37308A1C0BD29100052BFA /* B3PhiChildren.cpp */; };
 		0F37308D1C0BD29100052BFA /* B3PhiChildren.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F37308B1C0BD29100052BFA /* B3PhiChildren.h */; };
 		0F37308F1C0CD68500052BFA /* DisallowMacroScratchRegisterUsage.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F37308E1C0CD68500052BFA /* DisallowMacroScratchRegisterUsage.h */; };
-		0F3730911C0CD70C00052BFA /* AllowMacroScratchRegisterUsage.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F3730901C0CD70C00052BFA /* AllowMacroScratchRegisterUsage.h */; };
+		0F3730911C0CD70C00052BFA /* AllowMacroScratchRegisterUsage.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F3730901C0CD70C00052BFA /* AllowMacroScratchRegisterUsage.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		0F3730931C0D67EE00052BFA /* AirUseCounts.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F3730921C0D67EE00052BFA /* AirUseCounts.h */; };
 		0F38B01117CF078000B144D3 /* LLIntEntrypoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F38B00F17CF077F00B144D3 /* LLIntEntrypoint.cpp */; };
 		0F38B01217CF078300B144D3 /* LLIntEntrypoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F38B01017CF077F00B144D3 /* LLIntEntrypoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -1638,6 +1638,7 @@
 		969A079B0ED1D3AE00F1F681 /* Opcode.h in Headers */ = {isa = PBXBuildFile; fileRef = 969A07950ED1D3AE00F1F681 /* Opcode.h */; };
 		978801401471AD920041B016 /* JSDateMath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9788FC221471AD0C0068CE2D /* JSDateMath.cpp */; };
 		978801411471AD920041B016 /* JSDateMath.h in Headers */ = {isa = PBXBuildFile; fileRef = 9788FC231471AD0C0068CE2D /* JSDateMath.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		981ED82328234D91BAECCADE /* MachineContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 28806E21155E478A93FA7B02 /* MachineContext.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		990DA67F1C8E316A00295159 /* generate_objc_protocol_type_conversions_implementation.py in Headers */ = {isa = PBXBuildFile; fileRef = 990DA67E1C8E311D00295159 /* generate_objc_protocol_type_conversions_implementation.py */; settings = {ATTRIBUTES = (Private, ); }; };
 		9928FF3B18AC4AEC00B8CF12 /* JSReplayInputs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9928FF3918AC4AEC00B8CF12 /* JSReplayInputs.cpp */; };
 		9928FF3C18AC4AEC00B8CF12 /* JSReplayInputs.h in Headers */ = {isa = PBXBuildFile; fileRef = 9928FF3A18AC4AEC00B8CF12 /* JSReplayInputs.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -2081,6 +2082,8 @@
 		AD2FCC301DB83D4900B3E736 /* JSWebAssembly.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD2FCC2E1DB839F700B3E736 /* JSWebAssembly.cpp */; };
 		AD2FCC311DB83D4900B3E736 /* JSWebAssembly.h in Headers */ = {isa = PBXBuildFile; fileRef = AD2FCC2F1DB839F700B3E736 /* JSWebAssembly.h */; };
 		AD2FCC331DC4045400B3E736 /* WasmFormat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD2FCC321DC4045300B3E736 /* WasmFormat.cpp */; };
+		AD412B331E7B2E99008AF157 /* WasmContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD412B311E7B2E8A008AF157 /* WasmContext.cpp */; };
+		AD412B341E7B2E9E008AF157 /* WasmContext.h in Headers */ = {isa = PBXBuildFile; fileRef = AD412B321E7B2E8A008AF157 /* WasmContext.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		AD4252511E5D0E14009D2A97 /* FullCodeOrigin.h in Headers */ = {isa = PBXBuildFile; fileRef = AD4252501E5D0DEB009D2A97 /* FullCodeOrigin.h */; };
 		AD4252531E5D0F47009D2A97 /* FullCodeOrigin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD4252521E5D0F22009D2A97 /* FullCodeOrigin.cpp */; };
 		AD4937C31DDBE6140077C807 /* AbstractModuleRecord.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD4937C11DDBE60A0077C807 /* AbstractModuleRecord.cpp */; };
@@ -2441,7 +2444,6 @@
 		FEE43FCE1E6641710077D6D1 /* PlatformThread.h in Headers */ = {isa = PBXBuildFile; fileRef = FEE43FCD1E6641400077D6D1 /* PlatformThread.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		FEF040511AAE662D00BD28B0 /* CompareAndSwapTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FEF040501AAE662D00BD28B0 /* CompareAndSwapTest.cpp */; };
 		FEFD6FC61D5E7992008F2F0B /* JSStringInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = FEFD6FC51D5E7970008F2F0B /* JSStringInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
-		981ED82328234D91BAECCADE /* MachineContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 28806E21155E478A93FA7B02 /* MachineContext.h */; settings = {ATTRIBUTES = (Private, ); }; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
@@ -3732,6 +3734,7 @@
 		264091FA1BE2FD4100684DB2 /* AirOpcode.opcodes */ = {isa = PBXFileReference; lastKnownFileType = text; name = AirOpcode.opcodes; path = b3/air/AirOpcode.opcodes; sourceTree = "<group>"; };
 		2684D4371C00161C0081D663 /* AirLiveness.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirLiveness.h; path = b3/air/AirLiveness.h; sourceTree = "<group>"; };
 		269D636D1BFBE5D000101B1D /* FTLOutput.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLOutput.h; path = ftl/FTLOutput.h; sourceTree = "<group>"; };
+		28806E21155E478A93FA7B02 /* MachineContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MachineContext.h; sourceTree = "<group>"; };
 		2A05ABD31961DF2400341750 /* JSPropertyNameEnumerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPropertyNameEnumerator.cpp; sourceTree = "<group>"; };
 		2A05ABD41961DF2400341750 /* JSPropertyNameEnumerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSPropertyNameEnumerator.h; sourceTree = "<group>"; };
 		2A111243192FCE79005EE18D /* CustomGetterSetter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CustomGetterSetter.cpp; sourceTree = "<group>"; };
@@ -4648,6 +4651,9 @@
 		AD2FCC2E1DB839F700B3E736 /* JSWebAssembly.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSWebAssembly.cpp; sourceTree = "<group>"; };
 		AD2FCC2F1DB839F700B3E736 /* JSWebAssembly.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSWebAssembly.h; sourceTree = "<group>"; };
 		AD2FCC321DC4045300B3E736 /* WasmFormat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmFormat.cpp; sourceTree = "<group>"; };
+		AD412B311E7B2E8A008AF157 /* WasmContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmContext.cpp; sourceTree = "<group>"; };
+		AD412B321E7B2E8A008AF157 /* WasmContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmContext.h; sourceTree = "<group>"; };
+		AD412B351E7B57C0008AF157 /* AllowMacroScratchRegisterUsageIf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllowMacroScratchRegisterUsageIf.h; sourceTree = "<group>"; };
 		AD4252501E5D0DEB009D2A97 /* FullCodeOrigin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FullCodeOrigin.h; sourceTree = "<group>"; };
 		AD4252521E5D0F22009D2A97 /* FullCodeOrigin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FullCodeOrigin.cpp; sourceTree = "<group>"; };
 		AD4937C11DDBE60A0077C807 /* AbstractModuleRecord.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AbstractModuleRecord.cpp; sourceTree = "<group>"; };
@@ -5039,7 +5045,6 @@
 		FEF040501AAE662D00BD28B0 /* CompareAndSwapTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CompareAndSwapTest.cpp; path = API/tests/CompareAndSwapTest.cpp; sourceTree = "<group>"; };
 		FEF040521AAEC4ED00BD28B0 /* CompareAndSwapTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CompareAndSwapTest.h; path = API/tests/CompareAndSwapTest.h; sourceTree = "<group>"; };
 		FEFD6FC51D5E7970008F2F0B /* JSStringInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSStringInlines.h; sourceTree = "<group>"; };
-		28806E21155E478A93FA7B02 /* MachineContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MachineContext.h; path = MachineContext.h; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -6249,6 +6254,8 @@
 				AD4B1DF81DF244D70071AE32 /* WasmBinding.h */,
 				53FD04D11D7AB187003287D3 /* WasmCallingConvention.cpp */,
 				53FD04D21D7AB187003287D3 /* WasmCallingConvention.h */,
+				AD412B311E7B2E8A008AF157 /* WasmContext.cpp */,
+				AD412B321E7B2E8A008AF157 /* WasmContext.h */,
 				79DAE2791E03C82200B526AA /* WasmExceptionType.h */,
 				AD2FCC321DC4045300B3E736 /* WasmFormat.cpp */,
 				7BC547D21B69599B00959B58 /* WasmFormat.h */,
@@ -7391,6 +7398,7 @@
 				0F2C63BF1E660EA500C13839 /* AbstractMacroAssembler.cpp */,
 				860161DF0F3A83C100F84710 /* AbstractMacroAssembler.h */,
 				0F3730901C0CD70C00052BFA /* AllowMacroScratchRegisterUsage.h */,
+				AD412B351E7B57C0008AF157 /* AllowMacroScratchRegisterUsageIf.h */,
 				8640923B156EED3B00566CB2 /* ARM64Assembler.h */,
 				86D3B2BF10156BDE002865E7 /* ARMAssembler.cpp */,
 				86D3B2C010156BDE002865E7 /* ARMAssembler.h */,
@@ -8562,6 +8570,7 @@
 				0FEA0A0C170513DB00BB722C /* FTLCompile.h in Headers */,
 				E322E5A71DA644A8006E7709 /* FTLDOMJITPatchpointParams.h in Headers */,
 				0F9D4C0D1C3E1C11006CD984 /* FTLExceptionTarget.h in Headers */,
+				AD412B341E7B2E9E008AF157 /* WasmContext.h in Headers */,
 				0F235BD417178E1C00690C7F /* FTLExitArgument.h in Headers */,
 				0F235BD617178E1C00690C7F /* FTLExitArgumentForOperand.h in Headers */,
 				0F2B9CF519D0BAC100B1D1B5 /* FTLExitPropertyValue.h in Headers */,
@@ -10693,6 +10702,7 @@
 				BCDE3B430E6C832D001453A7 /* Structure.cpp in Sources */,
 				7E4EE70F0EBB7A5B005934AA /* StructureChain.cpp in Sources */,
 				2AF7382C18BBBF92008A5A37 /* StructureIDTable.cpp in Sources */,
+				AD412B331E7B2E99008AF157 /* WasmContext.cpp in Sources */,
 				C2F0F2D116BAEEE900187C19 /* StructureRareData.cpp in Sources */,
 				0FB438A319270B1D00E1FBC9 /* StructureSet.cpp in Sources */,
 				0F766D3815AE4A1C008F363E /* StructureStubClearingWatchpoint.cpp in Sources */,

Modified: trunk/Source/_javascript_Core/assembler/AbstractMacroAssembler.h (214383 => 214384)


--- trunk/Source/_javascript_Core/assembler/AbstractMacroAssembler.h	2017-03-24 23:16:52 UTC (rev 214383)
+++ trunk/Source/_javascript_Core/assembler/AbstractMacroAssembler.h	2017-03-24 23:25:16 UTC (rev 214384)
@@ -1108,6 +1108,7 @@
     }
 
     friend class AllowMacroScratchRegisterUsage;
+    friend class AllowMacroScratchRegisterUsageIf;
     friend class DisallowMacroScratchRegisterUsage;
     unsigned m_tempRegistersValidBits;
     bool m_allowScratchRegister { true };

Copied: trunk/Source/_javascript_Core/assembler/AllowMacroScratchRegisterUsageIf.h (from rev 214383, trunk/Source/_javascript_Core/wasm/js/WebAssemblyInstanceConstructor.h) (0 => 214384)


--- trunk/Source/_javascript_Core/assembler/AllowMacroScratchRegisterUsageIf.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/assembler/AllowMacroScratchRegisterUsageIf.h	2017-03-24 23:25:16 UTC (rev 214384)
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#pragma once
+
+#if ENABLE(ASSEMBLER)
+
+#include "MacroAssembler.h"
+
+namespace JSC {
+
+class AllowMacroScratchRegisterUsageIf {
+public:
+    AllowMacroScratchRegisterUsageIf(MacroAssembler& masm, bool allowIfTrue)
+        : m_masm(masm)
+        , m_allowIfTrue(allowIfTrue)
+        , m_oldValueOfAllowScratchRegister(masm.m_allowScratchRegister)
+    {
+        if (m_allowIfTrue)
+            masm.m_allowScratchRegister = true;
+    }
+
+    ~AllowMacroScratchRegisterUsageIf()
+    {
+        if (m_allowIfTrue)
+            m_masm.m_allowScratchRegister = m_oldValueOfAllowScratchRegister;
+    }
+
+private:
+    MacroAssembler& m_masm;
+    bool m_allowIfTrue;
+    bool m_oldValueOfAllowScratchRegister;
+};
+
+} // namespace JSC
+
+#endif // ENABLE(ASSEMBLER)

Modified: trunk/Source/_javascript_Core/assembler/MacroAssembler.h (214383 => 214384)


--- trunk/Source/_javascript_Core/assembler/MacroAssembler.h	2017-03-24 23:16:52 UTC (rev 214383)
+++ trunk/Source/_javascript_Core/assembler/MacroAssembler.h	2017-03-24 23:25:16 UTC (rev 214384)
@@ -657,6 +657,11 @@
     {
         loadFromTLS32(offset, dst);
     }
+
+    void storeToTLSPtr(RegisterID src, uint32_t offset)
+    {
+        storeToTLS32(src, offset);
+    }
 #endif
 
     DataLabel32 loadPtrWithAddressOffsetPatch(Address address, RegisterID dest)
@@ -971,6 +976,10 @@
     {
         loadFromTLS64(offset, dst);
     }
+    void storeToTLSPtr(RegisterID src, uint32_t offset)
+    {
+        storeToTLS64(src, offset);
+    }
 #endif
 
     DataLabel32 loadPtrWithAddressOffsetPatch(Address address, RegisterID dest)

Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64.h (214383 => 214384)


--- trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64.h	2017-03-24 23:16:52 UTC (rev 214383)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64.h	2017-03-24 23:25:16 UTC (rev 214384)
@@ -3600,7 +3600,7 @@
     
 #if ENABLE(FAST_TLS_JIT)
     // This will use scratch registers if the offset is not legal.
-    
+
     void loadFromTLS32(uint32_t offset, RegisterID dst)
     {
         m_assembler.mrs_TPIDRRO_EL0(dst);
@@ -3614,6 +3614,34 @@
         and64(TrustedImm32(~7), dst);
         load64(Address(dst, offset), dst);
     }
+
+    static bool loadFromTLSPtrNeedsMacroScratchRegister()
+    {
+        return true;
+    }
+
+    void storeToTLS32(RegisterID src, uint32_t offset)
+    {
+        RegisterID tmp = getCachedDataTempRegisterIDAndInvalidate();
+        ASSERT(src != tmp);
+        m_assembler.mrs_TPIDRRO_EL0(tmp);
+        and64(TrustedImm32(~7), tmp);
+        store32(src, Address(tmp, offset));
+    }
+    
+    void storeToTLS64(RegisterID src, uint32_t offset)
+    {
+        RegisterID tmp = getCachedDataTempRegisterIDAndInvalidate();
+        ASSERT(src != tmp);
+        m_assembler.mrs_TPIDRRO_EL0(tmp);
+        and64(TrustedImm32(~7), tmp);
+        store64(src, Address(tmp, offset));
+    }
+
+    static bool storeToTLSPtrNeedsMacroScratchRegister()
+    {
+        return true;
+    }
 #endif // ENABLE(FAST_TLS_JIT)
     
     // Misc helper functions.

Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h (214383 => 214384)


--- trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h	2017-03-24 23:16:52 UTC (rev 214383)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h	2017-03-24 23:25:16 UTC (rev 214384)
@@ -3864,6 +3864,23 @@
         m_assembler.gs();
         m_assembler.movl_mr(offset, dst);
     }
+
+
+    static bool loadFromTLSPtrNeedsMacroScratchRegister()
+    {
+        return false;
+    }
+
+    void storeToTLS32(RegisterID src, uint32_t offset)
+    {
+        m_assembler.gs();
+        m_assembler.movl_rm(src, offset);
+    }
+
+    static bool storeToTLSPtrNeedsMacroScratchRegister()
+    {
+        return false;
+    }
 #endif
 
     static void replaceWithBreakpoint(CodeLocationLabel instructionStart)

Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerX86_64.h (214383 => 214384)


--- trunk/Source/_javascript_Core/assembler/MacroAssemblerX86_64.h	2017-03-24 23:16:52 UTC (rev 214383)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerX86_64.h	2017-03-24 23:25:16 UTC (rev 214384)
@@ -1705,8 +1705,14 @@
     void loadFromTLS64(uint32_t offset, RegisterID dst)
     {
         m_assembler.gs();
-        m_assembler.movl_mr(offset, dst);
+        m_assembler.movq_mr(offset, dst);
     }
+
+    void storeToTLS64(RegisterID src, uint32_t offset)
+    {
+        m_assembler.gs();
+        m_assembler.movq_rm(src, offset);
+    }
 #endif
 
     void truncateDoubleToUint32(FPRegisterID src, RegisterID dest)

Modified: trunk/Source/_javascript_Core/assembler/X86Assembler.h (214383 => 214384)


--- trunk/Source/_javascript_Core/assembler/X86Assembler.h	2017-03-24 23:16:52 UTC (rev 214383)
+++ trunk/Source/_javascript_Core/assembler/X86Assembler.h	2017-03-24 23:25:16 UTC (rev 214384)
@@ -2360,6 +2360,11 @@
         m_formatter.oneByteOpAddr(OP_MOV_GvEv, dst, addr);
     }
 
+    void movl_rm(RegisterID src, uint32_t addr)
+    {
+        m_formatter.oneByteOpAddr(OP_MOV_EvGv, src, addr);
+    }
+
 #if CPU(X86_64)
     void movq_rr(RegisterID src, RegisterID dst)
     {
@@ -2381,6 +2386,11 @@
         m_formatter.oneByteOp64(OP_MOV_EvGv, src, base, index, scale, offset);
     }
 
+    void movq_rm(RegisterID src, int offset)
+    {
+        m_formatter.oneByteOp64Addr(OP_MOV_EvGv, src, offset);
+    }
+
     void movq_mEAX(const void* addr)
     {
         m_formatter.oneByteOp64(OP_MOV_EAXOv);

Modified: trunk/Source/_javascript_Core/b3/testb3.cpp (214383 => 214384)


--- trunk/Source/_javascript_Core/b3/testb3.cpp	2017-03-24 23:16:52 UTC (rev 214383)
+++ trunk/Source/_javascript_Core/b3/testb3.cpp	2017-03-24 23:25:16 UTC (rev 214384)
@@ -15211,7 +15211,7 @@
         CHECK_EQ(numToStore, value);
 }
 
-void testFastTLS()
+void testFastTLSLoad()
 {
 #if ENABLE(FAST_TLS_JIT)
     _pthread_setspecific_direct(WTF_TESTING_KEY, bitwise_cast<void*>(static_cast<uintptr_t>(0xbeef)));
@@ -15226,7 +15226,7 @@
             AllowMacroScratchRegisterUsage allowScratch(jit);
             jit.loadFromTLSPtr(fastTLSOffsetForKey(WTF_TESTING_KEY), params[0].gpr());
         });
-    
+
     root->appendNew<Value>(proc, Return, Origin(), patchpoint);
     
     CHECK_EQ(compileAndRun<uintptr_t>(proc), static_cast<uintptr_t>(0xbeef));
@@ -15233,6 +15233,30 @@
 #endif
 }
 
+void testFastTLSStore()
+{
+#if ENABLE(FAST_TLS_JIT)
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+
+    PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Void, Origin());
+    patchpoint->clobber(RegisterSet::macroScratchRegisters());
+    patchpoint->numGPScratchRegisters = 1;
+    patchpoint->setGenerator(
+        [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
+            AllowMacroScratchRegisterUsage allowScratch(jit);
+            GPRReg scratch = params.gpScratch(0);
+            jit.move(CCallHelpers::TrustedImm32(0xdead), scratch);
+            jit.storeToTLSPtr(scratch, fastTLSOffsetForKey(WTF_TESTING_KEY));
+        });
+
+    root->appendNewControlValue(proc, Return, Origin());
+
+    compileAndRun<void>(proc);
+    CHECK_EQ(bitwise_cast<uintptr_t>(_pthread_getspecific_direct(WTF_TESTING_KEY)), static_cast<uintptr_t>(0xdead));
+#endif
+}
+
 // Make sure the compiler does not try to optimize anything out.
 NEVER_INLINE double zero()
 {
@@ -16760,7 +16784,8 @@
     RUN(testWasmBoundsCheck(std::numeric_limits<unsigned>::max() - 5));
     RUN(testWasmAddress());
     
-    RUN(testFastTLS());
+    RUN(testFastTLSLoad());
+    RUN(testFastTLSStore());
 
     if (isX86()) {
         RUN(testBranchBitAndImmFusion(Identity, Int64, 1, Air::BranchTest32, Air::Arg::Tmp));

Modified: trunk/Source/_javascript_Core/jit/AssemblyHelpers.h (214383 => 214384)


--- trunk/Source/_javascript_Core/jit/AssemblyHelpers.h	2017-03-24 23:16:52 UTC (rev 214383)
+++ trunk/Source/_javascript_Core/jit/AssemblyHelpers.h	2017-03-24 23:25:16 UTC (rev 214384)
@@ -41,6 +41,7 @@
 #include "SuperSampler.h"
 #include "TypeofType.h"
 #include "VM.h"
+#include <wtf/FastTLS.h>
 
 namespace JSC {
 
@@ -1634,7 +1635,47 @@
 #if USE(JSVALUE64)
     void wangsInt64Hash(GPRReg inputAndResult, GPRReg scratch);
 #endif
-    
+
+    void loadWasmContext(GPRReg dst)
+    {
+#if ENABLE(FAST_TLS_JIT)
+        if (Options::useWebAssemblyFastTLS()) {
+            loadFromTLSPtr(fastTLSOffsetForKey(WTF_WASM_CONTEXT_KEY), dst);
+            return;
+        }
+#endif
+        // FIXME: Save this state elsewhere to allow PIC. https://bugs.webkit.org/show_bug.cgi?id=169773
+        loadPtr(&m_vm->wasmContext, dst);
+    }
+
+    void storeWasmContext(GPRReg src)
+    {
+#if ENABLE(FAST_TLS_JIT)
+        if (Options::useWebAssemblyFastTLS())
+            storeToTLSPtr(src, fastTLSOffsetForKey(WTF_WASM_CONTEXT_KEY));
+#endif
+        // FIXME: Save this state elsewhere to allow PIC. https://bugs.webkit.org/show_bug.cgi?id=169773
+        storePtr(src, &m_vm->wasmContext);
+    }
+
+    static bool loadWasmContextNeedsMacroScratchRegister()
+    {
+#if ENABLE(FAST_TLS_JIT)
+        if (Options::useWebAssemblyFastTLS())
+            return loadFromTLSPtrNeedsMacroScratchRegister();
+#endif
+        return true;
+    }
+
+    static bool storeWasmContextNeedsMacroScratchRegister()
+    {
+#if ENABLE(FAST_TLS_JIT)
+        if (Options::useWebAssemblyFastTLS())
+            return storeToTLSPtrNeedsMacroScratchRegister();
+#endif
+        return true;
+    }
+
 protected:
     VM* m_vm;
     CodeBlock* m_codeBlock;

Modified: trunk/Source/_javascript_Core/jit/Repatch.cpp (214383 => 214384)


--- trunk/Source/_javascript_Core/jit/Repatch.cpp	2017-03-24 23:16:52 UTC (rev 214383)
+++ trunk/Source/_javascript_Core/jit/Repatch.cpp	2017-03-24 23:25:16 UTC (rev 214384)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2011-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -59,6 +59,7 @@
 #include "StructureStubClearingWatchpoint.h"
 #include "StructureStubInfo.h"
 #include "ThunkGenerators.h"
+#include "WasmContext.h"
 #include <wtf/CommaPrinter.h>
 #include <wtf/ListDump.h>
 #include <wtf/StringPrintStream.h>
@@ -592,7 +593,7 @@
 {
 #if ENABLE(WEBASSEMBLY)
     // Each WebAssembly.Instance shares the stubs from their WebAssembly.Module, which are therefore the appropriate owner.
-    return vm.topJSWebAssemblyInstance->module();
+    return loadWasmContext(vm)->module();
 #else
     UNUSED_PARAM(vm);
     RELEASE_ASSERT_NOT_REACHED();

Modified: trunk/Source/_javascript_Core/jit/ThunkGenerators.cpp (214383 => 214384)


--- trunk/Source/_javascript_Core/jit/ThunkGenerators.cpp	2017-03-24 23:16:52 UTC (rev 214383)
+++ trunk/Source/_javascript_Core/jit/ThunkGenerators.cpp	2017-03-24 23:25:16 UTC (rev 214384)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010, 2012-2014, 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2010, 2012-2014, 2016-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -32,12 +32,13 @@
 #include "JITOperations.h"
 #include "JSArray.h"
 #include "JSBoundFunction.h"
-#include "MathCommon.h"
-#include "MaxFrameExtentForSlowPathCall.h"
 #include "JSCInlines.h"
 #include "JSWebAssemblyInstance.h"
 #include "JSWebAssemblyRuntimeError.h"
+#include "MathCommon.h"
+#include "MaxFrameExtentForSlowPathCall.h"
 #include "SpecializedThunkJIT.h"
+#include "WasmContext.h"
 #include "WasmExceptionType.h"
 #include <wtf/InlineASM.h>
 #include <wtf/StringPrintStream.h>
@@ -1156,7 +1157,7 @@
 
         {
             auto throwScope = DECLARE_THROW_SCOPE(*vm);
-            JSGlobalObject* globalObject = vm->topJSWebAssemblyInstance->globalObject();
+            JSGlobalObject* globalObject = loadWasmContext(*vm)->globalObject();
 
             JSWebAssemblyRuntimeError* error = JSWebAssemblyRuntimeError::create(exec, *vm, globalObject->WebAssemblyRuntimeErrorStructure(), Wasm::errorMessageForExceptionType(type));
             throwException(exec, throwScope, error);

Modified: trunk/Source/_javascript_Core/runtime/Options.h (214383 => 214384)


--- trunk/Source/_javascript_Core/runtime/Options.h	2017-03-24 23:16:52 UTC (rev 214383)
+++ trunk/Source/_javascript_Core/runtime/Options.h	2017-03-24 23:25:16 UTC (rev 214384)
@@ -429,7 +429,8 @@
     \
     v(bool, useWebAssembly, true, Normal, "Expose the WebAssembly global object.") \
     v(bool, simulateWebAssemblyLowMemory, false, Normal, "If true, the Memory object won't mmap the full 'maximum' range and instead will allocate the minimum required amount.") \
-    v(bool, useWebAssemblyFastMemory, true, Normal, "If true, we will try to use a 32-bit address space with a signal handler to bounds check wasm memory.")
+    v(bool, useWebAssemblyFastMemory, true, Normal, "If true, we will try to use a 32-bit address space with a signal handler to bounds check wasm memory.") \
+    v(bool, useWebAssemblyFastTLS, true, Normal, "If true, we will try to use fast thread-local storage if available on the current platform.")
 
 
 enum OptionEquivalence {

Modified: trunk/Source/_javascript_Core/runtime/VM.cpp (214383 => 214384)


--- trunk/Source/_javascript_Core/runtime/VM.cpp	2017-03-24 23:16:52 UTC (rev 214383)
+++ trunk/Source/_javascript_Core/runtime/VM.cpp	2017-03-24 23:25:16 UTC (rev 214384)
@@ -177,7 +177,6 @@
     , clientData(0)
     , topVMEntryFrame(nullptr)
     , topCallFrame(CallFrame::noCaller())
-    , topJSWebAssemblyInstance(nullptr)
     , m_atomicStringTable(vmType == Default ? wtfThreadData().atomicStringTable() : new AtomicStringTable)
     , propertyNames(nullptr)
     , emptyList(new ArgList)

Modified: trunk/Source/_javascript_Core/runtime/VM.h (214383 => 214384)


--- trunk/Source/_javascript_Core/runtime/VM.h	2017-03-24 23:16:52 UTC (rev 214383)
+++ trunk/Source/_javascript_Core/runtime/VM.h	2017-03-24 23:25:16 UTC (rev 214384)
@@ -315,7 +315,8 @@
     // FIXME: This should be a void*, because it might not point to a CallFrame.
     // https://bugs.webkit.org/show_bug.cgi?id=160441
     ExecState* topCallFrame { nullptr };
-    JSWebAssemblyInstance* topJSWebAssemblyInstance;
+    // FIXME: Save this state elsewhere to allow PIC. https://bugs.webkit.org/show_bug.cgi?id=169773
+    JSWebAssemblyInstance* wasmContext { nullptr };
     Strong<Structure> structureStructure;
     Strong<Structure> structureRareDataStructure;
     Strong<Structure> terminatedExecutionErrorStructure;

Modified: trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp (214383 => 214384)


--- trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp	2017-03-24 23:16:52 UTC (rev 214383)
+++ trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp	2017-03-24 23:25:16 UTC (rev 214384)
@@ -28,6 +28,7 @@
 
 #if ENABLE(WEBASSEMBLY)
 
+#include "AllowMacroScratchRegisterUsageIf.h"
 #include "B3BasicBlockInlines.h"
 #include "B3CCallValue.h"
 #include "B3Compile.h"
@@ -48,6 +49,7 @@
 #include "JSWebAssemblyRuntimeError.h"
 #include "VirtualRegister.h"
 #include "WasmCallingConvention.h"
+#include "WasmContext.h"
 #include "WasmExceptionType.h"
 #include "WasmFunctionParser.h"
 #include "WasmMemory.h"
@@ -226,9 +228,36 @@
     GPRReg m_memoryBaseGPR;
     GPRReg m_memorySizeGPR;
     Value* m_zeroValues[numTypes];
-    Value* m_instanceValue;
+    Value* m_instanceValue; // FIXME: make this lazy https://bugs.webkit.org/show_bug.cgi?id=169792
 };
 
+static Value* loadWasmContext(Procedure& proc, BasicBlock* block)
+{
+    PatchpointValue* patchpoint = block->appendNew<PatchpointValue>(proc, pointerType(), Origin());
+    if (CCallHelpers::loadWasmContextNeedsMacroScratchRegister())
+        patchpoint->clobber(RegisterSet::macroScratchRegisters());
+    patchpoint->setGenerator(
+        [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
+            AllowMacroScratchRegisterUsageIf allowScratch(jit, CCallHelpers::loadWasmContextNeedsMacroScratchRegister());
+            jit.loadWasmContext(params[0].gpr());
+        });
+
+    return block->appendNew<Value>(proc, Identity, Origin(), patchpoint);
+}
+
+static void storeWasmContext(Procedure& proc, BasicBlock* block, Value* arg)
+{
+    PatchpointValue* patchpoint = block->appendNew<PatchpointValue>(proc, B3::Void, Origin());
+    if (CCallHelpers::storeWasmContextNeedsMacroScratchRegister())
+        patchpoint->clobber(RegisterSet::macroScratchRegisters());
+    patchpoint->append(ConstrainedValue(arg, ValueRep::SomeRegister));
+    patchpoint->setGenerator(
+        [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
+            AllowMacroScratchRegisterUsageIf allowScratch(jit, CCallHelpers::storeWasmContextNeedsMacroScratchRegister());
+            jit.storeWasmContext(params[0].gpr());
+        });
+}
+
 B3IRGenerator::B3IRGenerator(VM& vm, const ModuleInformation& info, Procedure& procedure, WasmInternalFunction* compilation, Vector<UnlinkedWasmToWasmCall>& unlinkedWasmToWasmCalls)
     : m_vm(vm)
     , m_info(info)
@@ -270,8 +299,7 @@
 
     wasmCallingConvention().setupFrameInPrologue(&compilation->wasmCalleeMoveLocation, m_proc, Origin(), m_currentBlock);
 
-    m_instanceValue = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), Origin(),
-        m_currentBlock->appendNew<ConstPtrValue>(m_proc, Origin(), &m_vm.topJSWebAssemblyInstance));
+    m_instanceValue = loadWasmContext(m_proc, m_currentBlock);
 }
 
 struct MemoryBaseAndSize {
@@ -283,8 +311,8 @@
 {
     Value* memoryObject = block->appendNew<MemoryValue>(proc, Load, pointerType(), Origin(), instance, JSWebAssemblyInstance::offsetOfMemory());
 
-    static_assert(sizeof(decltype(vm.topJSWebAssemblyInstance->memory()->memory().memory())) == sizeof(void*), "codegen relies on this size");
-    static_assert(sizeof(decltype(vm.topJSWebAssemblyInstance->memory()->memory().size())) == sizeof(uint64_t), "codegen relies on this size");
+    static_assert(sizeof(decltype(loadWasmContext(vm)->memory()->memory().memory())) == sizeof(void*), "codegen relies on this size");
+    static_assert(sizeof(decltype(loadWasmContext(vm)->memory()->memory().size())) == sizeof(uint64_t), "codegen relies on this size");
     MemoryBaseAndSize result;
     result.base = block->appendNew<MemoryValue>(proc, Load, pointerType(), Origin(), memoryObject, JSWebAssemblyMemory::offsetOfMemory());
     result.size = block->appendNew<MemoryValue>(proc, Load, Int64, Origin(), memoryObject, JSWebAssemblyMemory::offsetOfSize());
@@ -292,9 +320,9 @@
     return result;
 }
 
-static void restoreWebAssemblyGlobalState(VM& vm, const MemoryInformation& memory, Value* instance, Procedure& proc, BasicBlock* block)
+static void restoreWebAssemblyGlobalState(const MemoryInformation& memory, Value* instance, Procedure& proc, BasicBlock* block)
 {
-    block->appendNew<MemoryValue>(proc, Store, Origin(), instance, block->appendNew<ConstPtrValue>(proc, Origin(), &vm.topJSWebAssemblyInstance));
+    storeWasmContext(proc, block, instance);
 
     if (!!memory) {
         const PinnedRegisterInfo* pinnedRegs = &PinnedRegisterInfo::get();
@@ -395,7 +423,7 @@
         VM& vm = exec->vm();
         auto scope = DECLARE_THROW_SCOPE(vm);
 
-        JSWebAssemblyInstance* instance = vm.topJSWebAssemblyInstance;
+        JSWebAssemblyInstance* instance = loadWasmContext(vm);
         JSWebAssemblyMemory* wasmMemory = instance->memory();
 
         if (delta < 0)
@@ -414,7 +442,7 @@
         m_currentBlock->appendNew<ConstPtrValue>(m_proc, Origin(), bitwise_cast<void*>(growMemory)),
         m_currentBlock->appendNew<B3::Value>(m_proc, B3::FramePointer, Origin()), delta);
 
-    restoreWebAssemblyGlobalState(m_vm, m_info.memory, m_instanceValue, m_proc, m_currentBlock);
+    restoreWebAssemblyGlobalState(m_info.memory, m_instanceValue, m_proc, m_currentBlock);
 
     return { };
 }
@@ -901,7 +929,7 @@
         }
 
         // The call could have been to another WebAssembly instance, and / or could have modified our Memory.
-        restoreWebAssemblyGlobalState(m_vm, m_info.memory, m_instanceValue, m_proc, continuation);
+        restoreWebAssemblyGlobalState(m_info.memory, m_instanceValue, m_proc, continuation);
     } else {
         result = wasmCallingConvention().setupCall(m_proc, m_currentBlock, Origin(), args, toB3Type(returnType),
             [&] (PatchpointValue* patchpoint) {
@@ -995,7 +1023,7 @@
         });
 
     // The call could have been to another WebAssembly instance, and / or could have modified our Memory.
-    restoreWebAssemblyGlobalState(m_vm, m_info.memory, m_instanceValue, m_proc, m_currentBlock);
+    restoreWebAssemblyGlobalState(m_info.memory, m_instanceValue, m_proc, m_currentBlock);
 
     return { };
 }
@@ -1037,7 +1065,7 @@
     dataLogLn();
 }
 
-static void createJSToWasmWrapper(VM& vm, CompilationContext& compilationContext, WasmInternalFunction& function, const Signature* signature, const ModuleInformation& info)
+static void createJSToWasmWrapper(CompilationContext& compilationContext, WasmInternalFunction& function, const Signature* signature, const ModuleInformation& info)
 {
     CCallHelpers& jit = *compilationContext.jsEntrypointJIT;
 
@@ -1165,7 +1193,7 @@
 
     if (!!info.memory) {
         GPRReg baseMemory = pinnedRegs.baseMemoryPointer;
-        jit.loadPtr(&vm.topJSWebAssemblyInstance, baseMemory);
+        jit.loadWasmContext(baseMemory);
         jit.loadPtr(CCallHelpers::Address(baseMemory, JSWebAssemblyInstance::offsetOfMemory()), baseMemory);
         const auto& sizeRegs = pinnedRegs.sizeRegisters;
         ASSERT(sizeRegs.size() >= 1);
@@ -1227,7 +1255,7 @@
         result->wasmEntrypoint.calleeSaveRegisters = procedure.calleeSaveRegisters();
     }
 
-    createJSToWasmWrapper(vm, compilationContext, *result, signature, info);
+    createJSToWasmWrapper(compilationContext, *result, signature, info);
     return WTFMove(result);
 }
 

Modified: trunk/Source/_javascript_Core/wasm/WasmBinding.cpp (214383 => 214384)


--- trunk/Source/_javascript_Core/wasm/WasmBinding.cpp	2017-03-24 23:16:52 UTC (rev 214383)
+++ trunk/Source/_javascript_Core/wasm/WasmBinding.cpp	2017-03-24 23:25:16 UTC (rev 214384)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -36,6 +36,7 @@
 #include "LinkBuffer.h"
 #include "NativeErrorConstructor.h"
 #include "WasmCallingConvention.h"
+#include "WasmContext.h"
 #include "WasmExceptionType.h"
 
 namespace JSC { namespace Wasm {
@@ -42,10 +43,10 @@
 
 typedef CCallHelpers JIT;
 
-static void materializeImportJSCell(VM* vm, JIT& jit, unsigned importIndex, GPRReg result)
+static void materializeImportJSCell(JIT& jit, unsigned importIndex, GPRReg result)
 {
-    // We're calling out of the current WebAssembly.Instance, which is identified on VM. That Instance has a list of all its import functions.
-    jit.loadPtr(&vm->topJSWebAssemblyInstance, result);
+    // We're calling out of the current WebAssembly.Instance. That Instance has a list of all its import functions.
+    jit.loadWasmContext(result);
     jit.loadPtr(JIT::Address(result, JSWebAssemblyInstance::offsetOfImportFunction(importIndex)), result);
 }
 
@@ -101,7 +102,7 @@
 
                 {
                     auto throwScope = DECLARE_THROW_SCOPE(*vm);
-                    JSGlobalObject* globalObject = vm->topJSWebAssemblyInstance->globalObject();
+                    JSGlobalObject* globalObject = loadWasmContext(*vm)->globalObject();
                     auto* error = ErrorInstance::create(exec, *vm, globalObject->typeErrorConstructor()->errorStructure(), ASCIILiteral("i64 not allowed as return type or argument to an imported function"));
                     throwException(exec, throwScope, error);
                 }
@@ -254,7 +255,7 @@
     GPRReg importJSCellGPRReg = GPRInfo::regT0; // Callee needs to be in regT0 for slow path below.
     ASSERT(!wasmCC.m_calleeSaveRegisters.get(importJSCellGPRReg));
 
-    materializeImportJSCell(vm, jit, importIndex, importJSCellGPRReg);
+    materializeImportJSCell(jit, importIndex, importJSCellGPRReg);
 
     jit.store64(importJSCellGPRReg, calleeFrame.withOffset(CallFrameSlot::callee * static_cast<int>(sizeof(Register))));
     jit.store32(JIT::TrustedImm32(numberOfParameters), calleeFrame.withOffset(CallFrameSlot::argumentCount * static_cast<int>(sizeof(Register)) + PayloadOffset));
@@ -426,13 +427,13 @@
     GPRReg scratch = GPRInfo::nonPreservedNonArgumentGPR;
 
     // B3's call codegen ensures that the JSCell is a WebAssemblyFunction.
-    materializeImportJSCell(vm, jit, importIndex, scratch);
+    materializeImportJSCell(jit, importIndex, scratch);
 
-    // Get the callee's WebAssembly.Instance and set it as vm.topJSWebAssemblyInstance. The caller will take care of restoring its own Instance.
+    // Get the callee's WebAssembly.Instance and set it as WasmContext. The caller will take care of restoring its own Instance.
     GPRReg baseMemory = pinnedRegs.baseMemoryPointer;
     ASSERT(baseMemory != scratch);
     jit.loadPtr(JIT::Address(scratch, WebAssemblyFunction::offsetOfInstance()), baseMemory); // Instance*.
-    jit.storePtr(baseMemory, &vm->topJSWebAssemblyInstance);
+    jit.storeWasmContext(baseMemory);
 
     // FIXME the following code assumes that all WebAssembly.Instance have the same pinned registers. https://bugs.webkit.org/show_bug.cgi?id=162952
     // Set up the callee's baseMemory register as well as the memory size registers.

Copied: trunk/Source/_javascript_Core/wasm/WasmContext.cpp (from rev 214383, trunk/Source/_javascript_Core/wasm/js/WebAssemblyInstanceConstructor.h) (0 => 214384)


--- trunk/Source/_javascript_Core/wasm/WasmContext.cpp	                        (rev 0)
+++ trunk/Source/_javascript_Core/wasm/WasmContext.cpp	2017-03-24 23:25:16 UTC (rev 214384)
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WasmContext.h"
+
+#if ENABLE(WEBASSEMBLY)
+
+#include "VM.h"
+#include <mutex>
+#include <wtf/FastTLS.h>
+
+namespace JSC {
+
+JSWebAssemblyInstance* loadWasmContext(VM& vm)
+{
+#if ENABLE(FAST_TLS_JIT)
+    if (Options::useWebAssemblyFastTLS())
+        return bitwise_cast<JSWebAssemblyInstance*>(_pthread_getspecific_direct(WTF_WASM_CONTEXT_KEY));
+#endif
+    // FIXME: Save this state elsewhere to allow PIC. https://bugs.webkit.org/show_bug.cgi?id=169773
+    return vm.wasmContext;
+}
+
+void storeWasmContext(VM& vm, JSWebAssemblyInstance* instance)
+{
+#if ENABLE(FAST_TLS_JIT)
+    if (Options::useWebAssemblyFastTLS())
+        _pthread_setspecific_direct(WTF_WASM_CONTEXT_KEY, bitwise_cast<void*>(instance));
+#endif
+    // FIXME: Save this state elsewhere to allow PIC. https://bugs.webkit.org/show_bug.cgi?id=169773
+    vm.wasmContext = instance;
+}
+
+} // namespace JSC
+
+#endif // ENABLE(WEBASSEMBLY)

Copied: trunk/Source/_javascript_Core/wasm/WasmContext.h (from rev 214383, trunk/Source/_javascript_Core/wasm/js/WebAssemblyInstanceConstructor.h) (0 => 214384)


--- trunk/Source/_javascript_Core/wasm/WasmContext.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/wasm/WasmContext.h	2017-03-24 23:25:16 UTC (rev 214384)
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(WEBASSEMBLY)
+
+namespace JSC {
+
+class JSWebAssemblyInstance;
+class VM;
+
+JSWebAssemblyInstance* loadWasmContext(VM&);
+void storeWasmContext(VM&, JSWebAssemblyInstance*);
+
+} // namespace JSC
+
+#endif // ENABLE(WEBASSEMBLY)

Modified: trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunction.cpp (214383 => 214384)


--- trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunction.cpp	2017-03-24 23:16:52 UTC (rev 214383)
+++ trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunction.cpp	2017-03-24 23:25:16 UTC (rev 214384)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -39,6 +39,7 @@
 #include "LLIntThunks.h"
 #include "ProtoCallFrame.h"
 #include "VM.h"
+#include "WasmContext.h"
 #include "WasmFormat.h"
 #include "WasmMemory.h"
 #include <wtf/SystemTracing.h>
@@ -120,11 +121,12 @@
     protoCallFrame.init(nullptr, wasmFunction, firstArgument, argCount, remainingArgs);
 
     // FIXME Do away with this entire function, and only use the entrypoint generated by B3. https://bugs.webkit.org/show_bug.cgi?id=166486
-    JSWebAssemblyInstance* prevJSWebAssemblyInstance = vm.topJSWebAssemblyInstance;
-    vm.topJSWebAssemblyInstance = wasmFunction->instance();
+    JSWebAssemblyInstance* prevJSWebAssemblyInstance = loadWasmContext(vm);
+    storeWasmContext(vm, wasmFunction->instance());
     ASSERT(wasmFunction->instance());
+    ASSERT(wasmFunction->instance() == loadWasmContext(vm));
     EncodedJSValue rawResult = vmEntryToWasm(wasmFunction->jsEntrypoint(), &vm, &protoCallFrame);
-    vm.topJSWebAssemblyInstance = prevJSWebAssemblyInstance;
+    storeWasmContext(vm, prevJSWebAssemblyInstance);
     RETURN_IF_EXCEPTION(scope, { });
 
     switch (signature->returnType()) {

Modified: trunk/Source/_javascript_Core/wasm/js/WebAssemblyInstanceConstructor.h (214383 => 214384)


--- trunk/Source/_javascript_Core/wasm/js/WebAssemblyInstanceConstructor.h	2017-03-24 23:16:52 UTC (rev 214383)
+++ trunk/Source/_javascript_Core/wasm/js/WebAssemblyInstanceConstructor.h	2017-03-24 23:25:16 UTC (rev 214384)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -32,6 +32,7 @@
 
 namespace JSC {
 
+class JSWebAssemblyInstance;
 class JSWebAssemblyModule;
 class WebAssemblyInstancePrototype;
 

Modified: trunk/Source/WTF/ChangeLog (214383 => 214384)


--- trunk/Source/WTF/ChangeLog	2017-03-24 23:16:52 UTC (rev 214383)
+++ trunk/Source/WTF/ChangeLog	2017-03-24 23:25:16 UTC (rev 214384)
@@ -1,3 +1,14 @@
+2017-03-24  JF Bastien  <[email protected]>
+
+        WebAssembly: store state in TLS instead of on VM
+        https://bugs.webkit.org/show_bug.cgi?id=169611
+
+        Reviewed by Filip Pizlo.
+
+        * wtf/FastTLS.h: reserve one key for WebAssembly, delete a bunch
+        of dead code which clang couldn't compile (it's valid GCC assembly
+        which LLVM dislikes).
+
 2017-03-24  Ryan Haddad  <[email protected]>
 
         Unreviewed, rolling out r214351.

Modified: trunk/Source/WTF/wtf/FastTLS.h (214383 => 214384)


--- trunk/Source/WTF/wtf/FastTLS.h	2017-03-24 23:16:52 UTC (rev 214383)
+++ trunk/Source/WTF/wtf/FastTLS.h	2017-03-24 23:25:16 UTC (rev 214384)
@@ -29,6 +29,7 @@
 
 #include <pthread.h>
 #include <System/pthread_machdep.h>
+#include <wtf/Platform.h>
 
 namespace WTF {
 
@@ -44,52 +45,20 @@
 // accidentally use the same key for more than one thing.
 
 #define WTF_THREAD_DATA_KEY WTF_FAST_TLS_KEY0
+#define WTF_WASM_CONTEXT_KEY WTF_FAST_TLS_KEY1
 #define WTF_TESTING_KEY WTF_FAST_TLS_KEY3
 
 #if ENABLE(FAST_TLS_JIT)
-// Below is the code that the JIT will emit.
-
-#if CPU(X86_64)
-inline uintptr_t loadFastTLS(unsigned offset)
-{
-    uintptr_t result;
-    asm volatile(
-        "movq %%gs:%1, %0"
-        : "=r"(result)
-        : "r"(offset)
-        : "memory");
-    return result;
-}
-#elif CPU(ARM64)
-inline uintptr_t loadFastTLS(unsigned passedOffset)
-{
-    uintptr_t result;
-    uintptr_t offset = passedOffset;
-    asm volatile(
-        "mrs %0, TPIDRRO_EL0\n\t"
-        "and %0, %0, #0xfffffffffffffff8\n\t"
-        "ldr %0, [%0, %1]"
-        : "=r"(result)
-        : "r"(offset)
-        : "memory");
-    return result;
-}
-#else
-#error "Bad architecture"
-#endif
-#endif // ENABLE(FAST_TLS_JIT)
-
 inline unsigned fastTLSOffsetForKey(unsigned long slot)
 {
     return slot * sizeof(void*);
 }
+#endif
 
 } // namespace WTF
 
+#if ENABLE(FAST_TLS_JIT)
 using WTF::fastTLSOffsetForKey;
-
-#if ENABLE(FAST_TLS_JIT)
-using WTF::loadFastTLS;
 #endif
 
 #endif // HAVE(FAST_TLS)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to