Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (214710 => 214711)
--- trunk/Source/_javascript_Core/ChangeLog 2017-04-01 02:05:01 UTC (rev 214710)
+++ trunk/Source/_javascript_Core/ChangeLog 2017-04-01 02:09:51 UTC (rev 214711)
@@ -1,3 +1,39 @@
+2017-03-31 Saam Barati <[email protected]>
+
+ WebAssembly: Make our calls out to JS PIC friendly
+ https://bugs.webkit.org/show_bug.cgi?id=170261
+
+ Reviewed by Keith Miller.
+
+ This patch removes a direct call from the module to the Wasm to JS stub.
+ Instead, we do an indirect call to the stub by loading the stub's executable
+ address off of the CodeBlock. This is to make the code we emit for comply with
+ requirements needed for PIC.
+
+ Adding this indirection is not ideal. Although this patch is neutral on
+ WasmBench, we really want to get back to a world where we have an IC
+ call infrastructure. This patch is obviously a regression on some
+ types of programs. I've filed this bug to make sure we implement a
+ PIC compliant Wasm to JS call IC:
+ https://bugs.webkit.org/show_bug.cgi?id=170375
+
+ * wasm/WasmB3IRGenerator.cpp:
+ * wasm/WasmFormat.h:
+ * wasm/WasmPlan.cpp:
+ (JSC::Wasm::Plan::complete):
+ * wasm/js/JSWebAssemblyCodeBlock.cpp:
+ (JSC::JSWebAssemblyCodeBlock::initialize):
+ * wasm/js/JSWebAssemblyCodeBlock.h:
+ (JSC::JSWebAssemblyCodeBlock::create):
+ (JSC::JSWebAssemblyCodeBlock::offsetOfImportWasmToJSStub):
+ (JSC::JSWebAssemblyCodeBlock::offsetOfCallees):
+ (JSC::JSWebAssemblyCodeBlock::allocationSize):
+ (JSC::JSWebAssemblyCodeBlock::importWasmToJSStub):
+ * wasm/js/JSWebAssemblyInstance.cpp:
+ (JSC::JSWebAssemblyInstance::addUnitializedCodeBlock):
+ * wasm/js/JSWebAssemblyInstance.h:
+ (JSC::JSWebAssemblyInstance::offsetOfCodeBlock):
+
2017-03-31 Keith Miller <[email protected]>
WebAssembly: webAssemblyB3OptimizationLevel should use defaultB3OptLevel by default
Modified: trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp (214710 => 214711)
--- trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp 2017-04-01 02:05:01 UTC (rev 214710)
+++ trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp 2017-04-01 02:09:51 UTC (rev 214711)
@@ -908,7 +908,7 @@
AllowMacroScratchRegisterUsage allowScratch(jit);
CCallHelpers::Call call = jit.call();
jit.addLinkTask([unlinkedWasmToWasmCalls, call, functionIndex] (LinkBuffer& linkBuffer) {
- unlinkedWasmToWasmCalls->append({ linkBuffer.locationOf(call), functionIndex, UnlinkedWasmToWasmCall::Target::ToWasm });
+ unlinkedWasmToWasmCalls->append({ linkBuffer.locationOf(call), functionIndex });
});
});
});
@@ -915,17 +915,23 @@
UpsilonValue* wasmCallResultUpsilon = returnType == Void ? nullptr : isWasmBlock->appendNew<UpsilonValue>(m_proc, origin(), wasmCallResult);
isWasmBlock->appendNewControlValue(m_proc, Jump, origin(), continuation);
+ // FIXME: Lets remove this indirection by creating a PIC friendly IC
+ // for calls out to JS. This shouldn't be that hard to do. We could probably
+ // implement the IC to be over Wasm::Context*.
+ // https://bugs.webkit.org/show_bug.cgi?id=170375
+ Value* codeBlock = isJSBlock->appendNew<MemoryValue>(m_proc,
+ Load, pointerType(), origin(), m_instanceValue, JSWebAssemblyInstance::offsetOfCodeBlock());
+ Value* jumpDestination = isJSBlock->appendNew<MemoryValue>(m_proc,
+ Load, pointerType(), origin(), codeBlock, JSWebAssemblyCodeBlock::offsetOfImportWasmToJSStub(m_info.internalFunctionCount(), functionIndex));
Value* jsCallResult = wasmCallingConvention().setupCall(m_proc, isJSBlock, origin(), args, toB3Type(returnType),
- [=] (PatchpointValue* patchpoint) {
+ [&] (PatchpointValue* patchpoint) {
patchpoint->effects.writesPinned = true;
patchpoint->effects.readsPinned = true;
+ patchpoint->append(jumpDestination, ValueRep::SomeRegister);
patchpoint->clobberLate(PinnedRegisterInfo::get().toSave());
- patchpoint->setGenerator([unlinkedWasmToWasmCalls, functionIndex] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
+ patchpoint->setGenerator([unlinkedWasmToWasmCalls, functionIndex, returnType] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
AllowMacroScratchRegisterUsage allowScratch(jit);
- CCallHelpers::Call call = jit.call();
- jit.addLinkTask([unlinkedWasmToWasmCalls, call, functionIndex] (LinkBuffer& linkBuffer) {
- unlinkedWasmToWasmCalls->append({ linkBuffer.locationOf(call), functionIndex, UnlinkedWasmToWasmCall::Target::ToJs });
- });
+ jit.call(params[returnType == Void ? 0 : 1].gpr());
});
});
UpsilonValue* jsCallResultUpsilon = returnType == Void ? nullptr : isJSBlock->appendNew<UpsilonValue>(m_proc, origin(), jsCallResult);
@@ -953,7 +959,7 @@
AllowMacroScratchRegisterUsage allowScratch(jit);
CCallHelpers::Call call = jit.call();
jit.addLinkTask([unlinkedWasmToWasmCalls, call, functionIndex] (LinkBuffer& linkBuffer) {
- unlinkedWasmToWasmCalls->append({ linkBuffer.locationOf(call), functionIndex, UnlinkedWasmToWasmCall::Target::ToWasm });
+ unlinkedWasmToWasmCalls->append({ linkBuffer.locationOf(call), functionIndex });
});
});
});
Modified: trunk/Source/_javascript_Core/wasm/WasmFormat.h (214710 => 214711)
--- trunk/Source/_javascript_Core/wasm/WasmFormat.h 2017-04-01 02:05:01 UTC (rev 214710)
+++ trunk/Source/_javascript_Core/wasm/WasmFormat.h 2017-04-01 02:09:51 UTC (rev 214711)
@@ -269,10 +269,6 @@
struct UnlinkedWasmToWasmCall {
CodeLocationCall callLocation;
size_t functionIndex;
- enum class Target : uint8_t {
- ToJs,
- ToWasm,
- } target;
};
struct Entrypoint {
Modified: trunk/Source/_javascript_Core/wasm/WasmPlan.cpp (214710 => 214711)
--- trunk/Source/_javascript_Core/wasm/WasmPlan.cpp 2017-04-01 02:05:01 UTC (rev 214710)
+++ trunk/Source/_javascript_Core/wasm/WasmPlan.cpp 2017-04-01 02:09:51 UTC (rev 214711)
@@ -296,13 +296,9 @@
void* executableAddress;
if (m_moduleInformation->isImportedFunctionFromFunctionIndexSpace(call.functionIndex)) {
// FIXME imports could have been linked in B3, instead of generating a patchpoint. This condition should be replaced by a RELEASE_ASSERT. https://bugs.webkit.org/show_bug.cgi?id=166462
- executableAddress = call.target == UnlinkedWasmToWasmCall::Target::ToJs
- ? m_wasmExitStubs.at(call.functionIndex).wasmToJs.code().executableAddress()
- : m_wasmExitStubs.at(call.functionIndex).wasmToWasm.code().executableAddress();
- } else {
- ASSERT(call.target != UnlinkedWasmToWasmCall::Target::ToJs);
+ executableAddress = m_wasmExitStubs.at(call.functionIndex).wasmToWasm.code().executableAddress();
+ } else
executableAddress = m_wasmInternalFunctions.at(call.functionIndex - m_wasmExitStubs.size())->wasmEntrypoint.compilation->code().executableAddress();
- }
MacroAssembler::repatchCall(call.callLocation, CodeLocationLabel(executableAddress));
}
}
Modified: trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyCodeBlock.cpp (214710 => 214711)
--- trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyCodeBlock.cpp 2017-04-01 02:05:01 UTC (rev 214710)
+++ trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyCodeBlock.cpp 2017-04-01 02:09:51 UTC (rev 214711)
@@ -72,6 +72,10 @@
m_callLinkInfos = plan().takeCallLinkInfos();
m_wasmExitStubs = plan().takeWasmExitStubs();
+ // The code a module emits to call into JS relies on us to set this up.
+ for (unsigned i = 0; i < m_wasmExitStubs.size(); i++)
+ importWasmToJSStub(m_calleeCount, i) = m_wasmExitStubs[i].wasmToJs.code().executableAddress();
+
plan().initializeCallees([&] (unsigned calleeIndex, JSWebAssemblyCallee* jsEntrypointCallee, JSWebAssemblyCallee* wasmEntrypointCallee) {
setJSEntrypointCallee(vm, calleeIndex, jsEntrypointCallee);
setWasmEntrypointCallee(vm, calleeIndex, wasmEntrypointCallee);
Modified: trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyCodeBlock.h (214710 => 214711)
--- trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyCodeBlock.h 2017-04-01 02:05:01 UTC (rev 214710)
+++ trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyCodeBlock.h 2017-04-01 02:09:51 UTC (rev 214711)
@@ -49,9 +49,9 @@
typedef JSCell Base;
static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
- static JSWebAssemblyCodeBlock* create(VM& vm, JSWebAssemblyModule* owner, Wasm::MemoryMode mode, Ref<Wasm::Plan>&& plan, unsigned calleeCount)
+ static JSWebAssemblyCodeBlock* create(VM& vm, JSWebAssemblyModule* owner, Wasm::MemoryMode mode, Ref<Wasm::Plan>&& plan, unsigned calleeCount, unsigned functionImportCount)
{
- auto* result = new (NotNull, allocateCell<JSWebAssemblyCodeBlock>(vm.heap, allocationSize(calleeCount))) JSWebAssemblyCodeBlock(vm, owner, mode, WTFMove(plan), calleeCount);
+ auto* result = new (NotNull, allocateCell<JSWebAssemblyCodeBlock>(vm.heap, allocationSize(calleeCount, functionImportCount))) JSWebAssemblyCodeBlock(vm, owner, mode, WTFMove(plan), calleeCount);
result->finishCreation(vm);
return result;
}
@@ -111,6 +111,13 @@
return m_wasmExitStubs[importIndex].wasmToJs.code().executableAddress();
}
+ static ptrdiff_t offsetOfImportWasmToJSStub(unsigned calleeCount, unsigned importIndex)
+ {
+ return offsetOfCallees()
+ + (sizeof(WriteBarrier<JSWebAssemblyCallee>) * calleeCount * 2)
+ + (sizeof(void*) * importIndex);
+ }
+
private:
JSWebAssemblyCodeBlock(VM&, JSWebAssemblyModule*, Wasm::MemoryMode, Ref<Wasm::Plan>&&, unsigned calleeCount);
DECLARE_EXPORT_INFO;
@@ -118,16 +125,23 @@
static void destroy(JSCell*);
static void visitChildren(JSCell*, SlotVisitor&);
- static size_t offsetOfCallees()
+ static ptrdiff_t offsetOfCallees()
{
return WTF::roundUpToMultipleOf<sizeof(WriteBarrier<JSWebAssemblyCallee>)>(sizeof(JSWebAssemblyCodeBlock));
}
- static size_t allocationSize(unsigned numCallees)
+ static size_t allocationSize(unsigned calleeCount, unsigned functionImportCount)
{
- return offsetOfCallees() + sizeof(WriteBarrier<JSWebAssemblyCallee>) * numCallees * 2;
+ return offsetOfCallees()
+ + (sizeof(WriteBarrier<JSWebAssemblyCallee>) * calleeCount * 2)
+ + (sizeof(void*) * functionImportCount);
}
+ void*& importWasmToJSStub(unsigned calleeCount, unsigned importIndex)
+ {
+ return *bitwise_cast<void**>(bitwise_cast<char*>(this) + offsetOfImportWasmToJSStub(calleeCount, importIndex));
+ }
+
class UnconditionalFinalizer : public JSC::UnconditionalFinalizer {
void finalizeUnconditionally() override;
};
Modified: trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyInstance.cpp (214710 => 214711)
--- trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyInstance.cpp 2017-04-01 02:05:01 UTC (rev 214710)
+++ trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyInstance.cpp 2017-04-01 02:09:51 UTC (rev 214711)
@@ -96,7 +96,8 @@
void JSWebAssemblyInstance::addUnitializedCodeBlock(VM& vm, Ref<Wasm::Plan> plan)
{
- auto* codeBlock = JSWebAssemblyCodeBlock::create(vm, module(), memoryMode(), WTFMove(plan), module()->moduleInformation().internalFunctionCount());
+ auto* codeBlock = JSWebAssemblyCodeBlock::create(
+ vm, module(), memoryMode(), WTFMove(plan), module()->moduleInformation().internalFunctionCount(), module()->moduleInformation().importFunctionCount());
m_codeBlock.set(vm, this, codeBlock);
ASSERT(!codeBlock->initialized());
}
Modified: trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyInstance.h (214710 => 214711)
--- trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyInstance.h 2017-04-01 02:05:01 UTC (rev 214710)
+++ trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyInstance.h 2017-04-01 02:09:51 UTC (rev 214711)
@@ -79,6 +79,7 @@
static ptrdiff_t offsetOfCallee() { return OBJECT_OFFSETOF(JSWebAssemblyInstance, m_callee); }
static ptrdiff_t offsetOfGlobals() { return OBJECT_OFFSETOF(JSWebAssemblyInstance, m_globals); }
static ptrdiff_t offsetOfVM() { return OBJECT_OFFSETOF(JSWebAssemblyInstance, m_vm); }
+ static ptrdiff_t offsetOfCodeBlock() { return OBJECT_OFFSETOF(JSWebAssemblyInstance, m_codeBlock); }
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>)); }