| Differences between
and this patch
- a/Source/JavaScriptCore/ChangeLog +60 lines
Lines 1-3 a/Source/JavaScriptCore/ChangeLog_sec1
1
2017-02-27  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 NOBODY (OOPS!).
7
8
        * JavaScriptCore.xcodeproj/project.pbxproj:
9
        * jit/JITThunks.cpp:
10
        (JSC::JITThunks::existingCTIStub):
11
        * jit/JITThunks.h:
12
        * jsc.cpp:
13
        (jscmain):
14
        * runtime/Options.h:
15
        * wasm/WasmB3IRGenerator.cpp:
16
        (JSC::Wasm::B3IRGenerator::B3IRGenerator):
17
        (JSC::Wasm::B3IRGenerator::emitCheckAndPreparePointer):
18
        * wasm/WasmCallingConvention.h:
19
        * wasm/WasmFormat.h:
20
        (JSC::Wasm::ModuleInformation::importFunctionCount):
21
        (JSC::Wasm::ModuleInformation::hasMemory): Deleted.
22
        * wasm/WasmMemory.cpp:
23
        (JSC::Wasm::Memory::mmapBytes):
24
        (JSC::Wasm::Memory::lastAllocatedMode):
25
        (JSC::Wasm::availableFastMemories):
26
        (JSC::Wasm::Memory::tryGetFastMemory):
27
        (JSC::Wasm::Memory::releaseFastMemory):
28
        (JSC::Wasm::Memory::Memory):
29
        (JSC::Wasm::Memory::~Memory):
30
        (JSC::Wasm::Memory::grow):
31
        (JSC::Wasm::Memory::dump):
32
        (JSC::Wasm::Memory::makeString):
33
        * wasm/WasmMemory.h:
34
        (JSC::Wasm::Memory::operator bool):
35
        (JSC::Wasm::Memory::operator=):
36
        (JSC::Wasm::Memory::Memory):
37
        * wasm/WasmMemoryInformation.cpp:
38
        (JSC::Wasm::MemoryInformation::MemoryInformation):
39
        * wasm/WasmMemoryInformation.h:
40
        (JSC::Wasm::MemoryInformation::MemoryInformation):
41
        (JSC::Wasm::MemoryInformation::hasReservedMemory):
42
        (JSC::Wasm::MemoryInformation::reservedMemory):
43
        (JSC::Wasm::MemoryInformation::mode):
44
        * wasm/WasmModuleParser.cpp:
45
        * wasm/WasmPlan.cpp:
46
        * wasm/WasmTrapSignalHandler.cpp: Added.
47
        (JSC::Wasm::trapHandler):
48
        (JSC::Wasm::registerCode):
49
        (JSC::Wasm::unregisterCode):
50
        (JSC::Wasm::fastMemoryEnabled):
51
        (JSC::Wasm::enableFastMemory):
52
        * wasm/WasmTrapSignalHandler.h: Copied from Source/JavaScriptCore/wasm/js/JSWebAssemblyCallee.cpp.
53
        * wasm/js/JSWebAssemblyCallee.cpp:
54
        (JSC::JSWebAssemblyCallee::finishCreation):
55
        (JSC::JSWebAssemblyCallee::destroy):
56
        * wasm/js/WebAssemblyInstanceConstructor.cpp:
57
        (JSC::constructJSWebAssemblyInstance):
58
        * wasm/js/WebAssemblyMemoryConstructor.cpp:
59
        (JSC::constructJSWebAssemblyMemory):
60
1
2017-02-24  Keith Miller  <keith_miller@apple.com>
61
2017-02-24  Keith Miller  <keith_miller@apple.com>
2
62
3
        We should be able to use std::tuples as keys in HashMap
63
        We should be able to use std::tuples as keys in HashMap
- a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj +16 lines
Lines 1320-1325 a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec1
1320
		535557161D9DFA32006D583B /* WasmMemory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 535557151D9DFA32006D583B /* WasmMemory.cpp */; };
1320
		535557161D9DFA32006D583B /* WasmMemory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 535557151D9DFA32006D583B /* WasmMemory.cpp */; };
1321
		5370B4F51BF26202005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5370B4F31BF25EA2005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.cpp */; };
1321
		5370B4F51BF26202005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5370B4F31BF25EA2005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.cpp */; };
1322
		5370B4F61BF26205005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 5370B4F41BF25EA2005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.h */; };
1322
		5370B4F61BF26205005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 5370B4F41BF25EA2005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.h */; };
1323
		5381B9371E60E9660090F794 /* WasmFaultSignalHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5381B9361E60E9660090F794 /* WasmFaultSignalHandler.cpp */; };
1324
		5381B9391E60E97D0090F794 /* WasmFaultSignalHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 5381B9381E60E97D0090F794 /* WasmFaultSignalHandler.h */; };
1325
		5381B9401E65DFEB0090F794 /* JSWebAssemblyCodeBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = 5381B93F1E65DFEB0090F794 /* JSWebAssemblyCodeBlock.h */; };
1326
		5383AA301E65E8A100A532FC /* JSWebAssemblyCodeBlock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5383AA2F1E65E8A100A532FC /* JSWebAssemblyCodeBlock.cpp */; };
1323
		53917E7B1B7906FA000EBD33 /* JSGenericTypedArrayViewPrototypeFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = 53917E7A1B7906E4000EBD33 /* JSGenericTypedArrayViewPrototypeFunctions.h */; };
1327
		53917E7B1B7906FA000EBD33 /* JSGenericTypedArrayViewPrototypeFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = 53917E7A1B7906E4000EBD33 /* JSGenericTypedArrayViewPrototypeFunctions.h */; };
1324
		539FB8BA1C99DA7C00940FA1 /* JSArrayInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 539FB8B91C99DA7C00940FA1 /* JSArrayInlines.h */; };
1328
		539FB8BA1C99DA7C00940FA1 /* JSArrayInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 539FB8B91C99DA7C00940FA1 /* JSArrayInlines.h */; };
1325
		53B0BE341E561AC900A8FC29 /* GetterSetterAccessCase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53B0BE331E561AC900A8FC29 /* GetterSetterAccessCase.cpp */; };
1329
		53B0BE341E561AC900A8FC29 /* GetterSetterAccessCase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53B0BE331E561AC900A8FC29 /* GetterSetterAccessCase.cpp */; };
Lines 3776-3781 a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec2
3776
		535557151D9DFA32006D583B /* WasmMemory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmMemory.cpp; sourceTree = "<group>"; };
3780
		535557151D9DFA32006D583B /* WasmMemory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmMemory.cpp; sourceTree = "<group>"; };
3777
		5370B4F31BF25EA2005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AdaptiveInferredPropertyValueWatchpointBase.cpp; sourceTree = "<group>"; };
3781
		5370B4F31BF25EA2005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AdaptiveInferredPropertyValueWatchpointBase.cpp; sourceTree = "<group>"; };
3778
		5370B4F41BF25EA2005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AdaptiveInferredPropertyValueWatchpointBase.h; sourceTree = "<group>"; };
3782
		5370B4F41BF25EA2005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AdaptiveInferredPropertyValueWatchpointBase.h; sourceTree = "<group>"; };
3783
		5381B9361E60E9660090F794 /* WasmFaultSignalHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmFaultSignalHandler.cpp; sourceTree = "<group>"; };
3784
		5381B9381E60E97D0090F794 /* WasmFaultSignalHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmFaultSignalHandler.h; sourceTree = "<group>"; };
3785
		5381B93F1E65DFEB0090F794 /* JSWebAssemblyCodeBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSWebAssemblyCodeBlock.h; sourceTree = "<group>"; };
3786
		5383AA2F1E65E8A100A532FC /* JSWebAssemblyCodeBlock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JSWebAssemblyCodeBlock.cpp; path = js/JSWebAssemblyCodeBlock.cpp; sourceTree = "<group>"; };
3779
		53917E7A1B7906E4000EBD33 /* JSGenericTypedArrayViewPrototypeFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGenericTypedArrayViewPrototypeFunctions.h; sourceTree = "<group>"; };
3787
		53917E7A1B7906E4000EBD33 /* JSGenericTypedArrayViewPrototypeFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGenericTypedArrayViewPrototypeFunctions.h; sourceTree = "<group>"; };
3780
		53917E7C1B791106000EBD33 /* JSTypedArrayViewPrototype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSTypedArrayViewPrototype.h; sourceTree = "<group>"; };
3788
		53917E7C1B791106000EBD33 /* JSTypedArrayViewPrototype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSTypedArrayViewPrototype.h; sourceTree = "<group>"; };
3781
		53917E831B791CB8000EBD33 /* TypedArrayPrototype.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = TypedArrayPrototype.js; path = builtins/TypedArrayPrototype.js; sourceTree = SOURCE_ROOT; };
3789
		53917E831B791CB8000EBD33 /* TypedArrayPrototype.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = TypedArrayPrototype.js; path = builtins/TypedArrayPrototype.js; sourceTree = SOURCE_ROOT; };
Lines 6201-6206 a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec3
6201
				53F40E961D5A7BEC0099A1B6 /* WasmModuleParser.cpp */,
6209
				53F40E961D5A7BEC0099A1B6 /* WasmModuleParser.cpp */,
6202
				53F40E941D5A7AEF0099A1B6 /* WasmModuleParser.h */,
6210
				53F40E941D5A7AEF0099A1B6 /* WasmModuleParser.h */,
6203
				ADB6F67C1E15D7500082F384 /* WasmPageCount.cpp */,
6211
				ADB6F67C1E15D7500082F384 /* WasmPageCount.cpp */,
6212
				5381B9361E60E9660090F794 /* WasmFaultSignalHandler.cpp */,
6213
				5381B9381E60E97D0090F794 /* WasmFaultSignalHandler.h */,
6204
				79B759731DFA4C600052174C /* WasmPageCount.h */,
6214
				79B759731DFA4C600052174C /* WasmPageCount.h */,
6205
				53F40E8C1D5901F20099A1B6 /* WasmParser.h */,
6215
				53F40E8C1D5901F20099A1B6 /* WasmParser.h */,
6206
				531374BE1D5CE95000AF7A0B /* WasmPlan.cpp */,
6216
				531374BE1D5CE95000AF7A0B /* WasmPlan.cpp */,
Lines 7788-7793 a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec4
7788
			children = (
7798
			children = (
7789
				79E423E01DEE65320078D355 /* JSWebAssemblyCallee.cpp */,
7799
				79E423E01DEE65320078D355 /* JSWebAssemblyCallee.cpp */,
7790
				79E423E11DEE65320078D355 /* JSWebAssemblyCallee.h */,
7800
				79E423E11DEE65320078D355 /* JSWebAssemblyCallee.h */,
7801
				5383AA2F1E65E8A100A532FC /* JSWebAssemblyCodeBlock.cpp */,
7802
				5381B93F1E65DFEB0090F794 /* JSWebAssemblyCodeBlock.h */,
7791
				AD2FCBA61DB58DA400B3E736 /* JSWebAssemblyCompileError.cpp */,
7803
				AD2FCBA61DB58DA400B3E736 /* JSWebAssemblyCompileError.cpp */,
7792
				AD2FCBA71DB58DA400B3E736 /* JSWebAssemblyCompileError.h */,
7804
				AD2FCBA71DB58DA400B3E736 /* JSWebAssemblyCompileError.h */,
7793
				796FB4391DFF8C3F0039C95D /* JSWebAssemblyHelpers.h */,
7805
				796FB4391DFF8C3F0039C95D /* JSWebAssemblyHelpers.h */,
Lines 7927-7932 a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec5
7927
				0FEC85721BDACDC70080FF74 /* AirBasicBlock.h in Headers */,
7939
				0FEC85721BDACDC70080FF74 /* AirBasicBlock.h in Headers */,
7928
				0FB3878E1BFBC44D00E3AB1E /* AirBlockWorklist.h in Headers */,
7940
				0FB3878E1BFBC44D00E3AB1E /* AirBlockWorklist.h in Headers */,
7929
				0F61832A1C45BF070072450B /* AirCCallingConvention.h in Headers */,
7941
				0F61832A1C45BF070072450B /* AirCCallingConvention.h in Headers */,
7942
				5381B9401E65DFEB0090F794 /* JSWebAssemblyCodeBlock.h in Headers */,
7930
				0FEC85741BDACDC70080FF74 /* AirCCallSpecial.h in Headers */,
7943
				0FEC85741BDACDC70080FF74 /* AirCCallSpecial.h in Headers */,
7931
				0FEC85761BDACDC70080FF74 /* AirCode.h in Headers */,
7944
				0FEC85761BDACDC70080FF74 /* AirCode.h in Headers */,
7932
				0F10F1A31C420BF0001C07D2 /* AirCustom.h in Headers */,
7945
				0F10F1A31C420BF0001C07D2 /* AirCustom.h in Headers */,
Lines 8246-8251 a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec6
8246
				A7D89CF417A0B8CC00773AD8 /* DFGBlockInsertionSet.h in Headers */,
8259
				A7D89CF417A0B8CC00773AD8 /* DFGBlockInsertionSet.h in Headers */,
8247
				0FC3CCFC19ADA410006AC72A /* DFGBlockMap.h in Headers */,
8260
				0FC3CCFC19ADA410006AC72A /* DFGBlockMap.h in Headers */,
8248
				0FC3CCFD19ADA410006AC72A /* DFGBlockMapInlines.h in Headers */,
8261
				0FC3CCFD19ADA410006AC72A /* DFGBlockMapInlines.h in Headers */,
8262
				5381B9391E60E97D0090F794 /* WasmFaultSignalHandler.h in Headers */,
8249
				0FC3CCFE19ADA410006AC72A /* DFGBlockSet.h in Headers */,
8263
				0FC3CCFE19ADA410006AC72A /* DFGBlockSet.h in Headers */,
8250
				0FBF158D19B7A53100695DD0 /* DFGBlockSetInlines.h in Headers */,
8264
				0FBF158D19B7A53100695DD0 /* DFGBlockSetInlines.h in Headers */,
8251
				0FC3CD0019ADA410006AC72A /* DFGBlockWorklist.h in Headers */,
8265
				0FC3CD0019ADA410006AC72A /* DFGBlockWorklist.h in Headers */,
Lines 10036-10041 a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec7
10036
				0FC841681BA8C3210061837D /* DFGInferredTypeCheck.cpp in Sources */,
10050
				0FC841681BA8C3210061837D /* DFGInferredTypeCheck.cpp in Sources */,
10037
				A704D90517A0BAA8006BA554 /* DFGInPlaceAbstractState.cpp in Sources */,
10051
				A704D90517A0BAA8006BA554 /* DFGInPlaceAbstractState.cpp in Sources */,
10038
				0F3BD1B71B896A0700598AA6 /* DFGInsertionSet.cpp in Sources */,
10052
				0F3BD1B71B896A0700598AA6 /* DFGInsertionSet.cpp in Sources */,
10053
				5381B9371E60E9660090F794 /* WasmFaultSignalHandler.cpp in Sources */,
10039
				0F300B7B18AB1B1400A6D72E /* DFGIntegerCheckCombiningPhase.cpp in Sources */,
10054
				0F300B7B18AB1B1400A6D72E /* DFGIntegerCheckCombiningPhase.cpp in Sources */,
10040
				0F898F311B27689F0083A33C /* DFGIntegerRangeOptimizationPhase.cpp in Sources */,
10055
				0F898F311B27689F0083A33C /* DFGIntegerRangeOptimizationPhase.cpp in Sources */,
10041
				0FC97F3D18202119002C9B26 /* DFGInvalidationPointInjectionPhase.cpp in Sources */,
10056
				0FC97F3D18202119002C9B26 /* DFGInvalidationPointInjectionPhase.cpp in Sources */,
Lines 10437-10442 a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec8
10437
				86C568E011A213EE0007F7F0 /* MacroAssemblerARM.cpp in Sources */,
10452
				86C568E011A213EE0007F7F0 /* MacroAssemblerARM.cpp in Sources */,
10438
				FEB137571BB11EF900CD5100 /* MacroAssemblerARM64.cpp in Sources */,
10453
				FEB137571BB11EF900CD5100 /* MacroAssemblerARM64.cpp in Sources */,
10439
				A729009C17976C6000317298 /* MacroAssemblerARMv7.cpp in Sources */,
10454
				A729009C17976C6000317298 /* MacroAssemblerARMv7.cpp in Sources */,
10455
				5383AA301E65E8A100A532FC /* JSWebAssemblyCodeBlock.cpp in Sources */,
10440
				0F6DB7EC1D617D1100CDBF8E /* MacroAssemblerCodeRef.cpp in Sources */,
10456
				0F6DB7EC1D617D1100CDBF8E /* MacroAssemblerCodeRef.cpp in Sources */,
10441
				FE68C6381B90DE0B0042BCB3 /* MacroAssemblerPrinter.cpp in Sources */,
10457
				FE68C6381B90DE0B0042BCB3 /* MacroAssemblerPrinter.cpp in Sources */,
10442
				A7A4AE0817973B26005612B1 /* MacroAssemblerX86Common.cpp in Sources */,
10458
				A7A4AE0817973B26005612B1 /* MacroAssemblerX86Common.cpp in Sources */,
- a/Source/JavaScriptCore/jit/JITThunks.cpp +9 lines
Lines 82-87 MacroAssemblerCodeRef JITThunks::ctiStub(VM* vm, ThunkGenerator generator) a/Source/JavaScriptCore/jit/JITThunks.cpp_sec1
82
    return entry.iterator->value;
82
    return entry.iterator->value;
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
void JITThunks::finalize(Handle<Unknown> handle, void*)
94
void JITThunks::finalize(Handle<Unknown> handle, void*)
86
{
95
{
87
    auto* nativeExecutable = static_cast<NativeExecutable*>(handle.get().asCell());
96
    auto* nativeExecutable = static_cast<NativeExecutable*>(handle.get().asCell());
- a/Source/JavaScriptCore/jit/JITThunks.h +1 lines
Lines 58-63 public: a/Source/JavaScriptCore/jit/JITThunks.h_sec1
58
    MacroAssemblerCodePtr ctiNativeTailCallWithoutSavedTags(VM*);    
58
    MacroAssemblerCodePtr ctiNativeTailCallWithoutSavedTags(VM*);    
59
59
60
    MacroAssemblerCodeRef ctiStub(VM*, ThunkGenerator);
60
    MacroAssemblerCodeRef ctiStub(VM*, ThunkGenerator);
61
    MacroAssemblerCodeRef existingCTIStub(ThunkGenerator);
61
62
62
    NativeExecutable* hostFunctionStub(VM*, NativeFunction, NativeFunction constructor, const String& name);
63
    NativeExecutable* hostFunctionStub(VM*, NativeFunction, NativeFunction constructor, const String& name);
63
    NativeExecutable* hostFunctionStub(VM*, NativeFunction, NativeFunction constructor, ThunkGenerator, Intrinsic, const DOMJIT::Signature*, const String& name);
64
    NativeExecutable* hostFunctionStub(VM*, NativeFunction, NativeFunction constructor, ThunkGenerator, Intrinsic, const DOMJIT::Signature*, const String& name);
- a/Source/JavaScriptCore/jsc.cpp +2 lines
Lines 73-78 a/Source/JavaScriptCore/jsc.cpp_sec1
73
#include "TypeProfilerLog.h"
73
#include "TypeProfilerLog.h"
74
#include "WasmPlan.h"
74
#include "WasmPlan.h"
75
#include "WasmMemory.h"
75
#include "WasmMemory.h"
76
#include "WasmFaultSignalHandler.h"
76
#include <locale.h>
77
#include <locale.h>
77
#include <math.h>
78
#include <math.h>
78
#include <stdio.h>
79
#include <stdio.h>
Lines 3766-3771 int jscmain(int argc, char** argv) a/Source/JavaScriptCore/jsc.cpp_sec2
3766
    WTF::initializeMainThread();
3767
    WTF::initializeMainThread();
3767
    JSC::initializeThreading();
3768
    JSC::initializeThreading();
3768
    startTimeoutThreadIfNeeded();
3769
    startTimeoutThreadIfNeeded();
3770
    JSC::Wasm::enableFastMemory();
3769
3771
3770
    int result;
3772
    int result;
3771
    result = runJSC(
3773
    result = runJSC(
- a/Source/JavaScriptCore/runtime/Options.h +2 lines
Lines 426-431 typedef const char* optionString; a/Source/JavaScriptCore/runtime/Options.h_sec1
426
    \
426
    \
427
    v(bool, useWebAssembly, true, Normal, "Expose the WebAssembly global object.") \
427
    v(bool, useWebAssembly, true, Normal, "Expose the WebAssembly global object.") \
428
    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.") \
428
    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.") \
429
    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.")
430
429
431
430
enum OptionEquivalence {
432
enum OptionEquivalence {
431
    SameOption,
433
    SameOption,
- a/Source/JavaScriptCore/runtime/VM.cpp +1 lines
Lines 240-245 VM::VM(VMType vmType, HeapType heapType) a/Source/JavaScriptCore/runtime/VM.cpp_sec1
240
#if ENABLE(WEBASSEMBLY)
240
#if ENABLE(WEBASSEMBLY)
241
    webAssemblyCalleeStructure.set(*this, JSWebAssemblyCallee::createStructure(*this, 0, jsNull()));
241
    webAssemblyCalleeStructure.set(*this, JSWebAssemblyCallee::createStructure(*this, 0, jsNull()));
242
    webAssemblyToJSCalleeStructure.set(*this, WebAssemblyToJSCallee::createStructure(*this, 0, jsNull()));
242
    webAssemblyToJSCalleeStructure.set(*this, WebAssemblyToJSCallee::createStructure(*this, 0, jsNull()));
243
    webAssemblyCodeBlockStructure.set(*this, JSWebAssemblyCodeBlock::createStructure(*this, 0, jsNull()));
243
    webAssemblyToJSCallee.set(*this, WebAssemblyToJSCallee::create(*this, webAssemblyToJSCalleeStructure.get()));
244
    webAssemblyToJSCallee.set(*this, WebAssemblyToJSCallee::create(*this, webAssemblyToJSCalleeStructure.get()));
244
#endif
245
#endif
245
    moduleProgramExecutableStructure.set(*this, ModuleProgramExecutable::createStructure(*this, 0, jsNull()));
246
    moduleProgramExecutableStructure.set(*this, ModuleProgramExecutable::createStructure(*this, 0, jsNull()));
- a/Source/JavaScriptCore/runtime/VM.h +1 lines
Lines 333-338 public: a/Source/JavaScriptCore/runtime/VM.h_sec1
333
#if ENABLE(WEBASSEMBLY)
333
#if ENABLE(WEBASSEMBLY)
334
    Strong<Structure> webAssemblyCalleeStructure;
334
    Strong<Structure> webAssemblyCalleeStructure;
335
    Strong<Structure> webAssemblyToJSCalleeStructure;
335
    Strong<Structure> webAssemblyToJSCalleeStructure;
336
    Strong<Structure> webAssemblyCodeBlockStructure;
336
    Strong<JSCell> webAssemblyToJSCallee;
337
    Strong<JSCell> webAssemblyToJSCallee;
337
#endif
338
#endif
338
    Strong<Structure> moduleProgramExecutableStructure;
339
    Strong<Structure> moduleProgramExecutableStructure;
- a/Source/JavaScriptCore/wasm/JSWebAssemblyCodeBlock.h +126 lines
Line 0 a/Source/JavaScriptCore/wasm/JSWebAssemblyCodeBlock.h_sec1
1
/*
2
 * Copyright (C) 2017 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
 */
25
26
#pragma once
27
28
#if ENABLE(WEBASSEMBLY)
29
30
#include "JSCell.h"
31
#include "JSWebAssemblyCallee.h"
32
#include "UnconditionalFinalizer.h"
33
#include "WasmFormat.h"
34
#include <wtf/Bag.h>
35
#include <wtf/Vector.h>
36
37
namespace JSC {
38
39
class JSWebAssemblyModule;
40
41
class JSWebAssemblyCodeBlock : public JSCell {
42
public:
43
    typedef JSCell Base;
44
    static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
45
46
    static JSWebAssemblyCodeBlock* create(VM& vm, JSWebAssemblyModule* owner, Bag<CallLinkInfo>&& callLinkInfos, Vector<Wasm::WasmExitStubs>&& exitStubs, Wasm::Memory::Mode mode, unsigned calleeCount)
47
    {
48
        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);
49
        result->finishCreation(vm);
50
        return result;
51
    }
52
53
    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
54
    {
55
        return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info());
56
    }
57
58
    unsigned functionImportCount() const { return m_wasmExitStubs.size(); }
59
    Wasm::Memory::Mode mode() const { return m_mode; }
60
    JSWebAssemblyModule* module() const { return m_module.get(); }
61
62
    JSWebAssemblyCallee* jsEntrypointCalleeFromFunctionIndexSpace(unsigned functionIndexSpace)
63
    {
64
        RELEASE_ASSERT(functionIndexSpace >= functionImportCount());
65
        unsigned calleeIndex = functionIndexSpace - functionImportCount();
66
        RELEASE_ASSERT(calleeIndex < m_calleeCount);
67
        return callees()[calleeIndex].get();
68
    }
69
70
    JSWebAssemblyCallee* wasmEntrypointCalleeFromFunctionIndexSpace(unsigned functionIndexSpace)
71
    {
72
        RELEASE_ASSERT(functionIndexSpace >= functionImportCount());
73
        unsigned calleeIndex = functionIndexSpace - functionImportCount();
74
        RELEASE_ASSERT(calleeIndex < m_calleeCount);
75
        return callees()[calleeIndex + m_calleeCount].get();
76
    }
77
78
    void setJSEntrypointCallee(VM& vm, unsigned calleeIndex, JSWebAssemblyCallee* callee)
79
    {
80
        RELEASE_ASSERT(calleeIndex < m_calleeCount);
81
        callees()[calleeIndex].set(vm, this, callee);
82
    }
83
84
    void setWasmEntrypointCallee(VM& vm, unsigned calleeIndex, JSWebAssemblyCallee* callee)
85
    {
86
        RELEASE_ASSERT(calleeIndex < m_calleeCount);
87
        callees()[calleeIndex + m_calleeCount].set(vm, this, callee);
88
    }
89
90
    WriteBarrier<JSWebAssemblyCallee>* callees()
91
    {
92
        return bitwise_cast<WriteBarrier<JSWebAssemblyCallee>*>(bitwise_cast<char*>(this) + offsetOfCallees());
93
    }
94
95
private:
96
    JSWebAssemblyCodeBlock(VM&, JSWebAssemblyModule*, Bag<CallLinkInfo>&&, Vector<Wasm::WasmExitStubs>&&, Wasm::Memory::Mode, unsigned calleeCount);
97
    DECLARE_EXPORT_INFO;
98
    static const bool needsDestruction = true;
99
    static void destroy(JSCell*);
100
    static void visitChildren(JSCell*, SlotVisitor&);
101
102
    static size_t offsetOfCallees()
103
    {
104
        return WTF::roundUpToMultipleOf<sizeof(WriteBarrier<JSWebAssemblyCallee>)>(sizeof(JSWebAssemblyCodeBlock));
105
    }
106
107
    static size_t allocationSize(unsigned numCallees)
108
    {
109
        return offsetOfCallees() + sizeof(WriteBarrier<JSWebAssemblyCallee>) * numCallees * 2;
110
    }
111
112
    class UnconditionalFinalizer : public JSC::UnconditionalFinalizer {
113
        void finalizeUnconditionally() override;
114
    };
115
116
    WriteBarrier<JSWebAssemblyModule> m_module;
117
    UnconditionalFinalizer m_unconditionalFinalizer;
118
    Bag<CallLinkInfo> m_callLinkInfos;
119
    Vector<Wasm::WasmExitStubs> m_wasmExitStubs;
120
    Wasm::Memory::Mode m_mode;
121
    unsigned m_calleeCount;
122
};
123
124
} // namespace JSC
125
126
#endif // ENABLE(WEBASSEMBLY)
- a/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp -21 / +34 lines
Lines 259-265 B3IRGenerator::B3IRGenerator(VM& vm, const ModuleInformation& info, Procedure& p a/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp_sec1
259
    for (const PinnedSizeRegisterInfo& regInfo : pinnedRegs.sizeRegisters)
259
    for (const PinnedSizeRegisterInfo& regInfo : pinnedRegs.sizeRegisters)
260
        m_proc.pinRegister(regInfo.sizeRegister);
260
        m_proc.pinRegister(regInfo.sizeRegister);
261
261
262
    if (info.hasMemory()) {
262
    if (info.memory) {
263
        m_proc.setWasmBoundsCheckGenerator([=] (CCallHelpers& jit, GPRReg pinnedGPR, unsigned) {
263
        m_proc.setWasmBoundsCheckGenerator([=] (CCallHelpers& jit, GPRReg pinnedGPR, unsigned) {
264
            AllowMacroScratchRegisterUsage allowScratch(jit);
264
            AllowMacroScratchRegisterUsage allowScratch(jit);
265
            ASSERT_UNUSED(pinnedGPR, m_memorySizeGPR == pinnedGPR);
265
            ASSERT_UNUSED(pinnedGPR, m_memorySizeGPR == pinnedGPR);
Lines 454-462 auto B3IRGenerator::setGlobal(uint32_t index, ExpressionType value) -> PartialRe a/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp_sec2
454
454
455
inline Value* B3IRGenerator::emitCheckAndPreparePointer(ExpressionType pointer, uint32_t offset, uint32_t sizeOfOperation)
455
inline Value* B3IRGenerator::emitCheckAndPreparePointer(ExpressionType pointer, uint32_t offset, uint32_t sizeOfOperation)
456
{
456
{
457
    ASSERT(m_memoryBaseGPR && m_memorySizeGPR);
457
    ASSERT(m_memoryBaseGPR);
458
    ASSERT(sizeOfOperation + offset > offset);
458
    if (m_info.memory.mode() == Memory::Mode::BoundsChecking) {
459
    m_currentBlock->appendNew<WasmBoundsCheckValue>(m_proc, Origin(), pointer, m_memorySizeGPR, sizeOfOperation + offset - 1);
459
        ASSERT(m_memorySizeGPR);
460
        ASSERT(sizeOfOperation + offset > offset);
461
        m_currentBlock->appendNew<WasmBoundsCheckValue>(m_proc, Origin(), pointer, m_memorySizeGPR, sizeOfOperation + offset - 1);
462
    }
460
    pointer = m_currentBlock->appendNew<Value>(m_proc, ZExt32, Origin(), pointer);
463
    pointer = m_currentBlock->appendNew<Value>(m_proc, ZExt32, Origin(), pointer);
461
    return m_currentBlock->appendNew<WasmAddressValue>(m_proc, Origin(), pointer, m_memoryBaseGPR);
464
    return m_currentBlock->appendNew<WasmAddressValue>(m_proc, Origin(), pointer, m_memoryBaseGPR);
462
}
465
}
Lines 488-555 inline uint32_t sizeOfLoadOp(LoadOpType op) a/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp_sec3
488
491
489
inline Value* B3IRGenerator::emitLoadOp(LoadOpType op, Origin origin, ExpressionType pointer, uint32_t offset)
492
inline Value* B3IRGenerator::emitLoadOp(LoadOpType op, Origin origin, ExpressionType pointer, uint32_t offset)
490
{
493
{
494
    auto makeKind = [&] (B3::Opcode opcode) -> B3::Kind {
495
        if (m_info.memory.mode() == Memory::Signaling)
496
            return trapping(opcode);
497
        return opcode;
498
    };
491
    switch (op) {
499
    switch (op) {
492
    case LoadOpType::I32Load8S: {
500
    case LoadOpType::I32Load8S: {
493
        return m_currentBlock->appendNew<MemoryValue>(m_proc, Load8S, origin, pointer, offset);
501
        return m_currentBlock->appendNew<MemoryValue>(m_proc, makeKind(Load8S), origin, pointer, offset);
494
    }
502
    }
495
503
496
    case LoadOpType::I64Load8S: {
504
    case LoadOpType::I64Load8S: {
497
        Value* value = m_currentBlock->appendNew<MemoryValue>(m_proc, Load8S, origin, pointer, offset);
505
        Value* value = m_currentBlock->appendNew<MemoryValue>(m_proc, makeKind(Load8S), origin, pointer, offset);
498
        return m_currentBlock->appendNew<Value>(m_proc, SExt32, origin, value);
506
        return m_currentBlock->appendNew<Value>(m_proc, SExt32, origin, value);
499
    }
507
    }
500
508
501
    case LoadOpType::I32Load8U: {
509
    case LoadOpType::I32Load8U: {
502
        return m_currentBlock->appendNew<MemoryValue>(m_proc, Load8Z, origin, pointer, offset);
510
        return m_currentBlock->appendNew<MemoryValue>(m_proc, makeKind(Load8Z), origin, pointer, offset);
503
    }
511
    }
504
512
505
    case LoadOpType::I64Load8U: {
513
    case LoadOpType::I64Load8U: {
506
        Value* value = m_currentBlock->appendNew<MemoryValue>(m_proc, Load8Z, origin, pointer, offset);
514
        Value* value = m_currentBlock->appendNew<MemoryValue>(m_proc, makeKind(Load8Z), origin, pointer, offset);
507
        return m_currentBlock->appendNew<Value>(m_proc, ZExt32, origin, value);
515
        return m_currentBlock->appendNew<Value>(m_proc, ZExt32, origin, value);
508
    }
516
    }
509
517
510
    case LoadOpType::I32Load16S: {
518
    case LoadOpType::I32Load16S: {
511
        return m_currentBlock->appendNew<MemoryValue>(m_proc, Load16S, origin, pointer, offset);
519
        return m_currentBlock->appendNew<MemoryValue>(m_proc, makeKind(Load16S), origin, pointer, offset);
512
    }
520
    }
513
    case LoadOpType::I64Load16S: {
521
    case LoadOpType::I64Load16S: {
514
        Value* value = m_currentBlock->appendNew<MemoryValue>(m_proc, Load16S, origin, pointer, offset);
522
        Value* value = m_currentBlock->appendNew<MemoryValue>(m_proc, makeKind(Load16S), origin, pointer, offset);
515
        return m_currentBlock->appendNew<Value>(m_proc, SExt32, origin, value);
523
        return m_currentBlock->appendNew<Value>(m_proc, SExt32, origin, value);
516
    }
524
    }
517
525
518
    case LoadOpType::I32Load: {
526
    case LoadOpType::I32Load: {
519
        return m_currentBlock->appendNew<MemoryValue>(m_proc, Load, Int32, origin, pointer, offset);
527
        return m_currentBlock->appendNew<MemoryValue>(m_proc, makeKind(Load), Int32, origin, pointer, offset);
520
    }
528
    }
521
529
522
    case LoadOpType::I64Load32U: {
530
    case LoadOpType::I64Load32U: {
523
        Value* value = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, Int32, origin, pointer, offset);
531
        Value* value = m_currentBlock->appendNew<MemoryValue>(m_proc, makeKind(Load), Int32, origin, pointer, offset);
524
        return m_currentBlock->appendNew<Value>(m_proc, ZExt32, origin, value);
532
        return m_currentBlock->appendNew<Value>(m_proc, ZExt32, origin, value);
525
    }
533
    }
526
534
527
    case LoadOpType::I64Load32S: {
535
    case LoadOpType::I64Load32S: {
528
        Value* value = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, Int32, origin, pointer, offset);
536
        Value* value = m_currentBlock->appendNew<MemoryValue>(m_proc, makeKind(Load), Int32, origin, pointer, offset);
529
        return m_currentBlock->appendNew<Value>(m_proc, SExt32, origin, value);
537
        return m_currentBlock->appendNew<Value>(m_proc, SExt32, origin, value);
530
    }
538
    }
531
539
532
    case LoadOpType::I64Load: {
540
    case LoadOpType::I64Load: {
533
        return m_currentBlock->appendNew<MemoryValue>(m_proc, Load, Int64, origin, pointer, offset);
541
        return m_currentBlock->appendNew<MemoryValue>(m_proc, makeKind(Load), Int64, origin, pointer, offset);
534
    }
542
    }
535
543
536
    case LoadOpType::F32Load: {
544
    case LoadOpType::F32Load: {
537
        return m_currentBlock->appendNew<MemoryValue>(m_proc, Load, Float, origin, pointer, offset);
545
        return m_currentBlock->appendNew<MemoryValue>(m_proc, makeKind(Load), Float, origin, pointer, offset);
538
    }
546
    }
539
547
540
    case LoadOpType::F64Load: {
548
    case LoadOpType::F64Load: {
541
        return m_currentBlock->appendNew<MemoryValue>(m_proc, Load, Double, origin, pointer, offset);
549
        return m_currentBlock->appendNew<MemoryValue>(m_proc, makeKind(Load), Double, origin, pointer, offset);
542
    }
550
    }
543
551
544
    // FIXME: B3 doesn't support Load16Z yet. We should lower to that value when
552
    // FIXME: B3 doesn't support Load16Z yet. We should lower to that value when
545
    // it's added. https://bugs.webkit.org/show_bug.cgi?id=165884
553
    // it's added. https://bugs.webkit.org/show_bug.cgi?id=165884
546
    case LoadOpType::I32Load16U: {
554
    case LoadOpType::I32Load16U: {
547
        Value* value = m_currentBlock->appendNew<MemoryValue>(m_proc, Load16S, origin, pointer, offset);
555
        Value* value = m_currentBlock->appendNew<MemoryValue>(m_proc, makeKind(Load16S), origin, pointer, offset);
548
        return m_currentBlock->appendNew<Value>(m_proc, BitAnd, Origin(), value,
556
        return m_currentBlock->appendNew<Value>(m_proc, BitAnd, Origin(), value,
549
                m_currentBlock->appendNew<Const32Value>(m_proc, Origin(), 0x0000ffff));
557
                m_currentBlock->appendNew<Const32Value>(m_proc, Origin(), 0x0000ffff));
550
    }
558
    }
551
    case LoadOpType::I64Load16U: {
559
    case LoadOpType::I64Load16U: {
552
        Value* value = m_currentBlock->appendNew<MemoryValue>(m_proc, Load16S, origin, pointer, offset);
560
        Value* value = m_currentBlock->appendNew<MemoryValue>(m_proc, makeKind(Load16S), origin, pointer, offset);
553
        Value* partialResult = m_currentBlock->appendNew<Value>(m_proc, BitAnd, Origin(), value,
561
        Value* partialResult = m_currentBlock->appendNew<Value>(m_proc, BitAnd, Origin(), value,
554
                m_currentBlock->appendNew<Const32Value>(m_proc, Origin(), 0x0000ffff));
562
                m_currentBlock->appendNew<Const32Value>(m_proc, Origin(), 0x0000ffff));
555
563
Lines 625-637 inline uint32_t sizeOfStoreOp(StoreOpType op) a/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp_sec4
625
633
626
inline void B3IRGenerator::emitStoreOp(StoreOpType op, Origin origin, ExpressionType pointer, ExpressionType value, uint32_t offset)
634
inline void B3IRGenerator::emitStoreOp(StoreOpType op, Origin origin, ExpressionType pointer, ExpressionType value, uint32_t offset)
627
{
635
{
636
    auto makeKind = [&] (B3::Opcode opcode) -> B3::Kind {
637
        if (m_info.memory.mode() == Memory::Signaling)
638
            return trapping(opcode);
639
        return opcode;
640
    };
628
    switch (op) {
641
    switch (op) {
629
    case StoreOpType::I64Store8:
642
    case StoreOpType::I64Store8:
630
        value = m_currentBlock->appendNew<Value>(m_proc, Trunc, origin, value);
643
        value = m_currentBlock->appendNew<Value>(m_proc, Trunc, origin, value);
631
        FALLTHROUGH;
644
        FALLTHROUGH;
632
645
633
    case StoreOpType::I32Store8:
646
    case StoreOpType::I32Store8:
634
        m_currentBlock->appendNew<MemoryValue>(m_proc, Store8, origin, value, pointer, offset);
647
        m_currentBlock->appendNew<MemoryValue>(m_proc, makeKind(Store8), origin, value, pointer, offset);
635
        return;
648
        return;
636
649
637
    case StoreOpType::I64Store16:
650
    case StoreOpType::I64Store16:
Lines 639-645 inline void B3IRGenerator::emitStoreOp(StoreOpType op, Origin origin, Expression a/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp_sec5
639
        FALLTHROUGH;
652
        FALLTHROUGH;
640
653
641
    case StoreOpType::I32Store16:
654
    case StoreOpType::I32Store16:
642
        m_currentBlock->appendNew<MemoryValue>(m_proc, Store16, origin, value, pointer, offset);
655
        m_currentBlock->appendNew<MemoryValue>(m_proc, makeKind(Store16), origin, value, pointer, offset);
643
        return;
656
        return;
644
657
645
    case StoreOpType::I64Store32:
658
    case StoreOpType::I64Store32:
Lines 650-656 inline void B3IRGenerator::emitStoreOp(StoreOpType op, Origin origin, Expression a/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp_sec6
650
    case StoreOpType::I32Store:
663
    case StoreOpType::I32Store:
651
    case StoreOpType::F32Store:
664
    case StoreOpType::F32Store:
652
    case StoreOpType::F64Store:
665
    case StoreOpType::F64Store:
653
        m_currentBlock->appendNew<MemoryValue>(m_proc, Store, origin, value, pointer, offset);
666
        m_currentBlock->appendNew<MemoryValue>(m_proc, makeKind(Store), origin, value, pointer, offset);
654
        return;
667
        return;
655
    }
668
    }
656
    RELEASE_ASSERT_NOT_REACHED();
669
    RELEASE_ASSERT_NOT_REACHED();
- a/Source/JavaScriptCore/wasm/WasmCallingConvention.h +1 lines
Lines 40-45 a/Source/JavaScriptCore/wasm/WasmCallingConvention.h_sec1
40
#include "LinkBuffer.h"
40
#include "LinkBuffer.h"
41
#include "RegisterSet.h"
41
#include "RegisterSet.h"
42
#include "WasmFormat.h"
42
#include "WasmFormat.h"
43
#include "WasmSignature.h"
43
44
44
namespace JSC { namespace Wasm {
45
namespace JSC { namespace Wasm {
45
46
- a/Source/JavaScriptCore/wasm/WasmFaultSignalHandler.cpp +135 lines
Line 0 a/Source/JavaScriptCore/wasm/WasmFaultSignalHandler.cpp_sec1
1
/*
2
 * Copyright (C) 2017 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
 */
25
26
#include "config.h"
27
#include "WasmFaultSignalHandler.h"
28
29
#if ENABLE(WEBASSEMBLY)
30
31
#include "ExecutableAllocator.h"
32
#include "VM.h"
33
#include "WasmExceptionType.h"
34
35
#include <wtf/Lock.h>
36
#include <wtf/NeverDestroyed.h>
37
38
namespace JSC { namespace Wasm {
39
40
41
namespace {
42
static const bool verbose = false;
43
}
44
45
static struct sigaction oldSigSegVHandler;
46
static struct sigaction oldSigBusHandler;
47
static bool fastHandlerInstalled { false };
48
static StaticLock codeLocationsLock;
49
static LazyNeverDestroyed<HashSet<std::tuple<VM*, void*, void*>>> codeLocations; // (vm, start, end)
50
51
static void trapHandler(int signal, siginfo_t*, void* ucontext)
52
{
53
    dataLogLnIf(verbose, "starting handler");
54
    mcontext_t context = static_cast<ucontext_t*>(ucontext)->uc_mcontext;
55
    void* faultingInstruction = reinterpret_cast<void*>(context->__ss.__rip);
56
57
    dataLogLnIf(verbose, "start: ", RawPointer(reinterpret_cast<void*>(startOfFixedExecutableMemoryPool)), ", faulting address: ", RawPointer(faultingInstruction), ", end: ", RawPointer(reinterpret_cast<void*>(endOfFixedExecutableMemoryPool)));
58
    // First we need to make sure we are in JIT code before we can aquire any locks. Otherwise,
59
    // we might have crashed in code that is already holding one of the locks we want to aquire.
60
    if (reinterpret_cast<void*>(startOfFixedExecutableMemoryPool) <= faultingInstruction
61
        && faultingInstruction < reinterpret_cast<void*>(endOfFixedExecutableMemoryPool)) {
62
63
        LockHolder locker(codeLocationsLock);
64
        for (auto range : codeLocations.get()) {
65
            VM* vm;
66
            void* start;
67
            void* end;
68
            std::tie(vm, start, end) = range;
69
            dataLogLnIf(verbose, "function start: ", RawPointer(start), " end: ", RawPointer(end));
70
            if (start <= faultingInstruction && faultingInstruction <= end) {
71
                dataLogLnIf(verbose, "found match");
72
                MacroAssemblerCodeRef exceptionStub = vm->jitStubs->existingCTIStub(throwExceptionFromWasmThunkGenerator);
73
                // If for whatever reason we don't have a stub then we should just treat this like a regular crash.
74
                if (!exceptionStub.size())
75
                    break;
76
                dataLogLnIf(verbose, "stub: ", RawPointer(exceptionStub.code().executableAddress()));
77
                context->__ss.__rsi = static_cast<uint64_t>(ExceptionType::OutOfBoundsMemoryAccess);
78
                context->__ss.__rip = reinterpret_cast<uint64_t>(exceptionStub.code().executableAddress());
79
                return;
80
            }
81
        }
82
    }
83
84
    if (signal == SIGSEGV)
85
        sigaction(signal, &oldSigSegVHandler, nullptr);
86
    else
87
        sigaction(signal, &oldSigBusHandler, nullptr);
88
}
89
90
void registerCode(VM& vm, void* start, void* end)
91
{
92
    if (!fastMemoryEnabled())
93
        return;
94
    LockHolder locker(codeLocationsLock);
95
    codeLocations->add(std::make_tuple(&vm, start, end));
96
}
97
98
void unregisterCode(VM& vm, void* start, void* end)
99
{
100
    if (!fastMemoryEnabled())
101
        return;
102
    LockHolder locker(codeLocationsLock);
103
    codeLocations->remove(std::make_tuple(&vm, start, end));
104
}
105
106
bool fastMemoryEnabled()
107
{
108
    return fastHandlerInstalled;
109
}
110
111
void enableFastMemory()
112
{
113
    static std::once_flag once;
114
    std::call_once(once, [] {
115
        if (!Options::useWebAssemblyFastMemory())
116
            return;
117
118
        struct sigaction action;
119
120
        action.sa_sigaction = trapHandler;
121
        sigfillset(&action.sa_mask);
122
        action.sa_flags = SA_SIGINFO;
123
        
124
        if (!sigaction(SIGBUS, &action, &oldSigBusHandler)) {
125
            fastHandlerInstalled = true;
126
            codeLocations.construct();
127
        }
128
129
    });
130
}
131
    
132
} } // namespace JSC::Wasm
133
134
#endif // ENABLE(WEBASSEMBLY)
135
- a/Source/JavaScriptCore/wasm/WasmFaultSignalHandler.h +42 lines
Line 0 a/Source/JavaScriptCore/wasm/WasmFaultSignalHandler.h_sec1
1
/*
2
 * Copyright (C) 2017 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
 */
25
26
#if ENABLE(WEBASSEMBLY)
27
28
namespace JSC {
29
30
class VM;
31
32
namespace Wasm {
33
34
void registerCode(VM& vm, void* start, void* end);
35
void unregisterCode(VM& vm, void* start, void* end);
36
37
bool fastMemoryEnabled();
38
JS_EXPORT_PRIVATE void enableFastMemory();
39
40
} } // namespace JSC::Wasm
41
42
#endif // ENABLE(WEBASSEMBLY)
- a/Source/JavaScriptCore/wasm/WasmFormat.h -1 lines
Lines 256-262 struct ModuleInformation { a/Source/JavaScriptCore/wasm/WasmFormat.h_sec1
256
    }
256
    }
257
257
258
    uint32_t importFunctionCount() const { return importFunctionSignatureIndices.size(); }
258
    uint32_t importFunctionCount() const { return importFunctionSignatureIndices.size(); }
259
    bool hasMemory() const { return !!memory; }
260
259
261
    ~ModuleInformation();
260
    ~ModuleInformation();
262
};
261
};
- a/Source/JavaScriptCore/wasm/WasmMemory.cpp -60 / +172 lines
Lines 28-33 a/Source/JavaScriptCore/wasm/WasmMemory.cpp_sec1
28
28
29
#if ENABLE(WEBASSEMBLY)
29
#if ENABLE(WEBASSEMBLY)
30
30
31
#include "WasmFaultSignalHandler.h"
32
33
#include <wtf/NeverDestroyed.h>
31
#include <wtf/HexNumber.h>
34
#include <wtf/HexNumber.h>
32
#include <wtf/PrintStream.h>
35
#include <wtf/PrintStream.h>
33
#include <wtf/text/WTFString.h>
36
#include <wtf/text/WTFString.h>
Lines 38-123 namespace { a/Source/JavaScriptCore/wasm/WasmMemory.cpp_sec2
38
const bool verbose = false;
41
const bool verbose = false;
39
}
42
}
40
43
41
void Memory::dump(PrintStream& out) const
44
inline bool mmapBytes(size_t bytes, void*& memory, size_t& mappedCapacity)
42
{
45
{
43
    String memoryHex;
46
    dataLogIf(verbose, "Attempting to mmap ", bytes, " bytes: ");
44
    WTF::appendUnsigned64AsHex((uint64_t)(uintptr_t)m_memory, memoryHex);
47
    // FIXME: It would be nice if we had a VM tag for wasm memory. https://bugs.webkit.org/show_bug.cgi?id=163600
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));
48
    void* result = mmap(nullptr, bytes, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0);
49
    if (result == MAP_FAILED) {
50
        dataLogLnIf(verbose, "failed");
51
        return false;
52
    }
53
    dataLogLnIf(verbose, "succeeded");
54
    memory = result;
55
    mappedCapacity = bytes;
56
    return true;
46
}
57
}
47
58
48
const char* Memory::makeString(Mode mode) const
59
// We use this as a heuristic to guess which mode we should assume we are going to get when a module imports a memory.
60
static Memory::Mode lastAllocatedMemoryMode { Memory::Mode::Signaling };
61
62
Memory::Mode Memory::lastAllocatedMode()
49
{
63
{
50
    switch (mode) {
64
    return lastAllocatedMemoryMode;
51
    case Mode::BoundsChecking: return "BoundsChecking";
65
}
66
67
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.");
68
69
static const size_t fastMemoryMappedBytes = static_cast<size_t>(std::numeric_limits<uint32_t>::max()) * 2; // pointer max + offset max. This is all we need since a load straddling readable memory will trap.
70
static const unsigned maxFastMemories = 4;
71
static unsigned allocatedFastMemories { 0 };
72
inline Deque<void*, maxFastMemories>& availableFastMemories()
73
{
74
    static NeverDestroyed<Deque<void*, maxFastMemories>> availableFastMemories;
75
    return availableFastMemories;
76
}
77
78
bool tryGetFastMemory(VM& vm, void*& memory, size_t& mappedCapacity, Memory::Mode& mode)
79
{
80
    // We might GC here so we should be holding the API lock.
81
    // FIXME: We should be able to syncronously trigger the GC from another thread.
82
    ASSERT(vm.currentThreadIsHoldingAPILock());
83
    if (!fastMemoryEnabled())
84
        return false;
85
86
    // We need to be sure we have a stub prior to running code.
87
    vm.getCTIStub(throwExceptionFromWasmThunkGenerator);
88
89
    auto dequeFastMemory = [&] () -> bool {
90
        if (!availableFastMemories().isEmpty()) {
91
            memory = availableFastMemories().takeFirst();
92
            mappedCapacity = fastMemoryMappedBytes;
93
            mode = Memory::Signaling;
94
            return true;
95
        }
96
        return false;
97
    };
98
99
    ASSERT(allocatedFastMemories <= maxFastMemories);
100
    if (dequeFastMemory())
101
        return true;
102
103
    // If we have allocated all the fast memories... too bad.
104
    if (allocatedFastMemories == maxFastMemories) {
105
        // There is a reasonable chance that another module has died but has not been collected yet. Don't lose hope yet!
106
        vm.heap.collectSync();
107
        return dequeFastMemory();
52
    }
108
    }
53
    RELEASE_ASSERT_NOT_REACHED();
109
54
    return "";
110
    if (mmapBytes(fastMemoryMappedBytes)) {
111
        mode = Mode::Signaling;
112
        allocatedFastMemories++;
113
    }
114
    return m_memory;
55
}
115
}
56
116
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.");
117
void releaseFastMemory(void*& memory, size_t writableSize)
118
{
119
    if (mode() != Mode::Signaling || !m_memory)
120
        return;
58
121
59
Memory::Memory(PageCount initial, PageCount maximum, bool& failed)
122
    RELEASE_ASSERT(m_memory && m_mappedCapacity == fastMemoryMappedBytes);
123
    ASSERT(fastMemoryEnabled());
124
125
    memset(m_memory, 0, m_size);
126
    // We need to mprotect PROT_NONE all the existing memory. If we can't, for
127
    // whatever reason, we should bail out and get rid of this memory.
128
    if (mprotect(m_memory, m_size, PROT_NONE))
129
        return;
130
131
    ASSERT(availableFastMemories().size() < allocatedFastMemories);
132
    availableFastMemories().append(m_memory);
133
    m_memory = nullptr;
134
}
135
136
Memory::Memory(VM& vm, PageCount initial, PageCount maximum, bool& failed)
60
    : m_size(initial.bytes())
137
    : m_size(initial.bytes())
61
    , m_initial(initial)
138
    , m_initial(initial)
62
    , m_maximum(maximum)
139
    , 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
66
{
140
{
67
    RELEASE_ASSERT(!maximum || maximum >= initial); // This should be guaranteed by our caller.
141
    initialize(vm, initial, maximum, failed);
68
142
    if (mode() == Signaling)
69
    m_mappedCapacity = maximum ? maximum.bytes() : PageCount::max().bytes();
143
        RELEASE_ASSERT(m_mappedCapacity == fastMemoryMappedBytes);
70
    if (!m_mappedCapacity) {
144
    if (!failed)
71
        // This means we specified a zero as maximum (which means we also have zero as initial size).
145
        ASSERT(lastAllocatedMode() == mode());
72
        RELEASE_ASSERT(m_size == 0);
146
}
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
147
81
    // FIXME: It would be nice if we had a VM tag for wasm memory. https://bugs.webkit.org/show_bug.cgi?id=163600
148
    RefPtr<Memory> Memory::createImpl(VM& vm, PageCount initial, PageCount maximum, std::optional<Mode> mode)
82
    void* result = Options::simulateWebAssemblyLowMemory() ? MAP_FAILED : mmap(nullptr, m_mappedCapacity, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0);
149
    {
83
    if (result == MAP_FAILED) {
150
        RELEASE_ASSERT(!maximum || maximum >= initial); // This should be guaranteed by our caller.
84
        // Try again with a different number.
151
85
        if (verbose)
152
        uint64_t size = initial.bytes();
86
            dataLogLn("Memory::Memory mmap failed once for capacity, trying again", *this);
153
        uint64_t mappedCapacity = maximum ? maximum.bytes() : PageCount::max().bytes();
87
        m_mappedCapacity = m_size;
88
        if (!m_mappedCapacity) {
154
        if (!m_mappedCapacity) {
89
            m_memory = nullptr;
155
            // This means we specified a zero as maximum (which means we also have zero as initial size).
90
            failed = false;
156
            RELEASE_ASSERT(size == 0);
91
            if (verbose)
157
            dataLogLnIf(verbose, "Memory::Memory allocating nothing ", *this);
92
                dataLogLn("Memory::Memory mmap not trying again because size is zero ", *this);
158
            return nullptr;
93
            return;
94
        }
159
        }
95
160
96
        result = mmap(nullptr, m_mappedCapacity, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0);
161
        if (!tryGetFastMemory(vm)) {
97
        if (result == MAP_FAILED) {
162
            if (Options::simulateWebAssemblyLowMemory() ? true : !mmapBytes(m_mappedCapacity)) {
98
            if (verbose)
163
                // Try again with a different number.
99
                dataLogLn("Memory::Memory mmap failed twice ", *this);
164
                dataLogLnIf(verbose, "Memory::Memory mmap failed once for capacity, trying again", *this);
165
                m_mappedCapacity = m_size;
166
                if (!m_mappedCapacity) {
167
                    m_memory = nullptr;
168
                    failed = false;
169
                    dataLogLnIf(verbose, "Memory::Memory mmap not trying again because size is zero ", *this);
170
                    return;
171
                }
172
173
                if (!mmapBytes(m_mappedCapacity)) {
174
                    dataLogLnIf(verbose, "Memory::Memory mmap failed twice ", *this);
175
                    failed = true;
176
                    return;
177
                }
178
            }
179
        }
180
181
        ASSERT(m_memory && m_size <= m_mappedCapacity);
182
        if (mprotect(m_memory, static_cast<size_t>(m_size), PROT_READ | PROT_WRITE)) {
183
            dataLogLnIf(verbose, "Memory::Memory mprotect failed ", *this);
184
            releaseFastMemory();
185
            if (m_memory) {
186
                if (munmap(m_memory, m_mappedCapacity))
187
                    CRASH();
188
            }
100
            failed = true;
189
            failed = true;
101
            return;
190
            return;
102
        }
191
        }
192
        
193
        lastAllocatedMemoryMode = m_mode;
194
        failed = false;
195
        dataLogLnIf(verbose, "Memory::Memory mmap succeeded ", *this);
103
    }
196
    }
104
197
105
    ASSERT(m_size <= m_mappedCapacity);
198
    RefPtr<Memory> Memory::create(VM& vm, PageCount initial, PageCount maximum, std::optional<Mode> mode)
106
    {
199
    {
107
        bool success = !mprotect(result, static_cast<size_t>(m_size), PROT_READ | PROT_WRITE);
200
        RELEASE_ASSERT(!maximum || maximum >= initial); // This should be guaranteed by our caller.
108
        RELEASE_ASSERT(success);
201
202
109
    }
203
    }
110
204
111
    m_memory = result;
205
void Memory::initialize(VM& vm, PageCount initial, PageCount maximum, bool& failed)
112
    failed = false;
206
{
113
    if (verbose)
207
114
        dataLogLn("Memory::Memory mmap succeeded ", *this);
115
}
208
}
116
209
117
Memory::~Memory()
210
Memory::~Memory()
118
{
211
{
119
    if (verbose)
212
    dataLogLnIf(verbose, "Memory::~Memory ", *this);
120
        dataLogLn("Memory::~Memory ", *this);
213
    releaseFastMemory();
121
    if (m_memory) {
214
    if (m_memory) {
122
        if (munmap(m_memory, m_mappedCapacity))
215
        if (munmap(m_memory, m_mappedCapacity))
123
            CRASH();
216
            CRASH();
Lines 128-135 bool Memory::grow(PageCount newSize) a/Source/JavaScriptCore/wasm/WasmMemory.cpp_sec3
128
{
221
{
129
    RELEASE_ASSERT(newSize > PageCount::fromBytes(m_size));
222
    RELEASE_ASSERT(newSize > PageCount::fromBytes(m_size));
130
223
131
    if (verbose)
224
    dataLogLnIf(verbose, "Memory::grow to ", newSize, " from ", *this);
132
        dataLogLn("Memory::grow to ", newSize, " from ", *this);
133
225
134
    if (maximum() && newSize > maximum())
226
    if (maximum() && newSize > maximum())
135
        return false;
227
        return false;
Lines 137-150 bool Memory::grow(PageCount newSize) a/Source/JavaScriptCore/wasm/WasmMemory.cpp_sec4
137
    uint64_t desiredSize = newSize.bytes();
229
    uint64_t desiredSize = newSize.bytes();
138
230
139
    if (m_memory && desiredSize <= m_mappedCapacity) {
231
    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);
232
        if (mprotect(static_cast<uint8_t*>(m_memory) + m_size, static_cast<size_t>(desiredSize - m_size), PROT_READ | PROT_WRITE)) {
141
        RELEASE_ASSERT(success);
233
            dataLogLnIf(verbose, "Memory::grow in-place failed ", *this);
234
            return false;
235
        }
236
142
        m_size = desiredSize;
237
        m_size = desiredSize;
143
        if (verbose)
238
        dataLogLnIf(verbose, "Memory::grow in-place ", *this);
144
            dataLogLn("Memory::grow in-place ", *this);
145
        return true;
239
        return true;
146
    }
240
    }
147
241
242
    ASSERT(mode() != Signaling);
148
    // Otherwise, let's try to make some new memory.
243
    // Otherwise, let's try to make some new memory.
149
    void* newMemory = mmap(nullptr, desiredSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
244
    void* newMemory = mmap(nullptr, desiredSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
150
    if (newMemory == MAP_FAILED)
245
    if (newMemory == MAP_FAILED)
Lines 159-169 bool Memory::grow(PageCount newSize) a/Source/JavaScriptCore/wasm/WasmMemory.cpp_sec5
159
    m_mappedCapacity = desiredSize;
254
    m_mappedCapacity = desiredSize;
160
    m_size = desiredSize;
255
    m_size = desiredSize;
161
256
162
    if (verbose)
257
    dataLogLnIf(verbose, "Memory::grow ", *this);
163
        dataLogLn("Memory::grow ", *this);
164
    return true;
258
    return true;
165
}
259
}
166
260
261
void Memory::dump(PrintStream& out) const
262
{
263
    String memoryHex;
264
    WTF::appendUnsigned64AsHex((uint64_t)(uintptr_t)m_memory, memoryHex);
265
    out.print("Memory at 0x", memoryHex, ", size ", m_size, "B capacity ", m_mappedCapacity, "B, initial ", m_initial, " maximum ", m_maximum, " mode ", makeString(m_mode));
266
}
267
268
const char* Memory::makeString(Mode mode) const
269
{
270
    switch (mode) {
271
    case Mode::BoundsChecking: return "BoundsChecking";
272
    case Mode::Signaling: return "Signaling";
273
    case Mode::NumberOfModes: break;
274
    }
275
    RELEASE_ASSERT_NOT_REACHED();
276
    return "";
277
}
278
167
} // namespace JSC
279
} // namespace JSC
168
280
169
} // namespace Wasm
281
} // namespace Wasm
- a/Source/JavaScriptCore/wasm/WasmMemory.h -15 / +45 lines
Lines 27-66 a/Source/JavaScriptCore/wasm/WasmMemory.h_sec1
27
27
28
#if ENABLE(WEBASSEMBLY)
28
#if ENABLE(WEBASSEMBLY)
29
29
30
#include "WasmCallingConvention.h"
31
#include "WasmPageCount.h"
30
#include "WasmPageCount.h"
32
31
32
#include <wtf/Optional.h>
33
#include <wtf/RefCounted.h>
34
#include <wtf/RefPtr.h>
35
33
namespace WTF {
36
namespace WTF {
34
class PrintStream;
37
class PrintStream;
35
}
38
}
36
39
37
namespace JSC { namespace Wasm {
40
namespace JSC {
41
42
class VM;
38
43
39
class Memory {
44
namespace Wasm {
45
46
class Memory : public RefCounted<Memory> {
40
    WTF_MAKE_NONCOPYABLE(Memory);
47
    WTF_MAKE_NONCOPYABLE(Memory);
41
    WTF_MAKE_FAST_ALLOCATED;
48
    WTF_MAKE_FAST_ALLOCATED;
42
public:
49
public:
43
    void dump(WTF::PrintStream&) const;
50
    void dump(WTF::PrintStream&) const;
44
51
45
    // FIXME: We should support other modes. see: https://bugs.webkit.org/show_bug.cgi?id=162693
52
    // FIXME: We should support other modes. see: https://bugs.webkit.org/show_bug.cgi?id=162693
46
    enum class Mode {
53
    enum Mode {
47
        BoundsChecking
54
        BoundsChecking,
55
        Signaling,
56
        NumberOfModes
48
    };
57
    };
49
    const char* makeString(Mode) const;
58
    const char* makeString(Mode) const;
50
59
60
    explicit operator bool() const { return !!m_memory; }
61
62
    Memory& operator=(Memory&& other)
63
    {
64
        // Moving transfers ownership of the allocated memory.
65
        ASSERT(m_memory == nullptr);
66
        std::swap(m_memory, other.m_memory);
67
        m_size = other.m_size;
68
        m_initial = other.m_initial;
69
        m_maximum = other.m_maximum;
70
        m_mappedCapacity = other.m_mappedCapacity;
71
        m_mode = other.m_mode;
72
        if (m_memory && m_mode == Mode::Signaling)
73
            ASSERT(m_mappedCapacity == static_cast<size_t>(std::numeric_limits<uint32_t>::max()) * 2);
74
        return *this;
75
76
    }
77
78
    static RefPtr<Memory> create(VM&, PageCount initial, PageCount maximum, std::optional<Mode> requiredMode = std::nullopt);
79
51
    Memory() = default;
80
    Memory() = default;
52
    JS_EXPORT_PRIVATE Memory(PageCount initial, PageCount maximum, bool& failed);
81
    JS_EXPORT_PRIVATE Memory(VM&, PageCount initial, PageCount maximum, bool& failed);
53
    Memory(Memory&& other)
82
    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
    {
83
    {
61
        // Moving transfers ownership of the allocated memory.
84
        *this = WTFMove(other);
62
        other.m_memory = nullptr;
63
    }
85
    }
86
64
    ~Memory();
87
    ~Memory();
65
88
66
    void* memory() const { return m_memory; }
89
    void* memory() const { return m_memory; }
Lines 70-83 public: a/Source/JavaScriptCore/wasm/WasmMemory.h_sec2
70
    PageCount initial() const { return m_initial; }
93
    PageCount initial() const { return m_initial; }
71
    PageCount maximum() const { return m_maximum; }
94
    PageCount maximum() const { return m_maximum; }
72
95
96
    static Mode lastAllocatedMode();
73
    Mode mode() const { return m_mode; }
97
    Mode mode() const { return m_mode; }
74
98
75
    bool grow(PageCount);
99
    bool grow(PageCount);
76
100
77
    static ptrdiff_t offsetOfMemory() { return OBJECT_OFFSETOF(Memory, m_memory); }
101
    static ptrdiff_t offsetOfMemory() { return OBJECT_OFFSETOF(Memory, m_memory); }
78
    static ptrdiff_t offsetOfSize() { return OBJECT_OFFSETOF(Memory, m_size); }
102
    static ptrdiff_t offsetOfSize() { return OBJECT_OFFSETOF(Memory, m_size); }
79
    
103
80
private:
104
private:
105
    static RefPtr<Memory> createImpl(VM&, PageCount initial, PageCount maximum, std::optional<Mode> requiredMode = std::nullopt);
106
    void initialize(VM& vm, PageCount initial, PageCount maximum, bool& failed);
107
108
    bool tryGetFastMemory(VM& vm);
109
    void releaseFastMemory();
110
81
    void* m_memory { nullptr };
111
    void* m_memory { nullptr };
82
    uint64_t m_size { 0 };
112
    uint64_t m_size { 0 };
83
    PageCount m_initial;
113
    PageCount m_initial;
- a/Source/JavaScriptCore/wasm/WasmMemoryInformation.cpp -1 / +14 lines
Lines 29-34 a/Source/JavaScriptCore/wasm/WasmMemoryInformation.cpp_sec1
29
#if ENABLE(WEBASSEMBLY)
29
#if ENABLE(WEBASSEMBLY)
30
30
31
#include "WasmCallingConvention.h"
31
#include "WasmCallingConvention.h"
32
#include "WasmMemory.h"
32
#include <wtf/NeverDestroyed.h>
33
#include <wtf/NeverDestroyed.h>
33
34
34
namespace JSC { namespace Wasm {
35
namespace JSC { namespace Wasm {
Lines 71-81 PinnedRegisterInfo::PinnedRegisterInfo(Vector<PinnedSizeRegisterInfo>&& sizeRegi a/Source/JavaScriptCore/wasm/WasmMemoryInformation.cpp_sec2
71
{
72
{
72
}
73
}
73
74
74
MemoryInformation::MemoryInformation(PageCount initial, PageCount maximum,  bool isImport)
75
MemoryInformation::MemoryInformation(VM& vm, PageCount initial, PageCount maximum, std::optional<Memory::Mode> recompileMode, bool isImport)
75
    : m_initial(initial)
76
    : m_initial(initial)
76
    , m_maximum(maximum)
77
    , m_maximum(maximum)
77
    , m_isImport(isImport)
78
    , m_isImport(isImport)
78
{
79
{
80
    if (!isImport && !recompileMode) {
81
        bool failedToReserve;
82
        auto adoptRef<Memory>(vm, initial, maximum, failedToReserve);
83
        if (!failedToReserve) {
84
            m_reservedMemory = WTFMove(mem);
85
        }
86
    }
87
    if (recompileMode)
88
        m_mode = *recompileMode;
89
    else
90
        m_mode = Memory::lastAllocatedMode();
91
79
    RELEASE_ASSERT(!!m_initial);
92
    RELEASE_ASSERT(!!m_initial);
80
    RELEASE_ASSERT(!m_maximum || m_maximum >= m_initial);
93
    RELEASE_ASSERT(!m_maximum || m_maximum >= m_initial);
81
    ASSERT(!!*this);
94
    ASSERT(!!*this);
- a/Source/JavaScriptCore/wasm/WasmMemoryInformation.h -1 / +10 lines
Lines 28-35 a/Source/JavaScriptCore/wasm/WasmMemoryInformation.h_sec1
28
#if ENABLE(WEBASSEMBLY)
28
#if ENABLE(WEBASSEMBLY)
29
29
30
#include "GPRInfo.h"
30
#include "GPRInfo.h"
31
#include "WasmMemory.h"
31
#include "WasmPageCount.h"
32
#include "WasmPageCount.h"
32
#include <wtf/Vector.h>
33
#include <wtf/Vector.h>
34
#include <wtf/Ref.h>
33
35
34
namespace JSC { namespace Wasm {
36
namespace JSC { namespace Wasm {
35
37
Lines 52-68 public: a/Source/JavaScriptCore/wasm/WasmMemoryInformation.h_sec2
52
        ASSERT(!*this);
54
        ASSERT(!*this);
53
    }
55
    }
54
56
55
    MemoryInformation(PageCount initial, PageCount maximum, bool isImport);
57
    MemoryInformation(VM&, PageCount initial, PageCount maximum, std::optional<Memory::Mode> mode, bool isImport);
56
58
57
    PageCount initial() const { return m_initial; }
59
    PageCount initial() const { return m_initial; }
58
    PageCount maximum() const { return m_maximum; }
60
    PageCount maximum() const { return m_maximum; }
61
    bool hasReservedMemory() const { return m_reservedMemory && !!*m_reservedMemory; }
62
    Memory& reservedMemory() const { ASSERT(hasReservedMemory()); return *m_reservedMemory; }
63
    Memory::Mode mode() const { return m_mode; }
59
    bool isImport() const { return m_isImport; }
64
    bool isImport() const { return m_isImport; }
60
65
61
    explicit operator bool() const { return !!m_initial; }
66
    explicit operator bool() const { return !!m_initial; }
62
67
63
private:
68
private:
69
    // This is a unique_ptr so we can pass ModuleInformation as const and still be
70
    // able to take ownership of this.
71
    RefPtr<Memory> m_reservedMemory;
64
    PageCount m_initial { };
72
    PageCount m_initial { };
65
    PageCount m_maximum { };
73
    PageCount m_maximum { };
74
    Memory::Mode m_mode { Memory::Mode::BoundsChecking };
66
    bool m_isImport { false };
75
    bool m_isImport { false };
67
};
76
};
68
77
- a/Source/JavaScriptCore/wasm/WasmModuleParser.cpp -1 / +1 lines
Lines 316-322 auto ModuleParser::parseMemoryHelper(bool isImport) -> PartialResult a/Source/JavaScriptCore/wasm/WasmModuleParser.cpp_sec1
316
    ASSERT(initialPageCount);
316
    ASSERT(initialPageCount);
317
    ASSERT(!maximumPageCount || maximumPageCount >= initialPageCount);
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
    return { };
320
    return { };
321
}
321
}
322
322
- a/Source/JavaScriptCore/wasm/WasmModuleParser.h -5 / +4 lines
Lines 30-35 a/Source/JavaScriptCore/wasm/WasmModuleParser.h_sec1
30
#include "WasmFormat.h"
30
#include "WasmFormat.h"
31
#include "WasmOps.h"
31
#include "WasmOps.h"
32
#include "WasmParser.h"
32
#include "WasmParser.h"
33
#include <wtf/Optional.h>
33
#include <wtf/Vector.h>
34
#include <wtf/Vector.h>
34
35
35
namespace JSC { namespace Wasm {
36
namespace JSC { namespace Wasm {
Lines 43-54 struct ModuleParserResult { a/Source/JavaScriptCore/wasm/WasmModuleParser.h_sec2
43
class ModuleParser : public Parser<ModuleParserResult> {
44
class ModuleParser : public Parser<ModuleParserResult> {
44
public:
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
        : Parser(vm, sourceBuffer, sourceLength)
48
        : Parser(vm, sourceBuffer, sourceLength)
48
    {
49
        , m_mode(mode)
49
    }
50
    ModuleParser(VM* vm, const Vector<uint8_t>& sourceBuffer)
51
        : ModuleParser(vm, sourceBuffer.data(), sourceBuffer.size())
52
    {
50
    {
53
    }
51
    }
54
52
Lines 68-73 private: a/Source/JavaScriptCore/wasm/WasmModuleParser.h_sec3
68
    PartialResult WARN_UNUSED_RETURN parseInitExpr(uint8_t&, uint64_t&, Type& initExprType);
66
    PartialResult WARN_UNUSED_RETURN parseInitExpr(uint8_t&, uint64_t&, Type& initExprType);
69
67
70
    ModuleParserResult m_result;
68
    ModuleParserResult m_result;
69
    std::optional<Memory::Mode> m_mode { std::nullopt };
71
    bool m_hasTable { false };
70
    bool m_hasTable { false };
72
};
71
};
73
72
- a/Source/JavaScriptCore/wasm/WasmPlan.cpp -4 / +7 lines
Lines 35-40 a/Source/JavaScriptCore/wasm/WasmPlan.cpp_sec1
35
#include "WasmB3IRGenerator.h"
35
#include "WasmB3IRGenerator.h"
36
#include "WasmBinding.h"
36
#include "WasmBinding.h"
37
#include "WasmCallingConvention.h"
37
#include "WasmCallingConvention.h"
38
#include "WasmFaultSignalHandler.h"
38
#include "WasmMemory.h"
39
#include "WasmMemory.h"
39
#include "WasmModuleParser.h"
40
#include "WasmModuleParser.h"
40
#include "WasmValidate.h"
41
#include "WasmValidate.h"
Lines 61-74 Plan::Plan(VM* vm, const uint8_t* source, size_t sourceLength) a/Source/JavaScriptCore/wasm/WasmPlan.cpp_sec2
61
{
62
{
62
}
63
}
63
64
64
bool Plan::parseAndValidateModule()
65
bool Plan::parseAndValidateModule(std::optional<Memory::Mode> recompileMode)
65
{
66
{
66
    MonotonicTime startTime;
67
    MonotonicTime startTime;
67
    if (verbose || Options::reportCompileTimes())
68
    if (verbose || Options::reportCompileTimes())
68
        startTime = MonotonicTime::now();
69
        startTime = MonotonicTime::now();
69
70
70
    {
71
    {
71
        ModuleParser moduleParser(m_vm, m_source, m_sourceLength);
72
        ModuleParser moduleParser(m_vm, m_source, m_sourceLength, recompileMode);
72
        auto parseResult = moduleParser.parse();
73
        auto parseResult = moduleParser.parse();
73
        if (!parseResult) {
74
        if (!parseResult) {
74
            m_errorMessage = parseResult.error();
75
            m_errorMessage = parseResult.error();
Lines 109-118 bool Plan::parseAndValidateModule() a/Source/JavaScriptCore/wasm/WasmPlan.cpp_sec3
109
// The reason this is OK is that we guarantee that the main thread doesn't continue until all threads
110
// The reason this is OK is that we guarantee that the main thread doesn't continue until all threads
110
// that could touch its stack are done executing.
111
// that could touch its stack are done executing.
111
SUPPRESS_ASAN 
112
SUPPRESS_ASAN 
112
void Plan::run()
113
void Plan::run(std::optional<Memory::Mode> recompileMode)
113
{
114
{
114
    if (!parseAndValidateModule())
115
    if (!parseAndValidateModule(recompileMode))
115
        return;
116
        return;
117
    if (recompileMode)
118
        ASSERT(m_moduleInformation->memory.mode() == recompileMode);
116
119
117
    auto tryReserveCapacity = [this] (auto& vector, size_t size, const char* what) {
120
    auto tryReserveCapacity = [this] (auto& vector, size_t size, const char* what) {
118
        if (UNLIKELY(!vector.tryReserveCapacity(size))) {
121
        if (UNLIKELY(!vector.tryReserveCapacity(size))) {
- a/Source/JavaScriptCore/wasm/WasmPlan.h -2 / +4 lines
Lines 49-57 public: a/Source/JavaScriptCore/wasm/WasmPlan.h_sec1
49
    JS_EXPORT_PRIVATE Plan(VM*, const uint8_t*, size_t);
49
    JS_EXPORT_PRIVATE Plan(VM*, const uint8_t*, size_t);
50
    JS_EXPORT_PRIVATE ~Plan();
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
    JS_EXPORT_PRIVATE void initializeCallees(JSGlobalObject*, std::function<void(unsigned, JSWebAssemblyCallee*, JSWebAssemblyCallee*)>);
56
    JS_EXPORT_PRIVATE void initializeCallees(JSGlobalObject*, std::function<void(unsigned, JSWebAssemblyCallee*, JSWebAssemblyCallee*)>);
57
57
Lines 92-97 public: a/Source/JavaScriptCore/wasm/WasmPlan.h_sec2
92
        return WTFMove(m_wasmExitStubs);
92
        return WTFMove(m_wasmExitStubs);
93
    }
93
    }
94
94
95
    Memory::Mode mode() const { return m_moduleInformation->memory.mode(); }
96
95
private:
97
private:
96
    std::unique_ptr<ModuleInformation> m_moduleInformation;
98
    std::unique_ptr<ModuleInformation> m_moduleInformation;
97
    Vector<FunctionLocationInBinary> m_functionLocationInBinary;
99
    Vector<FunctionLocationInBinary> m_functionLocationInBinary;
- a/Source/JavaScriptCore/wasm/js/JSWebAssemblyCallee.cpp +3 lines
Lines 29-34 a/Source/JavaScriptCore/wasm/js/JSWebAssemblyCallee.cpp_sec1
29
#if ENABLE(WEBASSEMBLY)
29
#if ENABLE(WEBASSEMBLY)
30
30
31
#include "JSCInlines.h"
31
#include "JSCInlines.h"
32
#include "WasmFaultSignalHandler.h"
32
33
33
namespace JSC {
34
namespace JSC {
34
35
Lines 43-53 void JSWebAssemblyCallee::finishCreation(VM& vm, Wasm::Entrypoint&& entrypoint) a/Source/JavaScriptCore/wasm/js/JSWebAssemblyCallee.cpp_sec2
43
    Base::finishCreation(vm);
44
    Base::finishCreation(vm);
44
45
45
    m_entrypoint = WTFMove(entrypoint);
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
48
void JSWebAssemblyCallee::destroy(JSCell* cell)
50
void JSWebAssemblyCallee::destroy(JSCell* cell)
49
{
51
{
50
    JSWebAssemblyCallee* thisObject = static_cast<JSWebAssemblyCallee*>(cell);
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
    thisObject->JSWebAssemblyCallee::~JSWebAssemblyCallee();
54
    thisObject->JSWebAssemblyCallee::~JSWebAssemblyCallee();
52
}
55
}
53
56
- a/Source/JavaScriptCore/wasm/js/JSWebAssemblyCodeBlock.cpp +78 lines
Line 0 a/Source/JavaScriptCore/wasm/js/JSWebAssemblyCodeBlock.cpp_sec1
1
/*
2
 * Copyright (C) 2017 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
 */
25
26
#include "config.h"
27
#include "JSWebAssemblyCodeBlock.h"
28
29
#if ENABLE(WEBASSEMBLY)
30
31
#include "JSCInlines.h"
32
#include "JSWebAssemblyMemory.h"
33
#include "JSWebAssemblyModule.h"
34
35
namespace JSC {
36
37
const ClassInfo JSWebAssemblyCodeBlock::s_info = { "WebAssemblyCodeBlock", nullptr, 0, CREATE_METHOD_TABLE(JSWebAssemblyCodeBlock) };
38
39
JSWebAssemblyCodeBlock::JSWebAssemblyCodeBlock(VM& vm, JSWebAssemblyModule* owner, Bag<CallLinkInfo>&& callLinkInfos, Vector<Wasm::WasmExitStubs>&& wasmExitStubs, Wasm::Memory::Mode mode, unsigned calleeCount)
40
    : Base(vm, vm.webAssemblyCodeBlockStructure.get())
41
    , m_callLinkInfos(WTFMove(callLinkInfos))
42
    , m_wasmExitStubs(WTFMove(wasmExitStubs))
43
    , m_mode(mode)
44
    , m_calleeCount(calleeCount)
45
{
46
    m_module.set(vm, this, owner);
47
    memset(callees(), 0, m_calleeCount * sizeof(WriteBarrier<JSWebAssemblyCallee>) * 2);
48
}
49
50
void JSWebAssemblyCodeBlock::destroy(JSCell* cell)
51
{
52
    static_cast<JSWebAssemblyCodeBlock*>(cell)->JSWebAssemblyCodeBlock::~JSWebAssemblyCodeBlock();
53
}
54
55
void JSWebAssemblyCodeBlock::visitChildren(JSCell* cell, SlotVisitor& visitor)
56
{
57
    JSWebAssemblyCodeBlock* thisObject = jsCast<JSWebAssemblyCodeBlock*>(cell);
58
    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
59
60
    Base::visitChildren(thisObject, visitor);
61
    visitor.append(thisObject->m_module);
62
    for (unsigned i = 0; i < thisObject->m_calleeCount * 2; i++)
63
        visitor.append(thisObject->callees()[i]);
64
65
    visitor.addUnconditionalFinalizer(&thisObject->m_unconditionalFinalizer);
66
}
67
68
void JSWebAssemblyCodeBlock::UnconditionalFinalizer::finalizeUnconditionally()
69
{
70
    JSWebAssemblyCodeBlock* thisObject = bitwise_cast<JSWebAssemblyCodeBlock*>(
71
        bitwise_cast<char*>(this) - OBJECT_OFFSETOF(JSWebAssemblyCodeBlock, m_unconditionalFinalizer));
72
    for (auto iter = thisObject->m_callLinkInfos.begin(); !!iter; ++iter)
73
        (*iter)->visitWeak(*thisObject->vm());
74
}
75
76
} // namespace JSC
77
78
#endif // ENABLE(WEBASSEMBLY)
- a/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp -3 / +15 lines
Lines 1-5 a/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp_sec1
1
/*
1
/*
2
 * Copyright (C) 2016 Apple Inc. All rights reserved.
2
 * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
3
 *
3
 *
4
 * Redistribution and use in source and binary forms, with or without
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
5
 * modification, are permitted provided that the following conditions
Lines 38-43 a/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp_sec2
38
38
39
namespace JSC {
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
JSWebAssemblyInstance* JSWebAssemblyInstance::create(VM& vm, Structure* structure, JSWebAssemblyModule* module, JSModuleNamespaceObject* moduleNamespaceObject)
53
JSWebAssemblyInstance* JSWebAssemblyInstance::create(VM& vm, Structure* structure, JSWebAssemblyModule* module, JSModuleNamespaceObject* moduleNamespaceObject)
42
{
54
{
43
    // FIXME: These objects could be pretty big we should try to throw OOM here.
55
    // FIXME: These objects could be pretty big we should try to throw OOM here.
Lines 67-73 void JSWebAssemblyInstance::finishCreation(VM& vm, JSWebAssemblyModule* module, a/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp_sec3
67
    m_globals = MallocPtr<uint64_t>::malloc(extraMemorySize);
79
    m_globals = MallocPtr<uint64_t>::malloc(extraMemorySize);
68
    heap()->reportExtraMemoryAllocated(extraMemorySize);
80
    heap()->reportExtraMemoryAllocated(extraMemorySize);
69
81
70
    m_module.set(vm, this, module);
82
    m_codeBlock.set(vm, this, module->codeBlock());
71
    m_moduleNamespaceObject.set(vm, this, moduleNamespaceObject);
83
    m_moduleNamespaceObject.set(vm, this, moduleNamespaceObject);
72
    putDirect(vm, Identifier::fromString(&vm, "exports"), moduleNamespaceObject, None);
84
    putDirect(vm, Identifier::fromString(&vm, "exports"), moduleNamespaceObject, None);
73
}
85
}
Lines 83-89 void JSWebAssemblyInstance::visitChildren(JSCell* cell, SlotVisitor& visitor) a/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp_sec4
83
    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
95
    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
84
96
85
    Base::visitChildren(thisObject, visitor);
97
    Base::visitChildren(thisObject, visitor);
86
    visitor.append(thisObject->m_module);
98
    visitor.append(thisObject->m_codeBlock);
87
    visitor.append(thisObject->m_moduleNamespaceObject);
99
    visitor.append(thisObject->m_moduleNamespaceObject);
88
    visitor.append(thisObject->m_memory);
100
    visitor.append(thisObject->m_memory);
89
    visitor.append(thisObject->m_table);
101
    visitor.append(thisObject->m_table);
- a/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h -5 / +14 lines
Lines 29-34 a/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h_sec1
29
29
30
#include "JSDestructibleObject.h"
30
#include "JSDestructibleObject.h"
31
#include "JSObject.h"
31
#include "JSObject.h"
32
#include "JSWebAssemblyCodeBlock.h"
32
#include "JSWebAssemblyMemory.h"
33
#include "JSWebAssemblyMemory.h"
33
#include "JSWebAssemblyTable.h"
34
#include "JSWebAssemblyTable.h"
34
35
Lines 47-56 public: a/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h_sec2
47
48
48
    DECLARE_INFO;
49
    DECLARE_INFO;
49
50
50
    JSWebAssemblyModule* module()
51
    JSWebAssemblyModule* module() const
51
    {
52
    {
52
        ASSERT(m_module);
53
        ASSERT(m_codeBlock);
53
        return m_module.get();
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
56
    WriteBarrier<JSCell>* importFunction(unsigned idx)
63
    WriteBarrier<JSCell>* importFunction(unsigned idx)
Lines 70-76 public: a/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h_sec3
70
    }
77
    }
71
78
72
    JSWebAssemblyMemory* memory() { return m_memory.get(); }
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& vm, ExecState*, JSWebAssemblyMemory* memory);
82
    Wasm::Memory::Mode memoryMode() { return memory()->memory()->mode(); }
74
83
75
    JSWebAssemblyTable* table() { return m_table.get(); }
84
    JSWebAssemblyTable* table() { return m_table.get(); }
76
    void setTable(VM& vm, JSWebAssemblyTable* table) { m_table.set(vm, this, table); }
85
    void setTable(VM& vm, JSWebAssemblyTable* table) { m_table.set(vm, this, table); }
Lines 104-110 protected: a/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h_sec4
104
    }
113
    }
105
114
106
private:
115
private:
107
    WriteBarrier<JSWebAssemblyModule> m_module;
116
    WriteBarrier<JSWebAssemblyCodeBlock> m_codeBlock;
108
    WriteBarrier<JSModuleNamespaceObject> m_moduleNamespaceObject;
117
    WriteBarrier<JSModuleNamespaceObject> m_moduleNamespaceObject;
109
    WriteBarrier<JSWebAssemblyMemory> m_memory;
118
    WriteBarrier<JSWebAssemblyMemory> m_memory;
110
    WriteBarrier<JSWebAssemblyTable> m_table;
119
    WriteBarrier<JSWebAssemblyTable> m_table;
- a/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.cpp -22 / +76 lines
Lines 30-47 a/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.cpp_sec1
30
30
31
#include "JSCInlines.h"
31
#include "JSCInlines.h"
32
#include "JSWebAssemblyCallee.h"
32
#include "JSWebAssemblyCallee.h"
33
#include "JSWebAssemblyCodeBlock.h"
34
#include "JSWebAssemblyCompileError.h"
35
#include "JSWebAssemblyMemory.h"
33
#include "WasmFormat.h"
36
#include "WasmFormat.h"
34
#include "WasmMemory.h"
37
#include "WasmMemory.h"
38
#include "WasmPlan.h"
35
#include <wtf/StdLibExtras.h>
39
#include <wtf/StdLibExtras.h>
36
40
37
namespace JSC {
41
namespace JSC {
38
42
39
const ClassInfo JSWebAssemblyModule::s_info = { "WebAssembly.Module", &Base::s_info, nullptr, CREATE_METHOD_TABLE(JSWebAssemblyModule) };
43
const ClassInfo JSWebAssemblyModule::s_info = { "WebAssembly.Module", &Base::s_info, nullptr, CREATE_METHOD_TABLE(JSWebAssemblyModule) };
40
44
41
JSWebAssemblyModule* 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);
47
    auto scope = DECLARE_THROW_SCOPE(vm);
44
    instance->finishCreation(vm, exportSymbolTable);
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
    return instance;
73
    return instance;
46
}
74
}
47
75
Lines 50-70 Structure* JSWebAssemblyModule::createStructure(VM& vm, JSGlobalObject* globalOb a/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.cpp_sec2
50
    return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
78
    return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
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
    : Base(vm, structure)
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
    if (!m_codeBlocks[mode]) {
90
        auto scope = DECLARE_THROW_SCOPE(vm);
91
        // We don't have a code block for this mode, we need to recompile...
92
        Wasm::Plan plan(&vm, static_cast<uint8_t*>(m_sourceBuffer->data()), m_sourceBuffer->byteLength());
93
94
        auto* codeBlock = buildCodeBlock(vm, exec, plan, mode);
95
        RETURN_IF_EXCEPTION(scope, nullptr);
96
97
        ASSERT(plan.exports().size() == m_exportSymbolTable->size());
98
        if (!ASSERT_DISABLED) {
99
            for (auto& exp : plan.exports())
100
                ASSERT(m_exportSymbolTable->contains(exp.field.impl()));
101
        }
102
103
        ASSERT(mode == codeBlock->mode());
104
        m_codeBlocks[mode].set(vm, this, codeBlock);
105
    }
106
107
    return m_codeBlocks[mode].get();
108
}
109
110
void JSWebAssemblyModule::finishCreation(VM& vm, ExecState* exec, uint8_t* source, size_t byteSize)
64
{
111
{
65
    Base::finishCreation(vm);
112
    Base::finishCreation(vm);
66
    ASSERT(inherits(vm, info()));
113
    ASSERT(inherits(vm, info()));
114
115
    auto scope = DECLARE_THROW_SCOPE(vm);
116
    Wasm::Plan plan(&vm, source, byteSize);
117
118
    auto* codeBlock = buildCodeBlock(vm, exec, plan);
119
    RETURN_IF_EXCEPTION(scope, );
120
121
    // On success, a new WebAssembly.Module object is returned with [[Module]] set to the validated Ast.module.
122
    SymbolTable* exportSymbolTable = SymbolTable::create(vm);
123
    for (auto& exp : plan.exports()) {
124
        auto offset = exportSymbolTable->takeNextScopeOffset(NoLockingNecessary);
125
        exportSymbolTable->set(NoLockingNecessary, exp.field.impl(), SymbolTableEntry(VarOffset(offset)));
126
    }
127
128
    m_sourceBuffer = ArrayBuffer::create(source, byteSize);
129
    m_moduleInformation = plan.takeModuleInformation();
67
    m_exportSymbolTable.set(vm, this, exportSymbolTable);
130
    m_exportSymbolTable.set(vm, this, exportSymbolTable);
131
    m_codeBlocks[codeBlock->mode()].set(vm, this, codeBlock);
68
}
132
}
69
133
70
void JSWebAssemblyModule::destroy(JSCell* cell)
134
void JSWebAssemblyModule::destroy(JSCell* cell)
Lines 79-96 void JSWebAssemblyModule::visitChildren(JSCell* cell, SlotVisitor& visitor) a/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.cpp_sec3
79
143
80
    Base::visitChildren(thisObject, visitor);
144
    Base::visitChildren(thisObject, visitor);
81
    visitor.append(thisObject->m_exportSymbolTable);
145
    visitor.append(thisObject->m_exportSymbolTable);
82
    for (unsigned i = 0; i < thisObject->m_calleeCount * 2; i++)
146
    for (unsigned i = 0; i < Wasm::Memory::NumberOfModes; ++i)
83
        visitor.append(thisObject->callees()[i]);
147
        visitor.append(thisObject->m_codeBlocks[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());
94
}
148
}
95
149
96
} // namespace JSC
150
} // namespace JSC
- a/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h -57 / +18 lines
Lines 1-5 a/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h_sec1
1
/*
1
/*
2
 * Copyright (C) 2016 Apple Inc. All rights reserved.
2
 * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
3
 *
3
 *
4
 * Redistribution and use in source and binary forms, with or without
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
5
 * modification, are permitted provided that the following conditions
Lines 29-35 a/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h_sec2
29
29
30
#include "JSDestructibleObject.h"
30
#include "JSDestructibleObject.h"
31
#include "JSObject.h"
31
#include "JSObject.h"
32
#include "JSWebAssemblyCallee.h"
32
#include "JSWebAssemblyCodeBlock.h"
33
#include "UnconditionalFinalizer.h"
33
#include "UnconditionalFinalizer.h"
34
#include "WasmFormat.h"
34
#include "WasmFormat.h"
35
#include <wtf/Bag.h>
35
#include <wtf/Bag.h>
Lines 37-49 a/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h_sec3
37
37
38
namespace JSC {
38
namespace JSC {
39
39
40
namespace Wasm {
41
class Plan;
42
}
43
40
class SymbolTable;
44
class SymbolTable;
45
class JSWebAssemblyMemory;
41
46
42
class JSWebAssemblyModule : public JSDestructibleObject {
47
class JSWebAssemblyModule : public JSDestructibleObject {
43
public:
48
public:
44
    typedef JSDestructibleObject Base;
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
    static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
52
    static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
48
53
49
    DECLARE_INFO;
54
    DECLARE_INFO;
Lines 54-121 public: a/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h_sec4
54
    {
59
    {
55
        return m_moduleInformation->signatureIndexFromFunctionIndexSpace(functionIndexSpace);
60
        return m_moduleInformation->signatureIndexFromFunctionIndexSpace(functionIndexSpace);
56
    }
61
    }
57
    unsigned functionImportCount() const { return m_wasmExitStubs.size(); }
58
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
    }
66
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
    }
74
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
62
81
    void setWasmEntrypointCallee(VM& vm, unsigned calleeIndex, JSWebAssemblyCallee* callee)
63
    // Returns the code block that this module was originally compiled expecting to use. This won't need to recompile.
82
    {
64
    JSWebAssemblyCodeBlock* codeBlock() { return m_codeBlocks[m_moduleInformation->memory.mode()].get(); }
83
        RELEASE_ASSERT(calleeIndex < m_calleeCount);
65
    // Returns the appropriate code block for the given memory, possibly triggering a recompile.
84
        callees()[calleeIndex + m_calleeCount].set(vm, this, callee);
66
    JSWebAssemblyCodeBlock* codeBlock(VM&, ExecState* exec, JSWebAssemblyMemory*);
85
    }
86
67
87
    WriteBarrier<JSWebAssemblyCallee>* callees()
68
private:
88
    {
69
    JSWebAssemblyCodeBlock* buildCodeBlock(VM& vm, ExecState* exec, Wasm::Plan&, std::optional<Wasm::Memory::Mode> mode = std::nullopt);
89
        return bitwise_cast<WriteBarrier<JSWebAssemblyCallee>*>(bitwise_cast<char*>(this) + offsetOfCallees());
90
    }
91
70
92
protected:
71
    JSWebAssemblyModule(VM&, Structure*);
93
    JSWebAssemblyModule(VM&, Structure*, std::unique_ptr<Wasm::ModuleInformation>&&, Bag<CallLinkInfo>&&, Vector<Wasm::WasmExitStubs>&&, unsigned calleeCount);
72
    void finishCreation(VM&, ExecState*, uint8_t* source, size_t byteSize);
94
    void finishCreation(VM&, SymbolTable*);
95
    static void destroy(JSCell*);
73
    static void destroy(JSCell*);
96
    static void visitChildren(JSCell*, SlotVisitor&);
74
    static void visitChildren(JSCell*, SlotVisitor&);
97
75
98
private:
76
    RefPtr<ArrayBuffer> m_sourceBuffer;
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;
114
    std::unique_ptr<Wasm::ModuleInformation> m_moduleInformation;
77
    std::unique_ptr<Wasm::ModuleInformation> m_moduleInformation;
115
    Bag<CallLinkInfo> m_callLinkInfos;
116
    WriteBarrier<SymbolTable> m_exportSymbolTable;
78
    WriteBarrier<SymbolTable> m_exportSymbolTable;
117
    Vector<Wasm::WasmExitStubs> m_wasmExitStubs;
79
    WriteBarrier<JSWebAssemblyCodeBlock> m_codeBlocks[Wasm::Memory::NumberOfModes];
118
    unsigned m_calleeCount;
119
};
80
};
120
81
121
} // namespace JSC
82
} // namespace JSC
- a/Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp -7 / +15 lines
Lines 87-93 static EncodedJSValue JSC_HOST_CALL constructJSWebAssemblyInstance(ExecState* ex a/Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp_sec1
87
    {
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.
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;
89
        Wasm::Memory memory;
90
        instance->setMemory(vm, JSWebAssemblyMemory::create(vm, exec->lexicalGlobalObject()->WebAssemblyMemoryStructure(), WTFMove(memory)));
90
        instance->setMemory(vm, exec, JSWebAssemblyMemory::create(vm, exec->lexicalGlobalObject()->WebAssemblyMemoryStructure(), WTFMove(memory)));
91
    }
91
    }
92
92
93
    // Let funcs, memories and tables be initially-empty lists of callable JavaScript objects, WebAssembly.Memory objects and WebAssembly.Table objects, respectively.
93
    // Let funcs, memories and tables be initially-empty lists of callable JavaScript objects, WebAssembly.Memory objects and WebAssembly.Table objects, respectively.
Lines 194-202 static EncodedJSValue JSC_HOST_CALL constructJSWebAssemblyInstance(ExecState* ex a/Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp_sec2
194
                        throwException(exec, throwScope, createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("Memory imports 'maximum' is larger than the module's expected 'maximum'"))));
194
                        throwException(exec, throwScope, createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("Memory imports 'maximum' is larger than the module's expected 'maximum'"))));
195
                }
195
                }
196
            }
196
            }
197
197
            // ii. Append v to memories.
198
            // ii. Append v to memories.
198
            // iii. Append v.[[Memory]] to imports.
199
            // iii. Append v.[[Memory]] to imports.
199
            instance->setMemory(vm, memory);
200
            instance->setMemory(vm, exec, memory);
201
            RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
200
            break;
202
            break;
201
        }
203
        }
202
        case Wasm::ExternalKind::Global: {
204
        case Wasm::ExternalKind::Global: {
Lines 235-246 static EncodedJSValue JSC_HOST_CALL constructJSWebAssemblyInstance(ExecState* ex a/Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp_sec3
235
        if (moduleInformation.memory && !hasMemoryImport) {
237
        if (moduleInformation.memory && !hasMemoryImport) {
236
            RELEASE_ASSERT(!moduleInformation.memory.isImport());
238
            RELEASE_ASSERT(!moduleInformation.memory.isImport());
237
            // We create a memory when it's a memory definition.
239
            // We create a memory when it's a memory definition.
238
            bool failed;
240
            Wasm::Memory memory;
239
            Wasm::Memory memory(moduleInformation.memory.initial(), moduleInformation.memory.maximum(), failed);
241
            if (moduleInformation.memory.hasReservedMemory())
240
            if (failed)
242
                memory = WTFMove(moduleInformation.memory.reservedMemory());
241
                return JSValue::encode(throwException(exec, throwScope, createOutOfMemoryError(exec)));
243
            else {
242
            instance->setMemory(vm,
244
                bool failed;
245
                Wasm::Memory memory(vm, moduleInformation.memory.initial(), moduleInformation.memory.maximum(), failed);
246
                if (failed)
247
                    return JSValue::encode(throwException(exec, throwScope, createOutOfMemoryError(exec)));
248
            }
249
            instance->setMemory(vm, exec,
243
               JSWebAssemblyMemory::create(vm, exec->lexicalGlobalObject()->WebAssemblyMemoryStructure(), WTFMove(memory)));
250
               JSWebAssemblyMemory::create(vm, exec->lexicalGlobalObject()->WebAssemblyMemoryStructure(), WTFMove(memory)));
251
            RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
244
        }
252
        }
245
    }
253
    }
246
254
- a/Source/JavaScriptCore/wasm/js/WebAssemblyMemoryConstructor.cpp -1 / +1 lines
Lines 97-103 static EncodedJSValue JSC_HOST_CALL constructJSWebAssemblyMemory(ExecState* exec a/Source/JavaScriptCore/wasm/js/WebAssemblyMemoryConstructor.cpp_sec1
97
    }
97
    }
98
98
99
    bool failed;
99
    bool failed;
100
    Wasm::Memory memory(initialPageCount, maximumPageCount, failed);
100
    Wasm::Memory memory(vm, initialPageCount, maximumPageCount, failed);
101
    if (failed)
101
    if (failed)
102
        return JSValue::encode(throwException(exec, throwScope, createOutOfMemoryError(exec)));
102
        return JSValue::encode(throwException(exec, throwScope, createOutOfMemoryError(exec)));
103
103
- a/Source/JavaScriptCore/wasm/js/WebAssemblyModuleConstructor.cpp -25 / +1 lines
Lines 80-110 JSValue WebAssemblyModuleConstructor::createModule(ExecState* state, Structure* a/Source/JavaScriptCore/wasm/js/WebAssemblyModuleConstructor.cpp_sec1
80
    uint8_t* base = getWasmBufferFromValue(state, state->argument(0), byteOffset, byteSize);
80
    uint8_t* base = getWasmBufferFromValue(state, state->argument(0), byteOffset, byteSize);
81
    RETURN_IF_EXCEPTION(scope, { });
81
    RETURN_IF_EXCEPTION(scope, { });
82
82
83
    Wasm::Plan plan(&vm, base + byteOffset, byteSize);
83
    return JSWebAssemblyModule::create(vm, state, structure, 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;
108
}
84
}
109
85
110
WebAssemblyModuleConstructor* WebAssemblyModuleConstructor::create(VM& vm, Structure* structure, WebAssemblyModulePrototype* thisPrototype)
86
WebAssemblyModuleConstructor* WebAssemblyModuleConstructor::create(VM& vm, Structure* structure, WebAssemblyModulePrototype* thisPrototype)
- a/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp -9 / +11 lines
Lines 92-101 void WebAssemblyModuleRecord::link(ExecState* state, JSWebAssemblyInstance* inst a/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp_sec1
92
    auto* globalObject = state->lexicalGlobalObject();
92
    auto* globalObject = state->lexicalGlobalObject();
93
93
94
    JSWebAssemblyModule* module = instance->module();
94
    JSWebAssemblyModule* module = instance->module();
95
    JSWebAssemblyCodeBlock* codeBlock = instance->codeBlock();
95
    const Wasm::ModuleInformation& moduleInformation = module->moduleInformation();
96
    const Wasm::ModuleInformation& moduleInformation = module->moduleInformation();
96
97
97
    SymbolTable* exportSymbolTable = module->exportSymbolTable();
98
    SymbolTable* exportSymbolTable = module->exportSymbolTable();
98
    unsigned functionImportCount = module->functionImportCount();
99
    unsigned functionImportCount = codeBlock->functionImportCount();
99
100
100
    // FIXME wire up the imports. https://bugs.webkit.org/show_bug.cgi?id=165118
101
    // FIXME wire up the imports. https://bugs.webkit.org/show_bug.cgi?id=165118
101
102
Lines 116-123 void WebAssemblyModuleRecord::link(ExecState* state, JSWebAssemblyInstance* inst a/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp_sec2
116
            //     a. Let func be an Exported Function Exotic Object created from c.
117
            //     a. Let func be an Exported Function Exotic Object created from c.
117
            //     b. Append func to funcs.
118
            //     b. Append func to funcs.
118
            //     c. Return func.
119
            //     c. Return func.
119
            JSWebAssemblyCallee* jsEntrypointCallee = module->jsEntrypointCalleeFromFunctionIndexSpace(exp.kindIndex);
120
            JSWebAssemblyCallee* jsEntrypointCallee = codeBlock->jsEntrypointCalleeFromFunctionIndexSpace(exp.kindIndex);
120
            JSWebAssemblyCallee* wasmEntrypointCallee = module->wasmEntrypointCalleeFromFunctionIndexSpace(exp.kindIndex);
121
            JSWebAssemblyCallee* wasmEntrypointCallee = codeBlock->wasmEntrypointCalleeFromFunctionIndexSpace(exp.kindIndex);
121
            Wasm::SignatureIndex signatureIndex = module->signatureIndexFromFunctionIndexSpace(exp.kindIndex);
122
            Wasm::SignatureIndex signatureIndex = module->signatureIndexFromFunctionIndexSpace(exp.kindIndex);
122
            const Wasm::Signature* signature = Wasm::SignatureInformation::get(&vm, signatureIndex);
123
            const Wasm::Signature* signature = Wasm::SignatureInformation::get(&vm, signatureIndex);
123
            WebAssemblyFunction* function = WebAssemblyFunction::create(vm, globalObject, signature->argumentCount(), exp.field.string(), instance, jsEntrypointCallee, wasmEntrypointCallee, signatureIndex);
124
            WebAssemblyFunction* function = WebAssemblyFunction::create(vm, globalObject, signature->argumentCount(), exp.field.string(), instance, jsEntrypointCallee, wasmEntrypointCallee, signatureIndex);
Lines 178-189 void WebAssemblyModuleRecord::link(ExecState* state, JSWebAssemblyInstance* inst a/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp_sec3
178
        // The start function must not take any arguments or return anything. This is enforced by the parser.
179
        // The start function must not take any arguments or return anything. This is enforced by the parser.
179
        ASSERT(!signature->argumentCount());
180
        ASSERT(!signature->argumentCount());
180
        ASSERT(signature->returnType() == Wasm::Void);
181
        ASSERT(signature->returnType() == Wasm::Void);
181
        if (startFunctionIndexSpace < module->functionImportCount()) {
182
        if (startFunctionIndexSpace < codeBlock->functionImportCount()) {
182
            JSCell* startFunction = instance->importFunction(startFunctionIndexSpace)->get();
183
            JSCell* startFunction = instance->importFunction(startFunctionIndexSpace)->get();
183
            m_startFunction.set(vm, this, startFunction);
184
            m_startFunction.set(vm, this, startFunction);
184
        } else {
185
        } else {
185
            JSWebAssemblyCallee* jsEntrypointCallee = module->jsEntrypointCalleeFromFunctionIndexSpace(startFunctionIndexSpace);
186
            JSWebAssemblyCallee* jsEntrypointCallee = codeBlock->jsEntrypointCalleeFromFunctionIndexSpace(startFunctionIndexSpace);
186
            JSWebAssemblyCallee* wasmEntrypointCallee = module->wasmEntrypointCalleeFromFunctionIndexSpace(startFunctionIndexSpace);
187
            JSWebAssemblyCallee* wasmEntrypointCallee = codeBlock->wasmEntrypointCalleeFromFunctionIndexSpace(startFunctionIndexSpace);
187
            WebAssemblyFunction* function = WebAssemblyFunction::create(vm, globalObject, signature->argumentCount(), "start", instance, jsEntrypointCallee, wasmEntrypointCallee, signatureIndex);
188
            WebAssemblyFunction* function = WebAssemblyFunction::create(vm, globalObject, signature->argumentCount(), "start", instance, jsEntrypointCallee, wasmEntrypointCallee, signatureIndex);
188
            m_startFunction.set(vm, this, function);
189
            m_startFunction.set(vm, this, function);
189
        }
190
        }
Lines 207-212 JSValue WebAssemblyModuleRecord::evaluate(ExecState* state) a/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp_sec4
207
208
208
    {
209
    {
209
        JSWebAssemblyModule* module = m_instance->module();
210
        JSWebAssemblyModule* module = m_instance->module();
211
        JSWebAssemblyCodeBlock* codeBlock = m_instance->codeBlock();
210
        const Wasm::ModuleInformation& moduleInformation = module->moduleInformation();
212
        const Wasm::ModuleInformation& moduleInformation = module->moduleInformation();
211
        JSWebAssemblyTable* table = m_instance->table();
213
        JSWebAssemblyTable* table = m_instance->table();
212
        for (const Wasm::Element& element : moduleInformation.elements) {
214
        for (const Wasm::Element& element : moduleInformation.elements) {
Lines 229-241 JSValue WebAssemblyModuleRecord::evaluate(ExecState* state) a/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp_sec5
229
                // for the import.
231
                // for the import.
230
                // https://bugs.webkit.org/show_bug.cgi?id=165510
232
                // https://bugs.webkit.org/show_bug.cgi?id=165510
231
                uint32_t functionIndex = element.functionIndices[i];
233
                uint32_t functionIndex = element.functionIndices[i];
232
                if (functionIndex < module->functionImportCount()) {
234
                if (functionIndex < codeBlock->functionImportCount()) {
233
                    return JSValue::decode(
235
                    return JSValue::decode(
234
                        throwVMRangeError(state, scope, ASCIILiteral("Element is setting the table value with an import. This is not yet implemented. FIXME.")));
236
                        throwVMRangeError(state, scope, ASCIILiteral("Element is setting the table value with an import. This is not yet implemented. FIXME.")));
235
                }
237
                }
236
238
237
                JSWebAssemblyCallee* jsEntrypointCallee = module->jsEntrypointCalleeFromFunctionIndexSpace(functionIndex);
239
                JSWebAssemblyCallee* jsEntrypointCallee = codeBlock->jsEntrypointCalleeFromFunctionIndexSpace(functionIndex);
238
                JSWebAssemblyCallee* wasmEntrypointCallee = module->wasmEntrypointCalleeFromFunctionIndexSpace(functionIndex);
240
                JSWebAssemblyCallee* wasmEntrypointCallee = codeBlock->wasmEntrypointCalleeFromFunctionIndexSpace(functionIndex);
239
                Wasm::SignatureIndex signatureIndex = module->signatureIndexFromFunctionIndexSpace(functionIndex);
241
                Wasm::SignatureIndex signatureIndex = module->signatureIndexFromFunctionIndexSpace(functionIndex);
240
                const Wasm::Signature* signature = Wasm::SignatureInformation::get(&vm, signatureIndex);
242
                const Wasm::Signature* signature = Wasm::SignatureInformation::get(&vm, signatureIndex);
241
                // FIXME: Say we export local function "foo" at funciton index 0.
243
                // FIXME: Say we export local function "foo" at funciton index 0.
- a/Source/WTF/wtf/DataLog.h -1 / +17 lines
Lines 48-60 void dataLog(const Types&... values) a/Source/WTF/wtf/DataLog.h_sec1
48
template<typename... Types>
48
template<typename... Types>
49
void dataLogLn(const Types&... values)
49
void dataLogLn(const Types&... values)
50
{
50
{
51
    dataFile().print(values..., "\n");
51
    dataLog(values..., "\n");
52
}
53
54
template<typename... Types>
55
void dataLogIf(bool shouldLog, const Types&... values)
56
{
57
    if (shouldLog)
58
        dataLog(values...);
59
}
60
61
template<typename... Types>
62
void dataLogLnIf(bool shouldLog, const Types&... values)
63
{
64
    if (shouldLog)
65
        dataLogLn(values...);
52
}
66
}
53
67
54
} // namespace WTF
68
} // namespace WTF
55
69
56
using WTF::dataLog;
70
using WTF::dataLog;
57
using WTF::dataLogLn;
71
using WTF::dataLogLn;
72
using WTF::dataLogIf;
73
using WTF::dataLogLnIf;
58
using WTF::dataLogF;
74
using WTF::dataLogF;
59
using WTF::dataLogFString;
75
using WTF::dataLogFString;
60
76
- a/Source/WTF/wtf/Ref.h +1 lines
Lines 137-142 public: a/Source/WTF/wtf/Ref.h_sec1
137
    T* ptr() const { ASSERT(m_ptr); return m_ptr; }
137
    T* ptr() const { ASSERT(m_ptr); return m_ptr; }
138
    T& get() const { ASSERT(m_ptr); return *m_ptr; }
138
    T& get() const { ASSERT(m_ptr); return *m_ptr; }
139
    operator T&() const { ASSERT(m_ptr); return *m_ptr; }
139
    operator T&() const { ASSERT(m_ptr); return *m_ptr; }
140
    bool operator!() const { ASSERT(m_ptr); return !*m_ptr; }
140
141
141
    template<typename U> Ref<T> replace(Ref<U>&&) WARN_UNUSED_RETURN;
142
    template<typename U> Ref<T> replace(Ref<U>&&) WARN_UNUSED_RETURN;
142
143
- a/JSTests/wasm/function-tests/trap-load-2.js -15 lines
Lines 4-24 import * as assert from '../assert.js' a/JSTests/wasm/function-tests/trap-load-2.js_sec1
4
const pageSize = 64 * 1024;
4
const pageSize = 64 * 1024;
5
const numPages = 10;
5
const numPages = 10;
6
6
7
const builder = (new Builder())
8
    .Type().End()
9
    .Import()
10
        .Memory("a", "b", {initial: numPages})
11
    .End()
12
    .Function().End()
13
    .Export().Function("foo").End()
14
    .Code()
15
        .Function("foo", {params: ["i32"], ret: "i32"})
16
            .GetLocal(0)
17
            .I32Load(2, 0)
18
            .Return()
19
        .End()
20
    .End();
21
22
function wasmFrameCountFromError(e) {
7
function wasmFrameCountFromError(e) {
23
    let stackFrames = e.stack.split("\n").filter((s) => s.indexOf("<wasm>@[wasm code]") !== -1);
8
    let stackFrames = e.stack.split("\n").filter((s) => s.indexOf("<wasm>@[wasm code]") !== -1);
24
    return stackFrames.length;
9
    return stackFrames.length;

Return to Bug 162693