Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (214497 => 214498)
--- trunk/Source/_javascript_Core/ChangeLog 2017-03-28 22:14:49 UTC (rev 214497)
+++ trunk/Source/_javascript_Core/ChangeLog 2017-03-28 22:16:01 UTC (rev 214498)
@@ -1,3 +1,102 @@
+2017-03-28 Yusuke Suzuki <[email protected]>
+
+ WebAssembly: add fallback to use pinned register to load/store state
+ https://bugs.webkit.org/show_bug.cgi?id=169773
+
+ Reviewed by Saam Barati.
+
+ This patch adds a new pinned register to hold JSWebAssemblyInstance,
+ which is used to represent the context of running Wasm code.
+ While we use fast TLS to hold the context in macOS, we do not have
+ any system reserved fast TLS slot in the other systems. This pinned
+ register approach is used in these systems. These changes decouple
+ VM from Wasm module to make Wasm module position independent code.
+
+ While using fast TLS could be beneficial in x64 systems which number of
+ registers is relatively small, pinned register approach could be
+ beneficial in ARM64 which has plenty of registers. In macOS, we can
+ switch the implementation with the runtime flag. Thus macOS port can
+ compare the performance and decide which implementation is used after
+ landing this patch.
+
+ * heap/MarkedBlock.h:
+ (JSC::MarkedBlock::offsetOfVM):
+ * jit/AssemblyHelpers.cpp:
+ (JSC::AssemblyHelpers::loadWasmContext):
+ (JSC::AssemblyHelpers::storeWasmContext):
+ (JSC::AssemblyHelpers::loadWasmContextNeedsMacroScratchRegister):
+ (JSC::AssemblyHelpers::storeWasmContextNeedsMacroScratchRegister):
+ * jit/AssemblyHelpers.h:
+ (JSC::AssemblyHelpers::loadWasmContext): Deleted.
+ (JSC::AssemblyHelpers::storeWasmContext): Deleted.
+ (JSC::AssemblyHelpers::loadWasmContextNeedsMacroScratchRegister): Deleted.
+ (JSC::AssemblyHelpers::storeWasmContextNeedsMacroScratchRegister): Deleted.
+ * jit/Repatch.cpp:
+ (JSC::webAssemblyOwner):
+ (JSC::linkFor):
+ (JSC::linkPolymorphicCall):
+ (JSC::isWebAssemblyToJSCallee): Deleted.
+ * jit/ThunkGenerators.cpp:
+ (JSC::throwExceptionFromWasmThunkGenerator):
+ * llint/LLIntData.cpp:
+ (JSC::LLInt::Data::performAssertions):
+ * llint/LowLevelInterpreter.asm:
+ * runtime/JSCell.cpp:
+ (JSC::JSCell::isAnyWasmCallee):
+ * runtime/JSCellInlines.h:
+ (JSC::isWebAssemblyToJSCallee):
+ * runtime/JSType.h:
+ * runtime/StackFrame.cpp:
+ (JSC::StackFrame::functionName):
+ * runtime/VM.cpp:
+ (JSC::VM::VM):
+ * runtime/VM.h:
+ (JSC::VM::wasmContextOffset):
+ * wasm/WasmB3IRGenerator.cpp:
+ (JSC::Wasm::B3IRGenerator::materializeWasmContext):
+ (JSC::Wasm::B3IRGenerator::restoreWasmContext):
+ (JSC::Wasm::B3IRGenerator::B3IRGenerator):
+ (JSC::Wasm::getMemoryBaseAndSize):
+ (JSC::Wasm::B3IRGenerator::restoreWebAssemblyGlobalState):
+ (JSC::Wasm::createJSToWasmWrapper):
+ (JSC::Wasm::loadWasmContext): Deleted.
+ (JSC::Wasm::storeWasmContext): Deleted.
+ (JSC::Wasm::restoreWebAssemblyGlobalState): Deleted.
+ * wasm/WasmBinding.cpp:
+ (JSC::Wasm::wasmToJs):
+ * wasm/WasmContext.cpp:
+ (JSC::loadWasmContext):
+ (JSC::storeWasmContext):
+ * wasm/WasmContext.h:
+ * wasm/WasmMemoryInformation.cpp:
+ (JSC::Wasm::getPinnedRegisters):
+ (JSC::Wasm::PinnedRegisterInfo::get):
+ (JSC::Wasm::PinnedRegisterInfo::PinnedRegisterInfo):
+ * wasm/WasmMemoryInformation.h:
+ (JSC::Wasm::PinnedRegisterInfo::toSave):
+ (JSC::Wasm::useFastTLS):
+ (JSC::Wasm::useFastTLSForWasmContext):
+ * wasm/js/JSWebAssemblyInstance.cpp:
+ (JSC::JSWebAssemblyInstance::finishCreation):
+ (JSC::JSWebAssemblyInstance::visitChildren):
+ * wasm/js/JSWebAssemblyInstance.h:
+ (JSC::JSWebAssemblyInstance::offsetOfCallee):
+ * wasm/js/JSWebAssemblyModule.cpp:
+ (JSC::JSWebAssemblyModule::finishCreation):
+ (JSC::JSWebAssemblyModule::visitChildren):
+ * wasm/js/JSWebAssemblyModule.h:
+ (JSC::JSWebAssemblyModule::callee):
+ * wasm/js/WebAssemblyFunction.cpp:
+ (JSC::callWebAssemblyFunction):
+ (JSC::WebAssemblyFunction::create):
+ * wasm/js/WebAssemblyToJSCallee.cpp:
+ (JSC::WebAssemblyToJSCallee::create):
+ (JSC::WebAssemblyToJSCallee::createStructure):
+ (JSC::WebAssemblyToJSCallee::finishCreation):
+ (JSC::WebAssemblyToJSCallee::visitChildren):
+ (JSC::WebAssemblyToJSCallee::destroy): Deleted.
+ * wasm/js/WebAssemblyToJSCallee.h:
+
2017-03-28 Brian Burg <[email protected]>
Web Inspector: Add "Disable Caches" option that only applies to the inspected page while Web Inspector is open
Modified: trunk/Source/_javascript_Core/heap/MarkedBlock.h (214497 => 214498)
--- trunk/Source/_javascript_Core/heap/MarkedBlock.h 2017-03-28 22:14:49 UTC (rev 214497)
+++ trunk/Source/_javascript_Core/heap/MarkedBlock.h 2017-03-28 22:16:01 UTC (rev 214498)
@@ -298,6 +298,11 @@
bool isMarkedRaw(const void* p);
HeapVersion markingVersion() const { return m_markingVersion; }
+
+ static ptrdiff_t offsetOfVM()
+ {
+ return OBJECT_OFFSETOF(MarkedBlock, m_vm);
+ }
private:
static const size_t atomAlignmentMask = atomSize - 1;
Modified: trunk/Source/_javascript_Core/jit/AssemblyHelpers.cpp (214497 => 214498)
--- trunk/Source/_javascript_Core/jit/AssemblyHelpers.cpp 2017-03-28 22:14:49 UTC (rev 214497)
+++ trunk/Source/_javascript_Core/jit/AssemblyHelpers.cpp 2017-03-28 22:16:01 UTC (rev 214498)
@@ -32,6 +32,10 @@
#include "JSCInlines.h"
#include "LinkBuffer.h"
+#if ENABLE(WEBASSEMBLY)
+#include "WasmMemoryInformation.h"
+#endif
+
namespace JSC {
ExecutableBase* AssemblyHelpers::executableFor(const CodeOrigin& codeOrigin)
@@ -766,6 +770,49 @@
done.link(this);
}
+#if ENABLE(WEBASSEMBLY)
+void AssemblyHelpers::loadWasmContext(GPRReg dst)
+{
+#if ENABLE(FAST_TLS_JIT)
+ if (Wasm::useFastTLSForWasmContext()) {
+ loadFromTLSPtr(fastTLSOffsetForKey(WTF_WASM_CONTEXT_KEY), dst);
+ return;
+ }
+#endif
+ move(Wasm::PinnedRegisterInfo::get().wasmContextPointer, dst);
+}
+
+void AssemblyHelpers::storeWasmContext(GPRReg src)
+{
+#if ENABLE(FAST_TLS_JIT)
+ if (Wasm::useFastTLSForWasmContext()) {
+ storeToTLSPtr(src, fastTLSOffsetForKey(WTF_WASM_CONTEXT_KEY));
+ return;
+ }
+#endif
+ move(src, Wasm::PinnedRegisterInfo::get().wasmContextPointer);
+}
+
+bool AssemblyHelpers::loadWasmContextNeedsMacroScratchRegister()
+{
+#if ENABLE(FAST_TLS_JIT)
+ if (Wasm::useFastTLSForWasmContext())
+ return loadFromTLSPtrNeedsMacroScratchRegister();
+#endif
+ return false;
+}
+
+bool AssemblyHelpers::storeWasmContextNeedsMacroScratchRegister()
+{
+#if ENABLE(FAST_TLS_JIT)
+ if (Wasm::useFastTLSForWasmContext())
+ return storeToTLSPtrNeedsMacroScratchRegister();
+#endif
+ return false;
+}
+
+#endif
+
} // namespace JSC
#endif // ENABLE(JIT)
Modified: trunk/Source/_javascript_Core/jit/AssemblyHelpers.h (214497 => 214498)
--- trunk/Source/_javascript_Core/jit/AssemblyHelpers.h 2017-03-28 22:14:49 UTC (rev 214497)
+++ trunk/Source/_javascript_Core/jit/AssemblyHelpers.h 2017-03-28 22:16:01 UTC (rev 214498)
@@ -1636,46 +1636,13 @@
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;
- }
+#if ENABLE(WEBASSEMBLY)
+ void loadWasmContext(GPRReg dst);
+ void storeWasmContext(GPRReg src);
+ static bool loadWasmContextNeedsMacroScratchRegister();
+ static bool storeWasmContextNeedsMacroScratchRegister();
#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())
- return 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 (214497 => 214498)
--- trunk/Source/_javascript_Core/jit/Repatch.cpp 2017-03-28 22:14:49 UTC (rev 214497)
+++ trunk/Source/_javascript_Core/jit/Repatch.cpp 2017-03-28 22:16:01 UTC (rev 214498)
@@ -59,7 +59,6 @@
#include "StructureStubClearingWatchpoint.h"
#include "StructureStubInfo.h"
#include "ThunkGenerators.h"
-#include "WasmContext.h"
#include <wtf/CommaPrinter.h>
#include <wtf/ListDump.h>
#include <wtf/StringPrintStream.h>
@@ -577,25 +576,13 @@
callLinkInfo.setSlowStub(createJITStubRoutine(virtualThunk, *vm, nullptr, true));
}
-static bool isWebAssemblyToJSCallee(VM& vm, JSCell* callee)
+static JSCell* webAssemblyOwner(JSCell* callee)
{
#if ENABLE(WEBASSEMBLY)
- // The WebAssembly -> JS stub sets it caller frame's callee to a singleton which lives on the VM.
- return callee == vm.webAssemblyToJSCallee.get();
+ // Each WebAssembly.Instance shares the stubs from their WebAssembly.Module, which are therefore the appropriate owner.
+ return jsCast<WebAssemblyToJSCallee*>(callee)->module();
#else
- UNUSED_PARAM(vm);
UNUSED_PARAM(callee);
- return false;
-#endif // ENABLE(WEBASSEMBLY)
-}
-
-static JSCell* webAssemblyOwner(VM& vm)
-{
-#if ENABLE(WEBASSEMBLY)
- // Each WebAssembly.Instance shares the stubs from their WebAssembly.Module, which are therefore the appropriate owner.
- return loadWasmContext(vm)->module();
-#else
- UNUSED_PARAM(vm);
RELEASE_ASSERT_NOT_REACHED();
return nullptr;
#endif // ENABLE(WEBASSEMBLY)
@@ -612,7 +599,7 @@
CodeBlock* callerCodeBlock = callerFrame->codeBlock();
// WebAssembly -> JS stubs don't have a valid CodeBlock.
- JSCell* owner = isWebAssemblyToJSCallee(vm, callerFrame->callee()) ? webAssemblyOwner(vm) : callerCodeBlock;
+ JSCell* owner = isWebAssemblyToJSCallee(callerFrame->callee()) ? webAssemblyOwner(callerFrame->callee()) : callerCodeBlock;
ASSERT(owner);
ASSERT(!callLinkInfo.isLinked());
@@ -732,10 +719,10 @@
CallFrame* callerFrame = exec->callerFrame();
VM& vm = callerFrame->vm();
CodeBlock* callerCodeBlock = callerFrame->codeBlock();
- bool isWebAssembly = isWebAssemblyToJSCallee(vm, callerFrame->callee());
+ bool isWebAssembly = isWebAssemblyToJSCallee(callerFrame->callee());
// WebAssembly -> JS stubs don't have a valid CodeBlock.
- JSCell* owner = isWebAssembly ? webAssemblyOwner(vm) : callerCodeBlock;
+ JSCell* owner = isWebAssembly ? webAssemblyOwner(callerFrame->callee()) : callerCodeBlock;
ASSERT(owner);
CallVariantList list;
Modified: trunk/Source/_javascript_Core/jit/ThunkGenerators.cpp (214497 => 214498)
--- trunk/Source/_javascript_Core/jit/ThunkGenerators.cpp 2017-03-28 22:14:49 UTC (rev 214497)
+++ trunk/Source/_javascript_Core/jit/ThunkGenerators.cpp 2017-03-28 22:16:01 UTC (rev 214498)
@@ -38,7 +38,6 @@
#include "MathCommon.h"
#include "MaxFrameExtentForSlowPathCall.h"
#include "SpecializedThunkJIT.h"
-#include "WasmContext.h"
#include "WasmExceptionType.h"
#include <wtf/InlineASM.h>
#include <wtf/StringPrintStream.h>
@@ -1148,16 +1147,17 @@
}
jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+ jit.loadWasmContext(GPRInfo::argumentGPR2);
CCallHelpers::Call call = jit.call();
jit.jumpToExceptionHandler();
- void (*throwWasmException)(ExecState*, Wasm::ExceptionType) = [] (ExecState* exec, Wasm::ExceptionType type) {
+ void (*throwWasmException)(ExecState*, Wasm::ExceptionType, JSWebAssemblyInstance*) = [] (ExecState* exec, Wasm::ExceptionType type, JSWebAssemblyInstance* wasmContext) {
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
{
auto throwScope = DECLARE_THROW_SCOPE(*vm);
- JSGlobalObject* globalObject = loadWasmContext(*vm)->globalObject();
+ JSGlobalObject* globalObject = wasmContext->globalObject();
JSWebAssemblyRuntimeError* error = JSWebAssemblyRuntimeError::create(exec, *vm, globalObject->WebAssemblyRuntimeErrorStructure(), Wasm::errorMessageForExceptionType(type));
throwException(exec, throwScope, error);
Modified: trunk/Source/_javascript_Core/llint/LLIntData.cpp (214497 => 214498)
--- trunk/Source/_javascript_Core/llint/LLIntData.cpp 2017-03-28 22:14:49 UTC (rev 214497)
+++ trunk/Source/_javascript_Core/llint/LLIntData.cpp 2017-03-28 22:16:01 UTC (rev 214498)
@@ -156,21 +156,21 @@
STATIC_ASSERT(StringType == 6);
STATIC_ASSERT(SymbolType == 7);
- STATIC_ASSERT(ObjectType == 23);
- STATIC_ASSERT(FinalObjectType == 24);
- STATIC_ASSERT(JSFunctionType == 26);
- STATIC_ASSERT(ArrayType == 34);
- STATIC_ASSERT(DerivedArrayType == 35);
- STATIC_ASSERT(ProxyObjectType == 53);
- STATIC_ASSERT(Int8ArrayType == 36);
- STATIC_ASSERT(Int16ArrayType == 37);
- STATIC_ASSERT(Int32ArrayType == 38);
- STATIC_ASSERT(Uint8ArrayType == 39);
- STATIC_ASSERT(Uint8ClampedArrayType == 40);
- STATIC_ASSERT(Uint16ArrayType == 41);
- STATIC_ASSERT(Uint32ArrayType == 42);
- STATIC_ASSERT(Float32ArrayType == 43);
- STATIC_ASSERT(Float64ArrayType == 44);
+ STATIC_ASSERT(ObjectType == 24);
+ STATIC_ASSERT(FinalObjectType == 25);
+ STATIC_ASSERT(JSFunctionType == 27);
+ STATIC_ASSERT(ArrayType == 35);
+ STATIC_ASSERT(DerivedArrayType == 36);
+ STATIC_ASSERT(ProxyObjectType == 54);
+ STATIC_ASSERT(Int8ArrayType == 37);
+ STATIC_ASSERT(Int16ArrayType == 38);
+ STATIC_ASSERT(Int32ArrayType == 39);
+ STATIC_ASSERT(Uint8ArrayType == 40);
+ STATIC_ASSERT(Uint8ClampedArrayType == 41);
+ STATIC_ASSERT(Uint16ArrayType == 42);
+ STATIC_ASSERT(Uint32ArrayType == 43);
+ STATIC_ASSERT(Float32ArrayType == 44);
+ STATIC_ASSERT(Float64ArrayType == 45);
STATIC_ASSERT(MasqueradesAsUndefined == 1);
STATIC_ASSERT(ImplementsDefaultHasInstance == 2);
STATIC_ASSERT(FirstConstantRegisterIndex == 0x40000000);
Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm (214497 => 214498)
--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm 2017-03-28 22:14:49 UTC (rev 214497)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm 2017-03-28 22:16:01 UTC (rev 214498)
@@ -345,24 +345,24 @@
# Type constants.
const StringType = 6
const SymbolType = 7
-const ObjectType = 23
-const FinalObjectType = 24
-const JSFunctionType = 26
-const ArrayType = 34
-const DerivedArrayType = 35
-const ProxyObjectType = 53
+const ObjectType = 24
+const FinalObjectType = 25
+const JSFunctionType = 27
+const ArrayType = 35
+const DerivedArrayType = 36
+const ProxyObjectType = 54
# The typed array types need to be numbered in a particular order because of the manually written
# switch statement in get_by_val and put_by_val.
-const Int8ArrayType = 36
-const Int16ArrayType = 37
-const Int32ArrayType = 38
-const Uint8ArrayType = 39
-const Uint8ClampedArrayType = 40
-const Uint16ArrayType = 41
-const Uint32ArrayType = 42
-const Float32ArrayType = 43
-const Float64ArrayType = 44
+const Int8ArrayType = 37
+const Int16ArrayType = 38
+const Int32ArrayType = 39
+const Uint8ArrayType = 40
+const Uint8ClampedArrayType = 41
+const Uint16ArrayType = 42
+const Uint32ArrayType = 43
+const Float32ArrayType = 44
+const Float64ArrayType = 45
const FirstArrayType = Int8ArrayType
const LastArrayType = Float64ArrayType
Modified: trunk/Source/_javascript_Core/runtime/JSCell.cpp (214497 => 214498)
--- trunk/Source/_javascript_Core/runtime/JSCell.cpp 2017-03-28 22:14:49 UTC (rev 214497)
+++ trunk/Source/_javascript_Core/runtime/JSCell.cpp 2017-03-28 22:16:01 UTC (rev 214498)
@@ -298,7 +298,7 @@
bool JSCell::isAnyWasmCallee(VM& vm) const
{
#if ENABLE(WEBASSEMBLY)
- return inherits(vm, JSWebAssemblyCallee::info()) || inherits(vm, WebAssemblyToJSCallee::info());
+ return inherits(vm, JSWebAssemblyCallee::info()) || isWebAssemblyToJSCallee(this);
#else
UNUSED_PARAM(vm);
return false;
Modified: trunk/Source/_javascript_Core/runtime/JSCellInlines.h (214497 => 214498)
--- trunk/Source/_javascript_Core/runtime/JSCellInlines.h 2017-03-28 22:14:49 UTC (rev 214497)
+++ trunk/Source/_javascript_Core/runtime/JSCellInlines.h 2017-03-28 22:16:01 UTC (rev 214498)
@@ -346,4 +346,9 @@
return toObjectSlow(exec, globalObject);
}
+inline bool isWebAssemblyToJSCallee(const JSCell* cell)
+{
+ return cell->type() == WebAssemblyToJSCalleeType;
+}
+
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/JSType.h (214497 => 214498)
--- trunk/Source/_javascript_Core/runtime/JSType.h 2017-03-28 22:14:49 UTC (rev 214497)
+++ trunk/Source/_javascript_Core/runtime/JSType.h 2017-03-28 22:16:01 UTC (rev 214498)
@@ -53,6 +53,8 @@
JSSourceCodeType,
JSScriptFetcherType,
+ WebAssemblyToJSCalleeType,
+
// The ObjectType value must come before any JSType that is a subclass of JSObject.
ObjectType,
FinalObjectType,
Modified: trunk/Source/_javascript_Core/runtime/StackFrame.cpp (214497 => 214498)
--- trunk/Source/_javascript_Core/runtime/StackFrame.cpp 2017-03-28 22:14:49 UTC (rev 214497)
+++ trunk/Source/_javascript_Core/runtime/StackFrame.cpp 2017-03-28 22:16:01 UTC (rev 214498)
@@ -72,10 +72,10 @@
}
String name;
if (m_callee) {
+ if (m_callee->isAnyWasmCallee(*m_callee->vm()))
+ return ASCIILiteral("<wasm>");
if (m_callee->isObject())
name = getCalculatedDisplayName(vm, jsCast<JSObject*>(m_callee.get())).impl();
- else if (m_callee->isAnyWasmCallee(*m_callee->vm()))
- return ASCIILiteral("<wasm>");
}
return name.isNull() ? emptyString() : name;
}
Modified: trunk/Source/_javascript_Core/runtime/VM.cpp (214497 => 214498)
--- trunk/Source/_javascript_Core/runtime/VM.cpp 2017-03-28 22:14:49 UTC (rev 214497)
+++ trunk/Source/_javascript_Core/runtime/VM.cpp 2017-03-28 22:16:01 UTC (rev 214498)
@@ -240,7 +240,6 @@
webAssemblyCalleeStructure.set(*this, JSWebAssemblyCallee::createStructure(*this, 0, jsNull()));
webAssemblyToJSCalleeStructure.set(*this, WebAssemblyToJSCallee::createStructure(*this, 0, jsNull()));
webAssemblyCodeBlockStructure.set(*this, JSWebAssemblyCodeBlock::createStructure(*this, 0, jsNull()));
- webAssemblyToJSCallee.set(*this, WebAssemblyToJSCallee::create(*this, webAssemblyToJSCalleeStructure.get()));
#endif
moduleProgramExecutableStructure.set(*this, ModuleProgramExecutable::createStructure(*this, 0, jsNull()));
regExpStructure.set(*this, RegExp::createStructure(*this, 0, jsNull()));
Modified: trunk/Source/_javascript_Core/runtime/VM.h (214497 => 214498)
--- trunk/Source/_javascript_Core/runtime/VM.h 2017-03-28 22:14:49 UTC (rev 214497)
+++ trunk/Source/_javascript_Core/runtime/VM.h 2017-03-28 22:16:01 UTC (rev 214498)
@@ -336,7 +336,6 @@
Strong<Structure> webAssemblyCalleeStructure;
Strong<Structure> webAssemblyToJSCalleeStructure;
Strong<Structure> webAssemblyCodeBlockStructure;
- Strong<JSCell> webAssemblyToJSCallee;
#endif
Strong<Structure> moduleProgramExecutableStructure;
Strong<Structure> regExpStructure;
@@ -490,6 +489,11 @@
return OBJECT_OFFSETOF(VM, targetMachinePCForThrow);
}
+ static ptrdiff_t wasmContextOffset()
+ {
+ return OBJECT_OFFSETOF(VM, wasmContext);
+ }
+
void restorePreviousException(Exception* exception) { setException(exception); }
void clearLastException() { m_lastException = nullptr; }
Modified: trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp (214497 => 214498)
--- trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp 2017-03-28 22:14:49 UTC (rev 214497)
+++ trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp 2017-03-28 22:16:01 UTC (rev 214498)
@@ -35,6 +35,7 @@
#include "B3ConstPtrValue.h"
#include "B3FixSSA.h"
#include "B3Generate.h"
+#include "B3SlotBaseValue.h"
#include "B3StackmapGenerationParams.h"
#include "B3SwitchValue.h"
#include "B3Validate.h"
@@ -49,7 +50,6 @@
#include "JSWebAssemblyRuntimeError.h"
#include "VirtualRegister.h"
#include "WasmCallingConvention.h"
-#include "WasmContext.h"
#include "WasmExceptionType.h"
#include "WasmFunctionParser.h"
#include "WasmMemory.h"
@@ -219,6 +219,10 @@
void emitChecksForModOrDiv(B3::Opcode, ExpressionType left, ExpressionType right);
+ Value* materializeWasmContext(Procedure&, BasicBlock*);
+ void restoreWasmContext(Procedure&, BasicBlock*, Value*);
+ void restoreWebAssemblyGlobalState(const MemoryInformation&, Value* instance, Procedure&, BasicBlock*);
+
VM& m_vm;
const ModuleInformation& m_info;
Procedure& m_proc;
@@ -227,35 +231,63 @@
Vector<UnlinkedWasmToWasmCall>& m_unlinkedWasmToWasmCalls; // List each call site and the function index whose address it should be patched with.
GPRReg m_memoryBaseGPR;
GPRReg m_memorySizeGPR;
+ GPRReg m_wasmContextGPR;
Value* m_zeroValues[numTypes];
Value* m_instanceValue; // FIXME: make this lazy https://bugs.webkit.org/show_bug.cgi?id=169792
};
-static Value* loadWasmContext(Procedure& proc, BasicBlock* block)
+Value* B3IRGenerator::materializeWasmContext(Procedure& proc, BasicBlock* block)
{
+ if (useFastTLSForWasmContext()) {
+ 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 patchpoint;
+ }
+
+ // FIXME: Because WasmToWasm call clobbers wasmContext register and does not restore it, we need to restore it in the caller side.
+ // This prevents us from using ArgumentReg to this (logically) immutable pinned register.
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);
+ patchpoint->effects.writesPinned = false;
+ patchpoint->effects.readsPinned = true;
+ patchpoint->resultConstraint = ValueRep::reg(m_wasmContextGPR);
+ patchpoint->setGenerator([] (CCallHelpers&, const StackmapGenerationParams&) { });
+ return patchpoint;
}
-static void storeWasmContext(Procedure& proc, BasicBlock* block, Value* arg)
+void B3IRGenerator::restoreWasmContext(Procedure& proc, BasicBlock* block, Value* arg)
{
+ if (useFastTLSForWasmContext()) {
+ 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());
+ });
+ return;
+ }
+
+ // FIXME: Because WasmToWasm call clobbers wasmContext register and does not restore it, we need to restore it in the caller side.
+ // This prevents us from using ArgumentReg to this (logically) immutable pinned register.
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());
- });
+ Effects effects = Effects::none();
+ effects.writesPinned = true;
+ effects.reads = B3::HeapRange::top();
+ patchpoint->effects = effects;
+ patchpoint->clobberLate(RegisterSet(m_wasmContextGPR));
+ patchpoint->append(m_instanceValue, ValueRep::SomeRegister);
+ GPRReg wasmContextGPR = m_wasmContextGPR;
+ patchpoint->setGenerator([=] (CCallHelpers& jit, const StackmapGenerationParams& param) {
+ jit.move(param[0].gpr(), wasmContextGPR);
+ });
}
B3IRGenerator::B3IRGenerator(VM& vm, const ModuleInformation& info, Procedure& procedure, WasmInternalFunction* compilation, Vector<UnlinkedWasmToWasmCall>& unlinkedWasmToWasmCalls)
@@ -283,7 +315,10 @@
// FIXME we don't really need to pin registers here if there's no memory. It makes wasm -> wasm thunks simpler for now. https://bugs.webkit.org/show_bug.cgi?id=166623
const PinnedRegisterInfo& pinnedRegs = PinnedRegisterInfo::get();
m_memoryBaseGPR = pinnedRegs.baseMemoryPointer;
+ m_wasmContextGPR = pinnedRegs.wasmContextPointer;
m_proc.pinRegister(m_memoryBaseGPR);
+ if (!useFastTLSForWasmContext())
+ m_proc.pinRegister(m_wasmContextGPR);
ASSERT(!pinnedRegs.sizeRegisters[0].sizeOffset);
m_memorySizeGPR = pinnedRegs.sizeRegisters[0].sizeRegister;
for (const PinnedSizeRegisterInfo& regInfo : pinnedRegs.sizeRegisters)
@@ -299,7 +334,7 @@
wasmCallingConvention().setupFrameInPrologue(&compilation->wasmCalleeMoveLocation, m_proc, Origin(), m_currentBlock);
- m_instanceValue = loadWasmContext(m_proc, m_currentBlock);
+ m_instanceValue = materializeWasmContext(m_proc, m_currentBlock);
}
struct MemoryBaseAndSize {
@@ -307,12 +342,12 @@
Value* size;
};
-static MemoryBaseAndSize getMemoryBaseAndSize(VM& vm, Value* instance, Procedure& proc, BasicBlock* block)
+static MemoryBaseAndSize getMemoryBaseAndSize(Value* instance, Procedure& proc, BasicBlock* block)
{
Value* memoryObject = block->appendNew<MemoryValue>(proc, Load, pointerType(), Origin(), instance, JSWebAssemblyInstance::offsetOfMemory());
- 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");
+ static_assert(sizeof(decltype(static_cast<JSWebAssemblyInstance*>(nullptr)->memory()->memory().memory())) == sizeof(void*), "codegen relies on this size");
+ static_assert(sizeof(decltype(static_cast<JSWebAssemblyInstance*>(nullptr)->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());
@@ -320,9 +355,9 @@
return result;
}
-static void restoreWebAssemblyGlobalState(const MemoryInformation& memory, Value* instance, Procedure& proc, BasicBlock* block)
+void B3IRGenerator::restoreWebAssemblyGlobalState(const MemoryInformation& memory, Value* instance, Procedure& proc, BasicBlock* block)
{
- storeWasmContext(proc, block, instance);
+ restoreWasmContext(proc, block, instance);
if (!!memory) {
const PinnedRegisterInfo* pinnedRegs = &PinnedRegisterInfo::get();
@@ -392,7 +427,7 @@
m_locals.grow(signature->argumentCount());
wasmCallingConvention().loadArguments(signature, m_proc, m_currentBlock, Origin(),
- [&] (ExpressionType argument, unsigned i) {
+ [=] (ExpressionType argument, unsigned i) {
Variable* argumentVariable = m_proc.addVariable(argument->type());
m_locals[i] = argumentVariable;
m_currentBlock->appendNew<VariableValue>(m_proc, Set, Origin(), argumentVariable, argument);
@@ -419,12 +454,11 @@
auto B3IRGenerator::addGrowMemory(ExpressionType delta, ExpressionType& result) -> PartialResult
{
- int32_t (*growMemory) (ExecState*, int32_t) = [] (ExecState* exec, int32_t delta) -> int32_t {
+ int32_t (*growMemory) (ExecState*, JSWebAssemblyInstance*, int32_t) = [] (ExecState* exec, JSWebAssemblyInstance* wasmContext, int32_t delta) -> int32_t {
VM& vm = exec->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
- JSWebAssemblyInstance* instance = loadWasmContext(vm);
- JSWebAssemblyMemory* wasmMemory = instance->memory();
+ JSWebAssemblyMemory* wasmMemory = wasmContext->memory();
if (delta < 0)
return -1;
@@ -440,7 +474,7 @@
result = m_currentBlock->appendNew<CCallValue>(m_proc, Int32, Origin(),
m_currentBlock->appendNew<ConstPtrValue>(m_proc, Origin(), bitwise_cast<void*>(growMemory)),
- m_currentBlock->appendNew<B3::Value>(m_proc, B3::FramePointer, Origin()), delta);
+ m_currentBlock->appendNew<B3::Value>(m_proc, B3::FramePointer, Origin()), m_instanceValue, delta);
restoreWebAssemblyGlobalState(m_info.memory, m_instanceValue, m_proc, m_currentBlock);
@@ -449,7 +483,7 @@
auto B3IRGenerator::addCurrentMemory(ExpressionType& result) -> PartialResult
{
- auto memoryValue = getMemoryBaseAndSize(m_vm, m_instanceValue, m_proc, m_currentBlock);
+ auto memoryValue = getMemoryBaseAndSize(m_instanceValue, m_proc, m_currentBlock);
constexpr uint32_t shiftValue = 16;
static_assert(PageCount::pageSize == 1 << shiftValue, "This must hold for the code below to be correct.");
@@ -889,9 +923,10 @@
m_currentBlock->appendNewControlValue(m_proc, B3::Branch, Origin(), isWasmCall, FrequentedBlock(isWasmBlock), FrequentedBlock(isJSBlock));
Value* wasmCallResult = wasmCallingConvention().setupCall(m_proc, isWasmBlock, Origin(), args, toB3Type(returnType),
- [&] (PatchpointValue* patchpoint) {
+ [=] (PatchpointValue* patchpoint) {
patchpoint->effects.writesPinned = true;
patchpoint->effects.readsPinned = true;
+ patchpoint->clobberLate(PinnedRegisterInfo::get().toSave());
patchpoint->setGenerator([unlinkedWasmToWasmCalls, functionIndex] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
AllowMacroScratchRegisterUsage allowScratch(jit);
CCallHelpers::Call call = jit.call();
@@ -904,9 +939,10 @@
isWasmBlock->appendNewControlValue(m_proc, Jump, Origin(), continuation);
Value* jsCallResult = wasmCallingConvention().setupCall(m_proc, isJSBlock, Origin(), args, toB3Type(returnType),
- [&] (PatchpointValue* patchpoint) {
+ [=] (PatchpointValue* patchpoint) {
patchpoint->effects.writesPinned = true;
patchpoint->effects.readsPinned = true;
+ patchpoint->clobberLate(PinnedRegisterInfo::get().toSave());
patchpoint->setGenerator([unlinkedWasmToWasmCalls, functionIndex] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
AllowMacroScratchRegisterUsage allowScratch(jit);
CCallHelpers::Call call = jit.call();
@@ -932,9 +968,10 @@
restoreWebAssemblyGlobalState(m_info.memory, m_instanceValue, m_proc, continuation);
} else {
result = wasmCallingConvention().setupCall(m_proc, m_currentBlock, Origin(), args, toB3Type(returnType),
- [&] (PatchpointValue* patchpoint) {
+ [=] (PatchpointValue* patchpoint) {
patchpoint->effects.writesPinned = true;
patchpoint->effects.readsPinned = true;
+
patchpoint->setGenerator([unlinkedWasmToWasmCalls, functionIndex] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
AllowMacroScratchRegisterUsage allowScratch(jit);
CCallHelpers::Call call = jit.call();
@@ -1010,12 +1047,12 @@
Type returnType = signature->returnType();
result = wasmCallingConvention().setupCall(m_proc, m_currentBlock, Origin(), args, toB3Type(returnType),
- [&] (PatchpointValue* patchpoint) {
+ [=] (PatchpointValue* patchpoint) {
patchpoint->effects.writesPinned = true;
patchpoint->effects.readsPinned = true;
+ patchpoint->clobberLate(PinnedRegisterInfo::get().toSave());
patchpoint->append(calleeCode, ValueRep::SomeRegister);
-
patchpoint->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
AllowMacroScratchRegisterUsage allowScratch(jit);
jit.call(params[returnType == Void ? 0 : 1].gpr());
@@ -1080,11 +1117,8 @@
*linkedCalleeMove = linkBuffer.locationOf(calleeMoveLocation);
});
- RegisterSet toSave;
const PinnedRegisterInfo& pinnedRegs = PinnedRegisterInfo::get();
- toSave.set(pinnedRegs.baseMemoryPointer);
- for (const PinnedSizeRegisterInfo& regInfo : pinnedRegs.sizeRegisters)
- toSave.set(regInfo.sizeRegister);
+ RegisterSet toSave = pinnedRegs.toSave();
#if !ASSERT_DISABLED
unsigned toSaveSize = toSave.numberOfSetGPRs();
@@ -1191,10 +1225,25 @@
}
}
+ // FIXME: JStoWasm wrapper should take JSWebAssemblyInstance pointer as an argument directly.
+ // https://bugs.webkit.org/show_bug.cgi?id=170182
+ GPRReg wasmContext = pinnedRegs.wasmContextPointer;
+ if (!useFastTLSForWasmContext()) {
+ jit.loadPtr(CCallHelpers::Address(GPRInfo::callFrameRegister, CallFrameSlot::callee * static_cast<int>(sizeof(Register))), wasmContext);
+ jit.andPtr(CCallHelpers::TrustedImmPtr(MarkedBlock::blockMask), wasmContext);
+ jit.loadPtr(CCallHelpers::Address(wasmContext, MarkedBlock::offsetOfVM()), wasmContext);
+ jit.loadPtr(CCallHelpers::Address(wasmContext, VM::wasmContextOffset()), wasmContext);
+ }
+
if (!!info.memory) {
GPRReg baseMemory = pinnedRegs.baseMemoryPointer;
- jit.loadWasmContext(baseMemory);
- jit.loadPtr(CCallHelpers::Address(baseMemory, JSWebAssemblyInstance::offsetOfMemory()), baseMemory);
+
+ if (!useFastTLSForWasmContext())
+ jit.loadPtr(CCallHelpers::Address(wasmContext, JSWebAssemblyInstance::offsetOfMemory()), baseMemory);
+ else {
+ jit.loadWasmContext(baseMemory);
+ jit.loadPtr(CCallHelpers::Address(baseMemory, JSWebAssemblyInstance::offsetOfMemory()), baseMemory);
+ }
const auto& sizeRegs = pinnedRegs.sizeRegisters;
ASSERT(sizeRegs.size() >= 1);
ASSERT(!sizeRegs[0].sizeOffset); // The following code assumes we start at 0, and calculates subsequent size registers relative to 0.
Modified: trunk/Source/_javascript_Core/wasm/WasmBinding.cpp (214497 => 214498)
--- trunk/Source/_javascript_Core/wasm/WasmBinding.cpp 2017-03-28 22:14:49 UTC (rev 214497)
+++ trunk/Source/_javascript_Core/wasm/WasmBinding.cpp 2017-03-28 22:16:01 UTC (rev 214498)
@@ -36,7 +36,6 @@
#include "LinkBuffer.h"
#include "NativeErrorConstructor.h"
#include "WasmCallingConvention.h"
-#include "WasmContext.h"
#include "WasmExceptionType.h"
namespace JSC { namespace Wasm {
@@ -66,9 +65,7 @@
jit.emitFunctionPrologue();
jit.store64(JIT::TrustedImm32(0), JIT::Address(GPRInfo::callFrameRegister, CallFrameSlot::codeBlock * static_cast<int>(sizeof(Register)))); // FIXME Stop using 0 as codeBlocks. https://bugs.webkit.org/show_bug.cgi?id=165321
- jit.storePtr(JIT::TrustedImmPtr(vm->webAssemblyToJSCallee.get()), JIT::Address(GPRInfo::callFrameRegister, CallFrameSlot::callee * static_cast<int>(sizeof(Register))));
-
{
bool hasBadI64Use = false;
hasBadI64Use |= signature->returnType() == I64;
@@ -93,16 +90,22 @@
if (hasBadI64Use) {
jit.copyCalleeSavesToVMEntryFrameCalleeSavesBuffer();
jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+ jit.loadWasmContext(GPRInfo::argumentGPR1);
+
+ // Store Callee.
+ jit.loadPtr(CCallHelpers::Address(GPRInfo::argumentGPR1, JSWebAssemblyInstance::offsetOfCallee()), GPRInfo::argumentGPR2);
+ jit.storePtr(GPRInfo::argumentGPR2, JIT::Address(GPRInfo::callFrameRegister, CallFrameSlot::callee * static_cast<int>(sizeof(Register))));
+
auto call = jit.call();
jit.jumpToExceptionHandler();
- void (*throwBadI64)(ExecState*) = [] (ExecState* exec) -> void {
+ void (*throwBadI64)(ExecState*, JSWebAssemblyInstance*) = [] (ExecState* exec, JSWebAssemblyInstance* wasmContext) -> void {
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
{
auto throwScope = DECLARE_THROW_SCOPE(*vm);
- JSGlobalObject* globalObject = loadWasmContext(*vm)->globalObject();
+ JSGlobalObject* globalObject = wasmContext->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);
}
@@ -252,6 +255,10 @@
}
}
+ jit.loadWasmContext(GPRInfo::argumentGPR0);
+ jit.loadPtr(CCallHelpers::Address(GPRInfo::argumentGPR0, JSWebAssemblyInstance::offsetOfCallee()), GPRInfo::argumentGPR0);
+ jit.storePtr(GPRInfo::argumentGPR0, JIT::Address(GPRInfo::callFrameRegister, CallFrameSlot::callee * static_cast<int>(sizeof(Register))));
+
GPRReg importJSCellGPRReg = GPRInfo::regT0; // Callee needs to be in regT0 for slow path below.
ASSERT(!wasmCC.m_calleeSaveRegisters.get(importJSCellGPRReg));
Modified: trunk/Source/_javascript_Core/wasm/WasmContext.cpp (214497 => 214498)
--- trunk/Source/_javascript_Core/wasm/WasmContext.cpp 2017-03-28 22:14:49 UTC (rev 214497)
+++ trunk/Source/_javascript_Core/wasm/WasmContext.cpp 2017-03-28 22:16:01 UTC (rev 214498)
@@ -34,17 +34,17 @@
namespace JSC {
-JSWebAssemblyInstance* loadWasmContext(VM& vm)
+WasmContext* loadWasmContext(VM& vm)
{
#if ENABLE(FAST_TLS_JIT)
if (Options::useWebAssemblyFastTLS())
- return bitwise_cast<JSWebAssemblyInstance*>(_pthread_getspecific_direct(WTF_WASM_CONTEXT_KEY));
+ return bitwise_cast<WasmContext*>(_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)
+void storeWasmContext(VM& vm, WasmContext* instance)
{
#if ENABLE(FAST_TLS_JIT)
if (Options::useWebAssemblyFastTLS())
Modified: trunk/Source/_javascript_Core/wasm/WasmContext.h (214497 => 214498)
--- trunk/Source/_javascript_Core/wasm/WasmContext.h 2017-03-28 22:14:49 UTC (rev 214497)
+++ trunk/Source/_javascript_Core/wasm/WasmContext.h 2017-03-28 22:16:01 UTC (rev 214498)
@@ -32,9 +32,11 @@
class JSWebAssemblyInstance;
class VM;
-JSWebAssemblyInstance* loadWasmContext(VM&);
-void storeWasmContext(VM&, JSWebAssemblyInstance*);
+using WasmContext = JSWebAssemblyInstance;
+WasmContext* loadWasmContext(VM&);
+void storeWasmContext(VM&, WasmContext*);
+
} // namespace JSC
#endif // ENABLE(WEBASSEMBLY)
Modified: trunk/Source/_javascript_Core/wasm/WasmMemoryInformation.cpp (214497 => 214498)
--- trunk/Source/_javascript_Core/wasm/WasmMemoryInformation.cpp 2017-03-28 22:14:49 UTC (rev 214497)
+++ trunk/Source/_javascript_Core/wasm/WasmMemoryInformation.cpp 2017-03-28 22:16:01 UTC (rev 214498)
@@ -34,6 +34,21 @@
namespace JSC { namespace Wasm {
+static Vector<GPRReg> getPinnedRegisters(unsigned remainingPinnedRegisters)
+{
+ Vector<GPRReg> registers;
+ jscCallingConvention().m_calleeSaveRegisters.forEach([&] (Reg reg) {
+ if (!reg.isGPR())
+ return;
+ GPRReg gpr = reg.gpr();
+ if (!remainingPinnedRegisters || RegisterSet::stackRegisters().get(reg))
+ return;
+ --remainingPinnedRegisters;
+ registers.append(gpr);
+ });
+ return registers;
+}
+
const PinnedRegisterInfo& PinnedRegisterInfo::get()
{
static LazyNeverDestroyed<PinnedRegisterInfo> staticPinnedRegisterInfo;
@@ -40,7 +55,8 @@
static std::once_flag staticPinnedRegisterInfoFlag;
std::call_once(staticPinnedRegisterInfoFlag, [] () {
Vector<PinnedSizeRegisterInfo> sizeRegisters;
- GPRReg baseMemoryPointer;
+ GPRReg baseMemoryPointer = InvalidGPRReg;
+ GPRReg wasmContextPointer = InvalidGPRReg;
// FIXME: We should support more than one memory size register, and we should allow different
// WebAssembly.Instance to have different pins. Right now we take a vector with only one entry.
@@ -47,30 +63,28 @@
// If we have more than one size register, we can have one for each load size class.
// see: https://bugs.webkit.org/show_bug.cgi?id=162952
Vector<unsigned> pinnedSizes = { 0 };
- unsigned remainingPinnedRegisters = pinnedSizes.size() + 1;
- jscCallingConvention().m_calleeSaveRegisters.forEach([&] (Reg reg) {
- if (!reg.isGPR())
- return;
- GPRReg gpr = reg.gpr();
- if (!remainingPinnedRegisters || RegisterSet::stackRegisters().get(reg))
- return;
- if (remainingPinnedRegisters == 1) {
- baseMemoryPointer = gpr;
- remainingPinnedRegisters--;
- } else
- sizeRegisters.append({ gpr, pinnedSizes[--remainingPinnedRegisters - 1] });
- });
+ unsigned numberOfPinnedRegisters = pinnedSizes.size() + 1;
+ if (!useFastTLSForWasmContext())
+ ++numberOfPinnedRegisters;
+ Vector<GPRReg> pinnedRegs = getPinnedRegisters(numberOfPinnedRegisters);
- ASSERT(!remainingPinnedRegisters);
- staticPinnedRegisterInfo.construct(WTFMove(sizeRegisters), baseMemoryPointer);
+ baseMemoryPointer = pinnedRegs.takeLast();
+ if (!useFastTLSForWasmContext())
+ wasmContextPointer = pinnedRegs.takeLast();
+
+ ASSERT(pinnedSizes.size() == pinnedRegs.size());
+ for (unsigned i = 0; i < pinnedSizes.size(); ++i)
+ sizeRegisters.append({ pinnedRegs[i], pinnedSizes[i] });
+ staticPinnedRegisterInfo.construct(WTFMove(sizeRegisters), baseMemoryPointer, wasmContextPointer);
});
return staticPinnedRegisterInfo.get();
}
-PinnedRegisterInfo::PinnedRegisterInfo(Vector<PinnedSizeRegisterInfo>&& sizeRegisters, GPRReg baseMemoryPointer)
+PinnedRegisterInfo::PinnedRegisterInfo(Vector<PinnedSizeRegisterInfo>&& sizeRegisters, GPRReg baseMemoryPointer, GPRReg wasmContextPointer)
: sizeRegisters(WTFMove(sizeRegisters))
, baseMemoryPointer(baseMemoryPointer)
+ , wasmContextPointer(wasmContextPointer)
{
}
Modified: trunk/Source/_javascript_Core/wasm/WasmMemoryInformation.h (214497 => 214498)
--- trunk/Source/_javascript_Core/wasm/WasmMemoryInformation.h 2017-03-28 22:14:49 UTC (rev 214497)
+++ trunk/Source/_javascript_Core/wasm/WasmMemoryInformation.h 2017-03-28 22:16:01 UTC (rev 214498)
@@ -28,6 +28,7 @@
#if ENABLE(WEBASSEMBLY)
#include "GPRInfo.h"
+#include "RegisterSet.h"
#include "WasmMemory.h"
#include "WasmPageCount.h"
#include <wtf/Ref.h>
@@ -43,8 +44,20 @@
struct PinnedRegisterInfo {
Vector<PinnedSizeRegisterInfo> sizeRegisters;
GPRReg baseMemoryPointer;
+ GPRReg wasmContextPointer;
static const PinnedRegisterInfo& get();
- PinnedRegisterInfo(Vector<PinnedSizeRegisterInfo>&&, GPRReg);
+ PinnedRegisterInfo(Vector<PinnedSizeRegisterInfo>&&, GPRReg, GPRReg);
+
+ RegisterSet toSave() const
+ {
+ RegisterSet result;
+ result.set(baseMemoryPointer);
+ if (wasmContextPointer != InvalidGPRReg)
+ result.set(wasmContextPointer);
+ for (const auto& info : sizeRegisters)
+ result.set(info.sizeRegister);
+ return result;
+ }
};
class MemoryInformation {
@@ -73,6 +86,20 @@
bool m_isImport { false };
};
+inline bool useFastTLS()
+{
+#if ENABLE(FAST_TLS_JIT)
+ return Options::useWebAssemblyFastTLS();
+#else
+ return false;
+#endif
+}
+
+inline bool useFastTLSForWasmContext()
+{
+ return useFastTLS();
+}
+
} } // namespace JSC::Wasm
#endif // ENABLE(WASM)
Modified: trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyInstance.cpp (214497 => 214498)
--- trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyInstance.cpp 2017-03-28 22:14:49 UTC (rev 214497)
+++ trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyInstance.cpp 2017-03-28 22:16:01 UTC (rev 214498)
@@ -34,6 +34,7 @@
#include "JSModuleNamespaceObject.h"
#include "JSWebAssemblyMemory.h"
#include "JSWebAssemblyModule.h"
+#include "WebAssemblyToJSCallee.h"
#include <wtf/StdLibExtras.h>
namespace JSC {
@@ -81,6 +82,7 @@
m_codeBlock.set(vm, this, module->codeBlock());
m_moduleNamespaceObject.set(vm, this, moduleNamespaceObject);
+ m_callee.set(vm, this, module->callee());
putDirect(vm, Identifier::fromString(&vm, "exports"), moduleNamespaceObject, None);
}
@@ -99,6 +101,7 @@
visitor.append(thisObject->m_moduleNamespaceObject);
visitor.append(thisObject->m_memory);
visitor.append(thisObject->m_table);
+ visitor.append(thisObject->m_callee);
visitor.reportExtraMemoryVisited(thisObject->module()->moduleInformation().globals.size());
for (unsigned i = 0; i < thisObject->m_numImportFunctions; ++i)
visitor.append(*thisObject->importFunction(i));
Modified: trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyInstance.h (214497 => 214498)
--- trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyInstance.h 2017-03-28 22:14:49 UTC (rev 214497)
+++ trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyInstance.h 2017-03-28 22:16:01 UTC (rev 214498)
@@ -37,6 +37,7 @@
class JSModuleNamespaceObject;
class JSWebAssemblyModule;
+class WebAssemblyToJSCallee;
class JSWebAssemblyInstance : public JSDestructibleObject {
public:
@@ -97,6 +98,7 @@
static ptrdiff_t offsetOfMemory() { return OBJECT_OFFSETOF(JSWebAssemblyInstance, m_memory); }
static ptrdiff_t offsetOfTable() { return OBJECT_OFFSETOF(JSWebAssemblyInstance, m_table); }
+ static ptrdiff_t offsetOfCallee() { return OBJECT_OFFSETOF(JSWebAssemblyInstance, m_callee); }
static ptrdiff_t offsetOfGlobals() { return OBJECT_OFFSETOF(JSWebAssemblyInstance, m_globals); }
static size_t offsetOfImportFunctions() { return WTF::roundUpToMultipleOf<sizeof(WriteBarrier<JSCell>)>(sizeof(JSWebAssemblyInstance)); }
static size_t offsetOfImportFunction(size_t importFunctionNum) { return offsetOfImportFunctions() + importFunctionNum * sizeof(sizeof(WriteBarrier<JSCell>)); }
@@ -117,6 +119,7 @@
WriteBarrier<JSModuleNamespaceObject> m_moduleNamespaceObject;
WriteBarrier<JSWebAssemblyMemory> m_memory;
WriteBarrier<JSWebAssemblyTable> m_table;
+ WriteBarrier<WebAssemblyToJSCallee> m_callee;
MallocPtr<uint64_t> m_globals;
unsigned m_numImportFunctions;
};
Modified: trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyModule.cpp (214497 => 214498)
--- trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyModule.cpp 2017-03-28 22:14:49 UTC (rev 214497)
+++ trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyModule.cpp 2017-03-28 22:16:01 UTC (rev 214498)
@@ -36,6 +36,7 @@
#include "WasmFormat.h"
#include "WasmMemory.h"
#include "WasmPlan.h"
+#include "WebAssemblyToJSCallee.h"
#include <wtf/StdLibExtras.h>
namespace JSC {
@@ -132,6 +133,7 @@
m_sourceBuffer = ArrayBuffer::create(source, byteSize);
m_moduleInformation = plan.takeModuleInformation();
m_exportSymbolTable.set(vm, this, exportSymbolTable);
+ m_callee.set(vm, this, WebAssemblyToJSCallee::create(vm, vm.webAssemblyToJSCalleeStructure.get(), this));
codeBlockFor(codeBlock->mode()).set(vm, this, codeBlock);
}
@@ -147,6 +149,7 @@
Base::visitChildren(thisObject, visitor);
visitor.append(thisObject->m_exportSymbolTable);
+ visitor.append(thisObject->m_callee);
for (unsigned i = 0; i < Wasm::NumberOfMemoryModes; ++i)
visitor.append(thisObject->m_codeBlocks[i]);
}
Modified: trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyModule.h (214497 => 214498)
--- trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyModule.h 2017-03-28 22:14:49 UTC (rev 214497)
+++ trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyModule.h 2017-03-28 22:16:01 UTC (rev 214498)
@@ -43,6 +43,7 @@
class SymbolTable;
class JSWebAssemblyMemory;
+class WebAssemblyToJSCallee;
class JSWebAssemblyModule : public JSDestructibleObject {
public:
@@ -60,6 +61,7 @@
{
return m_moduleInformation->signatureIndexFromFunctionIndexSpace(functionIndexSpace);
}
+ WebAssemblyToJSCallee* callee() const { return m_callee.get(); }
// Returns the code block that this module was originally compiled expecting to use. This won't need to recompile.
JSWebAssemblyCodeBlock* codeBlock() { return codeBlockFor(m_moduleInformation->memory.mode()).get(); }
@@ -79,6 +81,7 @@
std::unique_ptr<Wasm::ModuleInformation> m_moduleInformation;
WriteBarrier<SymbolTable> m_exportSymbolTable;
WriteBarrier<JSWebAssemblyCodeBlock> m_codeBlocks[Wasm::NumberOfMemoryModes];
+ WriteBarrier<WebAssemblyToJSCallee> m_callee;
};
} // namespace JSC
Modified: trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunction.cpp (214497 => 214498)
--- trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunction.cpp 2017-03-28 22:14:49 UTC (rev 214497)
+++ trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunction.cpp 2017-03-28 22:16:01 UTC (rev 214498)
@@ -42,6 +42,7 @@
#include "WasmContext.h"
#include "WasmFormat.h"
#include "WasmMemory.h"
+#include <wtf/FastTLS.h>
#include <wtf/SystemTracing.h>
namespace JSC {
@@ -121,6 +122,10 @@
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
+ // FIXME: We would like to make loadWasmContext and storeWasmContext no-op if we use pinned registers.
+ // However, we use VM.wasmContext field to pass instance to wasm function's JS glue code.
+ // We should pass JSWebAssemblyInstance directly to vmEntryToWasm.
+ // https://bugs.webkit.org/show_bug.cgi?id=170182
JSWebAssemblyInstance* prevJSWebAssemblyInstance = loadWasmContext(vm);
storeWasmContext(vm, wasmFunction->instance());
ASSERT(wasmFunction->instance());
@@ -153,6 +158,7 @@
Structure* structure = globalObject->webAssemblyFunctionStructure();
WebAssemblyFunction* function = new (NotNull, allocateCell<WebAssemblyFunction>(vm.heap)) WebAssemblyFunction(vm, globalObject, structure, wasmEntrypoint, signatureIndex);
function->finishCreation(vm, executable, length, name, instance, jsEntrypoint, wasmEntrypoint);
+ ASSERT_WITH_MESSAGE(!function->isLargeAllocation(), "WebAssemblyFunction should be allocated not in large allocation since it is JSCallee.");
return function;
}
Modified: trunk/Source/_javascript_Core/wasm/js/WebAssemblyToJSCallee.cpp (214497 => 214498)
--- trunk/Source/_javascript_Core/wasm/js/WebAssemblyToJSCallee.cpp 2017-03-28 22:14:49 UTC (rev 214497)
+++ trunk/Source/_javascript_Core/wasm/js/WebAssemblyToJSCallee.cpp 2017-03-28 22:16:01 UTC (rev 214498)
@@ -29,21 +29,22 @@
#if ENABLE(WEBASSEMBLY)
#include "JSCInlines.h"
+#include "JSWebAssemblyModule.h"
namespace JSC {
const ClassInfo WebAssemblyToJSCallee::s_info = { "WebAssemblyToJSCallee", nullptr, 0, CREATE_METHOD_TABLE(WebAssemblyToJSCallee) };
-WebAssemblyToJSCallee* WebAssemblyToJSCallee::create(VM& vm, Structure* structure)
+WebAssemblyToJSCallee* WebAssemblyToJSCallee::create(VM& vm, Structure* structure, JSWebAssemblyModule* module)
{
WebAssemblyToJSCallee* callee = new (NotNull, allocateCell<WebAssemblyToJSCallee>(vm.heap)) WebAssemblyToJSCallee(vm, structure);
- callee->finishCreation(vm);
+ callee->finishCreation(vm, module);
return callee;
}
Structure* WebAssemblyToJSCallee::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
{
- return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info());
+ return Structure::create(vm, globalObject, prototype, TypeInfo(WebAssemblyToJSCalleeType, StructureFlags), info());
}
WebAssemblyToJSCallee::WebAssemblyToJSCallee(VM& vm, Structure* structure)
@@ -51,15 +52,19 @@
{
}
-void WebAssemblyToJSCallee::finishCreation(VM& vm)
+void WebAssemblyToJSCallee::finishCreation(VM& vm, JSWebAssemblyModule* module)
{
Base::finishCreation(vm);
+ m_module.set(vm, this, module);
}
-void WebAssemblyToJSCallee::destroy(JSCell* cell)
+void WebAssemblyToJSCallee::visitChildren(JSCell* cell, SlotVisitor& visitor)
{
- WebAssemblyToJSCallee* thisObject = static_cast<WebAssemblyToJSCallee*>(cell);
- thisObject->WebAssemblyToJSCallee::~WebAssemblyToJSCallee();
+ auto* thisObject = jsCast<WebAssemblyToJSCallee*>(cell);
+ ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+
+ Base::visitChildren(thisObject, visitor);
+ visitor.append(thisObject->m_module);
}
} // namespace JSC
Modified: trunk/Source/_javascript_Core/wasm/js/WebAssemblyToJSCallee.h (214497 => 214498)
--- trunk/Source/_javascript_Core/wasm/js/WebAssemblyToJSCallee.h 2017-03-28 22:14:49 UTC (rev 214497)
+++ trunk/Source/_javascript_Core/wasm/js/WebAssemblyToJSCallee.h 2017-03-28 22:16:01 UTC (rev 214498)
@@ -31,21 +31,27 @@
namespace JSC {
-class WebAssemblyToJSCallee : public JSCell {
+class JSWebAssemblyModule;
+
+class WebAssemblyToJSCallee final : public JSCell {
public:
typedef JSCell Base;
static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
- static WebAssemblyToJSCallee* create(VM&, Structure*);
+ static WebAssemblyToJSCallee* create(VM&, Structure*, JSWebAssemblyModule*);
static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
DECLARE_EXPORT_INFO;
- static const bool needsDestruction = true;
- static void destroy(JSCell*);
+ static void visitChildren(JSCell*, SlotVisitor&);
+
+ JSWebAssemblyModule* module() { return m_module.get(); }
+
private:
- void finishCreation(VM&);
+ void finishCreation(VM&, JSWebAssemblyModule*);
WebAssemblyToJSCallee(VM&, Structure*);
+
+ WriteBarrier<JSWebAssemblyModule> m_module;
};
} // namespace JSC