WebKit Bugzilla
Attachment 370611 Details for
Bug 198102
: [WASM-References] Support Anyref in globals
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-198102-20190524171154.patch (text/plain), 29.39 KB, created by
Justin Michaud
on 2019-05-24 17:11:55 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Justin Michaud
Created:
2019-05-24 17:11:55 PDT
Size:
29.39 KB
patch
obsolete
>Subversion Revision: 245759 >diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog >index e9d34b8bafd14c1a66aab6c66f8d603fe17c128d..e282a5b0e621a5b992e6b53d1bc945e4e3674499 100644 >--- a/Source/JavaScriptCore/ChangeLog >+++ b/Source/JavaScriptCore/ChangeLog >@@ -1,3 +1,38 @@ >+2019-05-24 Justin Michaud <justin_michaud@apple.com> >+ >+ [WASM-References] Support Anyref in globals >+ https://bugs.webkit.org/show_bug.cgi?id=198102 >+ >+ Reviewed by Saam Barati. >+ >+ Support anyref for globals, imports and exports. This adds code in B3 and Air to emit a write barrier >+ on the JSWebAssemblyWrapper whenever an anyref global is set. This also fixes a small bug in emitCCall >+ for air where it adds code to the wrong block. >+ >+ * wasm/WasmAirIRGenerator.cpp: >+ (JSC::Wasm::AirIRGenerator::emitCCall): >+ (JSC::Wasm::AirIRGenerator::moveOpForValueType): >+ (JSC::Wasm::AirIRGenerator::setGlobal): >+ (JSC::Wasm::AirIRGenerator::emitWriteBarrierForJSWrapper): >+ * wasm/WasmB3IRGenerator.cpp: >+ (JSC::Wasm::B3IRGenerator::setGlobal): >+ (JSC::Wasm::B3IRGenerator::emitWriteBarrierForJSWrapper): >+ * wasm/WasmInstance.cpp: >+ (JSC::Wasm::Instance::Instance): >+ (JSC::Wasm::Instance::setGlobal): >+ * wasm/WasmInstance.h: >+ (JSC::Wasm::Instance::loadI32Global const): >+ (JSC::Wasm::Instance::loadI64Global const): >+ (JSC::Wasm::Instance::setGlobal): >+ (JSC::Wasm::Instance::shouldMarkGlobal): >+ (JSC::Wasm::Instance::numGlobals const): >+ * wasm/WasmSectionParser.cpp: >+ (JSC::Wasm::SectionParser::parseInitExpr): >+ * wasm/js/JSWebAssemblyInstance.cpp: >+ (JSC::JSWebAssemblyInstance::visitChildren): >+ * wasm/js/WebAssemblyModuleRecord.cpp: >+ (JSC::WebAssemblyModuleRecord::link): >+ > 2019-05-23 Devin Rousso <drousso@apple.com> > > Web Inspector: Overlay: rulers/guides should be shown whenever element selection is enabled >diff --git a/Source/JavaScriptCore/runtime/VM.h b/Source/JavaScriptCore/runtime/VM.h >index 3af48797b7bd405e491c7f87b62e1a5a9923f18a..918827ffa88b626b208abf26c1be16e1db570563 100644 >--- a/Source/JavaScriptCore/runtime/VM.h >+++ b/Source/JavaScriptCore/runtime/VM.h >@@ -687,6 +687,16 @@ public: > return OBJECT_OFFSETOF(VM, topEntryFrame); > } > >+ static ptrdiff_t offsetOfHeapBarrierThreshold() >+ { >+ return OBJECT_OFFSETOF(VM, heap) + OBJECT_OFFSETOF(Heap, m_barrierThreshold); >+ } >+ >+ static ptrdiff_t offsetOfHeapMutatorShouldBeFenced() >+ { >+ return OBJECT_OFFSETOF(VM, heap) + OBJECT_OFFSETOF(Heap, m_mutatorShouldBeFenced); >+ } >+ > void restorePreviousException(Exception* exception) { setException(exception); } > > void clearLastException() { m_lastException = nullptr; } >diff --git a/Source/JavaScriptCore/wasm/WasmAirIRGenerator.cpp b/Source/JavaScriptCore/wasm/WasmAirIRGenerator.cpp >index f7960731806ab7c6939f753075b7062c43cf68cf..ce524dfde94530e120abc8da79153d01f158029e 100644 >--- a/Source/JavaScriptCore/wasm/WasmAirIRGenerator.cpp >+++ b/Source/JavaScriptCore/wasm/WasmAirIRGenerator.cpp >@@ -42,6 +42,7 @@ > #include "BinarySwitch.h" > #include "DisallowMacroScratchRegisterUsage.h" > #include "JSCInlines.h" >+#include "JSWebAssemblyInstance.h" > #include "ScratchRegisterAllocator.h" > #include "VirtualRegister.h" > #include "WasmCallingConvention.h" >@@ -529,7 +530,7 @@ private: > Inst inst(CCall, origin); > > Tmp callee = g64(); >- append(Move, Arg::immPtr(tagCFunctionPtr<void*>(func, B3CCallPtrTag)), callee); >+ append(block, Move, Arg::immPtr(tagCFunctionPtr<void*>(func, B3CCallPtrTag)), callee); > inst.args.append(callee); > > if (result) >@@ -547,6 +548,7 @@ private: > case Type::I32: > return Move32; > case Type::I64: >+ case Type::Anyref: > return Move; > case Type::F32: > return MoveFloat; >@@ -561,6 +563,7 @@ private: > > void emitTierUpCheck(uint32_t decrementCount, B3::Origin); > >+ void emitWriteBarrierForJSWrapper(); > ExpressionType emitCheckAndPreparePointer(ExpressionType pointer, uint32_t offset, uint32_t sizeOfOp); > ExpressionType emitLoadOp(LoadOpType, ExpressionType pointer, uint32_t offset); > void emitStoreOp(StoreOpType, ExpressionType pointer, ExpressionType value, uint32_t offset); >@@ -1059,9 +1062,60 @@ auto AirIRGenerator::setGlobal(uint32_t index, ExpressionType value) -> PartialR > append(moveOpForValueType(type), value, Arg::addr(temp)); > } > >+ if (type == Anyref) >+ emitWriteBarrierForJSWrapper(); >+ > return { }; > } > >+inline void AirIRGenerator::emitWriteBarrierForJSWrapper() >+{ >+ auto cell = g64(); >+ auto vm = g64(); >+ auto cellState = g32(); >+ auto threshold = g32(); >+ >+ BasicBlock* fenceCheckPath = m_code.addBlock(); >+ BasicBlock* fencePath = m_code.addBlock(); >+ BasicBlock* doSlowPath = m_code.addBlock(); >+ BasicBlock* continuation = m_code.addBlock(); >+ >+ append(Move, Arg::addr(instanceValue(), Instance::offsetOfOwner()), cell); >+ append(Move, Arg::addr(cell, JSWebAssemblyInstance::offsetOfVM()), vm); >+ append(Load8, Arg::addr(cell, JSCell::cellStateOffset()), cellState); >+ append(Move32, Arg::addr(vm, VM::offsetOfHeapBarrierThreshold()), threshold); >+ >+ append(Branch32, Arg::relCond(MacroAssembler::Above), cellState, threshold); >+ m_currentBlock->setSuccessors(continuation, fenceCheckPath); >+ m_currentBlock = fenceCheckPath; >+ >+ append(Load8, Arg::addr(vm, VM::offsetOfHeapMutatorShouldBeFenced()), threshold); >+ append(BranchTest32, Arg::resCond(MacroAssembler::Zero), threshold, threshold); >+ m_currentBlock->setSuccessors(doSlowPath, fencePath); >+ m_currentBlock = fencePath; >+ >+ auto* doFence = addPatchpoint(B3::Void); >+ doFence->setGenerator([] (CCallHelpers& jit, const B3::StackmapGenerationParams&) { >+ jit.memoryFence(); >+ }); >+ emitPatchpoint(doFence, Tmp()); >+ >+ append(Load8, Arg::addr(cell, JSCell::cellStateOffset()), cellState); >+ append(Branch32, Arg::relCond(MacroAssembler::Above), cellState, Arg::imm(blackThreshold)); >+ m_currentBlock->setSuccessors(continuation, doSlowPath); >+ m_currentBlock = doSlowPath; >+ >+ void (*writeBarrier)(JSWebAssemblyInstance*, VM*) = [] (JSWebAssemblyInstance* cell, VM* vm) -> void { >+ ASSERT(cell); >+ ASSERT(vm); >+ vm->heap.writeBarrierSlowPath(cell); >+ }; >+ emitCCall(writeBarrier, TypedTmp(), cell, vm); >+ append(Jump); >+ m_currentBlock->setSuccessors(continuation); >+ m_currentBlock = continuation; >+} >+ > inline AirIRGenerator::ExpressionType AirIRGenerator::emitCheckAndPreparePointer(ExpressionType pointer, uint32_t offset, uint32_t sizeOfOperation) > { > ASSERT(m_memoryBaseGPR); >diff --git a/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp b/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp >index bb2471f8da7603808b564203f0078ba3c6681f7c..11b360373f4185cfffb8904ad2aa063b6c0b7333 100644 >--- a/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp >+++ b/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp >@@ -49,6 +49,7 @@ > #include "B3WasmBoundsCheckValue.h" > #include "DisallowMacroScratchRegisterUsage.h" > #include "JSCInlines.h" >+#include "JSWebAssemblyInstance.h" > #include "ScratchRegisterAllocator.h" > #include "VirtualRegister.h" > #include "WasmCallingConvention.h" >@@ -239,6 +240,7 @@ private: > > void emitTierUpCheck(uint32_t decrementCount, Origin); > >+ void emitWriteBarrierForJSWrapper(); > ExpressionType emitCheckAndPreparePointer(ExpressionType pointer, uint32_t offset, uint32_t sizeOfOp); > B3::Kind memoryKind(B3::Opcode memoryOp); > ExpressionType emitLoadOp(LoadOpType, ExpressionType pointer, uint32_t offset); >@@ -641,9 +643,65 @@ auto B3IRGenerator::setGlobal(uint32_t index, ExpressionType value) -> PartialRe > ASSERT(toB3Type(m_info.globals[index].type) == value->type()); > Value* globalsArray = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(), instanceValue(), safeCast<int32_t>(Instance::offsetOfGlobals())); > m_currentBlock->appendNew<MemoryValue>(m_proc, Store, origin(), value, globalsArray, safeCast<int32_t>(index * sizeof(Register))); >+ >+ if (m_info.globals[index].type == Anyref) >+ emitWriteBarrierForJSWrapper(); >+ > return { }; > } > >+inline void B3IRGenerator::emitWriteBarrierForJSWrapper() >+{ >+ Value* cell = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(), instanceValue(), safeCast<int32_t>(Instance::offsetOfOwner())); >+ Value* cellState = m_currentBlock->appendNew<MemoryValue>(m_proc, Load8Z, Int32, origin(), cell, safeCast<int32_t>(JSCell::cellStateOffset())); >+ Value* vm = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(), cell, safeCast<int32_t>(JSWebAssemblyInstance::offsetOfVM())); >+ Value* threshold = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, Int32, origin(), vm, safeCast<int32_t>(VM::offsetOfHeapBarrierThreshold())); >+ >+ BasicBlock* fenceCheckPath = m_proc.addBlock(); >+ BasicBlock* fencePath = m_proc.addBlock(); >+ BasicBlock* doSlowPath = m_proc.addBlock(); >+ BasicBlock* continuation = m_proc.addBlock(); >+ >+ m_currentBlock->appendNewControlValue(m_proc, B3::Branch, origin(), >+ m_currentBlock->appendNew<Value>(m_proc, Above, origin(), cellState, threshold), >+ FrequentedBlock(continuation), FrequentedBlock(fenceCheckPath, FrequencyClass::Rare)); >+ fenceCheckPath->addPredecessor(m_currentBlock); >+ continuation->addPredecessor(m_currentBlock); >+ m_currentBlock = fenceCheckPath; >+ >+ Value* shouldFence = m_currentBlock->appendNew<MemoryValue>(m_proc, Load8Z, Int32, origin(), vm, safeCast<int32_t>(VM::offsetOfHeapMutatorShouldBeFenced())); >+ m_currentBlock->appendNewControlValue(m_proc, B3::Branch, origin(), >+ shouldFence, >+ FrequentedBlock(fencePath), FrequentedBlock(doSlowPath)); >+ fencePath->addPredecessor(m_currentBlock); >+ doSlowPath->addPredecessor(m_currentBlock); >+ m_currentBlock = fencePath; >+ >+ B3::PatchpointValue* doFence = m_currentBlock->appendNew<B3::PatchpointValue>(m_proc, B3::Void, origin()); >+ doFence->setGenerator([] (CCallHelpers& jit, const B3::StackmapGenerationParams&) { >+ jit.memoryFence(); >+ }); >+ >+ Value* cellStateLoadAfterFence = m_currentBlock->appendNew<MemoryValue>(m_proc, Load8Z, Int32, origin(), cell, safeCast<int32_t>(JSCell::cellStateOffset())); >+ m_currentBlock->appendNewControlValue(m_proc, B3::Branch, origin(), >+ m_currentBlock->appendNew<Value>(m_proc, Above, origin(), cellStateLoadAfterFence, m_currentBlock->appendNew<Const32Value>(m_proc, origin(), blackThreshold)), >+ FrequentedBlock(continuation), FrequentedBlock(doSlowPath, FrequencyClass::Rare)); >+ doSlowPath->addPredecessor(m_currentBlock); >+ continuation->addPredecessor(m_currentBlock); >+ m_currentBlock = doSlowPath; >+ >+ void (*writeBarrier)(JSWebAssemblyInstance*, VM*) = [] (JSWebAssemblyInstance* cell, VM* vm) -> void { >+ vm->heap.writeBarrierSlowPath(cell); >+ }; >+ >+ Value* writeBarrierAddress = m_currentBlock->appendNew<ConstPtrValue>(m_proc, origin(), tagCFunctionPtr<void*>(writeBarrier, B3CCallPtrTag)); >+ m_currentBlock->appendNew<CCallValue>(m_proc, B3::Void, origin(), writeBarrierAddress, cell, vm); >+ m_currentBlock->appendNewControlValue(m_proc, Jump, origin(), continuation); >+ >+ continuation->addPredecessor(m_currentBlock); >+ m_currentBlock = continuation; >+} >+ > inline Value* B3IRGenerator::emitCheckAndPreparePointer(ExpressionType pointer, uint32_t offset, uint32_t sizeOfOperation) > { > ASSERT(m_memoryBaseGPR); >diff --git a/Source/JavaScriptCore/wasm/WasmInstance.cpp b/Source/JavaScriptCore/wasm/WasmInstance.cpp >index dcbaa357e63a2beb9594f635a6805495c6306983..a5e0fcd83d5b23d395dcbe976c4d6d58a2ecebd1 100644 >--- a/Source/JavaScriptCore/wasm/WasmInstance.cpp >+++ b/Source/JavaScriptCore/wasm/WasmInstance.cpp >@@ -28,6 +28,8 @@ > > #if ENABLE(WEBASSEMBLY) > >+#include "JSCInlines.h" >+#include "JSWebAssemblyInstance.h" > #include "Register.h" > #include "WasmModuleInformation.h" > #include <wtf/CheckedArithmetic.h> >@@ -44,7 +46,8 @@ size_t globalMemoryByteSize(Module& module) > Instance::Instance(Context* context, Ref<Module>&& module, EntryFrame** pointerToTopEntryFrame, void** pointerToActualStackLimit, StoreTopCallFrameCallback&& storeTopCallFrame) > : m_context(context) > , m_module(WTFMove(module)) >- , m_globals(MallocPtr<uint64_t>::malloc(globalMemoryByteSize(m_module.get()))) >+ , m_globals(MallocPtr<GlobalValue>::malloc(globalMemoryByteSize(m_module.get()))) >+ , m_globalsToMark(m_module.get().moduleInformation().globals.size()) > , m_pointerToTopEntryFrame(pointerToTopEntryFrame) > , m_pointerToActualStackLimit(pointerToActualStackLimit) > , m_storeTopCallFrame(WTFMove(storeTopCallFrame)) >@@ -52,6 +55,11 @@ Instance::Instance(Context* context, Ref<Module>&& module, EntryFrame** pointerT > { > for (unsigned i = 0; i < m_numImportFunctions; ++i) > new (importFunctionInfo(i)) ImportFunctionInfo(); >+ memset(m_globals.get(), 0, globalMemoryByteSize(m_module.get())); >+ for (unsigned i = 0; i < m_module->moduleInformation().globals.size(); ++i) { >+ if (m_module.get().moduleInformation().globals[i].type == Anyref) >+ m_globalsToMark.set(i); >+ } > } > > Ref<Instance> Instance::create(Context* context, Ref<Module>&& module, EntryFrame** pointerToTopEntryFrame, void** pointerToActualStackLimit, StoreTopCallFrameCallback&& storeTopCallFrame) >@@ -66,6 +74,12 @@ size_t Instance::extraMemoryAllocated() const > return globalMemoryByteSize(m_module.get()) + allocationSize(m_numImportFunctions); > } > >+void Instance::setGlobal(unsigned i, JSValue value) >+{ >+ ASSERT(m_owner); >+ m_globals.get()[i].anyref.set(*owner<JSWebAssemblyInstance>()->vm(), owner<JSWebAssemblyInstance>(), value); >+} >+ > } } // namespace JSC::Wasm > > #endif // ENABLE(WEBASSEMBLY) >diff --git a/Source/JavaScriptCore/wasm/WasmInstance.h b/Source/JavaScriptCore/wasm/WasmInstance.h >index cd34a648dd52fcdbe2474e68b2b7c687277f40e0..5d1fcf3f9d3b82bd0981a20cccd544e7807ce4d7 100644 >--- a/Source/JavaScriptCore/wasm/WasmInstance.h >+++ b/Source/JavaScriptCore/wasm/WasmInstance.h >@@ -31,6 +31,8 @@ > #include "WasmMemory.h" > #include "WasmModule.h" > #include "WasmTable.h" >+#include "WriteBarrier.h" >+#include <wtf/BitVector.h> > #include <wtf/RefPtr.h> > #include <wtf/ThreadSafeRefCounted.h> > >@@ -82,11 +84,13 @@ public: > } > void setTable(Ref<Table>&& table) { m_table = WTFMove(table); } > >- int32_t loadI32Global(unsigned i) const { return m_globals.get()[i]; } >- int64_t loadI64Global(unsigned i) const { return m_globals.get()[i]; } >+ int32_t loadI32Global(unsigned i) const { return m_globals.get()[i].primitive; } >+ int64_t loadI64Global(unsigned i) const { return m_globals.get()[i].primitive; } > float loadF32Global(unsigned i) const { return bitwise_cast<float>(loadI32Global(i)); } > double loadF64Global(unsigned i) const { return bitwise_cast<double>(loadI64Global(i)); } >- void setGlobal(unsigned i, int64_t bits) { m_globals.get()[i] = bits; } >+ void setGlobal(unsigned i, int64_t bits) { m_globals.get()[i].primitive = bits; } >+ void setGlobal(unsigned, JSValue); >+ const BitVector& globalsToMark() { return m_globalsToMark; } > > static ptrdiff_t offsetOfMemory() { return OBJECT_OFFSETOF(Instance, m_memory); } > static ptrdiff_t offsetOfGlobals() { return OBJECT_OFFSETOF(Instance, m_globals); } >@@ -149,7 +153,13 @@ private: > RefPtr<CodeBlock> m_codeBlock; > RefPtr<Memory> m_memory; > RefPtr<Table> m_table; >- MallocPtr<uint64_t> m_globals; >+ >+ union GlobalValue { >+ WriteBarrier<Unknown> anyref; >+ uint64_t primitive; >+ }; >+ MallocPtr<GlobalValue> m_globals; >+ BitVector m_globalsToMark; > EntryFrame** m_pointerToTopEntryFrame { nullptr }; > void** m_pointerToActualStackLimit { nullptr }; > void* m_cachedStackLimit { bitwise_cast<void*>(std::numeric_limits<uintptr_t>::max()) }; >diff --git a/Source/JavaScriptCore/wasm/WasmSectionParser.cpp b/Source/JavaScriptCore/wasm/WasmSectionParser.cpp >index b85ccea426631bc3c167137744863c93a7b7e778..6b940f7364e434d3f33dfda819a97c6f94b0731d 100644 >--- a/Source/JavaScriptCore/wasm/WasmSectionParser.cpp >+++ b/Source/JavaScriptCore/wasm/WasmSectionParser.cpp >@@ -476,6 +476,12 @@ auto SectionParser::parseInitExpr(uint8_t& opcode, uint64_t& bitsOrImportNumber, > break; > } > >+ case RefNull: { >+ resultType = Anyref; >+ bitsOrImportNumber = JSValue::encode(jsNull()); >+ break; >+ } >+ > default: > WASM_PARSER_FAIL_IF(true, "unknown init_expr opcode ", opcode); > } >diff --git a/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp b/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp >index a63cff2fb1878036f1857fd57cbd84a4bdc44f7e..666bf47f1fe23302fc30fd4e1dc73945ea4b3d3f 100644 >--- a/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp >+++ b/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp >@@ -52,6 +52,7 @@ Structure* JSWebAssemblyInstance::createStructure(VM& vm, JSGlobalObject* global > JSWebAssemblyInstance::JSWebAssemblyInstance(VM& vm, Structure* structure, Ref<Wasm::Instance>&& instance) > : Base(vm, structure) > , m_instance(WTFMove(instance)) >+ , m_vm(&vm) > { > for (unsigned i = 0; i < this->instance().numImportFunctions(); ++i) > new (this->instance().importFunction<WriteBarrier<JSObject>>(i)) WriteBarrier<JSObject>(); >@@ -89,6 +90,12 @@ void JSWebAssemblyInstance::visitChildren(JSCell* cell, SlotVisitor& visitor) > visitor.reportExtraMemoryVisited(thisObject->m_instance->extraMemoryAllocated()); > for (unsigned i = 0; i < thisObject->instance().numImportFunctions(); ++i) > visitor.append(*thisObject->instance().importFunction<WriteBarrier<JSObject>>(i)); // This also keeps the functions' JSWebAssemblyInstance alive. >+ >+ for (size_t i : thisObject->instance().globalsToMark()) { >+ // FIXME: We need to box wasm Funcrefs once they are supported here. >+ // <https://bugs.webkit.org/show_bug.cgi?id=198157> >+ visitor.appendUnbarriered(JSValue::decode(thisObject->instance().loadI64Global(i))); >+ } > } > > void JSWebAssemblyInstance::finalizeCreation(VM& vm, ExecState* exec, Ref<Wasm::CodeBlock>&& wasmCodeBlock, JSObject* importObject, Wasm::CreationMode creationMode) >diff --git a/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h b/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h >index faab9369aac2d4bb9d8b3af0fea91b9e4029170d..21784a939d8eb47e8f5246e2663ef367704928e5 100644 >--- a/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h >+++ b/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h >@@ -82,6 +82,7 @@ public: > > static size_t offsetOfInstance() { return OBJECT_OFFSETOF(JSWebAssemblyInstance, m_instance); } > static size_t offsetOfCallee() { return OBJECT_OFFSETOF(JSWebAssemblyInstance, m_callee); } >+ static size_t offsetOfVM() { return OBJECT_OFFSETOF(JSWebAssemblyInstance, m_vm); } > > protected: > JSWebAssemblyInstance(VM&, Structure*, Ref<Wasm::Instance>&&); >@@ -91,6 +92,7 @@ protected: > > private: > Ref<Wasm::Instance> m_instance; >+ VM* m_vm; > > WriteBarrier<JSWebAssemblyModule> m_module; > WriteBarrier<JSWebAssemblyCodeBlock> m_codeBlock; >diff --git a/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp b/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp >index 3765552c1b5aa2f7bc70e743f84f03367bb12e63..5c04d4ed5ac5d8d2c61eed28d773b1c2176fa4fe 100644 >--- a/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp >+++ b/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp >@@ -235,10 +235,13 @@ void WebAssemblyModuleRecord::link(ExecState* exec, JSValue, JSObject* importObj > // ii. If the global_type of i is i64 or Type(v) is not Number, throw a WebAssembly.LinkError. > if (moduleInformation.globals[import.kindIndex].type == Wasm::I64) > return exception(createJSWebAssemblyLinkError(exec, vm, importFailMessage(import, "imported global", "cannot be an i64"))); >- if (!value.isNumber()) >+ if (moduleInformation.globals[import.kindIndex].type != Wasm::Anyref && !value.isNumber()) > return exception(createJSWebAssemblyLinkError(exec, vm, importFailMessage(import, "imported global", "must be a number"))); > // iii. Append ToWebAssemblyValue(v) to imports. > switch (moduleInformation.globals[import.kindIndex].type) { >+ case Wasm::Anyref: >+ m_instance->instance().setGlobal(import.kindIndex, value); >+ break; > case Wasm::I32: > m_instance->instance().setGlobal(import.kindIndex, value.toInt32(exec)); > break; >@@ -379,6 +382,12 @@ void WebAssemblyModuleRecord::link(ExecState* exec, JSValue, JSObject* importObj > ASSERT(global.mutability == Wasm::Global::Immutable); > // Return ToJSValue(v). > switch (global.type) { >+ case Wasm::Anyref: >+ // FIXME: We need to box wasm Funcrefs once they are supported here. >+ // <https://bugs.webkit.org/show_bug.cgi?id=198157> >+ exportedValue = JSValue::decode(m_instance->instance().loadI64Global(exp.kindIndex)); >+ break; >+ > case Wasm::I32: > exportedValue = JSValue(m_instance->instance().loadI32Global(exp.kindIndex)); > break; >diff --git a/Tools/Scripts/run-jsc-stress-tests b/Tools/Scripts/run-jsc-stress-tests >index 2703c4053a23aa3dcce1ab03172d8c6d2a211861..028c16ad9b1b01404e73a89dd6758c99a7ebbf48 100755 >--- a/Tools/Scripts/run-jsc-stress-tests >+++ b/Tools/Scripts/run-jsc-stress-tests >@@ -1081,6 +1081,7 @@ def runWebAssembly > run("wasm-no-tls-context", "-m", "--useFastTLSForWasmContext=false", *FTL_OPTIONS) > run("wasm-slow-memory", "-m", "--useWebAssemblyFastMemory=false", *FTL_OPTIONS) > run("wasm-no-air", "-m", "--wasmBBQUsesAir=false", *FTL_OPTIONS) >+ run("wasm-collect-continuously", "-m", "--collectContinuously=true", *FTL_OPTIONS) > end > end > >@@ -1098,6 +1099,7 @@ def runWebAssemblySuite > run("wasm-no-tls-context", "-m", "--useFastTLSForWasmContext=false", *FTL_OPTIONS) > run("wasm-slow-memory", "-m", "--useWebAssemblyFastMemory=false", *FTL_OPTIONS) > run("wasm-no-air", "-m", "--wasmBBQUsesAir=false", *FTL_OPTIONS) >+ run("wasm-collect-continuously", "-m", "--collectContinuously=true", *FTL_OPTIONS) > end > end > >@@ -1117,6 +1119,7 @@ def runWebAssemblyEmscripten(mode) > run("wasm-no-call-ic", "--useCallICsForWebAssemblyToJSCalls=false", *FTL_OPTIONS) > run("wasm-no-tls-context", "--useFastTLSForWasmContext=false", *FTL_OPTIONS) > run("wasm-no-air", "--wasmBBQUsesAir=false", *FTL_OPTIONS) >+ run("wasm-collect-continuously", "--collectContinuously=true", *FTL_OPTIONS) > end > end > >@@ -1142,6 +1145,7 @@ def runWebAssemblySpecTest(mode) > runWithOutputHandler("wasm-no-call-ic", noisyOutputHandler, "../spec-harness.js", "--useCallICsForWebAssemblyToJSCalls=false", *FTL_OPTIONS) > runWithOutputHandler("wasm-no-tls-context", noisyOutputHandler, "../spec-harness.js", "--useFastTLSForWasmContext=false", *FTL_OPTIONS) > runWithOutputHandler("wasm-no-air", noisyOutputHandler, "../spec-harness.js", "--wasmBBQUsesAir=false", *FTL_OPTIONS) >+ runWithOutputHandler("wasm-collect-continuously", noisyOutputHandler, "../spec-harness.js", "--collectContinuously=true", *FTL_OPTIONS) > end > end > >diff --git a/JSTests/ChangeLog b/JSTests/ChangeLog >index 68de36b936122f781bac003da877ac8209041dfa..cbf193ba3929ad6f14f5c2e77f2382fc9de9c3b4 100644 >--- a/JSTests/ChangeLog >+++ b/JSTests/ChangeLog >@@ -1,3 +1,22 @@ >+2019-05-24 Justin Michaud <justin_michaud@apple.com> >+ >+ [WASM-References] Support Anyref in globals >+ https://bugs.webkit.org/show_bug.cgi?id=198102 >+ >+ Reviewed by Saam Barati. >+ >+ Add test for anyrefs in globals, as well as adding a new RefNull initExpr for Builder. >+ >+ * wasm/Builder.js: >+ (export.default.Builder.prototype._registerSectionBuilders.const.section.in.WASM.description.section.switch.section.case.string_appeared_here.this.section): >+ * wasm/Builder_WebAssemblyBinary.js: >+ (const.putInitExpr): >+ * wasm/references/anyref_globals.js: Added. >+ (GetGlobal.0.End.End.WebAssembly): >+ (5.doGCSet): >+ (doGCTest): >+ (doGCSet.doGCTest.let.count.0.doBarrierSet): >+ > 2019-05-23 Tadeu Zagallo <tzagallo@apple.com> > > DFG::OSREntry should not perform arity check >diff --git a/JSTests/wasm/Builder.js b/JSTests/wasm/Builder.js >index f22de1b81c8409da044bb05112a45cd29fd72896..7e7c1b7dc223c883e10e6f373bcdd3c6c29d511b 100644 >--- a/JSTests/wasm/Builder.js >+++ b/JSTests/wasm/Builder.js >@@ -535,6 +535,10 @@ export default class Builder { > GetGlobal: (type, initValue, mutability) => { > s.data.push({ type, op: "get_global", mutability: _normalizeMutability(mutability), initValue }); > return _errorHandlingProxyFor(globalBuilder); >+ }, >+ RefNull: (type, mutability) => { >+ s.data.push({ type, op: "ref.null", mutability: _normalizeMutability(mutability) }); >+ return _errorHandlingProxyFor(globalBuilder); > } > }; > for (let op of WASM.description.value_type) { >diff --git a/JSTests/wasm/Builder_WebAssemblyBinary.js b/JSTests/wasm/Builder_WebAssemblyBinary.js >index e949835d848c7539582dd801e564c3f88389c155..ca8fd8f65f696f9b509810c1c602ca4a7ad4c6e4 100644 >--- a/JSTests/wasm/Builder_WebAssemblyBinary.js >+++ b/JSTests/wasm/Builder_WebAssemblyBinary.js >@@ -90,7 +90,10 @@ const putOp = (bin, op) => { > }; > > const putInitExpr = (bin, expr) => { >- putOp(bin, { value: WASM.description.opcode[expr.op].value, name: expr.op, immediates: [expr.initValue], arguments: [] }); >+ if (expr.op == "ref.null") >+ putOp(bin, { value: WASM.description.opcode[expr.op].value, name: expr.op, immediates: [], arguments: [] }); >+ else >+ putOp(bin, { value: WASM.description.opcode[expr.op].value, name: expr.op, immediates: [expr.initValue], arguments: [] }); > putOp(bin, { value: WASM.description.opcode.end.value, name: "end", immediates: [], arguments: [] }); > }; > >diff --git a/JSTests/wasm/references/anyref_globals.js b/JSTests/wasm/references/anyref_globals.js >new file mode 100644 >index 0000000000000000000000000000000000000000..184457a33fecb0b08ade13decfcf19e7d33089ae >--- /dev/null >+++ b/JSTests/wasm/references/anyref_globals.js >@@ -0,0 +1,112 @@ >+import * as assert from '../assert.js'; >+import Builder from '../Builder.js'; >+ >+fullGC() >+gc() >+ >+const $1 = new WebAssembly.Instance(new WebAssembly.Module((new Builder()) >+ .Type().End() >+ .Import() >+ .Global().Anyref("imp", "ref", "immutable").End() >+ .End() >+ .Function().End() >+ .Global() >+ .RefNull("anyref", "mutable") >+ .RefNull("anyref", "immutable") >+ .GetGlobal("anyref", 0, "mutable") >+ .End() >+ .Export() >+ .Function("set_glob") >+ .Function("get_glob") >+ .Function("glob_is_null") >+ .Function("set_glob_null") >+ .Function("get_import") >+ .Global("expglob", 2) >+ .Global("expglob2", 0) >+ .End() >+ .Code() >+ .Function("set_glob", { params: ["anyref"], ret: "void" }) >+ .GetLocal(0) >+ .SetGlobal(1) >+ .End() >+ >+ .Function("get_glob", { params: [], ret: "anyref" }) >+ .GetGlobal(1) >+ .End() >+ >+ .Function("glob_is_null", { params: [], ret: "i32" }) >+ .Call(1) >+ .RefIsNull() >+ .End() >+ >+ .Function("set_glob_null", { params: [], ret: "void" }) >+ .RefNull() >+ .Call(0) >+ .End() >+ >+ .Function("get_import", { params: [], ret: "anyref" }) >+ .GetGlobal(0) >+ .End() >+ .End().WebAssembly().get()), { imp: { ref: "hi" } }); >+ >+assert.eq($1.exports.get_import(), "hi") >+assert.eq($1.exports.expglob, null) >+assert.eq($1.exports.expglob2, "hi") >+assert.eq($1.exports.get_glob(), null) >+ >+const obj = { test: "hi" } >+ >+$1.exports.set_glob(obj); assert.eq($1.exports.get_glob(), obj); >+$1.exports.set_glob(5); assert.eq($1.exports.get_glob(), 5) >+$1.exports.set_glob(null); assert.eq($1.exports.get_glob(), null) >+$1.exports.set_glob("hi"); assert.eq($1.exports.get_glob(), "hi") >+$1.exports.set_glob(undefined); assert.eq($1.exports.get_glob(), undefined) >+assert.eq($1.exports.glob_is_null(), 0) >+$1.exports.set_glob_null(); assert.eq($1.exports.get_glob(), null) >+assert.eq($1.exports.glob_is_null(), 1) >+ >+const obj2 = { test: 21 } >+$1.exports.set_glob(obj2); assert.eq($1.exports.get_glob(), obj2) >+ >+$1.exports.get_glob(obj2).test = 5; >+assert.eq($1.exports.get_glob().test, 5) >+assert.eq(obj2.test, 5) >+ >+function doGCSet() { >+ fullGC() >+ $1.exports.set_glob({ test: -1 }) >+ fullGC() >+} >+ >+function doGCTest() { >+ for (let i=0; i<1000; ++i) { >+ assert.eq($1.exports.get_glob().test, -1) >+ fullGC() >+ } >+} >+ >+doGCSet() >+doGCTest() >+ >+let count = 0 >+ >+function doBarrierSet() { >+ ++count >+ $1.exports.set_glob({ test: -count }) >+} >+ >+function doBarrierTest() { >+ let garbage = { val: "hi", val2: 5, arr: [] } >+ for (let i=0; i<100; ++i) garbage.arr += ({ field: i }) >+ >+ for (let j=0; j<1000; ++j) { >+ assert.eq($1.exports.get_glob().test, -count) >+ edenGC() >+ } >+} >+ >+for (let i=0; i<5; ++i) { >+ doBarrierSet() >+ doBarrierTest() >+ doBarrierTest() >+}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 198102
:
370381
|
370485
|
370525
|
370552
|
370562
|
370584
| 370611