Diff
Modified: trunk/JSTests/ChangeLog (224809 => 224810)
--- trunk/JSTests/ChangeLog 2017-11-14 08:56:15 UTC (rev 224809)
+++ trunk/JSTests/ChangeLog 2017-11-14 09:05:33 UTC (rev 224810)
@@ -1,3 +1,15 @@
+2017-11-14 Saam Barati <sbar...@apple.com>
+
+ We need to set topCallFrame when calling Wasm::Memory::grow from the JIT
+ https://bugs.webkit.org/show_bug.cgi?id=179639
+ <rdar://problem/35513018>
+
+ Reviewed by JF Bastien.
+
+ * wasm/function-tests/grow-memory-cause-gc.js: Added.
+ (escape):
+ (i.func):
+
2017-11-13 Mark Lam <mark....@apple.com>
Add more overflow check book-keeping for MarkedArgumentBuffer.
Added: trunk/JSTests/wasm/function-tests/grow-memory-cause-gc.js (0 => 224810)
--- trunk/JSTests/wasm/function-tests/grow-memory-cause-gc.js (rev 0)
+++ trunk/JSTests/wasm/function-tests/grow-memory-cause-gc.js 2017-11-14 09:05:33 UTC (rev 224810)
@@ -0,0 +1,61 @@
+import Builder from '../Builder.js';
+import * as assert from '../assert.js';
+
+function escape(){}
+noInline(escape);
+
+for (let i = 0; i < 10; ++i) {
+ const max = 1024*2;
+ const memoryDescription = {initial: 0, maximum: max};
+ const growMemoryAmount = 256;
+
+ const builder = (new Builder())
+ .Type().End()
+ .Import()
+ .Function("imp", "func", {params: [], ret: "void"})
+ .Memory("imp", "memory", memoryDescription)
+ .End()
+ .Function().End()
+ .Export()
+ .Function("foo")
+ .End()
+ .Code()
+ .Function("foo", {params: [], ret: "i32"})
+ .I32Const(1)
+ .I32Const(1)
+ .I32Const(1)
+ .I32Const(1)
+ .I32Const(1)
+ .I32Const(1)
+ .I32Const(1)
+ .I32Const(1)
+ .I32Const(1)
+ .I32Const(1)
+ .I32Const(1)
+ .I32Const(1)
+ .I32Const(1)
+ .I32Const(1)
+ .I32Const(1)
+ .I32Const(1)
+ .Call(2)
+ .I32Const(growMemoryAmount)
+ .GrowMemory(0)
+ .Return()
+ .End()
+ .Function("bar", {params: ["i32", "i32", "i32", "i32", "i32", "i32", "i32", "i32", "i32", "i32", "i32", "i32", "i32", "i32", "i32", "i32"], ret: "void"})
+ .Call(0)
+ .Return()
+ .End()
+ .End();
+
+ const bin = builder.WebAssembly().get();
+ const module = new WebAssembly.Module(bin);
+ const memory = new WebAssembly.Memory(memoryDescription);
+
+ function func() { }
+
+ const instance = new WebAssembly.Instance(module, {imp: {memory, func}});
+ for (let i = 0; i < max/growMemoryAmount; ++i) {
+ instance.exports.foo();
+ }
+}
Modified: trunk/Source/_javascript_Core/ChangeLog (224809 => 224810)
--- trunk/Source/_javascript_Core/ChangeLog 2017-11-14 08:56:15 UTC (rev 224809)
+++ trunk/Source/_javascript_Core/ChangeLog 2017-11-14 09:05:33 UTC (rev 224810)
@@ -1,3 +1,37 @@
+2017-11-14 Saam Barati <sbar...@apple.com>
+
+ We need to set topCallFrame when calling Wasm::Memory::grow from the JIT
+ https://bugs.webkit.org/show_bug.cgi?id=179639
+ <rdar://problem/35513018>
+
+ Reviewed by JF Bastien.
+
+ Calling Wasm::Memory::grow from the JIT may cause us to GC. When we GC, we will
+ walk the stack for ShadowChicken (and maybe other things). We weren't updating
+ topCallFrame when calling grow from the Wasm JIT. This would cause the GC to
+ use stale topCallFrame bits in VM, often leading to crashes. This patch fixes
+ this bug by giving Wasm::Instance a lambda that is called when we need to store
+ the topCallFrame. Users of Wasm::Instance can provide a function to do this action.
+ Currently, JSWebAssemblyInstance passes in a lambda that stores to
+ VM.topCallFrame.
+
+ * wasm/WasmB3IRGenerator.cpp:
+ (JSC::Wasm::B3IRGenerator::addGrowMemory):
+ * wasm/WasmInstance.cpp:
+ (JSC::Wasm::Instance::Instance):
+ (JSC::Wasm::Instance::create):
+ * wasm/WasmInstance.h:
+ (JSC::Wasm::Instance::storeTopCallFrame):
+ * wasm/js/JSWebAssemblyInstance.cpp:
+ (JSC::JSWebAssemblyInstance::create):
+ * wasm/js/JSWebAssemblyInstance.h:
+ * wasm/js/WasmToJS.cpp:
+ (JSC::Wasm::wasmToJSException):
+ * wasm/js/WebAssemblyInstanceConstructor.cpp:
+ (JSC::constructJSWebAssemblyInstance):
+ * wasm/js/WebAssemblyPrototype.cpp:
+ (JSC::instantiate):
+
2017-11-13 Saam Barati <sbar...@apple.com>
Remove pointer caging for HashMapImpl, JSLexicalEnvironment, DirectArguments, ScopedArguments, and ScopedArgumentsTable
Modified: trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp (224809 => 224810)
--- trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp 2017-11-14 08:56:15 UTC (rev 224809)
+++ trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp 2017-11-14 09:05:33 UTC (rev 224810)
@@ -558,7 +558,9 @@
auto B3IRGenerator::addGrowMemory(ExpressionType delta, ExpressionType& result) -> PartialResult
{
- int32_t (*growMemory)(Instance*, int32_t) = [] (Instance* instance, int32_t delta) -> int32_t {
+ int32_t (*growMemory)(void*, Instance*, int32_t) = [] (void* callFrame, Instance* instance, int32_t delta) -> int32_t {
+ instance->storeTopCallFrame(callFrame);
+
if (delta < 0)
return -1;
@@ -571,6 +573,7 @@
case Memory::GrowFailReason::OutOfMemory:
return -1;
}
+ RELEASE_ASSERT_NOT_REACHED();
}
return grown.value().pageCount();
@@ -578,7 +581,7 @@
result = m_currentBlock->appendNew<CCallValue>(m_proc, Int32, origin(),
m_currentBlock->appendNew<ConstPtrValue>(m_proc, origin(), bitwise_cast<void*>(growMemory)),
- instanceValue(), delta);
+ m_currentBlock->appendNew<B3::Value>(m_proc, B3::FramePointer, origin()), instanceValue(), delta);
restoreWebAssemblyGlobalState(m_info.memory, instanceValue(), m_proc, m_currentBlock);
Modified: trunk/Source/_javascript_Core/wasm/WasmInstance.cpp (224809 => 224810)
--- trunk/Source/_javascript_Core/wasm/WasmInstance.cpp 2017-11-14 08:56:15 UTC (rev 224809)
+++ trunk/Source/_javascript_Core/wasm/WasmInstance.cpp 2017-11-14 09:05:33 UTC (rev 224810)
@@ -41,11 +41,12 @@
}
}
-Instance::Instance(Context* context, Ref<Module>&& module, EntryFrame** topEntryFramePointer)
+Instance::Instance(Context* context, Ref<Module>&& module, EntryFrame** topEntryFramePointer, StoreTopCallFrameCallback&& storeTopCallFrame)
: m_context(context)
, m_module(WTFMove(module))
, m_globals(MallocPtr<uint64_t>::malloc(globalMemoryByteSize(m_module.get())))
, m_topEntryFramePointer(topEntryFramePointer)
+ , m_storeTopCallFrame(WTFMove(storeTopCallFrame))
, m_numImportFunctions(m_module->moduleInformation().importFunctionCount())
{
for (unsigned i = 0; i < m_numImportFunctions; ++i)
@@ -52,9 +53,9 @@
new (importFunctionInfo(i)) ImportFunctionInfo();
}
-Ref<Instance> Instance::create(Context* context, Ref<Module>&& module, EntryFrame** topEntryFramePointer)
+Ref<Instance> Instance::create(Context* context, Ref<Module>&& module, EntryFrame** topEntryFramePointer, StoreTopCallFrameCallback&& storeTopCallFrame)
{
- return adoptRef(*new (NotNull, fastMalloc(allocationSize(module->moduleInformation().importFunctionCount()))) Instance(context, WTFMove(module), topEntryFramePointer));
+ return adoptRef(*new (NotNull, fastMalloc(allocationSize(module->moduleInformation().importFunctionCount()))) Instance(context, WTFMove(module), topEntryFramePointer, WTFMove(storeTopCallFrame)));
}
Instance::~Instance() { }
Modified: trunk/Source/_javascript_Core/wasm/WasmInstance.h (224809 => 224810)
--- trunk/Source/_javascript_Core/wasm/WasmInstance.h 2017-11-14 08:56:15 UTC (rev 224809)
+++ trunk/Source/_javascript_Core/wasm/WasmInstance.h 2017-11-14 09:05:33 UTC (rev 224810)
@@ -42,8 +42,10 @@
class Instance : public ThreadSafeRefCounted<Instance> {
public:
- static Ref<Instance> create(Context* context, Ref<Module>&& module, EntryFrame** topEntryFramePointer);
+ using StoreTopCallFrameCallback = WTF::Function<void(void*)>;
+ static Ref<Instance> create(Context*, Ref<Module>&&, EntryFrame** topEntryFramePointer, StoreTopCallFrameCallback&&);
+
void finalizeCreation(void* owner, Ref<CodeBlock>&& codeBlock)
{
m_owner = owner;
@@ -103,8 +105,13 @@
static size_t offsetOfImportFunction(size_t importFunctionNum) { return offsetOfTail() + importFunctionNum * sizeof(ImportFunctionInfo) + OBJECT_OFFSETOF(ImportFunctionInfo, importFunction); }
template<typename T> T* importFunction(unsigned importFunctionNum) { return reinterpret_cast<T*>(&importFunctionInfo(importFunctionNum)->importFunction); }
+ void storeTopCallFrame(void* callFrame)
+ {
+ m_storeTopCallFrame(callFrame);
+ }
+
private:
- Instance(Context* context, Ref<Module>&&, EntryFrame**);
+ Instance(Context*, Ref<Module>&&, EntryFrame**, StoreTopCallFrameCallback&&);
static size_t allocationSize(Checked<size_t> numImportFunctions)
{
@@ -120,7 +127,7 @@
MallocPtr<uint64_t> m_globals;
EntryFrame** m_topEntryFramePointer { nullptr };
void* m_cachedStackLimit { bitwise_cast<void*>(std::numeric_limits<uintptr_t>::max()) };
-
+ StoreTopCallFrameCallback m_storeTopCallFrame;
unsigned m_numImportFunctions { 0 };
};
Modified: trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyInstance.cpp (224809 => 224810)
--- trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyInstance.cpp 2017-11-14 08:56:15 UTC (rev 224809)
+++ trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyInstance.cpp 2017-11-14 09:05:33 UTC (rev 224810)
@@ -135,7 +135,7 @@
RETURN_IF_EXCEPTION(scope, void());
}
-JSWebAssemblyInstance* JSWebAssemblyInstance::create(VM& vm, ExecState* exec, JSWebAssemblyModule* jsModule, JSObject* importObject, Structure* instanceStructure, Ref<Wasm::Instance>&& instance)
+JSWebAssemblyInstance* JSWebAssemblyInstance::create(VM& vm, ExecState* exec, JSWebAssemblyModule* jsModule, JSObject* importObject, Structure* instanceStructure, Ref<Wasm::Module>&& module)
{
auto throwScope = DECLARE_THROW_SCOPE(vm);
auto* globalObject = exec->lexicalGlobalObject();
@@ -163,8 +163,14 @@
RETURN_IF_EXCEPTION(throwScope, nullptr);
JSModuleNamespaceObject* moduleNamespace = moduleRecord->getModuleNamespace(exec);
+
+ auto storeTopCallFrame = [&vm] (void* topCallFrame) {
+ vm.topCallFrame = bitwise_cast<ExecState*>(topCallFrame);
+ };
+
// FIXME: These objects could be pretty big we should try to throw OOM here.
- auto* jsInstance = new (NotNull, allocateCell<JSWebAssemblyInstance>(vm.heap)) JSWebAssemblyInstance(vm, instanceStructure, WTFMove(instance));
+ auto* jsInstance = new (NotNull, allocateCell<JSWebAssemblyInstance>(vm.heap)) JSWebAssemblyInstance(vm, instanceStructure,
+ Wasm::Instance::create(&vm.wasmContext, WTFMove(module), &vm.topEntryFrame, WTFMove(storeTopCallFrame)));
jsInstance->finishCreation(vm, jsModule, moduleNamespace);
RETURN_IF_EXCEPTION(throwScope, nullptr);
Modified: trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyInstance.h (224809 => 224810)
--- trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyInstance.h 2017-11-14 08:56:15 UTC (rev 224809)
+++ trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyInstance.h 2017-11-14 09:05:33 UTC (rev 224810)
@@ -48,7 +48,7 @@
public:
typedef JSDestructibleObject Base;
- static JSWebAssemblyInstance* create(VM&, ExecState*, JSWebAssemblyModule*, JSObject* importObject, Structure*, Ref<Wasm::Instance>&&);
+ static JSWebAssemblyInstance* create(VM&, ExecState*, JSWebAssemblyModule*, JSObject* importObject, Structure*, Ref<Wasm::Module>&&);
static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
DECLARE_EXPORT_INFO;
Modified: trunk/Source/_javascript_Core/wasm/js/WasmToJS.cpp (224809 => 224810)
--- trunk/Source/_javascript_Core/wasm/js/WasmToJS.cpp 2017-11-14 08:56:15 UTC (rev 224809)
+++ trunk/Source/_javascript_Core/wasm/js/WasmToJS.cpp 2017-11-14 09:05:33 UTC (rev 224810)
@@ -638,25 +638,25 @@
void* wasmToJSException(ExecState* exec, Wasm::ExceptionType type, Instance* wasmInstance)
{
+ wasmInstance->storeTopCallFrame(exec);
JSWebAssemblyInstance* instance = wasmInstance->owner<JSWebAssemblyInstance>();
- VM* vm = instance->vm();
- NativeCallFrameTracer tracer(vm, exec);
+ JSGlobalObject* globalObject = instance->globalObject();
+ VM& vm = globalObject->vm();
{
- auto throwScope = DECLARE_THROW_SCOPE(*vm);
- JSGlobalObject* globalObject = instance->globalObject();
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
JSObject* error;
if (type == ExceptionType::StackOverflow)
error = createStackOverflowError(exec, globalObject);
else
- error = JSWebAssemblyRuntimeError::create(exec, *vm, globalObject->WebAssemblyRuntimeErrorStructure(), Wasm::errorMessageForExceptionType(type));
+ error = JSWebAssemblyRuntimeError::create(exec, vm, globalObject->WebAssemblyRuntimeErrorStructure(), Wasm::errorMessageForExceptionType(type));
throwException(exec, throwScope, error);
}
- genericUnwind(vm, exec);
- ASSERT(!!vm->callFrameForCatch);
- ASSERT(!!vm->targetMachinePCForThrow);
+ genericUnwind(&vm, exec);
+ ASSERT(!!vm.callFrameForCatch);
+ ASSERT(!!vm.targetMachinePCForThrow);
// FIXME: We could make this better:
// This is a total hack, but the llint (both op_catch and handleUncaughtException)
// require a cell in the callee field to load the VM. (The baseline JIT does not require
@@ -665,7 +665,7 @@
// to the exception handler. If we did this, we could remove this terrible hack.
// https://bugs.webkit.org/show_bug.cgi?id=170440
bitwise_cast<uint64_t*>(exec)[CallFrameSlot::callee] = bitwise_cast<uint64_t>(instance->webAssemblyToJSCallee());
- return vm->targetMachinePCForThrow;
+ return vm.targetMachinePCForThrow;
}
} } // namespace JSC::Wasm
Modified: trunk/Source/_javascript_Core/wasm/js/WebAssemblyInstanceConstructor.cpp (224809 => 224810)
--- trunk/Source/_javascript_Core/wasm/js/WebAssemblyInstanceConstructor.cpp 2017-11-14 08:56:15 UTC (rev 224809)
+++ trunk/Source/_javascript_Core/wasm/js/WebAssemblyInstanceConstructor.cpp 2017-11-14 09:05:33 UTC (rev 224810)
@@ -77,7 +77,7 @@
Structure* instanceStructure = InternalFunction::createSubclassStructure(exec, exec->newTarget(), exec->lexicalGlobalObject()->WebAssemblyInstanceStructure());
RETURN_IF_EXCEPTION(scope, { });
- JSWebAssemblyInstance* instance = JSWebAssemblyInstance::create(vm, exec, module, importObject, instanceStructure, Wasm::Instance::create(&vm.wasmContext, Ref<Wasm::Module>(module->module()), &vm.topEntryFrame));
+ JSWebAssemblyInstance* instance = JSWebAssemblyInstance::create(vm, exec, module, importObject, instanceStructure, Ref<Wasm::Module>(module->module()));
RETURN_IF_EXCEPTION(scope, { });
instance->finalizeCreation(vm, exec, module->module().compileSync(&vm.wasmContext, instance->memoryMode(), &Wasm::createJSToWasmWrapper, &Wasm::wasmToJSException));
Modified: trunk/Source/_javascript_Core/wasm/js/WebAssemblyPrototype.cpp (224809 => 224810)
--- trunk/Source/_javascript_Core/wasm/js/WebAssemblyPrototype.cpp 2017-11-14 08:56:15 UTC (rev 224809)
+++ trunk/Source/_javascript_Core/wasm/js/WebAssemblyPrototype.cpp 2017-11-14 09:05:33 UTC (rev 224810)
@@ -137,7 +137,7 @@
{
auto scope = DECLARE_CATCH_SCOPE(vm);
// In order to avoid potentially recompiling a module. We first gather all the import/memory information prior to compiling code.
- JSWebAssemblyInstance* instance = JSWebAssemblyInstance::create(vm, exec, module, importObject, exec->lexicalGlobalObject()->WebAssemblyInstanceStructure(), Wasm::Instance::create(&vm.wasmContext, Ref<Wasm::Module>(module->module()), &vm.topEntryFrame));
+ JSWebAssemblyInstance* instance = JSWebAssemblyInstance::create(vm, exec, module, importObject, exec->lexicalGlobalObject()->WebAssemblyInstanceStructure(), Ref<Wasm::Module>(module->module()));
RETURN_IF_EXCEPTION(scope, reject(exec, scope, promise));
Vector<Strong<JSCell>> dependencies;