Changeset 213386 in webkit
- Timestamp:
- Mar 3, 2017 2:24:21 PM (7 years ago)
- Location:
- trunk/Source
- Files:
-
- 2 added
- 34 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r213381 r213386 1 2017-03-03 Keith Miller <keith_miller@apple.com> 2 3 WASM should support faster loads. 4 https://bugs.webkit.org/show_bug.cgi?id=162693 5 6 Reviewed by Saam Barati. 7 8 This patch adds support for WebAssembly using a 32-bit address 9 space for memory (along with some extra space for offset 10 overflow). With a 32-bit address space (we call them 11 Signaling/fast memories), we reserve the virtual address space for 12 2^32 + offset bytes of memory and only mark the usable section as 13 read/write. If wasm code would read/write out of bounds we use a 14 custom signal handler to catch the SIGBUS. The signal handler then 15 checks if the faulting instruction is wasm code and tells the 16 thread to resume executing from the wasm exception 17 handler. Otherwise, the signal handler crashes the process, as 18 usual. 19 20 All of the allocations of these memories are managed by the 21 Wasm::Memory class. In order to avoid TLB churn in the OS we cache 22 old Signaling memories that are no longer in use. Since getting 23 the wrong memory can cause recompiles, we try to reserve a memory 24 for modules that do not import a memory. If a module does import a 25 memory, we try to guess the type of memory we are going to get 26 based on the last one allocated. 27 28 This patch also changes how the wasm JS-api manages objects. Since 29 we can compile different versions of code, this patch adds a new 30 JSWebAssemblyCodeBlock class that holds all the information 31 specific to running a module in a particular bounds checking 32 mode. Additionally, the Wasm::Memory object is now a reference 33 counted class that is shared between the JSWebAssemblyMemory 34 object and the ArrayBuffer that also views it. 35 36 * JavaScriptCore.xcodeproj/project.pbxproj: 37 * jit/JITThunks.cpp: 38 (JSC::JITThunks::existingCTIStub): 39 * jit/JITThunks.h: 40 * jsc.cpp: 41 (jscmain): 42 * runtime/Options.h: 43 * runtime/VM.cpp: 44 (JSC::VM::VM): 45 * runtime/VM.h: 46 * wasm/JSWebAssemblyCodeBlock.h: Copied from Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h. 47 (JSC::JSWebAssemblyCodeBlock::create): 48 (JSC::JSWebAssemblyCodeBlock::createStructure): 49 (JSC::JSWebAssemblyCodeBlock::functionImportCount): 50 (JSC::JSWebAssemblyCodeBlock::mode): 51 (JSC::JSWebAssemblyCodeBlock::module): 52 (JSC::JSWebAssemblyCodeBlock::jsEntrypointCalleeFromFunctionIndexSpace): 53 (JSC::JSWebAssemblyCodeBlock::wasmEntrypointCalleeFromFunctionIndexSpace): 54 (JSC::JSWebAssemblyCodeBlock::setJSEntrypointCallee): 55 (JSC::JSWebAssemblyCodeBlock::setWasmEntrypointCallee): 56 (JSC::JSWebAssemblyCodeBlock::callees): 57 (JSC::JSWebAssemblyCodeBlock::offsetOfCallees): 58 (JSC::JSWebAssemblyCodeBlock::allocationSize): 59 * wasm/WasmB3IRGenerator.cpp: 60 (JSC::Wasm::B3IRGenerator::B3IRGenerator): 61 (JSC::Wasm::getMemoryBaseAndSize): 62 (JSC::Wasm::B3IRGenerator::emitCheckAndPreparePointer): 63 (JSC::Wasm::B3IRGenerator::emitLoadOp): 64 (JSC::Wasm::B3IRGenerator::emitStoreOp): 65 * wasm/WasmCallingConvention.h: 66 * wasm/WasmFaultSignalHandler.cpp: Added. 67 (JSC::Wasm::trapHandler): 68 (JSC::Wasm::registerCode): 69 (JSC::Wasm::unregisterCode): 70 (JSC::Wasm::fastMemoryEnabled): 71 (JSC::Wasm::enableFastMemory): 72 * wasm/WasmFaultSignalHandler.h: Copied from Source/JavaScriptCore/wasm/js/JSWebAssemblyCallee.cpp. 73 * wasm/WasmFormat.h: 74 (JSC::Wasm::ModuleInformation::importFunctionCount): 75 (JSC::Wasm::ModuleInformation::hasMemory): Deleted. 76 * wasm/WasmMemory.cpp: 77 (JSC::Wasm::mmapBytes): 78 (JSC::Wasm::Memory::lastAllocatedMode): 79 (JSC::Wasm::availableFastMemories): 80 (JSC::Wasm::tryGetFastMemory): 81 (JSC::Wasm::releaseFastMemory): 82 (JSC::Wasm::Memory::Memory): 83 (JSC::Wasm::Memory::createImpl): 84 (JSC::Wasm::Memory::create): 85 (JSC::Wasm::Memory::~Memory): 86 (JSC::Wasm::Memory::grow): 87 (JSC::Wasm::Memory::dump): 88 (JSC::Wasm::Memory::makeString): 89 * wasm/WasmMemory.h: 90 (JSC::Wasm::Memory::operator bool): 91 (JSC::Wasm::Memory::size): 92 (JSC::Wasm::Memory::check): 93 (JSC::Wasm::Memory::Memory): Deleted. 94 (JSC::Wasm::Memory::offsetOfMemory): Deleted. 95 (JSC::Wasm::Memory::offsetOfSize): Deleted. 96 * wasm/WasmMemoryInformation.cpp: 97 (JSC::Wasm::MemoryInformation::MemoryInformation): 98 * wasm/WasmMemoryInformation.h: 99 (JSC::Wasm::MemoryInformation::hasReservedMemory): 100 (JSC::Wasm::MemoryInformation::takeReservedMemory): 101 (JSC::Wasm::MemoryInformation::mode): 102 * wasm/WasmModuleParser.cpp: 103 * wasm/WasmModuleParser.h: 104 (JSC::Wasm::ModuleParser::ModuleParser): 105 * wasm/WasmPlan.cpp: 106 (JSC::Wasm::Plan::parseAndValidateModule): 107 (JSC::Wasm::Plan::run): 108 * wasm/WasmPlan.h: 109 (JSC::Wasm::Plan::mode): 110 * wasm/js/JSWebAssemblyCallee.cpp: 111 (JSC::JSWebAssemblyCallee::finishCreation): 112 (JSC::JSWebAssemblyCallee::destroy): 113 * wasm/js/JSWebAssemblyCodeBlock.cpp: Added. 114 (JSC::JSWebAssemblyCodeBlock::JSWebAssemblyCodeBlock): 115 (JSC::JSWebAssemblyCodeBlock::destroy): 116 (JSC::JSWebAssemblyCodeBlock::isSafeToRun): 117 (JSC::JSWebAssemblyCodeBlock::visitChildren): 118 (JSC::JSWebAssemblyCodeBlock::UnconditionalFinalizer::finalizeUnconditionally): 119 * wasm/js/JSWebAssemblyInstance.cpp: 120 (JSC::JSWebAssemblyInstance::setMemory): 121 (JSC::JSWebAssemblyInstance::finishCreation): 122 (JSC::JSWebAssemblyInstance::visitChildren): 123 * wasm/js/JSWebAssemblyInstance.h: 124 (JSC::JSWebAssemblyInstance::module): 125 (JSC::JSWebAssemblyInstance::codeBlock): 126 (JSC::JSWebAssemblyInstance::memoryMode): 127 (JSC::JSWebAssemblyInstance::setMemory): Deleted. 128 * wasm/js/JSWebAssemblyMemory.cpp: 129 (JSC::JSWebAssemblyMemory::create): 130 (JSC::JSWebAssemblyMemory::JSWebAssemblyMemory): 131 (JSC::JSWebAssemblyMemory::buffer): 132 (JSC::JSWebAssemblyMemory::grow): 133 (JSC::JSWebAssemblyMemory::destroy): 134 * wasm/js/JSWebAssemblyMemory.h: 135 (JSC::JSWebAssemblyMemory::memory): 136 (JSC::JSWebAssemblyMemory::offsetOfMemory): 137 (JSC::JSWebAssemblyMemory::offsetOfSize): 138 * wasm/js/JSWebAssemblyModule.cpp: 139 (JSC::JSWebAssemblyModule::buildCodeBlock): 140 (JSC::JSWebAssemblyModule::create): 141 (JSC::JSWebAssemblyModule::JSWebAssemblyModule): 142 (JSC::JSWebAssemblyModule::codeBlock): 143 (JSC::JSWebAssemblyModule::finishCreation): 144 (JSC::JSWebAssemblyModule::visitChildren): 145 (JSC::JSWebAssemblyModule::UnconditionalFinalizer::finalizeUnconditionally): Deleted. 146 * wasm/js/JSWebAssemblyModule.h: 147 (JSC::JSWebAssemblyModule::takeReservedMemory): 148 (JSC::JSWebAssemblyModule::signatureIndexFromFunctionIndexSpace): 149 (JSC::JSWebAssemblyModule::codeBlock): 150 (JSC::JSWebAssemblyModule::functionImportCount): Deleted. 151 (JSC::JSWebAssemblyModule::jsEntrypointCalleeFromFunctionIndexSpace): Deleted. 152 (JSC::JSWebAssemblyModule::wasmEntrypointCalleeFromFunctionIndexSpace): Deleted. 153 (JSC::JSWebAssemblyModule::setJSEntrypointCallee): Deleted. 154 (JSC::JSWebAssemblyModule::setWasmEntrypointCallee): Deleted. 155 (JSC::JSWebAssemblyModule::callees): Deleted. 156 (JSC::JSWebAssemblyModule::offsetOfCallees): Deleted. 157 (JSC::JSWebAssemblyModule::allocationSize): Deleted. 158 * wasm/js/WebAssemblyFunction.cpp: 159 (JSC::callWebAssemblyFunction): 160 * wasm/js/WebAssemblyInstanceConstructor.cpp: 161 (JSC::constructJSWebAssemblyInstance): 162 * wasm/js/WebAssemblyMemoryConstructor.cpp: 163 (JSC::constructJSWebAssemblyMemory): 164 * wasm/js/WebAssemblyModuleConstructor.cpp: 165 (JSC::WebAssemblyModuleConstructor::createModule): 166 * wasm/js/WebAssemblyModuleRecord.cpp: 167 (JSC::WebAssemblyModuleRecord::link): 168 (JSC::WebAssemblyModuleRecord::evaluate): 169 1 170 2017-03-03 Mark Lam <mark.lam@apple.com> 2 171 -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r213238 r213386 1325 1325 5370B4F51BF26202005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5370B4F31BF25EA2005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.cpp */; }; 1326 1326 5370B4F61BF26205005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 5370B4F41BF25EA2005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.h */; }; 1327 5381B9371E60E9660090F794 /* WasmFaultSignalHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5381B9361E60E9660090F794 /* WasmFaultSignalHandler.cpp */; }; 1328 5381B9391E60E97D0090F794 /* WasmFaultSignalHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 5381B9381E60E97D0090F794 /* WasmFaultSignalHandler.h */; }; 1329 5381B9401E65DFEB0090F794 /* JSWebAssemblyCodeBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = 5381B93F1E65DFEB0090F794 /* JSWebAssemblyCodeBlock.h */; }; 1330 5383AA301E65E8A100A532FC /* JSWebAssemblyCodeBlock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5383AA2F1E65E8A100A532FC /* JSWebAssemblyCodeBlock.cpp */; }; 1327 1331 53917E7B1B7906FA000EBD33 /* JSGenericTypedArrayViewPrototypeFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = 53917E7A1B7906E4000EBD33 /* JSGenericTypedArrayViewPrototypeFunctions.h */; }; 1328 1332 539FB8BA1C99DA7C00940FA1 /* JSArrayInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 539FB8B91C99DA7C00940FA1 /* JSArrayInlines.h */; }; … … 3792 3796 5370B4F31BF25EA2005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AdaptiveInferredPropertyValueWatchpointBase.cpp; sourceTree = "<group>"; }; 3793 3797 5370B4F41BF25EA2005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AdaptiveInferredPropertyValueWatchpointBase.h; sourceTree = "<group>"; }; 3798 5381B9361E60E9660090F794 /* WasmFaultSignalHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmFaultSignalHandler.cpp; sourceTree = "<group>"; }; 3799 5381B9381E60E97D0090F794 /* WasmFaultSignalHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmFaultSignalHandler.h; sourceTree = "<group>"; }; 3800 5381B93F1E65DFEB0090F794 /* JSWebAssemblyCodeBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSWebAssemblyCodeBlock.h; sourceTree = "<group>"; }; 3801 5383AA2F1E65E8A100A532FC /* JSWebAssemblyCodeBlock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JSWebAssemblyCodeBlock.cpp; path = js/JSWebAssemblyCodeBlock.cpp; sourceTree = "<group>"; }; 3794 3802 53917E7A1B7906E4000EBD33 /* JSGenericTypedArrayViewPrototypeFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGenericTypedArrayViewPrototypeFunctions.h; sourceTree = "<group>"; }; 3795 3803 53917E7C1B791106000EBD33 /* JSTypedArrayViewPrototype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSTypedArrayViewPrototype.h; sourceTree = "<group>"; }; … … 6228 6236 53F40E941D5A7AEF0099A1B6 /* WasmModuleParser.h */, 6229 6237 ADB6F67C1E15D7500082F384 /* WasmPageCount.cpp */, 6238 5381B9361E60E9660090F794 /* WasmFaultSignalHandler.cpp */, 6239 5381B9381E60E97D0090F794 /* WasmFaultSignalHandler.h */, 6230 6240 79B759731DFA4C600052174C /* WasmPageCount.h */, 6231 6241 53F40E8C1D5901F20099A1B6 /* WasmParser.h */, … … 7822 7832 79E423E01DEE65320078D355 /* JSWebAssemblyCallee.cpp */, 7823 7833 79E423E11DEE65320078D355 /* JSWebAssemblyCallee.h */, 7834 5383AA2F1E65E8A100A532FC /* JSWebAssemblyCodeBlock.cpp */, 7835 5381B93F1E65DFEB0090F794 /* JSWebAssemblyCodeBlock.h */, 7824 7836 AD2FCBA61DB58DA400B3E736 /* JSWebAssemblyCompileError.cpp */, 7825 7837 AD2FCBA71DB58DA400B3E736 /* JSWebAssemblyCompileError.h */, … … 7962 7974 0FB3878E1BFBC44D00E3AB1E /* AirBlockWorklist.h in Headers */, 7963 7975 0F61832A1C45BF070072450B /* AirCCallingConvention.h in Headers */, 7976 5381B9401E65DFEB0090F794 /* JSWebAssemblyCodeBlock.h in Headers */, 7964 7977 0FEC85741BDACDC70080FF74 /* AirCCallSpecial.h in Headers */, 7965 7978 0FEC85761BDACDC70080FF74 /* AirCode.h in Headers */, … … 8281 8294 0FC3CCFC19ADA410006AC72A /* DFGBlockMap.h in Headers */, 8282 8295 0FC3CCFD19ADA410006AC72A /* DFGBlockMapInlines.h in Headers */, 8296 5381B9391E60E97D0090F794 /* WasmFaultSignalHandler.h in Headers */, 8283 8297 0FC3CCFE19ADA410006AC72A /* DFGBlockSet.h in Headers */, 8284 8298 0FBF158D19B7A53100695DD0 /* DFGBlockSetInlines.h in Headers */, … … 10078 10092 A704D90517A0BAA8006BA554 /* DFGInPlaceAbstractState.cpp in Sources */, 10079 10093 0F3BD1B71B896A0700598AA6 /* DFGInsertionSet.cpp in Sources */, 10094 5381B9371E60E9660090F794 /* WasmFaultSignalHandler.cpp in Sources */, 10080 10095 0F300B7B18AB1B1400A6D72E /* DFGIntegerCheckCombiningPhase.cpp in Sources */, 10081 10096 0F898F311B27689F0083A33C /* DFGIntegerRangeOptimizationPhase.cpp in Sources */, … … 10481 10496 FEB137571BB11EF900CD5100 /* MacroAssemblerARM64.cpp in Sources */, 10482 10497 A729009C17976C6000317298 /* MacroAssemblerARMv7.cpp in Sources */, 10498 5383AA301E65E8A100A532FC /* JSWebAssemblyCodeBlock.cpp in Sources */, 10483 10499 0F6DB7EC1D617D1100CDBF8E /* MacroAssemblerCodeRef.cpp in Sources */, 10484 10500 FE68C6381B90DE0B0042BCB3 /* MacroAssemblerPrinter.cpp in Sources */, -
trunk/Source/JavaScriptCore/jit/JITThunks.cpp
r212365 r213386 83 83 } 84 84 85 MacroAssemblerCodeRef JITThunks::existingCTIStub(ThunkGenerator generator) 86 { 87 LockHolder locker(m_lock); 88 CTIStubMap::iterator entry = m_ctiStubMap.find(generator); 89 if (entry == m_ctiStubMap.end()) 90 return MacroAssemblerCodeRef(); 91 return entry->value; 92 } 93 85 94 void JITThunks::finalize(Handle<Unknown> handle, void*) 86 95 { -
trunk/Source/JavaScriptCore/jit/JITThunks.h
r209764 r213386 59 59 60 60 MacroAssemblerCodeRef ctiStub(VM*, ThunkGenerator); 61 MacroAssemblerCodeRef existingCTIStub(ThunkGenerator); 61 62 62 63 NativeExecutable* hostFunctionStub(VM*, NativeFunction, NativeFunction constructor, const String& name); -
trunk/Source/JavaScriptCore/jsc.cpp
r213151 r213386 73 73 #include "TestRunnerUtils.h" 74 74 #include "TypeProfilerLog.h" 75 #include "WasmFaultSignalHandler.h" 75 76 #include "WasmPlan.h" 76 77 #include "WasmMemory.h" … … 3774 3775 JSC::initializeThreading(); 3775 3776 startTimeoutThreadIfNeeded(); 3777 #if ENABLE(WEBASSEMBLY) 3778 JSC::Wasm::enableFastMemory(); 3779 #endif 3776 3780 3777 3781 int result; -
trunk/Source/JavaScriptCore/runtime/Options.h
r213302 r213386 431 431 v(bool, useWebAssembly, true, Normal, "Expose the WebAssembly global object.") \ 432 432 v(bool, simulateWebAssemblyLowMemory, false, Normal, "If true, the Memory object won't mmap the full 'maximum' range and instead will allocate the minimum required amount.") \ 433 v(bool, useWebAssemblyFastMemory, true, Normal, "If true, we will try to use a 32-bit address space with a signal handler to bounds check wasm memory.") 434 433 435 434 436 enum OptionEquivalence { -
trunk/Source/JavaScriptCore/runtime/VM.cpp
r213338 r213386 242 242 webAssemblyCalleeStructure.set(*this, JSWebAssemblyCallee::createStructure(*this, 0, jsNull())); 243 243 webAssemblyToJSCalleeStructure.set(*this, WebAssemblyToJSCallee::createStructure(*this, 0, jsNull())); 244 webAssemblyCodeBlockStructure.set(*this, JSWebAssemblyCodeBlock::createStructure(*this, 0, jsNull())); 244 245 webAssemblyToJSCallee.set(*this, WebAssemblyToJSCallee::create(*this, webAssemblyToJSCalleeStructure.get())); 245 246 #endif -
trunk/Source/JavaScriptCore/runtime/VM.h
r213338 r213386 335 335 Strong<Structure> webAssemblyCalleeStructure; 336 336 Strong<Structure> webAssemblyToJSCalleeStructure; 337 Strong<Structure> webAssemblyCodeBlockStructure; 337 338 Strong<JSCell> webAssemblyToJSCallee; 338 339 #endif -
trunk/Source/JavaScriptCore/wasm/JSWebAssemblyCodeBlock.h
r213385 r213386 1 1 /* 2 * Copyright (C) 201 6Apple Inc. All rights reserved.2 * Copyright (C) 2017 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 28 28 #if ENABLE(WEBASSEMBLY) 29 29 30 #include "JSDestructibleObject.h" 31 #include "JSObject.h" 30 #include "JSCell.h" 32 31 #include "JSWebAssemblyCallee.h" 33 32 #include "UnconditionalFinalizer.h" … … 38 37 namespace JSC { 39 38 40 class SymbolTable; 39 class JSWebAssemblyModule; 40 class JSWebAssemblyMemory; 41 41 42 class JSWebAssembly Module : public JSDestructibleObject{42 class JSWebAssemblyCodeBlock : public JSCell { 43 43 public: 44 typedef JSDestructibleObject Base; 44 typedef JSCell Base; 45 static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal; 45 46 46 static JSWebAssemblyModule* create(VM&, Structure*, std::unique_ptr<Wasm::ModuleInformation>&&, Bag<CallLinkInfo>&&, Vector<Wasm::WasmExitStubs>&&, SymbolTable*, unsigned); 47 static Structure* createStructure(VM&, JSGlobalObject*, JSValue); 47 static JSWebAssemblyCodeBlock* create(VM& vm, JSWebAssemblyModule* owner, Bag<CallLinkInfo>&& callLinkInfos, Vector<Wasm::WasmExitStubs>&& exitStubs, Wasm::Memory::Mode mode, unsigned calleeCount) 48 { 49 auto* result = new (NotNull, allocateCell<JSWebAssemblyCodeBlock>(vm.heap, allocationSize(calleeCount))) JSWebAssemblyCodeBlock(vm, owner, std::forward<Bag<CallLinkInfo>>(callLinkInfos), std::forward<Vector<Wasm::WasmExitStubs>>(exitStubs), mode, calleeCount); 50 result->finishCreation(vm); 51 return result; 52 } 48 53 49 DECLARE_INFO; 54 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) 55 { 56 return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info()); 57 } 50 58 51 const Wasm::ModuleInformation& moduleInformation() const { return *m_moduleInformation.get(); }52 SymbolTable* exportSymbolTable() const { return m_exportSymbolTable.get(); }53 Wasm::SignatureIndex signatureIndexFromFunctionIndexSpace(unsigned functionIndexSpace) const54 {55 return m_moduleInformation->signatureIndexFromFunctionIndexSpace(functionIndexSpace);56 }57 59 unsigned functionImportCount() const { return m_wasmExitStubs.size(); } 60 Wasm::Memory::Mode mode() const { return m_mode; } 61 JSWebAssemblyModule* module() const { return m_module.get(); } 62 bool isSafeToRun(JSWebAssemblyMemory*); 58 63 59 64 JSWebAssemblyCallee* jsEntrypointCalleeFromFunctionIndexSpace(unsigned functionIndexSpace) … … 90 95 } 91 96 92 protected: 93 JSWebAssemblyModule(VM&, Structure*, std::unique_ptr<Wasm::ModuleInformation>&&, Bag<CallLinkInfo>&&, Vector<Wasm::WasmExitStubs>&&, unsigned calleeCount); 94 void finishCreation(VM&, SymbolTable*); 97 private: 98 JSWebAssemblyCodeBlock(VM&, JSWebAssemblyModule*, Bag<CallLinkInfo>&&, Vector<Wasm::WasmExitStubs>&&, Wasm::Memory::Mode, unsigned calleeCount); 99 DECLARE_EXPORT_INFO; 100 static const bool needsDestruction = true; 95 101 static void destroy(JSCell*); 96 102 static void visitChildren(JSCell*, SlotVisitor&); 97 103 98 private:99 104 static size_t offsetOfCallees() 100 105 { 101 return WTF::roundUpToMultipleOf<sizeof(WriteBarrier<JSWebAssemblyCallee>)>(sizeof(JSWebAssembly Module));106 return WTF::roundUpToMultipleOf<sizeof(WriteBarrier<JSWebAssemblyCallee>)>(sizeof(JSWebAssemblyCodeBlock)); 102 107 } 103 108 … … 107 112 } 108 113 109 class UnconditionalFinalizer : public JSC::UnconditionalFinalizer { 114 class UnconditionalFinalizer : public JSC::UnconditionalFinalizer { 110 115 void finalizeUnconditionally() override; 111 116 }; 112 117 118 WriteBarrier<JSWebAssemblyModule> m_module; 113 119 UnconditionalFinalizer m_unconditionalFinalizer; 114 std::unique_ptr<Wasm::ModuleInformation> m_moduleInformation;115 120 Bag<CallLinkInfo> m_callLinkInfos; 116 WriteBarrier<SymbolTable> m_exportSymbolTable;117 121 Vector<Wasm::WasmExitStubs> m_wasmExitStubs; 122 Wasm::Memory::Mode m_mode; 118 123 unsigned m_calleeCount; 119 124 }; -
trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp
r211195 r213386 208 208 private: 209 209 ExpressionType emitCheckAndPreparePointer(ExpressionType pointer, uint32_t offset, uint32_t sizeOfOp); 210 B3::Kind memoryKind(B3::Opcode memoryOp); 210 211 ExpressionType emitLoadOp(LoadOpType, Origin, ExpressionType pointer, uint32_t offset); 211 212 void emitStoreOp(StoreOpType, Origin, ExpressionType pointer, ExpressionType value, uint32_t offset); … … 260 261 m_proc.pinRegister(regInfo.sizeRegister); 261 262 262 if (info. hasMemory()) {263 if (info.memory) { 263 264 m_proc.setWasmBoundsCheckGenerator([=] (CCallHelpers& jit, GPRReg pinnedGPR, unsigned) { 264 265 AllowMacroScratchRegisterUsage allowScratch(jit); … … 283 284 Value* memoryObject = block->appendNew<MemoryValue>(proc, Load, pointerType(), Origin(), instance, JSWebAssemblyInstance::offsetOfMemory()); 284 285 285 static_assert(sizeof(decltype(vm.topJSWebAssemblyInstance->memory()->memory() ->memory())) == sizeof(void*), "codegen relies on this size");286 static_assert(sizeof(decltype(vm.topJSWebAssemblyInstance->memory()->memory() ->size())) == sizeof(uint64_t), "codegen relies on this size");286 static_assert(sizeof(decltype(vm.topJSWebAssemblyInstance->memory()->memory().memory())) == sizeof(void*), "codegen relies on this size"); 287 static_assert(sizeof(decltype(vm.topJSWebAssemblyInstance->memory()->memory().size())) == sizeof(uint64_t), "codegen relies on this size"); 287 288 MemoryBaseAndSize result; 288 289 result.base = block->appendNew<MemoryValue>(proc, Load, pointerType(), Origin(), memoryObject, JSWebAssemblyMemory::offsetOfMemory()); … … 455 456 inline Value* B3IRGenerator::emitCheckAndPreparePointer(ExpressionType pointer, uint32_t offset, uint32_t sizeOfOperation) 456 457 { 457 ASSERT(m_memoryBaseGPR && m_memorySizeGPR); 458 ASSERT(sizeOfOperation + offset > offset); 459 m_currentBlock->appendNew<WasmBoundsCheckValue>(m_proc, Origin(), pointer, m_memorySizeGPR, sizeOfOperation + offset - 1); 458 ASSERT(m_memoryBaseGPR); 459 if (m_info.memory.mode() == Memory::Mode::BoundsChecking) { 460 ASSERT(m_memorySizeGPR); 461 ASSERT(sizeOfOperation + offset > offset); 462 m_currentBlock->appendNew<WasmBoundsCheckValue>(m_proc, Origin(), pointer, m_memorySizeGPR, sizeOfOperation + offset - 1); 463 } 460 464 pointer = m_currentBlock->appendNew<Value>(m_proc, ZExt32, Origin(), pointer); 461 465 return m_currentBlock->appendNew<WasmAddressValue>(m_proc, Origin(), pointer, m_memoryBaseGPR); … … 487 491 } 488 492 493 inline B3::Kind B3IRGenerator::memoryKind(B3::Opcode memoryOp) 494 { 495 if (m_info.memory.mode() == Memory::Signaling) 496 return trapping(memoryOp); 497 return memoryOp; 498 } 499 489 500 inline Value* B3IRGenerator::emitLoadOp(LoadOpType op, Origin origin, ExpressionType pointer, uint32_t offset) 490 501 { 491 502 switch (op) { 492 503 case LoadOpType::I32Load8S: { 493 return m_currentBlock->appendNew<MemoryValue>(m_proc, Load8S, origin, pointer, offset);504 return m_currentBlock->appendNew<MemoryValue>(m_proc, memoryKind(Load8S), origin, pointer, offset); 494 505 } 495 506 496 507 case LoadOpType::I64Load8S: { 497 Value* value = m_currentBlock->appendNew<MemoryValue>(m_proc, Load8S, origin, pointer, offset);508 Value* value = m_currentBlock->appendNew<MemoryValue>(m_proc, memoryKind(Load8S), origin, pointer, offset); 498 509 return m_currentBlock->appendNew<Value>(m_proc, SExt32, origin, value); 499 510 } 500 511 501 512 case LoadOpType::I32Load8U: { 502 return m_currentBlock->appendNew<MemoryValue>(m_proc, Load8Z, origin, pointer, offset);513 return m_currentBlock->appendNew<MemoryValue>(m_proc, memoryKind(Load8Z), origin, pointer, offset); 503 514 } 504 515 505 516 case LoadOpType::I64Load8U: { 506 Value* value = m_currentBlock->appendNew<MemoryValue>(m_proc, Load8Z, origin, pointer, offset);517 Value* value = m_currentBlock->appendNew<MemoryValue>(m_proc, memoryKind(Load8Z), origin, pointer, offset); 507 518 return m_currentBlock->appendNew<Value>(m_proc, ZExt32, origin, value); 508 519 } 509 520 510 521 case LoadOpType::I32Load16S: { 511 return m_currentBlock->appendNew<MemoryValue>(m_proc, Load16S, origin, pointer, offset);522 return m_currentBlock->appendNew<MemoryValue>(m_proc, memoryKind(Load16S), origin, pointer, offset); 512 523 } 513 524 case LoadOpType::I64Load16S: { 514 Value* value = m_currentBlock->appendNew<MemoryValue>(m_proc, Load16S, origin, pointer, offset);525 Value* value = m_currentBlock->appendNew<MemoryValue>(m_proc, memoryKind(Load16S), origin, pointer, offset); 515 526 return m_currentBlock->appendNew<Value>(m_proc, SExt32, origin, value); 516 527 } 517 528 518 529 case LoadOpType::I32Load: { 519 return m_currentBlock->appendNew<MemoryValue>(m_proc, Load, Int32, origin, pointer, offset);530 return m_currentBlock->appendNew<MemoryValue>(m_proc, memoryKind(Load), Int32, origin, pointer, offset); 520 531 } 521 532 522 533 case LoadOpType::I64Load32U: { 523 Value* value = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, Int32, origin, pointer, offset);534 Value* value = m_currentBlock->appendNew<MemoryValue>(m_proc, memoryKind(Load), Int32, origin, pointer, offset); 524 535 return m_currentBlock->appendNew<Value>(m_proc, ZExt32, origin, value); 525 536 } 526 537 527 538 case LoadOpType::I64Load32S: { 528 Value* value = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, Int32, origin, pointer, offset);539 Value* value = m_currentBlock->appendNew<MemoryValue>(m_proc, memoryKind(Load), Int32, origin, pointer, offset); 529 540 return m_currentBlock->appendNew<Value>(m_proc, SExt32, origin, value); 530 541 } 531 542 532 543 case LoadOpType::I64Load: { 533 return m_currentBlock->appendNew<MemoryValue>(m_proc, Load, Int64, origin, pointer, offset);544 return m_currentBlock->appendNew<MemoryValue>(m_proc, memoryKind(Load), Int64, origin, pointer, offset); 534 545 } 535 546 536 547 case LoadOpType::F32Load: { 537 return m_currentBlock->appendNew<MemoryValue>(m_proc, Load, Float, origin, pointer, offset);548 return m_currentBlock->appendNew<MemoryValue>(m_proc, memoryKind(Load), Float, origin, pointer, offset); 538 549 } 539 550 540 551 case LoadOpType::F64Load: { 541 return m_currentBlock->appendNew<MemoryValue>(m_proc, Load, Double, origin, pointer, offset);552 return m_currentBlock->appendNew<MemoryValue>(m_proc, memoryKind(Load), Double, origin, pointer, offset); 542 553 } 543 554 … … 545 556 // it's added. https://bugs.webkit.org/show_bug.cgi?id=165884 546 557 case LoadOpType::I32Load16U: { 547 Value* value = m_currentBlock->appendNew<MemoryValue>(m_proc, Load16S, origin, pointer, offset);558 Value* value = m_currentBlock->appendNew<MemoryValue>(m_proc, memoryKind(Load16S), origin, pointer, offset); 548 559 return m_currentBlock->appendNew<Value>(m_proc, BitAnd, Origin(), value, 549 560 m_currentBlock->appendNew<Const32Value>(m_proc, Origin(), 0x0000ffff)); 550 561 } 551 562 case LoadOpType::I64Load16U: { 552 Value* value = m_currentBlock->appendNew<MemoryValue>(m_proc, Load16S, origin, pointer, offset);563 Value* value = m_currentBlock->appendNew<MemoryValue>(m_proc, memoryKind(Load16S), origin, pointer, offset); 553 564 Value* partialResult = m_currentBlock->appendNew<Value>(m_proc, BitAnd, Origin(), value, 554 565 m_currentBlock->appendNew<Const32Value>(m_proc, Origin(), 0x0000ffff)); … … 632 643 633 644 case StoreOpType::I32Store8: 634 m_currentBlock->appendNew<MemoryValue>(m_proc, Store8, origin, value, pointer, offset);645 m_currentBlock->appendNew<MemoryValue>(m_proc, memoryKind(Store8), origin, value, pointer, offset); 635 646 return; 636 647 … … 640 651 641 652 case StoreOpType::I32Store16: 642 m_currentBlock->appendNew<MemoryValue>(m_proc, Store16, origin, value, pointer, offset);653 m_currentBlock->appendNew<MemoryValue>(m_proc, memoryKind(Store16), origin, value, pointer, offset); 643 654 return; 644 655 … … 651 662 case StoreOpType::F32Store: 652 663 case StoreOpType::F64Store: 653 m_currentBlock->appendNew<MemoryValue>(m_proc, Store, origin, value, pointer, offset);664 m_currentBlock->appendNew<MemoryValue>(m_proc, memoryKind(Store), origin, value, pointer, offset); 654 665 return; 655 666 } -
trunk/Source/JavaScriptCore/wasm/WasmCallingConvention.h
r210047 r213386 41 41 #include "RegisterSet.h" 42 42 #include "WasmFormat.h" 43 #include "WasmSignature.h" 43 44 44 45 namespace JSC { namespace Wasm { -
trunk/Source/JavaScriptCore/wasm/WasmFaultSignalHandler.h
r213385 r213386 1 1 /* 2 * Copyright (C) 201 6Apple Inc. All rights reserved.2 * Copyright (C) 2017 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 24 24 */ 25 25 26 #include "config.h"27 #include "JSWebAssemblyCallee.h"28 29 26 #if ENABLE(WEBASSEMBLY) 30 31 #include "JSCInlines.h"32 27 33 28 namespace JSC { 34 29 35 c onst ClassInfo JSWebAssemblyCallee::s_info = { "WebAssemblyCallee", nullptr, 0, CREATE_METHOD_TABLE(JSWebAssemblyCallee) };30 class VM; 36 31 37 JSWebAssemblyCallee::JSWebAssemblyCallee(VM& vm) 38 : Base(vm, vm.webAssemblyCalleeStructure.get()) 39 { } 32 namespace Wasm { 40 33 41 void JSWebAssemblyCallee::finishCreation(VM& vm, Wasm::Entrypoint&& entrypoint) 42 { 43 Base::finishCreation(vm); 34 void registerCode(VM&, void* start, void* end); 35 void unregisterCode(VM&, void* start, void* end); 44 36 45 m_entrypoint = WTFMove(entrypoint);46 } 37 bool fastMemoryEnabled(); 38 JS_EXPORT_PRIVATE void enableFastMemory(); 47 39 48 void JSWebAssemblyCallee::destroy(JSCell* cell) 49 { 50 JSWebAssemblyCallee* thisObject = static_cast<JSWebAssemblyCallee*>(cell); 51 thisObject->JSWebAssemblyCallee::~JSWebAssemblyCallee(); 52 } 53 54 } // namespace JSC 40 } } // namespace JSC::Wasm 55 41 56 42 #endif // ENABLE(WEBASSEMBLY) -
trunk/Source/JavaScriptCore/wasm/WasmFormat.h
r210282 r213386 257 257 258 258 uint32_t importFunctionCount() const { return importFunctionSignatureIndices.size(); } 259 bool hasMemory() const { return !!memory; }260 259 261 260 ~ModuleInformation(); -
trunk/Source/JavaScriptCore/wasm/WasmMemory.cpp
r210229 r213386 29 29 #if ENABLE(WEBASSEMBLY) 30 30 31 #include "VM.h" 32 #include "WasmFaultSignalHandler.h" 33 31 34 #include <wtf/HexNumber.h> 35 #include <wtf/NeverDestroyed.h> 32 36 #include <wtf/PrintStream.h> 33 37 #include <wtf/text/WTFString.h> … … 39 43 } 40 44 41 void Memory::dump(PrintStream& out) const 42 { 43 String memoryHex; 44 WTF::appendUnsigned64AsHex((uint64_t)(uintptr_t)m_memory, memoryHex); 45 out.print("Memory at 0x", memoryHex, ", size ", m_size, "B capacity ", m_mappedCapacity, "B, initial ", m_initial, " maximum ", m_maximum, " mode ", makeString(m_mode)); 46 } 47 48 const char* Memory::makeString(Mode mode) const 49 { 50 switch (mode) { 51 case Mode::BoundsChecking: return "BoundsChecking"; 52 } 53 RELEASE_ASSERT_NOT_REACHED(); 54 return ""; 55 } 56 57 static_assert(sizeof(uint64_t) == sizeof(size_t), "We rely on allowing the maximum size of Memory we map to be 2^32 which is larger than fits in a 32-bit integer that we'd pass to mprotect if this didn't hold."); 58 59 Memory::Memory(PageCount initial, PageCount maximum, bool& failed) 60 : m_size(initial.bytes()) 45 inline bool mmapBytes(size_t bytes, void*& memory) 46 { 47 dataLogIf(verbose, "Attempting to mmap ", bytes, " bytes: "); 48 // FIXME: It would be nice if we had a VM tag for wasm memory. https://bugs.webkit.org/show_bug.cgi?id=163600 49 void* result = mmap(nullptr, bytes, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0); 50 if (result == MAP_FAILED) { 51 dataLogLnIf(verbose, "failed"); 52 return false; 53 } 54 dataLogLnIf(verbose, "succeeded"); 55 memory = result; 56 return true; 57 } 58 59 // We use this as a heuristic to guess what mode a memory import will be. Most of the time we expect users to 60 // allocate the memory they are going to pass to all their modules right before compilation. 61 static Memory::Mode lastAllocatedMemoryMode { Memory::Mode::Signaling }; 62 63 Memory::Mode Memory::lastAllocatedMode() 64 { 65 return lastAllocatedMemoryMode; 66 } 67 68 static_assert(sizeof(uint64_t) == sizeof(size_t), "We rely on allowing the maximum size of Memory we map to be 2^33 which is larger than fits in a 32-bit integer that we'd pass to mprotect if this didn't hold."); 69 70 static const size_t fastMemoryMappedBytes = (static_cast<size_t>(std::numeric_limits<uint32_t>::max()) + 1) * 2; // pointer max + offset max. This is all we need since a load straddling readable memory will trap. 71 static const unsigned maxFastMemories = 4; 72 static unsigned allocatedFastMemories { 0 }; 73 static StaticLock memoryLock; 74 inline Deque<void*, maxFastMemories>& availableFastMemories(const LockHolder&) 75 { 76 static NeverDestroyed<Deque<void*, maxFastMemories>> availableFastMemories; 77 return availableFastMemories; 78 } 79 80 inline bool tryGetFastMemory(VM& vm, void*& memory, size_t& mappedCapacity, Memory::Mode& mode) 81 { 82 // We might GC here so we should be holding the API lock. 83 // FIXME: We should be able to syncronously trigger the GC from another thread. 84 ASSERT(vm.currentThreadIsHoldingAPILock()); 85 if (!fastMemoryEnabled()) 86 return false; 87 88 // We need to be sure we have a stub prior to running code. 89 if (!vm.getCTIStub(throwExceptionFromWasmThunkGenerator).size()) 90 return false; 91 92 auto dequeFastMemory = [&] () -> bool { 93 // FIXME: We should eventually return these to the OS if we go some number of GCs 94 // without using them. 95 LockHolder locker(memoryLock); 96 if (!availableFastMemories(locker).isEmpty()) { 97 memory = availableFastMemories(locker).takeFirst(); 98 mappedCapacity = fastMemoryMappedBytes; 99 mode = Memory::Signaling; 100 return true; 101 } 102 return false; 103 }; 104 105 ASSERT(allocatedFastMemories <= maxFastMemories); 106 if (dequeFastMemory()) 107 return true; 108 109 // If we have allocated all the fast memories... too bad. 110 if (allocatedFastMemories == maxFastMemories) { 111 // There is a reasonable chance that another module has died but has not been collected yet. Don't lose hope yet! 112 vm.heap.collectSync(); 113 return dequeFastMemory(); 114 } 115 116 if (mmapBytes(fastMemoryMappedBytes, memory)) { 117 mappedCapacity = fastMemoryMappedBytes; 118 mode = Memory::Signaling; 119 allocatedFastMemories++; 120 } 121 return memory; 122 } 123 124 inline void releaseFastMemory(void*& memory, size_t writableSize, size_t mappedCapacity, Memory::Mode mode) 125 { 126 if (mode != Memory::Signaling || !memory) 127 return; 128 129 RELEASE_ASSERT(memory && mappedCapacity == fastMemoryMappedBytes); 130 ASSERT(fastMemoryEnabled()); 131 132 memset(memory, 0, writableSize); 133 if (mprotect(memory, writableSize, PROT_NONE)) 134 CRASH(); 135 136 LockHolder locker(memoryLock); 137 ASSERT(availableFastMemories(locker).size() < allocatedFastMemories); 138 availableFastMemories(locker).append(memory); 139 memory = nullptr; 140 } 141 142 Memory::Memory(PageCount initial, PageCount maximum) 143 : m_initial(initial) 144 , m_maximum(maximum) 145 { 146 ASSERT(!initial.bytes()); 147 } 148 149 Memory::Memory(void* memory, PageCount initial, PageCount maximum, size_t mappedCapacity, Mode mode) 150 : m_memory(memory) 151 , m_size(initial.bytes()) 61 152 , m_initial(initial) 62 153 , m_maximum(maximum) 63 , m_mode(Mode::BoundsChecking) 64 // FIXME: If we add signal based bounds checking then we need extra space for overflow on load. 65 // see: https://bugs.webkit.org/show_bug.cgi?id=162693 154 , m_mappedCapacity(mappedCapacity) 155 , m_mode(mode) 156 { 157 dataLogLnIf(verbose, "Memory::Memory allocating ", *this); 158 } 159 160 RefPtr<Memory> Memory::createImpl(VM& vm, PageCount initial, PageCount maximum, std::optional<Mode> requiredMode) 66 161 { 67 162 RELEASE_ASSERT(!maximum || maximum >= initial); // This should be guaranteed by our caller. 68 163 69 m_mappedCapacity = maximum ? maximum.bytes() : PageCount::max().bytes(); 70 if (!m_mappedCapacity) { 164 Mode mode = requiredMode ? *requiredMode : BoundsChecking; 165 const size_t size = initial.bytes(); 166 size_t mappedCapacity = maximum ? maximum.bytes() : PageCount::max().bytes(); 167 void* memory = nullptr; 168 169 auto makeEmptyMemory = [&] () -> RefPtr<Memory> { 170 if (mode == Signaling) 171 return nullptr; 172 173 lastAllocatedMemoryMode = BoundsChecking; 174 return adoptRef(new Memory(initial, maximum)); 175 }; 176 177 if (!mappedCapacity) { 71 178 // This means we specified a zero as maximum (which means we also have zero as initial size). 72 RELEASE_ASSERT(m_size == 0); 73 m_memory = nullptr; 74 m_mappedCapacity = 0; 75 failed = false; 76 if (verbose) 77 dataLogLn("Memory::Memory allocating nothing ", *this); 78 return; 79 } 80 81 // FIXME: It would be nice if we had a VM tag for wasm memory. https://bugs.webkit.org/show_bug.cgi?id=163600 82 void* result = Options::simulateWebAssemblyLowMemory() ? MAP_FAILED : mmap(nullptr, m_mappedCapacity, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0); 83 if (result == MAP_FAILED) { 84 // Try again with a different number. 85 if (verbose) 86 dataLogLn("Memory::Memory mmap failed once for capacity, trying again", *this); 87 m_mappedCapacity = m_size; 88 if (!m_mappedCapacity) { 89 m_memory = nullptr; 90 failed = false; 91 if (verbose) 92 dataLogLn("Memory::Memory mmap not trying again because size is zero ", *this); 93 return; 179 RELEASE_ASSERT(!size); 180 dataLogLnIf(verbose, "Memory::create allocating nothing"); 181 return makeEmptyMemory(); 182 } 183 184 bool canUseFastMemory = !requiredMode || requiredMode == Signaling; 185 if (!canUseFastMemory || !tryGetFastMemory(vm, memory, mappedCapacity, mode)) { 186 if (mode == Signaling) 187 return nullptr; 188 189 if (Options::simulateWebAssemblyLowMemory() ? true : !mmapBytes(mappedCapacity, memory)) { 190 // Try again with a different number. 191 dataLogLnIf(verbose, "Memory::create mmap failed once for capacity, trying again"); 192 mappedCapacity = size; 193 if (!mappedCapacity) { 194 dataLogLnIf(verbose, "Memory::create mmap not trying again because size is zero"); 195 return makeEmptyMemory(); 196 } 197 198 if (!mmapBytes(mappedCapacity, memory)) { 199 dataLogLnIf(verbose, "Memory::create mmap failed twice"); 200 return nullptr; 201 } 94 202 } 95 96 result = mmap(nullptr, m_mappedCapacity, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0); 97 if (result == MAP_FAILED) { 98 if (verbose) 99 dataLogLn("Memory::Memory mmap failed twice ", *this); 100 failed = true; 101 return; 203 } 204 205 ASSERT(memory && size <= mappedCapacity); 206 if (mprotect(memory, size, PROT_READ | PROT_WRITE)) { 207 dataLogLnIf(verbose, "Memory::create mprotect failed"); 208 releaseFastMemory(memory, 0, mappedCapacity, mode); 209 if (memory) { 210 if (munmap(memory, mappedCapacity)) 211 CRASH(); 102 212 } 103 } 104 105 ASSERT(m_size <= m_mappedCapacity); 106 { 107 bool success = !mprotect(result, static_cast<size_t>(m_size), PROT_READ | PROT_WRITE); 108 RELEASE_ASSERT(success); 109 } 110 111 m_memory = result; 112 failed = false; 113 if (verbose) 114 dataLogLn("Memory::Memory mmap succeeded ", *this); 213 return nullptr; 214 } 215 216 lastAllocatedMemoryMode = mode; 217 dataLogLnIf(verbose, "Memory::create mmap succeeded"); 218 return adoptRef(new Memory(memory, initial, maximum, mappedCapacity, mode)); 219 } 220 221 RefPtr<Memory> Memory::create(VM& vm, PageCount initial, PageCount maximum, std::optional<Mode> mode) 222 { 223 RELEASE_ASSERT(!maximum || maximum >= initial); // This should be guaranteed by our caller. 224 RefPtr<Memory> result = createImpl(vm, initial, maximum, mode); 225 if (result) { 226 if (result->mode() == Signaling) 227 RELEASE_ASSERT(result->m_mappedCapacity == fastMemoryMappedBytes); 228 if (mode) 229 ASSERT(*mode == result->mode()); 230 ASSERT(lastAllocatedMemoryMode == result->mode()); 231 } 232 return result; 115 233 } 116 234 117 235 Memory::~Memory() 118 236 { 119 if (verbose)120 dataLogLn("Memory::~Memory ", *this);237 dataLogLnIf(verbose, "Memory::~Memory ", *this); 238 releaseFastMemory(m_memory, m_size, m_mappedCapacity, m_mode); 121 239 if (m_memory) { 122 240 if (munmap(m_memory, m_mappedCapacity)) … … 129 247 RELEASE_ASSERT(newSize > PageCount::fromBytes(m_size)); 130 248 131 if (verbose) 132 dataLogLn("Memory::grow to ", newSize, " from ", *this); 249 dataLogLnIf(verbose, "Memory::grow to ", newSize, " from ", *this); 133 250 134 251 if (maximum() && newSize > maximum()) 135 252 return false; 136 253 137 uint64_t desiredSize = newSize.bytes();254 size_t desiredSize = newSize.bytes(); 138 255 139 256 if (m_memory && desiredSize <= m_mappedCapacity) { 140 bool success = !mprotect(static_cast<uint8_t*>(m_memory) + m_size, static_cast<size_t>(desiredSize - m_size), PROT_READ | PROT_WRITE); 141 RELEASE_ASSERT(success); 257 if (mprotect(static_cast<uint8_t*>(m_memory) + m_size, static_cast<size_t>(desiredSize - m_size), PROT_READ | PROT_WRITE)) { 258 dataLogLnIf(verbose, "Memory::grow in-place failed ", *this); 259 return false; 260 } 261 142 262 m_size = desiredSize; 143 if (verbose) 144 dataLogLn("Memory::grow in-place ", *this); 263 dataLogLnIf(verbose, "Memory::grow in-place ", *this); 145 264 return true; 146 265 } 147 266 267 ASSERT(mode() != Signaling); 148 268 // Otherwise, let's try to make some new memory. 149 269 void* newMemory = mmap(nullptr, desiredSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); … … 160 280 m_size = desiredSize; 161 281 162 if (verbose) 163 dataLogLn("Memory::grow ", *this); 282 dataLogLnIf(verbose, "Memory::grow ", *this); 164 283 return true; 165 284 } 166 285 286 void Memory::dump(PrintStream& out) const 287 { 288 out.print("Memory at ", RawPointer(m_memory), ", size ", m_size, "B capacity ", m_mappedCapacity, "B, initial ", m_initial, " maximum ", m_maximum, " mode ", makeString(m_mode)); 289 } 290 291 const char* Memory::makeString(Mode mode) const 292 { 293 switch (mode) { 294 case Mode::BoundsChecking: return "BoundsChecking"; 295 case Mode::Signaling: return "Signaling"; 296 case Mode::NumberOfModes: break; 297 } 298 RELEASE_ASSERT_NOT_REACHED(); 299 return ""; 300 } 301 167 302 } // namespace JSC 168 303 -
trunk/Source/JavaScriptCore/wasm/WasmMemory.h
r210229 r213386 28 28 #if ENABLE(WEBASSEMBLY) 29 29 30 #include "WasmCallingConvention.h"31 30 #include "WasmPageCount.h" 31 32 #include <wtf/Optional.h> 33 #include <wtf/RefCounted.h> 34 #include <wtf/RefPtr.h> 32 35 33 36 namespace WTF { … … 35 38 } 36 39 37 namespace JSC { namespace Wasm {40 namespace JSC { 38 41 39 class Memory { 42 class VM; 43 44 namespace Wasm { 45 46 class Memory : public RefCounted<Memory> { 40 47 WTF_MAKE_NONCOPYABLE(Memory); 41 48 WTF_MAKE_FAST_ALLOCATED; … … 44 51 45 52 // FIXME: We should support other modes. see: https://bugs.webkit.org/show_bug.cgi?id=162693 46 enum class Mode { 47 BoundsChecking 53 enum Mode { 54 BoundsChecking, 55 Signaling, 56 NumberOfModes 48 57 }; 49 58 const char* makeString(Mode) const; 50 59 60 explicit operator bool() const { return !!m_memory; } 61 62 static RefPtr<Memory> create(VM&, PageCount initial, PageCount maximum, std::optional<Mode> requiredMode = std::nullopt); 63 51 64 Memory() = default; 52 JS_EXPORT_PRIVATE Memory(PageCount initial, PageCount maximum, bool& failed);53 Memory(Memory&& other)54 : m_memory(other.m_memory)55 , m_size(other.m_size)56 , m_initial(other.m_initial)57 , m_maximum(other.m_maximum)58 , m_mappedCapacity(other.m_mappedCapacity)59 , m_mode(other.m_mode)60 {61 // Moving transfers ownership of the allocated memory.62 other.m_memory = nullptr;63 }64 65 ~Memory(); 65 66 66 67 void* memory() const { return m_memory; } 67 uint64_t size() const { return m_size; }68 size_t size() const { return m_size; } 68 69 PageCount sizeInPages() const { return PageCount::fromBytes(m_size); } 69 70 … … 71 72 PageCount maximum() const { return m_maximum; } 72 73 74 static Mode lastAllocatedMode(); 73 75 Mode mode() const { return m_mode; } 74 76 77 // grow() should only be called from the JSWebAssemblyMemory object since that object needs to update internal 78 // pointers with the current base and size. 75 79 bool grow(PageCount); 76 80 77 static ptrdiff_t offsetOfMemory() { return OBJECT_OFFSETOF(Memory, m_memory); } 78 static ptrdiff_t offsetOfSize() { return OBJECT_OFFSETOF(Memory, m_size); } 79 81 void check() { ASSERT(!deletionHasBegun()); } 80 82 private: 83 static RefPtr<Memory> createImpl(VM&, PageCount initial, PageCount maximum, std::optional<Mode> requiredMode = std::nullopt); 84 Memory(void* memory, PageCount initial, PageCount maximum, size_t mappedCapacity, Mode); 85 Memory(PageCount initial, PageCount maximum); 86 87 // FIXME: we should move these to the instance to avoid a load on instance->instance calls. 81 88 void* m_memory { nullptr }; 82 uint64_t m_size { 0 };89 size_t m_size { 0 }; 83 90 PageCount m_initial; 84 91 PageCount m_maximum; 85 uint64_t m_mappedCapacity { 0 };92 size_t m_mappedCapacity { 0 }; 86 93 Mode m_mode { Mode::BoundsChecking }; 87 94 }; -
trunk/Source/JavaScriptCore/wasm/WasmMemoryInformation.cpp
r210229 r213386 30 30 31 31 #include "WasmCallingConvention.h" 32 #include "WasmMemory.h" 32 33 #include <wtf/NeverDestroyed.h> 33 34 … … 49 50 unsigned remainingPinnedRegisters = pinnedSizes.size() + 1; 50 51 jscCallingConvention().m_calleeSaveRegisters.forEach([&] (Reg reg) { 52 if (!reg.isGPR()) 53 return; 51 54 GPRReg gpr = reg.gpr(); 52 55 if (!remainingPinnedRegisters || RegisterSet::stackRegisters().get(reg)) … … 72 75 } 73 76 74 MemoryInformation::MemoryInformation( PageCount initial, PageCount maximum,bool isImport)77 MemoryInformation::MemoryInformation(VM& vm, PageCount initial, PageCount maximum, std::optional<Memory::Mode> recompileMode, bool isImport) 75 78 : m_initial(initial) 76 79 , m_maximum(maximum) … … 80 83 RELEASE_ASSERT(!m_maximum || m_maximum >= m_initial); 81 84 ASSERT(!!*this); 85 86 if (!recompileMode) { 87 if (!isImport) { 88 m_reservedMemory = Memory::create(vm, initial, maximum, Memory::Signaling); 89 if (m_reservedMemory) { 90 ASSERT(!!*m_reservedMemory); 91 m_mode = m_reservedMemory->mode(); 92 return; 93 } 94 } 95 m_mode = Memory::lastAllocatedMode(); 96 } else 97 m_mode = *recompileMode; 82 98 } 83 99 -
trunk/Source/JavaScriptCore/wasm/WasmMemoryInformation.h
r210229 r213386 29 29 30 30 #include "GPRInfo.h" 31 #include "WasmMemory.h" 31 32 #include "WasmPageCount.h" 33 #include <wtf/Ref.h> 32 34 #include <wtf/Vector.h> 33 35 … … 53 55 } 54 56 55 MemoryInformation( PageCount initial, PageCount maximum, bool isImport);57 MemoryInformation(VM&, PageCount initial, PageCount maximum, std::optional<Memory::Mode>, bool isImport); 56 58 57 59 PageCount initial() const { return m_initial; } 58 60 PageCount maximum() const { return m_maximum; } 61 bool hasReservedMemory() const { return m_reservedMemory; } 62 RefPtr<Memory> takeReservedMemory() { ASSERT(hasReservedMemory()); return m_reservedMemory.release(); } 63 Memory::Mode mode() const { return m_mode; } 59 64 bool isImport() const { return m_isImport; } 60 65 … … 62 67 63 68 private: 69 RefPtr<Memory> m_reservedMemory; 64 70 PageCount m_initial { }; 65 71 PageCount m_maximum { }; 72 Memory::Mode m_mode { Memory::Mode::BoundsChecking }; 66 73 bool m_isImport { false }; 67 74 }; -
trunk/Source/JavaScriptCore/wasm/WasmModuleParser.cpp
r212983 r213386 317 317 ASSERT(!maximumPageCount || maximumPageCount >= initialPageCount); 318 318 319 m_result.module->memory = MemoryInformation( initialPageCount, maximumPageCount, isImport);319 m_result.module->memory = MemoryInformation(*m_vm, initialPageCount, maximumPageCount, m_mode, isImport); 320 320 return { }; 321 321 } -
trunk/Source/JavaScriptCore/wasm/WasmModuleParser.h
r210282 r213386 31 31 #include "WasmOps.h" 32 32 #include "WasmParser.h" 33 #include <wtf/Optional.h> 33 34 #include <wtf/Vector.h> 34 35 … … 44 45 public: 45 46 46 ModuleParser(VM* vm, const uint8_t* sourceBuffer, size_t sourceLength )47 ModuleParser(VM* vm, const uint8_t* sourceBuffer, size_t sourceLength, std::optional<Memory::Mode> mode) 47 48 : Parser(vm, sourceBuffer, sourceLength) 48 { 49 } 50 ModuleParser(VM* vm, const Vector<uint8_t>& sourceBuffer) 51 : ModuleParser(vm, sourceBuffer.data(), sourceBuffer.size()) 49 , m_mode(mode) 52 50 { 53 51 } … … 69 67 70 68 ModuleParserResult m_result; 69 std::optional<Memory::Mode> m_mode { std::nullopt }; 71 70 bool m_hasTable { false }; 72 71 }; -
trunk/Source/JavaScriptCore/wasm/WasmPlan.cpp
r210229 r213386 36 36 #include "WasmBinding.h" 37 37 #include "WasmCallingConvention.h" 38 #include "WasmFaultSignalHandler.h" 38 39 #include "WasmMemory.h" 39 40 #include "WasmModuleParser.h" … … 62 63 } 63 64 64 bool Plan::parseAndValidateModule( )65 bool Plan::parseAndValidateModule(std::optional<Memory::Mode> recompileMode) 65 66 { 66 67 MonotonicTime startTime; … … 69 70 70 71 { 71 ModuleParser moduleParser(m_vm, m_source, m_sourceLength );72 ModuleParser moduleParser(m_vm, m_source, m_sourceLength, recompileMode); 72 73 auto parseResult = moduleParser.parse(); 73 74 if (!parseResult) { … … 110 111 // that could touch its stack are done executing. 111 112 SUPPRESS_ASAN 112 void Plan::run( )113 { 114 if (!parseAndValidateModule( ))113 void Plan::run(std::optional<Memory::Mode> recompileMode) 114 { 115 if (!parseAndValidateModule(recompileMode)) 115 116 return; 117 if (recompileMode) 118 ASSERT(m_moduleInformation->memory.mode() == recompileMode); 116 119 117 120 auto tryReserveCapacity = [this] (auto& vector, size_t size, const char* what) { -
trunk/Source/JavaScriptCore/wasm/WasmPlan.h
r210229 r213386 50 50 JS_EXPORT_PRIVATE ~Plan(); 51 51 52 bool parseAndValidateModule( );52 bool parseAndValidateModule(std::optional<Memory::Mode> = std::nullopt); 53 53 54 JS_EXPORT_PRIVATE void run( );54 JS_EXPORT_PRIVATE void run(std::optional<Memory::Mode> = std::nullopt); 55 55 56 56 JS_EXPORT_PRIVATE void initializeCallees(JSGlobalObject*, std::function<void(unsigned, JSWebAssemblyCallee*, JSWebAssemblyCallee*)>); … … 93 93 } 94 94 95 Memory::Mode mode() const { return m_moduleInformation->memory.mode(); } 96 95 97 private: 96 98 std::unique_ptr<ModuleInformation> m_moduleInformation; -
trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyCallee.cpp
r210829 r213386 30 30 31 31 #include "JSCInlines.h" 32 #include "WasmFaultSignalHandler.h" 32 33 33 34 namespace JSC { … … 44 45 45 46 m_entrypoint = WTFMove(entrypoint); 47 Wasm::registerCode(vm, m_entrypoint.compilation->codeRef().executableMemory()->start(), m_entrypoint.compilation->codeRef().executableMemory()->end()); 46 48 } 47 49 … … 49 51 { 50 52 JSWebAssemblyCallee* thisObject = static_cast<JSWebAssemblyCallee*>(cell); 53 Wasm::unregisterCode(*cell->vm(), thisObject->m_entrypoint.compilation->codeRef().executableMemory()->start(), thisObject->m_entrypoint.compilation->codeRef().executableMemory()->end()); 51 54 thisObject->JSWebAssemblyCallee::~JSWebAssemblyCallee(); 52 55 } -
trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp
r211247 r213386 1 1 /* 2 * Copyright (C) 2016 Apple Inc. All rights reserved.2 * Copyright (C) 2016-2017 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 39 39 namespace JSC { 40 40 41 void JSWebAssemblyInstance::setMemory(VM& vm, ExecState* exec, JSWebAssemblyMemory* memory) 42 { 43 auto scope = DECLARE_THROW_SCOPE(vm); 44 // We create stub memories even for modules that should eventually get a memory so we want to avoid recompling there. 45 if (memory->memory()) { 46 auto codeBlock = m_codeBlock->module()->codeBlock(vm, exec, memory); 47 RETURN_IF_EXCEPTION(scope,); 48 m_codeBlock.set(vm, this, codeBlock); 49 } 50 m_memory.set(vm, this, memory); 51 } 52 41 53 JSWebAssemblyInstance* JSWebAssemblyInstance::create(VM& vm, Structure* structure, JSWebAssemblyModule* module, JSModuleNamespaceObject* moduleNamespaceObject) 42 54 { … … 68 80 heap()->reportExtraMemoryAllocated(extraMemorySize); 69 81 70 m_ module.set(vm, this, module);82 m_codeBlock.set(vm, this, module->codeBlock()); 71 83 m_moduleNamespaceObject.set(vm, this, moduleNamespaceObject); 72 84 putDirect(vm, Identifier::fromString(&vm, "exports"), moduleNamespaceObject, None); … … 84 96 85 97 Base::visitChildren(thisObject, visitor); 86 visitor.append(thisObject->m_ module);98 visitor.append(thisObject->m_codeBlock); 87 99 visitor.append(thisObject->m_moduleNamespaceObject); 88 100 visitor.append(thisObject->m_memory); -
trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h
r210229 r213386 30 30 #include "JSDestructibleObject.h" 31 31 #include "JSObject.h" 32 #include "JSWebAssemblyCodeBlock.h" 32 33 #include "JSWebAssemblyMemory.h" 33 34 #include "JSWebAssemblyTable.h" … … 48 49 DECLARE_INFO; 49 50 50 JSWebAssemblyModule* module() 51 JSWebAssemblyModule* module() const 51 52 { 52 ASSERT(m_module); 53 return m_module.get(); 53 ASSERT(m_codeBlock); 54 return m_codeBlock->module(); 55 } 56 57 JSWebAssemblyCodeBlock* codeBlock() const 58 { 59 ASSERT(m_codeBlock); 60 return m_codeBlock.get(); 54 61 } 55 62 … … 71 78 72 79 JSWebAssemblyMemory* memory() { return m_memory.get(); } 73 void setMemory(VM& vm, JSWebAssemblyMemory* memory) { m_memory.set(vm, this, memory); } 80 // Calling this might trigger a recompile. 81 void setMemory(VM&, ExecState*, JSWebAssemblyMemory*); 82 Wasm::Memory::Mode memoryMode() { return memory()->memory().mode(); } 74 83 75 84 JSWebAssemblyTable* table() { return m_table.get(); } … … 105 114 106 115 private: 107 WriteBarrier<JSWebAssembly Module> m_module;116 WriteBarrier<JSWebAssemblyCodeBlock> m_codeBlock; 108 117 WriteBarrier<JSModuleNamespaceObject> m_moduleNamespaceObject; 109 118 WriteBarrier<JSWebAssemblyMemory> m_memory; -
trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyMemory.cpp
r211247 r213386 38 38 const ClassInfo JSWebAssemblyMemory::s_info = { "WebAssembly.Memory", &Base::s_info, 0, CREATE_METHOD_TABLE(JSWebAssemblyMemory) }; 39 39 40 JSWebAssemblyMemory* JSWebAssemblyMemory::create(VM& vm, Structure* structure, Wasm::Memory&& memory)40 JSWebAssemblyMemory* JSWebAssemblyMemory::create(VM& vm, Structure* structure, Ref<Wasm::Memory>&& memory) 41 41 { 42 auto* instance = new (NotNull, allocateCell<JSWebAssemblyMemory>(vm.heap)) JSWebAssemblyMemory(vm, structure, std::forward<Wasm::Memory>(memory)); 42 auto* instance = new (NotNull, allocateCell<JSWebAssemblyMemory>(vm.heap)) JSWebAssemblyMemory(vm, structure, WTFMove(memory)); 43 instance->m_memory->check(); 43 44 instance->finishCreation(vm); 44 45 return instance; … … 50 51 } 51 52 52 JSWebAssemblyMemory::JSWebAssemblyMemory(VM& vm, Structure* structure, Wasm::Memory&& memory)53 JSWebAssemblyMemory::JSWebAssemblyMemory(VM& vm, Structure* structure, Ref<Wasm::Memory>&& memory) 53 54 : Base(vm, structure) 54 55 , m_memory(WTFMove(memory)) 55 56 { 57 ASSERT(m_memory->refCount() == 1); 58 m_memoryBase = m_memory->memory(); 59 m_memorySize = m_memory->size(); 56 60 } 57 61 … … 61 65 return m_bufferWrapper.get(); 62 66 63 auto destructor = [] (void*) { 64 // We don't need to do anything here to destroy the memory. 65 // The ArrayBuffer backing the JSArrayBuffer is only owned by us, 66 // so we guarantee its lifecycle. 67 }; 68 m_buffer = ArrayBuffer::createFromBytes(memory()->memory(), memory()->size(), WTFMove(destructor)); 67 // We can't use a ref here since it doesn't have a copy constructor... 68 Ref<Wasm::Memory> protectedMemory = m_memory.get(); 69 auto destructor = [protectedMemory = WTFMove(protectedMemory)] (void*) { }; 70 m_buffer = ArrayBuffer::createFromBytes(memory().memory(), memory().size(), WTFMove(destructor)); 69 71 m_bufferWrapper.set(vm, this, JSArrayBuffer::create(vm, globalObject->m_arrayBufferStructure.get(), m_buffer.get())); 70 72 RELEASE_ASSERT(m_bufferWrapper); … … 77 79 auto throwScope = DECLARE_THROW_SCOPE(vm); 78 80 79 Wasm::PageCount oldPageCount = memory() ->sizeInPages();81 Wasm::PageCount oldPageCount = memory().sizeInPages(); 80 82 81 83 if (!Wasm::PageCount::isValid(delta)) { … … 93 95 94 96 if (delta) { 95 bool success = memory() ->grow(newSize);97 bool success = memory().grow(newSize); 96 98 if (!success) { 99 ASSERT(m_memoryBase == memory().memory()); 100 ASSERT(m_memorySize == memory().size()); 97 101 if (shouldThrowExceptionsOnFailure) 98 102 throwException(exec, throwScope, createOutOfMemoryError(exec)); 99 103 return Wasm::PageCount(); 100 104 } 105 m_memoryBase = memory().memory(); 106 m_memorySize = memory().size(); 101 107 } 102 108 … … 111 117 } 112 118 119 memory().check(); 113 120 return oldPageCount; 114 121 } … … 124 131 auto memory = static_cast<JSWebAssemblyMemory*>(cell); 125 132 ASSERT(memory->classInfo() == info()); 126 VM& vm = *memory->vm();127 128 if (memory->m_buffer) {129 ArrayBufferContents dummyContents;130 memory->m_buffer->transferTo(vm, dummyContents);131 memory->m_buffer = nullptr;132 }133 133 134 134 memory->JSWebAssemblyMemory::~JSWebAssemblyMemory(); -
trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyMemory.h
r211247 r213386 42 42 typedef JSDestructibleObject Base; 43 43 44 static JSWebAssemblyMemory* create(VM&, Structure*, Wasm::Memory&&);44 static JSWebAssemblyMemory* create(VM&, Structure*, Ref<Wasm::Memory>&&); 45 45 static Structure* createStructure(VM&, JSGlobalObject*, JSValue); 46 46 47 47 DECLARE_INFO; 48 48 49 Wasm::Memory * memory() { return &m_memory; }49 Wasm::Memory& memory() { return m_memory.get(); } 50 50 JSArrayBuffer* buffer(VM& vm, JSGlobalObject*); 51 51 Wasm::PageCount grow(ExecState*, uint32_t delta, bool shouldThrowExceptionsOnFailure); 52 52 53 static ptrdiff_t offsetOfMemory() { return OBJECT_OFFSETOF(JSWebAssemblyMemory, m_memory ) + Wasm::Memory::offsetOfMemory(); }54 static ptrdiff_t offsetOfSize() { return OBJECT_OFFSETOF(JSWebAssemblyMemory, m_memory ) + Wasm::Memory::offsetOfSize(); }53 static ptrdiff_t offsetOfMemory() { return OBJECT_OFFSETOF(JSWebAssemblyMemory, m_memoryBase); } 54 static ptrdiff_t offsetOfSize() { return OBJECT_OFFSETOF(JSWebAssemblyMemory, m_memorySize); } 55 55 56 pr otected:57 JSWebAssemblyMemory(VM&, Structure*, Wasm::Memory&&);56 private: 57 JSWebAssemblyMemory(VM&, Structure*, Ref<Wasm::Memory>&&); 58 58 void finishCreation(VM&); 59 59 static void destroy(JSCell*); 60 60 static void visitChildren(JSCell*, SlotVisitor&); 61 61 62 Wasm::Memory m_memory; 62 void* m_memoryBase; 63 size_t m_memorySize; 64 Ref<Wasm::Memory> m_memory; 63 65 WriteBarrier<JSArrayBuffer> m_bufferWrapper; 64 66 RefPtr<ArrayBuffer> m_buffer; -
trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.cpp
r211247 r213386 31 31 #include "JSCInlines.h" 32 32 #include "JSWebAssemblyCallee.h" 33 #include "JSWebAssemblyCodeBlock.h" 34 #include "JSWebAssemblyCompileError.h" 35 #include "JSWebAssemblyMemory.h" 33 36 #include "WasmFormat.h" 34 37 #include "WasmMemory.h" 38 #include "WasmPlan.h" 35 39 #include <wtf/StdLibExtras.h> 36 40 … … 39 43 const ClassInfo JSWebAssemblyModule::s_info = { "WebAssembly.Module", &Base::s_info, nullptr, CREATE_METHOD_TABLE(JSWebAssemblyModule) }; 40 44 41 JSWebAssembly Module* JSWebAssemblyModule::create(VM& vm, Structure* structure, std::unique_ptr<Wasm::ModuleInformation>&& moduleInformation, Bag<CallLinkInfo>&& callLinkInfos, Vector<Wasm::WasmExitStubs>&& wasmExitStubs, SymbolTable* exportSymbolTable, unsigned calleeCount)45 JSWebAssemblyCodeBlock* JSWebAssemblyModule::buildCodeBlock(VM& vm, ExecState* exec, Wasm::Plan& plan, std::optional<Wasm::Memory::Mode> mode) 42 46 { 43 auto* instance = new (NotNull, allocateCell<JSWebAssemblyModule>(vm.heap, allocationSize(calleeCount))) JSWebAssemblyModule(vm, structure, std::forward<std::unique_ptr<Wasm::ModuleInformation>>(moduleInformation), std::forward<Bag<CallLinkInfo>>(callLinkInfos), std::forward<Vector<Wasm::WasmExitStubs>>(wasmExitStubs), calleeCount); 44 instance->finishCreation(vm, exportSymbolTable); 47 auto scope = DECLARE_THROW_SCOPE(vm); 48 // On failure, a new WebAssembly.CompileError is thrown. 49 plan.run(mode); 50 if (plan.failed()) { 51 throwException(exec, scope, createJSWebAssemblyCompileError(exec, vm, plan.errorMessage())); 52 return nullptr; 53 } 54 if (mode) 55 ASSERT(*mode == plan.mode()); 56 57 unsigned calleeCount = plan.internalFunctionCount(); 58 auto* codeBlock = JSWebAssemblyCodeBlock::create(vm, this, plan.takeCallLinkInfos(), plan.takeWasmExitStubs(), plan.mode(), calleeCount); 59 60 plan.initializeCallees(exec->jsCallee()->globalObject(), 61 [&] (unsigned calleeIndex, JSWebAssemblyCallee* jsEntrypointCallee, JSWebAssemblyCallee* wasmEntrypointCallee) { 62 codeBlock->setJSEntrypointCallee(vm, calleeIndex, jsEntrypointCallee); 63 codeBlock->setWasmEntrypointCallee(vm, calleeIndex, wasmEntrypointCallee); 64 }); 65 return codeBlock; 66 } 67 68 JSWebAssemblyModule* JSWebAssemblyModule::create(VM& vm, ExecState* exec, Structure* structure, uint8_t* source, size_t byteSize) 69 { 70 auto* instance = new (NotNull, allocateCell<JSWebAssemblyModule>(vm.heap)) JSWebAssemblyModule(vm, structure); 71 72 instance->finishCreation(vm, exec, source, byteSize); 45 73 return instance; 46 74 } … … 51 79 } 52 80 53 JSWebAssemblyModule::JSWebAssemblyModule(VM& vm, Structure* structure , std::unique_ptr<Wasm::ModuleInformation>&& moduleInformation, Bag<CallLinkInfo>&& callLinkInfos, Vector<Wasm::WasmExitStubs>&& wasmExitStubs, unsigned calleeCount)81 JSWebAssemblyModule::JSWebAssemblyModule(VM& vm, Structure* structure) 54 82 : Base(vm, structure) 55 , m_moduleInformation(WTFMove(moduleInformation))56 , m_callLinkInfos(WTFMove(callLinkInfos))57 , m_wasmExitStubs(WTFMove(wasmExitStubs))58 , m_calleeCount(calleeCount)59 83 { 60 memset(callees(), 0, m_calleeCount * sizeof(WriteBarrier<JSWebAssemblyCallee>) * 2);61 84 } 62 85 63 void JSWebAssemblyModule::finishCreation(VM& vm, SymbolTable* exportSymbolTable) 86 JSWebAssemblyCodeBlock* JSWebAssemblyModule::codeBlock(VM& vm, ExecState* exec, JSWebAssemblyMemory* memory) 87 { 88 Wasm::Memory::Mode mode = memory->memory().mode(); 89 90 for (unsigned i = 0; i < Wasm::Memory::NumberOfModes; ++i) { 91 if (m_codeBlocks[i] && m_codeBlocks[i]->isSafeToRun(memory)) 92 return m_codeBlocks[i].get(); 93 } 94 95 ASSERT(!m_codeBlocks[mode]); 96 auto scope = DECLARE_THROW_SCOPE(vm); 97 // We don't have a code block for this mode, we need to recompile... 98 Wasm::Plan plan(&vm, static_cast<uint8_t*>(m_sourceBuffer->data()), m_sourceBuffer->byteLength()); 99 100 auto* codeBlock = buildCodeBlock(vm, exec, plan, mode); 101 RETURN_IF_EXCEPTION(scope, nullptr); 102 103 ASSERT(plan.exports().size() == m_exportSymbolTable->size()); 104 if (!ASSERT_DISABLED) { 105 for (auto& exp : plan.exports()) 106 ASSERT_UNUSED(exp, m_exportSymbolTable->contains(exp.field.impl())); 107 } 108 109 ASSERT(mode == codeBlock->mode()); 110 m_codeBlocks[mode].set(vm, this, codeBlock); 111 return codeBlock; 112 } 113 114 void JSWebAssemblyModule::finishCreation(VM& vm, ExecState* exec, uint8_t* source, size_t byteSize) 64 115 { 65 116 Base::finishCreation(vm); 66 117 ASSERT(inherits(vm, info())); 118 119 auto scope = DECLARE_THROW_SCOPE(vm); 120 Wasm::Plan plan(&vm, source, byteSize); 121 122 auto* codeBlock = buildCodeBlock(vm, exec, plan); 123 RETURN_IF_EXCEPTION(scope,); 124 125 // On success, a new WebAssembly.Module object is returned with [[Module]] set to the validated Ast.module. 126 SymbolTable* exportSymbolTable = SymbolTable::create(vm); 127 for (auto& exp : plan.exports()) { 128 auto offset = exportSymbolTable->takeNextScopeOffset(NoLockingNecessary); 129 exportSymbolTable->set(NoLockingNecessary, exp.field.impl(), SymbolTableEntry(VarOffset(offset))); 130 } 131 132 m_sourceBuffer = ArrayBuffer::create(source, byteSize); 133 m_moduleInformation = plan.takeModuleInformation(); 67 134 m_exportSymbolTable.set(vm, this, exportSymbolTable); 135 m_codeBlocks[codeBlock->mode()].set(vm, this, codeBlock); 68 136 } 69 137 … … 80 148 Base::visitChildren(thisObject, visitor); 81 149 visitor.append(thisObject->m_exportSymbolTable); 82 for (unsigned i = 0; i < thisObject->m_calleeCount * 2; i++) 83 visitor.append(thisObject->callees()[i]); 84 85 visitor.addUnconditionalFinalizer(&thisObject->m_unconditionalFinalizer); 86 } 87 88 void JSWebAssemblyModule::UnconditionalFinalizer::finalizeUnconditionally() 89 { 90 JSWebAssemblyModule* thisObject = bitwise_cast<JSWebAssemblyModule*>( 91 bitwise_cast<char*>(this) - OBJECT_OFFSETOF(JSWebAssemblyModule, m_unconditionalFinalizer)); 92 for (auto iter = thisObject->m_callLinkInfos.begin(); !!iter; ++iter) 93 (*iter)->visitWeak(*thisObject->vm()); 150 for (unsigned i = 0; i < Wasm::Memory::NumberOfModes; ++i) 151 visitor.append(thisObject->m_codeBlocks[i]); 94 152 } 95 153 -
trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h
r210229 r213386 1 1 /* 2 * Copyright (C) 2016 Apple Inc. All rights reserved.2 * Copyright (C) 2016-2017 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 30 30 #include "JSDestructibleObject.h" 31 31 #include "JSObject.h" 32 #include "JSWebAssemblyC allee.h"32 #include "JSWebAssemblyCodeBlock.h" 33 33 #include "UnconditionalFinalizer.h" 34 34 #include "WasmFormat.h" … … 38 38 namespace JSC { 39 39 40 namespace Wasm { 41 class Plan; 42 } 43 40 44 class SymbolTable; 45 class JSWebAssemblyMemory; 41 46 42 47 class JSWebAssemblyModule : public JSDestructibleObject { … … 44 49 typedef JSDestructibleObject Base; 45 50 46 static JSWebAssemblyModule* create(VM&, Structure*, std::unique_ptr<Wasm::ModuleInformation>&&, Bag<CallLinkInfo>&&, Vector<Wasm::WasmExitStubs>&&, SymbolTable*, unsigned);51 static JSWebAssemblyModule* create(VM&, ExecState*, Structure*, uint8_t* source, size_t byteSize); 47 52 static Structure* createStructure(VM&, JSGlobalObject*, JSValue); 48 53 … … 50 55 51 56 const Wasm::ModuleInformation& moduleInformation() const { return *m_moduleInformation.get(); } 57 RefPtr<Wasm::Memory> takeReservedMemory() { return m_moduleInformation->memory.takeReservedMemory(); } 52 58 SymbolTable* exportSymbolTable() const { return m_exportSymbolTable.get(); } 53 59 Wasm::SignatureIndex signatureIndexFromFunctionIndexSpace(unsigned functionIndexSpace) const … … 55 61 return m_moduleInformation->signatureIndexFromFunctionIndexSpace(functionIndexSpace); 56 62 } 57 unsigned functionImportCount() const { return m_wasmExitStubs.size(); }58 63 59 JSWebAssemblyCallee* jsEntrypointCalleeFromFunctionIndexSpace(unsigned functionIndexSpace) 60 { 61 RELEASE_ASSERT(functionIndexSpace >= functionImportCount()); 62 unsigned calleeIndex = functionIndexSpace - functionImportCount(); 63 RELEASE_ASSERT(calleeIndex < m_calleeCount); 64 return callees()[calleeIndex].get(); 65 } 64 // Returns the code block that this module was originally compiled expecting to use. This won't need to recompile. 65 JSWebAssemblyCodeBlock* codeBlock() { return m_codeBlocks[m_moduleInformation->memory.mode()].get(); } 66 // Returns the appropriate code block for the given memory, possibly triggering a recompile. 67 JSWebAssemblyCodeBlock* codeBlock(VM&, ExecState*, JSWebAssemblyMemory*); 66 68 67 JSWebAssemblyCallee* wasmEntrypointCalleeFromFunctionIndexSpace(unsigned functionIndexSpace) 68 { 69 RELEASE_ASSERT(functionIndexSpace >= functionImportCount()); 70 unsigned calleeIndex = functionIndexSpace - functionImportCount(); 71 RELEASE_ASSERT(calleeIndex < m_calleeCount); 72 return callees()[calleeIndex + m_calleeCount].get(); 73 } 69 private: 70 JSWebAssemblyCodeBlock* buildCodeBlock(VM&, ExecState*, Wasm::Plan&, std::optional<Wasm::Memory::Mode> mode = std::nullopt); 74 71 75 void setJSEntrypointCallee(VM& vm, unsigned calleeIndex, JSWebAssemblyCallee* callee) 76 { 77 RELEASE_ASSERT(calleeIndex < m_calleeCount); 78 callees()[calleeIndex].set(vm, this, callee); 79 } 80 81 void setWasmEntrypointCallee(VM& vm, unsigned calleeIndex, JSWebAssemblyCallee* callee) 82 { 83 RELEASE_ASSERT(calleeIndex < m_calleeCount); 84 callees()[calleeIndex + m_calleeCount].set(vm, this, callee); 85 } 86 87 WriteBarrier<JSWebAssemblyCallee>* callees() 88 { 89 return bitwise_cast<WriteBarrier<JSWebAssemblyCallee>*>(bitwise_cast<char*>(this) + offsetOfCallees()); 90 } 91 92 protected: 93 JSWebAssemblyModule(VM&, Structure*, std::unique_ptr<Wasm::ModuleInformation>&&, Bag<CallLinkInfo>&&, Vector<Wasm::WasmExitStubs>&&, unsigned calleeCount); 94 void finishCreation(VM&, SymbolTable*); 72 JSWebAssemblyModule(VM&, Structure*); 73 void finishCreation(VM&, ExecState*, uint8_t* source, size_t byteSize); 95 74 static void destroy(JSCell*); 96 75 static void visitChildren(JSCell*, SlotVisitor&); 97 76 98 private: 99 static size_t offsetOfCallees() 100 { 101 return WTF::roundUpToMultipleOf<sizeof(WriteBarrier<JSWebAssemblyCallee>)>(sizeof(JSWebAssemblyModule)); 102 } 103 104 static size_t allocationSize(unsigned numCallees) 105 { 106 return offsetOfCallees() + sizeof(WriteBarrier<JSWebAssemblyCallee>) * numCallees * 2; 107 } 108 109 class UnconditionalFinalizer : public JSC::UnconditionalFinalizer { 110 void finalizeUnconditionally() override; 111 }; 112 113 UnconditionalFinalizer m_unconditionalFinalizer; 77 RefPtr<ArrayBuffer> m_sourceBuffer; 114 78 std::unique_ptr<Wasm::ModuleInformation> m_moduleInformation; 115 Bag<CallLinkInfo> m_callLinkInfos;116 79 WriteBarrier<SymbolTable> m_exportSymbolTable; 117 Vector<Wasm::WasmExitStubs> m_wasmExitStubs; 118 unsigned m_calleeCount; 80 WriteBarrier<JSWebAssemblyCodeBlock> m_codeBlocks[Wasm::Memory::NumberOfModes]; 119 81 }; 120 82 -
trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp
r211247 r213386 57 57 const Wasm::Signature* signature = Wasm::SignatureInformation::get(&vm, signatureIndex); 58 58 59 // Make sure that the memory we think we are going to run with matches the one we expect. 60 ASSERT(wasmFunction->instance()->codeBlock()->isSafeToRun(wasmFunction->instance()->memory())); 59 61 { 60 62 // Check if we have a disallowed I64 use. -
trunk/Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp
r212983 r213386 85 85 JSWebAssemblyInstance* instance = JSWebAssemblyInstance::create(vm, instanceStructure, jsModule, moduleRecord->getModuleNamespace(exec)); 86 86 RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); 87 { 88 // Always start with a dummy Memory, so that wasm -> wasm thunks avoid checking for a nullptr Memory when trying to set pinned registers. 89 Wasm::Memory memory; 90 instance->setMemory(vm, JSWebAssemblyMemory::create(vm, exec->lexicalGlobalObject()->WebAssemblyMemoryStructure(), WTFMove(memory))); 91 } 87 92 88 93 89 // Let funcs, memories and tables be initially-empty lists of callable JavaScript objects, WebAssembly.Memory objects and WebAssembly.Table objects, respectively. … … 179 175 180 176 Wasm::PageCount expectedInitial = moduleInformation.memory.initial(); 181 Wasm::PageCount actualInitial = memory->memory() ->initial();177 Wasm::PageCount actualInitial = memory->memory().initial(); 182 178 if (actualInitial < expectedInitial) 183 179 return JSValue::encode(throwException(exec, throwScope, createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("Memory import provided an 'initial' that is too small")))); 184 180 185 181 if (Wasm::PageCount expectedMaximum = moduleInformation.memory.maximum()) { 186 Wasm::PageCount actualMaximum = memory->memory() ->maximum();182 Wasm::PageCount actualMaximum = memory->memory().maximum(); 187 183 if (!actualMaximum) { 188 184 return JSValue::encode( … … 195 191 } 196 192 } 193 197 194 // ii. Append v to memories. 198 195 // iii. Append v.[[Memory]] to imports. 199 instance->setMemory(vm, memory); 196 instance->setMemory(vm, exec, memory); 197 RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); 200 198 break; 201 199 } … … 238 236 RELEASE_ASSERT(!moduleInformation.memory.isImport()); 239 237 // We create a memory when it's a memory definition. 240 bool failed; 241 Wasm::Memory memory(moduleInformation.memory.initial(), moduleInformation.memory.maximum(), failed); 242 if (failed) 243 return JSValue::encode(throwException(exec, throwScope, createOutOfMemoryError(exec))); 244 instance->setMemory(vm, 245 JSWebAssemblyMemory::create(vm, exec->lexicalGlobalObject()->WebAssemblyMemoryStructure(), WTFMove(memory))); 238 RefPtr<Wasm::Memory> memory; 239 if (moduleInformation.memory.hasReservedMemory()) 240 memory = jsModule->takeReservedMemory(); 241 else { 242 memory = Wasm::Memory::create(vm, moduleInformation.memory.initial(), moduleInformation.memory.maximum()); 243 if (!memory) 244 return JSValue::encode(throwException(exec, throwScope, createOutOfMemoryError(exec))); 245 } 246 instance->setMemory(vm, exec, 247 JSWebAssemblyMemory::create(vm, exec->lexicalGlobalObject()->WebAssemblyMemoryStructure(), memory.releaseNonNull())); 248 RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); 246 249 } 247 250 } … … 264 267 instance->setTable(vm, table); 265 268 } 269 } 270 271 if (!instance->memory()) { 272 // Make sure we have a dummy memory, so that wasm -> wasm thunks avoid checking for a nullptr Memory when trying to set pinned registers. 273 instance->setMemory(vm, exec, JSWebAssemblyMemory::create(vm, exec->lexicalGlobalObject()->WebAssemblyMemoryStructure(), adoptRef(*(new Wasm::Memory())))); 266 274 } 267 275 -
trunk/Source/JavaScriptCore/wasm/js/WebAssemblyMemoryConstructor.cpp
r210229 r213386 97 97 } 98 98 99 bool failed; 100 Wasm::Memory memory(initialPageCount, maximumPageCount, failed); 101 if (failed) 99 RefPtr<Wasm::Memory> memory = Wasm::Memory::create(vm, initialPageCount, maximumPageCount); 100 if (!memory) 102 101 return JSValue::encode(throwException(exec, throwScope, createOutOfMemoryError(exec))); 103 102 104 return JSValue::encode(JSWebAssemblyMemory::create(vm, exec->lexicalGlobalObject()->WebAssemblyMemoryStructure(), WTFMove(memory)));103 return JSValue::encode(JSWebAssemblyMemory::create(vm, exec->lexicalGlobalObject()->WebAssemblyMemoryStructure(), adoptRef(*memory.leakRef()))); 105 104 } 106 105 -
trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleConstructor.cpp
r210229 r213386 81 81 RETURN_IF_EXCEPTION(scope, { }); 82 82 83 Wasm::Plan plan(&vm, base + byteOffset, byteSize); 84 // On failure, a new WebAssembly.CompileError is thrown. 85 plan.run(); 86 if (plan.failed()) 87 return throwException(state, scope, createJSWebAssemblyCompileError(state, vm, plan.errorMessage())); 88 89 // On success, a new WebAssembly.Module object is returned with [[Module]] set to the validated Ast.module. 90 91 // The export symbol table is the same for all Instances of a Module. 92 SymbolTable* exportSymbolTable = SymbolTable::create(vm); 93 for (auto& exp : plan.exports()) { 94 auto offset = exportSymbolTable->takeNextScopeOffset(NoLockingNecessary); 95 exportSymbolTable->set(NoLockingNecessary, exp.field.impl(), SymbolTableEntry(VarOffset(offset))); 96 } 97 98 // Only wasm-internal functions have a callee, stubs to JS do not. 99 unsigned calleeCount = plan.internalFunctionCount(); 100 JSWebAssemblyModule* result = JSWebAssemblyModule::create(vm, structure, plan.takeModuleInformation(), plan.takeCallLinkInfos(), plan.takeWasmExitStubs(), exportSymbolTable, calleeCount); 101 plan.initializeCallees(state->jsCallee()->globalObject(), 102 [&] (unsigned calleeIndex, JSWebAssemblyCallee* jsEntrypointCallee, JSWebAssemblyCallee* wasmEntrypointCallee) { 103 result->setJSEntrypointCallee(vm, calleeIndex, jsEntrypointCallee); 104 result->setWasmEntrypointCallee(vm, calleeIndex, wasmEntrypointCallee); 105 }); 106 107 return result; 83 scope.release(); 84 return JSWebAssemblyModule::create(vm, state, structure, base + byteOffset, byteSize); 108 85 } 109 86 -
trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp
r212983 r213386 93 93 94 94 JSWebAssemblyModule* module = instance->module(); 95 JSWebAssemblyCodeBlock* codeBlock = instance->codeBlock(); 95 96 const Wasm::ModuleInformation& moduleInformation = module->moduleInformation(); 96 97 97 98 SymbolTable* exportSymbolTable = module->exportSymbolTable(); 98 unsigned functionImportCount = module->functionImportCount();99 unsigned functionImportCount = codeBlock->functionImportCount(); 99 100 100 101 // FIXME wire up the imports. https://bugs.webkit.org/show_bug.cgi?id=165118 … … 117 118 // b. Append func to funcs. 118 119 // c. Return func. 119 JSWebAssemblyCallee* jsEntrypointCallee = module->jsEntrypointCalleeFromFunctionIndexSpace(exp.kindIndex);120 JSWebAssemblyCallee* wasmEntrypointCallee = module->wasmEntrypointCalleeFromFunctionIndexSpace(exp.kindIndex);120 JSWebAssemblyCallee* jsEntrypointCallee = codeBlock->jsEntrypointCalleeFromFunctionIndexSpace(exp.kindIndex); 121 JSWebAssemblyCallee* wasmEntrypointCallee = codeBlock->wasmEntrypointCalleeFromFunctionIndexSpace(exp.kindIndex); 121 122 Wasm::SignatureIndex signatureIndex = module->signatureIndexFromFunctionIndexSpace(exp.kindIndex); 122 123 const Wasm::Signature* signature = Wasm::SignatureInformation::get(&vm, signatureIndex); … … 183 184 ASSERT(!signature->argumentCount()); 184 185 ASSERT(signature->returnType() == Wasm::Void); 185 if (startFunctionIndexSpace < module->functionImportCount()) {186 if (startFunctionIndexSpace < codeBlock->functionImportCount()) { 186 187 JSCell* startFunction = instance->importFunction(startFunctionIndexSpace)->get(); 187 188 m_startFunction.set(vm, this, startFunction); 188 189 } else { 189 JSWebAssemblyCallee* jsEntrypointCallee = module->jsEntrypointCalleeFromFunctionIndexSpace(startFunctionIndexSpace);190 JSWebAssemblyCallee* wasmEntrypointCallee = module->wasmEntrypointCalleeFromFunctionIndexSpace(startFunctionIndexSpace);190 JSWebAssemblyCallee* jsEntrypointCallee = codeBlock->jsEntrypointCalleeFromFunctionIndexSpace(startFunctionIndexSpace); 191 JSWebAssemblyCallee* wasmEntrypointCallee = codeBlock->wasmEntrypointCalleeFromFunctionIndexSpace(startFunctionIndexSpace); 191 192 WebAssemblyFunction* function = WebAssemblyFunction::create(vm, globalObject, signature->argumentCount(), "start", instance, jsEntrypointCallee, wasmEntrypointCallee, signatureIndex); 192 193 m_startFunction.set(vm, this, function); … … 212 213 { 213 214 JSWebAssemblyModule* module = m_instance->module(); 215 JSWebAssemblyCodeBlock* codeBlock = m_instance->codeBlock(); 214 216 const Wasm::ModuleInformation& moduleInformation = module->moduleInformation(); 215 217 JSWebAssemblyTable* table = m_instance->table(); … … 234 236 // https://bugs.webkit.org/show_bug.cgi?id=165510 235 237 uint32_t functionIndex = element.functionIndices[i]; 236 if (functionIndex < module->functionImportCount()) {238 if (functionIndex < codeBlock->functionImportCount()) { 237 239 return JSValue::decode( 238 240 throwVMRangeError(state, scope, ASCIILiteral("Element is setting the table value with an import. This is not yet implemented. FIXME."))); 239 241 } 240 242 241 JSWebAssemblyCallee* jsEntrypointCallee = module->jsEntrypointCalleeFromFunctionIndexSpace(functionIndex);242 JSWebAssemblyCallee* wasmEntrypointCallee = module->wasmEntrypointCalleeFromFunctionIndexSpace(functionIndex);243 JSWebAssemblyCallee* jsEntrypointCallee = codeBlock->jsEntrypointCalleeFromFunctionIndexSpace(functionIndex); 244 JSWebAssemblyCallee* wasmEntrypointCallee = codeBlock->wasmEntrypointCalleeFromFunctionIndexSpace(functionIndex); 243 245 Wasm::SignatureIndex signatureIndex = module->signatureIndexFromFunctionIndexSpace(functionIndex); 244 246 const Wasm::Signature* signature = Wasm::SignatureInformation::get(&vm, signatureIndex); … … 260 262 JSWebAssemblyMemory* jsMemory = m_instance->memory(); 261 263 if (!data.isEmpty()) { 262 uint8_t* memory = reinterpret_cast<uint8_t*>(jsMemory->memory() ->memory());263 uint64_t sizeInBytes = jsMemory->memory() ->size();264 uint8_t* memory = reinterpret_cast<uint8_t*>(jsMemory->memory().memory()); 265 uint64_t sizeInBytes = jsMemory->memory().size(); 264 266 for (auto& segment : data) { 265 267 if (segment->sizeInBytes) { -
trunk/Source/WTF/ChangeLog
r213324 r213386 1 2017-03-03 Keith Miller <keith_miller@apple.com> 2 3 WASM should support faster loads. 4 https://bugs.webkit.org/show_bug.cgi?id=162693 5 6 Reviewed by Saam Barati. 7 8 Add new forms of dataLog that take a boolean which describes if the log should happen. This makes cases where we have a static const bool for printing nicer since you can do: 9 10 dataLogIf(verbose, things, to, print); 11 12 instead of: 13 14 if (verbose) 15 dataLog(things, to, print); 16 17 Also, add a operator! to Ref that has the same semantics as C++ refs. 18 19 * wtf/DataLog.h: 20 (WTF::dataLogLn): 21 (WTF::dataLogIf): 22 (WTF::dataLogLnIf): 23 * wtf/Ref.h: 24 (WTF::Ref::operator!): 25 1 26 2017-03-02 Jer Noble <jer.noble@apple.com> 2 27 -
trunk/Source/WTF/wtf/DataLog.h
r213151 r213386 50 50 void dataLogLn(const Types&... values) 51 51 { 52 dataFile().print(values..., "\n"); 52 dataLog(values..., "\n"); 53 } 54 55 template<typename... Types> 56 void dataLogIf(bool shouldLog, const Types&... values) 57 { 58 if (shouldLog) 59 dataLog(values...); 60 } 61 62 template<typename... Types> 63 void dataLogLnIf(bool shouldLog, const Types&... values) 64 { 65 if (shouldLog) 66 dataLogLn(values...); 53 67 } 54 68 … … 57 71 using WTF::dataLog; 58 72 using WTF::dataLogLn; 73 using WTF::dataLogIf; 74 using WTF::dataLogLnIf; 59 75 using WTF::dataLogF; 60 76 using WTF::dataLogFString; -
trunk/Source/WTF/wtf/Ref.h
r212817 r213386 138 138 T& get() const { ASSERT(m_ptr); return *m_ptr; } 139 139 operator T&() const { ASSERT(m_ptr); return *m_ptr; } 140 bool operator!() const { ASSERT(m_ptr); return !*m_ptr; } 140 141 141 142 template<typename U> Ref<T> replace(Ref<U>&&) WARN_UNUSED_RETURN;
Note: See TracChangeset
for help on using the changeset viewer.