| Differences between
and this patch
- a/Source/JavaScriptCore/ChangeLog +159 lines
Lines 1-3 a/Source/JavaScriptCore/ChangeLog_sec1
1
2015-07-11  Sukolsak Sakshuwong  <sukolsak@gmail.com>
2
3
        JSC should natively support WebAssembly
4
        https://bugs.webkit.org/show_bug.cgi?id=146064
5
6
        Reviewed by NOBODY (OOPS!).
7
8
        * JavaScriptCore.xcodeproj/project.pbxproj:
9
        * bytecode/CodeBlock.cpp:
10
        (JSC::CodeBlock::CodeBlock):
11
        (JSC::WebAssemblyCodeBlock::replacement):
12
        (JSC::WebAssemblyCodeBlock::capabilityLevelInternal):
13
        * bytecode/CodeBlock.h:
14
        (JSC::WebAssemblyCodeBlock::WebAssemblyCodeBlock):
15
        * jit/JITOperations.cpp:
16
        * jsc.cpp:
17
        (GlobalObject::finishCreation):
18
        (functionLoadWebAssembly):
19
        * llint/LLIntSlowPaths.cpp:
20
        (JSC::LLInt::setUpCall):
21
        * runtime/Executable.cpp:
22
        (JSC::ScriptExecutable::installCode):
23
        (JSC::ScriptExecutable::newCodeBlockFor):
24
        (JSC::ScriptExecutable::prepareForExecutionImpl):
25
        (JSC::WebAssemblyExecutable::WebAssemblyExecutable):
26
        (JSC::WebAssemblyExecutable::finishCreation):
27
        (JSC::WebAssemblyExecutable::destroy):
28
        (JSC::WebAssemblyExecutable::baselineCodeBlockFor):
29
        (JSC::WebAssemblyExecutable::visitChildren):
30
        (JSC::WebAssemblyExecutable::symbolTable):
31
        (JSC::WebAssemblyExecutable::clearCode):
32
        (JSC::WebAssemblyExecutable::unlinkCalls):
33
        * runtime/Executable.h:
34
        (JSC::ExecutableBase::isWebAssemblyExecutable):
35
        (JSC::ExecutableBase::clearCodeVirtual):
36
        * runtime/JSFunction.cpp:
37
        (JSC::JSFunction::create):
38
        * runtime/JSFunction.h:
39
        (JSC::JSFunction::createImpl):
40
        * runtime/JSFunctionInlines.h:
41
        (JSC::JSFunction::JSFunction):
42
        (JSC::JSFunction::isHostFunction):
43
        * runtime/JSType.h:
44
        * runtime/VM.cpp:
45
        (JSC::VM::VM):
46
        * runtime/VM.h:
47
        * wasm/WasmJITCompiler.cpp: Added.
48
        (JSC::Wasm::JumpScope::JumpScope):
49
        (JSC::Wasm::JumpScope::jump):
50
        (JSC::Wasm::JumpScope::link):
51
        (JSC::Wasm::JITCompiler::compileFunction):
52
        (JSC::Wasm::JITCompiler::allocateSpaceOnStack):
53
        (JSC::Wasm::JITCompiler::deallocateSpaceOnStack):
54
        (JSC::Wasm::JITCompiler::parseArguments):
55
        (JSC::Wasm::JITCompiler::parseVars):
56
        (JSC::Wasm::JITCompiler::parseStmt):
57
        (JSC::Wasm::JITCompiler::parseGetLocal):
58
        (JSC::Wasm::JITCompiler::parseSetLocal):
59
        (JSC::Wasm::JITCompiler::parseReturnStmt):
60
        (JSC::Wasm::JITCompiler::parseStmtList):
61
        (JSC::Wasm::JITCompiler::parseBlockStmt):
62
        (JSC::Wasm::JITCompiler::parseIfStmt):
63
        (JSC::Wasm::JITCompiler::parseIfElseStmt):
64
        (JSC::Wasm::JITCompiler::parseWhileStmt):
65
        (JSC::Wasm::JITCompiler::parseDoStmt):
66
        (JSC::Wasm::JITCompiler::parseLabelStmt):
67
        (JSC::Wasm::JITCompiler::parseBreakStmt):
68
        (JSC::Wasm::JITCompiler::parseBreakLabelStmt):
69
        (JSC::Wasm::JITCompiler::parseContinueStmt):
70
        (JSC::Wasm::JITCompiler::parseContinueLabelStmt):
71
        (JSC::Wasm::JITCompiler::parseSwitchStmt):
72
        (JSC::Wasm::JITCompiler::parseExpr):
73
        (JSC::Wasm::JITCompiler::parseExprI32):
74
        (JSC::Wasm::JITCompiler::parseExprF64):
75
        (JSC::Wasm::getInternalFunction):
76
        (JSC::Wasm::JITCompiler::parseCallInternal):
77
        (JSC::Wasm::getImportedFunction):
78
        (JSC::Wasm::JITCompiler::parseCallImport):
79
        (JSC::Wasm::JITCompiler::callFunctionSlowCase):
80
        (JSC::Wasm::JITCompiler::parseCallArguments):
81
        (JSC::Wasm::JITCompiler::parseUnaryOp):
82
        (JSC::Wasm::JITCompiler::parseBinaryOp):
83
        (JSC::Wasm::JITCompiler::parseRelationalOpI32):
84
        (JSC::Wasm::JITCompiler::parseRelationalOpF64):
85
        (JSC::Wasm::JITCompiler::parseComma):
86
        (JSC::Wasm::JITCompiler::parseCond):
87
        * wasm/WasmJITCompiler.h: Added.
88
        (JSC::Wasm::JITCompiler::JITCompiler):
89
        (JSC::Wasm::JITCompiler::stackAddress):
90
        (JSC::Wasm::JITCompiler::temporaryAddress):
91
        (JSC::Wasm::JITCompiler::pushContinueLabelLabel):
92
        (JSC::Wasm::JITCompiler::popContinueLabelLabel):
93
        (JSC::Wasm::JITCompiler::continueLabelLabel):
94
        (JSC::Wasm::JITCompiler::pushBreakLabelJumpList):
95
        (JSC::Wasm::JITCompiler::popBreakLabelJumpList):
96
        (JSC::Wasm::JITCompiler::breakLabelJumpList):
97
        (JSC::Wasm::JITCompiler::pushContinueJumpScope):
98
        (JSC::Wasm::JITCompiler::popContinueJumpScope):
99
        (JSC::Wasm::JITCompiler::topContinueJumpScope):
100
        (JSC::Wasm::JITCompiler::pushBreakJumpList):
101
        (JSC::Wasm::JITCompiler::popBreakJumpList):
102
        (JSC::Wasm::JITCompiler::topBreakJumpList):
103
        * wasm/WasmModule.cpp: Added.
104
        (JSC::Wasm::Module::compile):
105
        (JSC::Wasm::Module::parseConstantPoolSection):
106
        (JSC::Wasm::Module::parseSignatureSection):
107
        (JSC::Wasm::Module::parseFunctionImportSection):
108
        (JSC::Wasm::Module::parseGlobalSection):
109
        (JSC::Wasm::Module::parseFunctionDeclarationSection):
110
        (JSC::Wasm::Module::parseFunctionPointerTables):
111
        (JSC::Wasm::Module::parseFunctionDefinitionSection):
112
        (JSC::Wasm::Module::parseExportSection):
113
        (JSC::Wasm::Module::parseFunctionDefinition):
114
        (JSC::Wasm::Module::internalFunction):
115
        (JSC::Wasm::Module::visitChildren):
116
        (JSC::Wasm::compile):
117
        * wasm/WasmModule.h: Added.
118
        (JSC::Wasm::Module::create):
119
        (JSC::Wasm::Module::createStructure):
120
        (JSC::Wasm::Module::functionImportName):
121
        (JSC::Wasm::Module::Module):
122
        * wasm/WasmOpcodes.h: Added.
123
        (JSC::Wasm::operator| ):
124
        (JSC::Wasm::operator&):
125
        (JSC::Wasm::Expr::Expr):
126
        (JSC::Wasm::Expr::type):
127
        (JSC::Wasm::Expr::i32):
128
        (JSC::Wasm::Expr::f32):
129
        (JSC::Wasm::Expr::f64):
130
        (JSC::Wasm::Expr::operator==):
131
        (JSC::Wasm::Expr::operator!=):
132
        (JSC::Wasm::PackOpWithImm):
133
        (JSC::Wasm::UnpackOpWithImm):
134
        (JSC::Wasm::ExprWithImm::ExprWithImm):
135
        (JSC::Wasm::ExprWithImm::type):
136
        (JSC::Wasm::ExprWithImm::i32):
137
        (JSC::Wasm::ExprWithImm::f32):
138
        (JSC::Wasm::ExprWithImm::f64):
139
        (JSC::Wasm::Signature::Signature):
140
        (JSC::Wasm::Signature::operator==):
141
        (JSC::Wasm::Signature::operator!=):
142
        (JSC::Wasm::Signature::Hash::operator()):
143
        (JSC::Wasm::Reader::Reader):
144
        (JSC::Wasm::Reader::stmt):
145
        (JSC::Wasm::Reader::switchCase):
146
        (JSC::Wasm::Reader::voidExpr):
147
        (JSC::Wasm::Reader::exportFormat):
148
        (JSC::Wasm::Reader::type):
149
        (JSC::Wasm::Reader::rtype):
150
        (JSC::Wasm::Reader::singleChar):
151
        (JSC::Wasm::Reader::u8):
152
        (JSC::Wasm::Reader::fixedWidth<uint32_t>):
153
        (JSC::Wasm::Reader::fixedWidth<float>):
154
        (JSC::Wasm::Reader::fixedWidth<double>):
155
        (JSC::Wasm::Reader::code):
156
        (JSC::Wasm::Reader::immU32):
157
        (JSC::Wasm::Reader::immS32):
158
        (JSC::Wasm::Reader::ifI32Lit):
159
1
2015-07-08  Joseph Pecoraro  <pecoraro@apple.com>
160
2015-07-08  Joseph Pecoraro  <pecoraro@apple.com>
2
161
3
        Fix grammar issue in TypeError attempting to change an unconfigurable property
162
        Fix grammar issue in TypeError attempting to change an unconfigurable property
- a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj +28 lines
Lines 1020-1025 a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec1
1020
		70ECA6071AFDBEA200449739 /* TemplateRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 70ECA6021AFDBEA200449739 /* TemplateRegistry.cpp */; };
1020
		70ECA6071AFDBEA200449739 /* TemplateRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 70ECA6021AFDBEA200449739 /* TemplateRegistry.cpp */; };
1021
		70ECA6081AFDBEA200449739 /* TemplateRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = 70ECA6031AFDBEA200449739 /* TemplateRegistry.h */; settings = {ATTRIBUTES = (Private, ); }; };
1021
		70ECA6081AFDBEA200449739 /* TemplateRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = 70ECA6031AFDBEA200449739 /* TemplateRegistry.h */; settings = {ATTRIBUTES = (Private, ); }; };
1022
		70ECA6091AFDBEA200449739 /* TemplateRegistryKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 70ECA6041AFDBEA200449739 /* TemplateRegistryKey.h */; settings = {ATTRIBUTES = (Private, ); }; };
1022
		70ECA6091AFDBEA200449739 /* TemplateRegistryKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 70ECA6041AFDBEA200449739 /* TemplateRegistryKey.h */; settings = {ATTRIBUTES = (Private, ); }; };
1023
		7BD10C421B4ED43C00BD541A /* WasmJITCompiler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7BD10C3D1B4ED43900BD541A /* WasmJITCompiler.cpp */; };
1024
		7BD10C431B4ED44000BD541A /* WasmJITCompiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BD10C3E1B4ED43900BD541A /* WasmJITCompiler.h */; settings = {ATTRIBUTES = (Private, ); }; };
1025
		7BD10C441B4ED44500BD541A /* WasmModule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7BD10C3F1B4ED43900BD541A /* WasmModule.cpp */; };
1026
		7BD10C451B4ED44900BD541A /* WasmModule.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BD10C401B4ED43900BD541A /* WasmModule.h */; settings = {ATTRIBUTES = (Private, ); }; };
1027
		7BD10C461B4ED44E00BD541A /* WasmOpcodes.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BD10C411B4ED43900BD541A /* WasmOpcodes.h */; settings = {ATTRIBUTES = (Private, ); }; };
1023
		7C008CDA187124BB00955C24 /* JSPromiseDeferred.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C008CD8187124BB00955C24 /* JSPromiseDeferred.cpp */; };
1028
		7C008CDA187124BB00955C24 /* JSPromiseDeferred.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C008CD8187124BB00955C24 /* JSPromiseDeferred.cpp */; };
1024
		7C008CDB187124BB00955C24 /* JSPromiseDeferred.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C008CD9187124BB00955C24 /* JSPromiseDeferred.h */; settings = {ATTRIBUTES = (Private, ); }; };
1029
		7C008CDB187124BB00955C24 /* JSPromiseDeferred.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C008CD9187124BB00955C24 /* JSPromiseDeferred.h */; settings = {ATTRIBUTES = (Private, ); }; };
1025
		7C008CE7187631B600955C24 /* Microtask.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C008CE5187631B600955C24 /* Microtask.h */; settings = {ATTRIBUTES = (Private, ); }; };
1030
		7C008CE7187631B600955C24 /* Microtask.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C008CE5187631B600955C24 /* Microtask.h */; settings = {ATTRIBUTES = (Private, ); }; };
Lines 2762-2767 a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec2
2762
		70ECA6021AFDBEA200449739 /* TemplateRegistry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TemplateRegistry.cpp; sourceTree = "<group>"; };
2767
		70ECA6021AFDBEA200449739 /* TemplateRegistry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TemplateRegistry.cpp; sourceTree = "<group>"; };
2763
		70ECA6031AFDBEA200449739 /* TemplateRegistry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TemplateRegistry.h; sourceTree = "<group>"; };
2768
		70ECA6031AFDBEA200449739 /* TemplateRegistry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TemplateRegistry.h; sourceTree = "<group>"; };
2764
		70ECA6041AFDBEA200449739 /* TemplateRegistryKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TemplateRegistryKey.h; sourceTree = "<group>"; };
2769
		70ECA6041AFDBEA200449739 /* TemplateRegistryKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TemplateRegistryKey.h; sourceTree = "<group>"; };
2770
		7BD10C3D1B4ED43900BD541A /* WasmJITCompiler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmJITCompiler.cpp; sourceTree = "<group>"; };
2771
		7BD10C3E1B4ED43900BD541A /* WasmJITCompiler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmJITCompiler.h; sourceTree = "<group>"; };
2772
		7BD10C3F1B4ED43900BD541A /* WasmModule.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmModule.cpp; sourceTree = "<group>"; };
2773
		7BD10C401B4ED43900BD541A /* WasmModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmModule.h; sourceTree = "<group>"; };
2774
		7BD10C411B4ED43900BD541A /* WasmOpcodes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmOpcodes.h; sourceTree = "<group>"; };
2765
		7C008CD8187124BB00955C24 /* JSPromiseDeferred.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPromiseDeferred.cpp; sourceTree = "<group>"; };
2775
		7C008CD8187124BB00955C24 /* JSPromiseDeferred.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPromiseDeferred.cpp; sourceTree = "<group>"; };
2766
		7C008CD9187124BB00955C24 /* JSPromiseDeferred.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSPromiseDeferred.h; sourceTree = "<group>"; };
2776
		7C008CD9187124BB00955C24 /* JSPromiseDeferred.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSPromiseDeferred.h; sourceTree = "<group>"; };
2767
		7C008CE5187631B600955C24 /* Microtask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Microtask.h; sourceTree = "<group>"; };
2777
		7C008CE5187631B600955C24 /* Microtask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Microtask.h; sourceTree = "<group>"; };
Lines 3617-3622 a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec3
3617
				7EF6E0BB0EB7A1EC0079AFAF /* runtime */,
3627
				7EF6E0BB0EB7A1EC0079AFAF /* runtime */,
3618
				141211000A48772600480255 /* tests */,
3628
				141211000A48772600480255 /* tests */,
3619
				8603CEF014C753EF00AE59E3 /* tools */,
3629
				8603CEF014C753EF00AE59E3 /* tools */,
3630
				7BD10C3C1B4ED41D00BD541A /* wasm */,
3620
				86EAC48C0F93E8B9008EC948 /* yarr */,
3631
				86EAC48C0F93E8B9008EC948 /* yarr */,
3621
			);
3632
			);
3622
			name = JavaScriptCore;
3633
			name = JavaScriptCore;
Lines 4279-4284 a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec4
4279
			path = disassembler/ARMv7;
4290
			path = disassembler/ARMv7;
4280
			sourceTree = "<group>";
4291
			sourceTree = "<group>";
4281
		};
4292
		};
4293
		7BD10C3C1B4ED41D00BD541A /* wasm */ = {
4294
			isa = PBXGroup;
4295
			children = (
4296
				7BD10C3D1B4ED43900BD541A /* WasmJITCompiler.cpp */,
4297
				7BD10C3E1B4ED43900BD541A /* WasmJITCompiler.h */,
4298
				7BD10C3F1B4ED43900BD541A /* WasmModule.cpp */,
4299
				7BD10C401B4ED43900BD541A /* WasmModule.h */,
4300
				7BD10C411B4ED43900BD541A /* WasmOpcodes.h */,
4301
			);
4302
			path = wasm;
4303
			sourceTree = "<group>";
4304
		};
4282
		7E39D81D0EC38EFA003AF11A /* bytecompiler */ = {
4305
		7E39D81D0EC38EFA003AF11A /* bytecompiler */ = {
4283
			isa = PBXGroup;
4306
			isa = PBXGroup;
4284
			children = (
4307
			children = (
Lines 6011-6016 a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec5
6011
				BC18C4050E16F5CD00B34460 /* FunctionPrototype.h in Headers */,
6034
				BC18C4050E16F5CD00B34460 /* FunctionPrototype.h in Headers */,
6012
				BCBE2CAE14E985AA000593AD /* GCAssertions.h in Headers */,
6035
				BCBE2CAE14E985AA000593AD /* GCAssertions.h in Headers */,
6013
				0F766D3015A8DCE2008F363E /* GCAwareJITStubRoutine.h in Headers */,
6036
				0F766D3015A8DCE2008F363E /* GCAwareJITStubRoutine.h in Headers */,
6037
				7BD10C451B4ED44900BD541A /* WasmModule.h in Headers */,
6014
				70EC0EC71AA0D7DA00B6AAFA /* StringIteratorPrototype.h in Headers */,
6038
				70EC0EC71AA0D7DA00B6AAFA /* StringIteratorPrototype.h in Headers */,
6015
				0F2B66AC17B6B53F00A7AE3F /* GCIncomingRefCounted.h in Headers */,
6039
				0F2B66AC17B6B53F00A7AE3F /* GCIncomingRefCounted.h in Headers */,
6016
				0F2B66AD17B6B54500A7AE3F /* GCIncomingRefCountedInlines.h in Headers */,
6040
				0F2B66AD17B6B54500A7AE3F /* GCIncomingRefCountedInlines.h in Headers */,
Lines 6145-6150 a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec6
6145
				BC18C41D0E16F5CD00B34460 /* JSClassRef.h in Headers */,
6169
				BC18C41D0E16F5CD00B34460 /* JSClassRef.h in Headers */,
6146
				86E3C613167BABD7006D760A /* JSContext.h in Headers */,
6170
				86E3C613167BABD7006D760A /* JSContext.h in Headers */,
6147
				86E3C617167BABEE006D760A /* JSContextInternal.h in Headers */,
6171
				86E3C617167BABEE006D760A /* JSContextInternal.h in Headers */,
6172
				7BD10C431B4ED44000BD541A /* WasmJITCompiler.h in Headers */,
6148
				BC18C41E0E16F5CD00B34460 /* JSContextRef.h in Headers */,
6173
				BC18C41E0E16F5CD00B34460 /* JSContextRef.h in Headers */,
6149
				148CD1D8108CF902008163C6 /* JSContextRefPrivate.h in Headers */,
6174
				148CD1D8108CF902008163C6 /* JSContextRefPrivate.h in Headers */,
6150
				A72028B81797601E0098028C /* JSCTestRunnerUtils.h in Headers */,
6175
				A72028B81797601E0098028C /* JSCTestRunnerUtils.h in Headers */,
Lines 6154-6159 a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec7
6154
				978801411471AD920041B016 /* JSDateMath.h in Headers */,
6179
				978801411471AD920041B016 /* JSDateMath.h in Headers */,
6155
				C2A7F688160432D400F76B98 /* JSDestructibleObject.h in Headers */,
6180
				C2A7F688160432D400F76B98 /* JSDestructibleObject.h in Headers */,
6156
				86E3C614167BABD7006D760A /* JSExport.h in Headers */,
6181
				86E3C614167BABD7006D760A /* JSExport.h in Headers */,
6182
				7BD10C461B4ED44E00BD541A /* WasmOpcodes.h in Headers */,
6157
				A7B4ACAF1484C9CE00B38A36 /* JSExportMacros.h in Headers */,
6183
				A7B4ACAF1484C9CE00B38A36 /* JSExportMacros.h in Headers */,
6158
				0F2B66EF17B6B5AB00A7AE3F /* JSFloat32Array.h in Headers */,
6184
				0F2B66EF17B6B5AB00A7AE3F /* JSFloat32Array.h in Headers */,
6159
				0F2B66F017B6B5AB00A7AE3F /* JSFloat64Array.h in Headers */,
6185
				0F2B66F017B6B5AB00A7AE3F /* JSFloat64Array.h in Headers */,
Lines 7152-7157 a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec8
7152
				0FA581BA150E952C00B9A2D9 /* DFGNodeFlags.cpp in Sources */,
7178
				0FA581BA150E952C00B9A2D9 /* DFGNodeFlags.cpp in Sources */,
7153
				86EC9DCF1328DF82002B2AD7 /* DFGOperations.cpp in Sources */,
7179
				86EC9DCF1328DF82002B2AD7 /* DFGOperations.cpp in Sources */,
7154
				A7D89CFD17A0B8CC00773AD8 /* DFGOSRAvailabilityAnalysisPhase.cpp in Sources */,
7180
				A7D89CFD17A0B8CC00773AD8 /* DFGOSRAvailabilityAnalysisPhase.cpp in Sources */,
7181
				7BD10C421B4ED43C00BD541A /* WasmJITCompiler.cpp in Sources */,
7155
				0FD82E56141DAF0800179C94 /* DFGOSREntry.cpp in Sources */,
7182
				0FD82E56141DAF0800179C94 /* DFGOSREntry.cpp in Sources */,
7156
				0FD8A32517D51F5700CA2C40 /* DFGOSREntrypointCreationPhase.cpp in Sources */,
7183
				0FD8A32517D51F5700CA2C40 /* DFGOSREntrypointCreationPhase.cpp in Sources */,
7157
				FE5068671AE25E280009DAB7 /* DeferredSourceDump.cpp in Sources */,
7184
				FE5068671AE25E280009DAB7 /* DeferredSourceDump.cpp in Sources */,
Lines 7188-7193 a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec9
7188
				0FC097A1146B28CA00CF2442 /* DFGThunks.cpp in Sources */,
7215
				0FC097A1146B28CA00CF2442 /* DFGThunks.cpp in Sources */,
7189
				0F93B4A918B92C4D00178A3F /* PutByIdVariant.cpp in Sources */,
7216
				0F93B4A918B92C4D00178A3F /* PutByIdVariant.cpp in Sources */,
7190
				709FB8671AE335C60039D069 /* JSWeakSet.cpp in Sources */,
7217
				709FB8671AE335C60039D069 /* JSWeakSet.cpp in Sources */,
7218
				7BD10C441B4ED44500BD541A /* WasmModule.cpp in Sources */,
7191
				0FD8A32717D51F5700CA2C40 /* DFGTierUpCheckInjectionPhase.cpp in Sources */,
7219
				0FD8A32717D51F5700CA2C40 /* DFGTierUpCheckInjectionPhase.cpp in Sources */,
7192
				0FD8A32917D51F5700CA2C40 /* DFGToFTLDeferredCompilationCallback.cpp in Sources */,
7220
				0FD8A32917D51F5700CA2C40 /* DFGToFTLDeferredCompilationCallback.cpp in Sources */,
7193
				0FB17662196B8F9E0091052A /* DFGPureValue.cpp in Sources */,
7221
				0FB17662196B8F9E0091052A /* DFGPureValue.cpp in Sources */,
- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp +75 lines
Lines 86-91 CString CodeBlock::inferredName() const a/Source/JavaScriptCore/bytecode/CodeBlock.cpp_sec1
86
    case EvalCode:
86
    case EvalCode:
87
        return "<eval>";
87
        return "<eval>";
88
    case FunctionCode:
88
    case FunctionCode:
89
        // FIXME: hacky
90
        if (ownerExecutable()->isWebAssemblyExecutable())
91
            return "<webassembly>";
89
        return jsCast<FunctionExecutable*>(ownerExecutable())->inferredName().utf8();
92
        return jsCast<FunctionExecutable*>(ownerExecutable())->inferredName().utf8();
90
    default:
93
    default:
91
        CRASH();
94
        CRASH();
Lines 2183-2188 CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin a/Source/JavaScriptCore/bytecode/CodeBlock.cpp_sec2
2183
    m_heap->reportExtraMemoryAllocated(sizeof(CodeBlock) + m_instructions.size() * sizeof(Instruction));
2186
    m_heap->reportExtraMemoryAllocated(sizeof(CodeBlock) + m_instructions.size() * sizeof(Instruction));
2184
}
2187
}
2185
2188
2189
CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, JSGlobalObject* globalObject)
2190
    : m_globalObject(globalObject->vm(), ownerExecutable, globalObject)
2191
    , m_heap(&m_globalObject->vm().heap)
2192
    , m_numCalleeRegisters(0) // FIXME
2193
    , m_numVars(0) // FIXME
2194
    , m_isConstructor(false) // FIXME
2195
    , m_shouldAlwaysBeInlined(true)
2196
    , m_didFailFTLCompilation(false)
2197
    , m_hasBeenCompiledWithFTL(false)
2198
    // , m_unlinkedCode(m_globalObject->vm(), ownerExecutable, unlinkedCodeBlock)
2199
    , m_hasDebuggerStatement(false)
2200
    , m_steppingMode(SteppingModeDisabled)
2201
    , m_numBreakpoints(0)
2202
    , m_ownerExecutable(m_globalObject->vm(), ownerExecutable, ownerExecutable)
2203
    , m_vm(&m_globalObject->vm()) // FIXME
2204
    , m_thisRegister(VirtualRegister()) // FIXME
2205
    , m_scopeRegister(VirtualRegister()) // FIXME
2206
    , m_lexicalEnvironmentRegister(VirtualRegister()) // FIXME
2207
    , m_isStrictMode(false) // FIXME
2208
    , m_needsActivation(false)
2209
    , m_mayBeExecuting(false)
2210
    , m_source(nullptr)
2211
    , m_sourceOffset(0)
2212
    , m_firstLineColumnOffset(0)
2213
    , m_codeType(FunctionCode) // FIXME
2214
    , m_osrExitCounter(0)
2215
    , m_optimizationDelayCounter(0)
2216
    , m_reoptimizationRetryCounter(0)
2217
#if ENABLE(JIT)
2218
    , m_capabilityLevelState(DFG::CapabilityLevelNotSet)
2219
#endif
2220
{
2221
    m_visitAggregateHasBeenCalled.store(false, std::memory_order_relaxed);
2222
2223
    ASSERT(m_heap->isDeferred());
2224
2225
    /*
2226
    ASSERT(m_scopeRegister.isLocal());
2227
2228
    bool didCloneSymbolTable = false;
2229
2230
    if (SymbolTable* symbolTable = unlinkedCodeBlock->symbolTable()) {
2231
        if (m_vm->typeProfiler()) {
2232
            ConcurrentJITLocker locker(symbolTable->m_lock);
2233
            symbolTable->prepareForTypeProfiling(locker);
2234
        }
2235
2236
        if (codeType() == FunctionCode && symbolTable->scopeSize()) {
2237
            m_symbolTable.set(*m_vm, m_ownerExecutable.get(), symbolTable->cloneScopePart(*m_vm));
2238
            didCloneSymbolTable = true;
2239
        } else
2240
            m_symbolTable.set(*m_vm, m_ownerExecutable.get(), symbolTable);
2241
    }
2242
    */
2243
2244
    // FIXME:
2245
    setNumParameters(0);
2246
2247
    m_heap->m_codeBlocks.add(this);
2248
    m_heap->reportExtraMemoryAllocated(sizeof(CodeBlock));
2249
}
2250
2186
CodeBlock::~CodeBlock()
2251
CodeBlock::~CodeBlock()
2187
{
2252
{
2188
    if (m_vm->m_perBytecodeProfiler)
2253
    if (m_vm->m_perBytecodeProfiler)
Lines 3057-3062 CodeBlock* FunctionCodeBlock::replacement() a/Source/JavaScriptCore/bytecode/CodeBlock.cpp_sec3
3057
    return jsCast<FunctionExecutable*>(ownerExecutable())->codeBlockFor(m_isConstructor ? CodeForConstruct : CodeForCall);
3122
    return jsCast<FunctionExecutable*>(ownerExecutable())->codeBlockFor(m_isConstructor ? CodeForConstruct : CodeForCall);
3058
}
3123
}
3059
3124
3125
CodeBlock* WebAssemblyCodeBlock::replacement()
3126
{
3127
    return jsCast<WebAssemblyExecutable*>(ownerExecutable())->codeBlockFor(m_isConstructor ? CodeForConstruct : CodeForCall);
3128
}
3129
3060
DFG::CapabilityLevel ProgramCodeBlock::capabilityLevelInternal()
3130
DFG::CapabilityLevel ProgramCodeBlock::capabilityLevelInternal()
3061
{
3131
{
3062
    return DFG::programCapabilityLevel(this);
3132
    return DFG::programCapabilityLevel(this);
Lines 3073-3078 DFG::CapabilityLevel FunctionCodeBlock::capabilityLevelInternal() a/Source/JavaScriptCore/bytecode/CodeBlock.cpp_sec4
3073
        return DFG::functionForConstructCapabilityLevel(this);
3143
        return DFG::functionForConstructCapabilityLevel(this);
3074
    return DFG::functionForCallCapabilityLevel(this);
3144
    return DFG::functionForCallCapabilityLevel(this);
3075
}
3145
}
3146
3147
DFG::CapabilityLevel WebAssemblyCodeBlock::capabilityLevelInternal()
3148
{
3149
    return DFG::CannotCompile;
3150
}
3076
#endif
3151
#endif
3077
3152
3078
void CodeBlock::jettison(Profiler::JettisonReason reason, ReoptimizationMode mode, const FireDetail* detail)
3153
void CodeBlock::jettison(Profiler::JettisonReason reason, ReoptimizationMode mode, const FireDetail* detail)
- a/Source/JavaScriptCore/bytecode/CodeBlock.h -1 / +31 lines
Lines 97-102 protected: a/Source/JavaScriptCore/bytecode/CodeBlock.h_sec1
97
        
97
        
98
    CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock*, JSScope*, PassRefPtr<SourceProvider>, unsigned sourceOffset, unsigned firstLineColumnOffset);
98
    CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock*, JSScope*, PassRefPtr<SourceProvider>, unsigned sourceOffset, unsigned firstLineColumnOffset);
99
99
100
    CodeBlock(ScriptExecutable* ownerExecutable, JSGlobalObject*);
101
100
    WriteBarrier<JSGlobalObject> m_globalObject;
102
    WriteBarrier<JSGlobalObject> m_globalObject;
101
    Heap* m_heap;
103
    Heap* m_heap;
102
104
Lines 348-354 public: a/Source/JavaScriptCore/bytecode/CodeBlock.h_sec2
348
        return m_needsActivation;
350
        return m_needsActivation;
349
    }
351
    }
350
    
352
    
351
    CodeType codeType() const { return m_unlinkedCode->codeType(); }
353
    CodeType codeType() const
354
    {
355
        // FIXME: hacky
356
        if (ownerExecutable()->isWebAssemblyExecutable())
357
            return FunctionCode;
358
        return m_unlinkedCode->codeType();
359
    }
360
352
    PutPropertySlot::Context putByIdContext() const
361
    PutPropertySlot::Context putByIdContext() const
353
    {
362
    {
354
        if (codeType() == EvalCode)
363
        if (codeType() == EvalCode)
Lines 1142-1147 protected: a/Source/JavaScriptCore/bytecode/CodeBlock.h_sec3
1142
#endif
1151
#endif
1143
};
1152
};
1144
1153
1154
class WebAssemblyCodeBlock : public CodeBlock {
1155
public:
1156
    WebAssemblyCodeBlock(CopyParsedBlockTag, WebAssemblyCodeBlock& other)
1157
        : CodeBlock(CopyParsedBlock, other)
1158
    {
1159
    }
1160
1161
    WebAssemblyCodeBlock(WebAssemblyExecutable* ownerExecutable, JSGlobalObject* globalObject)
1162
        : CodeBlock(ownerExecutable, globalObject)
1163
    {
1164
    }
1165
1166
protected:
1167
    virtual void finalizeUnconditionally() override { };
1168
1169
#if ENABLE(JIT)
1170
    virtual CodeBlock* replacement() override;
1171
    virtual DFG::CapabilityLevel capabilityLevelInternal() override;
1172
#endif
1173
};
1174
1145
inline CodeBlock* baselineCodeBlockForInlineCallFrame(InlineCallFrame* inlineCallFrame)
1175
inline CodeBlock* baselineCodeBlockForInlineCallFrame(InlineCallFrame* inlineCallFrame)
1146
{
1176
{
1147
    RELEASE_ASSERT(inlineCallFrame);
1177
    RELEASE_ASSERT(inlineCallFrame);
- a/Source/JavaScriptCore/jit/JITOperations.cpp -6 / +12 lines
Lines 778-784 inline char* linkFor( a/Source/JavaScriptCore/jit/JITOperations.cpp_sec1
778
778
779
    MacroAssemblerCodePtr codePtr;
779
    MacroAssemblerCodePtr codePtr;
780
    CodeBlock* codeBlock = 0;
780
    CodeBlock* codeBlock = 0;
781
    if (executable->isHostFunction())
781
    if (executable->isWebAssemblyExecutable()) {
782
        // FIXME: Should we really use RegisterPreservationNotRequired?
783
        codePtr = executable->entrypointFor(*vm, kind, ArityCheckNotRequired, RegisterPreservationNotRequired);
784
    } else if (executable->isHostFunction())
782
        codePtr = executable->entrypointFor(*vm, kind, MustCheckArity, registers);
785
        codePtr = executable->entrypointFor(*vm, kind, MustCheckArity, registers);
783
    else {
786
    else {
784
        FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
787
        FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
Lines 795-810 inline char* linkFor( a/Source/JavaScriptCore/jit/JITOperations.cpp_sec2
795
        }
798
        }
796
        codeBlock = functionExecutable->codeBlockFor(kind);
799
        codeBlock = functionExecutable->codeBlockFor(kind);
797
        ArityCheckMode arity;
800
        ArityCheckMode arity;
798
        if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()) || callLinkInfo->callType() == CallLinkInfo::CallVarargs || callLinkInfo->callType() == CallLinkInfo::ConstructVarargs)
801
        if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()) || (callLinkInfo && (callLinkInfo->callType() == CallLinkInfo::CallVarargs || callLinkInfo->callType() == CallLinkInfo::ConstructVarargs)))
799
            arity = MustCheckArity;
802
            arity = MustCheckArity;
800
        else
803
        else
801
            arity = ArityCheckNotRequired;
804
            arity = ArityCheckNotRequired;
802
        codePtr = functionExecutable->entrypointFor(*vm, kind, arity, registers);
805
        codePtr = functionExecutable->entrypointFor(*vm, kind, arity, registers);
803
    }
806
    }
804
    if (!callLinkInfo->seenOnce())
807
    // TODO: support repatching
805
        callLinkInfo->setSeen();
808
    if (callLinkInfo) {
806
    else
809
        if (!callLinkInfo->seenOnce())
807
        linkFor(execCallee, *callLinkInfo, codeBlock, callee, codePtr, kind, registers);
810
            callLinkInfo->setSeen();
811
        else
812
            linkFor(execCallee, *callLinkInfo, codeBlock, callee, codePtr, kind, registers);
813
    }
808
    
814
    
809
    return reinterpret_cast<char*>(codePtr.executableAddress());
815
    return reinterpret_cast<char*>(codePtr.executableAddress());
810
}
816
}
- a/Source/JavaScriptCore/jsc.cpp +14 lines
Lines 49-54 a/Source/JavaScriptCore/jsc.cpp_sec1
49
#include "StructureRareDataInlines.h"
49
#include "StructureRareDataInlines.h"
50
#include "TestRunnerUtils.h"
50
#include "TestRunnerUtils.h"
51
#include "TypeProfilerLog.h"
51
#include "TypeProfilerLog.h"
52
#include "WasmJITCompiler.h"
52
#include <math.h>
53
#include <math.h>
53
#include <stdio.h>
54
#include <stdio.h>
54
#include <stdlib.h>
55
#include <stdlib.h>
Lines 491-496 static EncodedJSValue JSC_HOST_CALL functionReturnTypeFor(ExecState*); a/Source/JavaScriptCore/jsc.cpp_sec2
491
static EncodedJSValue JSC_HOST_CALL functionDumpBasicBlockExecutionRanges(ExecState*);
492
static EncodedJSValue JSC_HOST_CALL functionDumpBasicBlockExecutionRanges(ExecState*);
492
static EncodedJSValue JSC_HOST_CALL functionHasBasicBlockExecuted(ExecState*);
493
static EncodedJSValue JSC_HOST_CALL functionHasBasicBlockExecuted(ExecState*);
493
static EncodedJSValue JSC_HOST_CALL functionEnableExceptionFuzz(ExecState*);
494
static EncodedJSValue JSC_HOST_CALL functionEnableExceptionFuzz(ExecState*);
495
static EncodedJSValue JSC_HOST_CALL functionLoadWebAssembly(ExecState*);
494
496
495
#if ENABLE(SAMPLING_FLAGS)
497
#if ENABLE(SAMPLING_FLAGS)
496
static EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState*);
498
static EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState*);
Lines 653-658 protected: a/Source/JavaScriptCore/jsc.cpp_sec3
653
        addFunction(vm, "hasBasicBlockExecuted", functionHasBasicBlockExecuted, 2);
655
        addFunction(vm, "hasBasicBlockExecuted", functionHasBasicBlockExecuted, 2);
654
656
655
        addFunction(vm, "enableExceptionFuzz", functionEnableExceptionFuzz, 0);
657
        addFunction(vm, "enableExceptionFuzz", functionEnableExceptionFuzz, 0);
658
659
        addFunction(vm, "loadWebAssembly", functionLoadWebAssembly, 1);
656
        
660
        
657
        JSArray* array = constructEmptyArray(globalExec(), 0);
661
        JSArray* array = constructEmptyArray(globalExec(), 0);
658
        for (size_t i = 0; i < arguments.size(); ++i)
662
        for (size_t i = 0; i < arguments.size(); ++i)
Lines 1182-1187 EncodedJSValue JSC_HOST_CALL functionEnableExceptionFuzz(ExecState*) a/Source/JavaScriptCore/jsc.cpp_sec4
1182
    return JSValue::encode(jsUndefined());
1186
    return JSValue::encode(jsUndefined());
1183
}
1187
}
1184
1188
1189
EncodedJSValue JSC_HOST_CALL functionLoadWebAssembly(ExecState* exec)
1190
{
1191
    String fileName = exec->argument(0).toString(exec)->value(exec);
1192
    Vector<char> buffer;
1193
    if (!fillBufferWithContentsOfFile(fileName, buffer))
1194
        return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Could not open file."))));
1195
    Wasm::Module* module = Wasm::compile(exec, buffer);
1196
    return JSValue::encode(module);
1197
}
1198
1185
// Use SEH for Release builds only to get rid of the crash report dialog
1199
// Use SEH for Release builds only to get rid of the crash report dialog
1186
// (luckily the same tests fail in Release and Debug builds so far). Need to
1200
// (luckily the same tests fail in Release and Debug builds so far). Need to
1187
// be in a separate main function because the jscmain function requires object
1201
// be in a separate main function because the jscmain function requires object
- a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp -1 / +3 lines
Lines 1119-1125 inline SlowPathReturnType setUpCall(ExecState* execCallee, Instruction* pc, Code a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp_sec1
1119
    
1119
    
1120
    MacroAssemblerCodePtr codePtr;
1120
    MacroAssemblerCodePtr codePtr;
1121
    CodeBlock* codeBlock = 0;
1121
    CodeBlock* codeBlock = 0;
1122
    if (executable->isHostFunction())
1122
    if (executable->isWebAssemblyExecutable())
1123
        codePtr = executable->entrypointFor(vm, kind, ArityCheckNotRequired, RegisterPreservationNotRequired);
1124
    else if (executable->isHostFunction())
1123
        codePtr = executable->entrypointFor(vm, kind, MustCheckArity, RegisterPreservationNotRequired);
1125
        codePtr = executable->entrypointFor(vm, kind, MustCheckArity, RegisterPreservationNotRequired);
1124
    else {
1126
    else {
1125
        FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
1127
        FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
- a/Source/JavaScriptCore/runtime/Executable.cpp +87 lines
Lines 149-154 void ScriptExecutable::installCode(CodeBlock* genericCodeBlock) a/Source/JavaScriptCore/runtime/Executable.cpp_sec1
149
        break;
149
        break;
150
    }
150
    }
151
    
151
    
152
    if (isWebAssemblyExecutable()) {
153
        WebAssemblyExecutable* executable = jsCast<WebAssemblyExecutable*>(this);
154
        WebAssemblyCodeBlock* codeBlock = static_cast<WebAssemblyCodeBlock*>(genericCodeBlock);
155
156
        ASSERT(kind == CodeForCall);
157
158
        executable->m_codeBlockForCall = codeBlock;
159
        
160
        // FIXME: this is just to make isHostFunction() happy.
161
        // But this will make isHostFunction() return true.
162
        m_numParametersForCall = 0;
163
        m_numParametersForConstruct = 0;
164
    } else {
165
166
        // FIXME: need to deal with codeType()
152
    switch (genericCodeBlock->codeType()) {
167
    switch (genericCodeBlock->codeType()) {
153
    case GlobalCode: {
168
    case GlobalCode: {
154
        ProgramExecutable* executable = jsCast<ProgramExecutable*>(this);
169
        ProgramExecutable* executable = jsCast<ProgramExecutable*>(this);
Lines 192-197 void ScriptExecutable::installCode(CodeBlock* genericCodeBlock) a/Source/JavaScriptCore/runtime/Executable.cpp_sec2
192
    if (oldCodeBlock)
207
    if (oldCodeBlock)
193
        oldCodeBlock->unlinkIncomingCalls();
208
        oldCodeBlock->unlinkIncomingCalls();
194
209
210
    }
211
    
195
    Debugger* debugger = genericCodeBlock->globalObject()->debugger();
212
    Debugger* debugger = genericCodeBlock->globalObject()->debugger();
196
    if (debugger)
213
    if (debugger)
197
        debugger->registerCodeBlock(genericCodeBlock);
214
        debugger->registerCodeBlock(genericCodeBlock);
Lines 228-233 RefPtr<CodeBlock> ScriptExecutable::newCodeBlockFor( a/Source/JavaScriptCore/runtime/Executable.cpp_sec3
228
            executable->source().provider(), executable->source().startColumn()));
245
            executable->source().provider(), executable->source().startColumn()));
229
    }
246
    }
230
    
247
    
248
    ASSERT(!isWebAssemblyExecutable());
249
    
231
    RELEASE_ASSERT(classInfo() == FunctionExecutable::info());
250
    RELEASE_ASSERT(classInfo() == FunctionExecutable::info());
232
    RELEASE_ASSERT(function);
251
    RELEASE_ASSERT(function);
233
    FunctionExecutable* executable = jsCast<FunctionExecutable*>(this);
252
    FunctionExecutable* executable = jsCast<FunctionExecutable*>(this);
Lines 323-328 static void setupJIT(VM& vm, CodeBlock* codeBlock) a/Source/JavaScriptCore/runtime/Executable.cpp_sec4
323
JSObject* ScriptExecutable::prepareForExecutionImpl(
342
JSObject* ScriptExecutable::prepareForExecutionImpl(
324
    ExecState* exec, JSFunction* function, JSScope* scope, CodeSpecializationKind kind)
343
    ExecState* exec, JSFunction* function, JSScope* scope, CodeSpecializationKind kind)
325
{
344
{
345
    ASSERT(!isWebAssemblyExecutable());
346
    
326
    VM& vm = exec->vm();
347
    VM& vm = exec->vm();
327
    DeferGC deferGC(vm.heap);
348
    DeferGC deferGC(vm.heap);
328
    
349
    
Lines 425-430 void FunctionExecutable::destroy(JSCell* cell) a/Source/JavaScriptCore/runtime/Executable.cpp_sec5
425
    static_cast<FunctionExecutable*>(cell)->FunctionExecutable::~FunctionExecutable();
446
    static_cast<FunctionExecutable*>(cell)->FunctionExecutable::~FunctionExecutable();
426
}
447
}
427
448
449
const ClassInfo WebAssemblyExecutable::s_info = { "WebAssemblyExecutable", &ScriptExecutable::s_info, 0, CREATE_METHOD_TABLE(WebAssemblyExecutable) };
450
451
WebAssemblyExecutable::WebAssemblyExecutable(VM& vm, const SourceCode& source)
452
    : ScriptExecutable(vm.webAssemblyExecutableStructure.get(), vm, source, /*isInStrictContext*/ false )
453
{
454
    /*
455
    RELEASE_ASSERT(!source.isNull());
456
    ASSERT(source.length());
457
    m_firstLine = firstLine;
458
    m_lastLine = lastLine;
459
    m_startColumn = startColumn;
460
    m_endColumn = endColumn;
461
    m_parametersStartOffset = unlinkedExecutable->parametersStartOffset();
462
    m_typeProfilingStartOffset = unlinkedExecutable->typeProfilingStartOffset();
463
    m_typeProfilingEndOffset = unlinkedExecutable->typeProfilingEndOffset();
464
    */
465
}
466
467
void WebAssemblyExecutable::finishCreation(VM& vm)
468
{
469
    Base::finishCreation(vm);
470
    m_singletonFunction.set(vm, this, InferredValue::create(vm));
471
}
472
473
void WebAssemblyExecutable::destroy(JSCell* cell)
474
{
475
    static_cast<WebAssemblyExecutable*>(cell)->WebAssemblyExecutable::~WebAssemblyExecutable();
476
}
477
428
inline const char* samplingDescription(JITCode::JITType jitType)
478
inline const char* samplingDescription(JITCode::JITType jitType)
429
{
479
{
430
    switch (jitType) {
480
    switch (jitType) {
Lines 619-624 FunctionExecutable* FunctionExecutable::fromGlobalCode( a/Source/JavaScriptCore/runtime/Executable.cpp_sec6
619
    return unlinkedExecutable->link(exec.vm(), source, overrideLineNumber);
669
    return unlinkedExecutable->link(exec.vm(), source, overrideLineNumber);
620
}
670
}
621
671
672
WebAssemblyCodeBlock* WebAssemblyExecutable::baselineCodeBlockFor(CodeSpecializationKind kind)
673
{
674
    ASSERT(kind == CodeForCall);
675
676
    WebAssemblyCodeBlock* result = m_codeBlockForCall.get();
677
    if (!result)
678
        return 0;
679
    return static_cast<WebAssemblyCodeBlock*>(result->baselineAlternative());
680
}
681
682
void WebAssemblyExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
683
{
684
    WebAssemblyExecutable* thisObject = jsCast<WebAssemblyExecutable*>(cell);
685
    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
686
    ScriptExecutable::visitChildren(thisObject, visitor);
687
    if (thisObject->m_codeBlockForCall)
688
        thisObject->m_codeBlockForCall->visitAggregate(visitor);
689
    visitor.append(&thisObject->m_singletonFunction);
690
}
691
692
SymbolTable* WebAssemblyExecutable::symbolTable(CodeSpecializationKind kind)
693
{
694
    return codeBlockFor(kind)->symbolTable();
695
}
696
697
void WebAssemblyExecutable::clearCode()
698
{
699
    // FIXME: hacky
700
    // m_codeBlockForCall = nullptr;
701
    // Base::clearCode();
702
}
703
704
void WebAssemblyExecutable::unlinkCalls()
705
{
706
    // FIXME: hacky
707
}
708
622
void ExecutableBase::dump(PrintStream& out) const
709
void ExecutableBase::dump(PrintStream& out) const
623
{
710
{
624
    ExecutableBase* realThis = const_cast<ExecutableBase*>(this);
711
    ExecutableBase* realThis = const_cast<ExecutableBase*>(this);
- a/Source/JavaScriptCore/runtime/Executable.h +122 lines
Lines 50-55 class EvalCodeBlock; a/Source/JavaScriptCore/runtime/Executable.h_sec1
50
class FunctionCodeBlock;
50
class FunctionCodeBlock;
51
class LLIntOffsetsExtractor;
51
class LLIntOffsetsExtractor;
52
class ProgramCodeBlock;
52
class ProgramCodeBlock;
53
class WebAssemblyCodeBlock;
53
class JSScope;
54
class JSScope;
54
    
55
    
55
enum CompilationKind { FirstCompilation, OptimizingCompilation };
56
enum CompilationKind { FirstCompilation, OptimizingCompilation };
Lines 98-103 public: a/Source/JavaScriptCore/runtime/Executable.h_sec2
98
    {
99
    {
99
        return type() == FunctionExecutableType;
100
        return type() == FunctionExecutableType;
100
    }
101
    }
102
    bool isWebAssemblyExecutable()
103
    {
104
        return type() == WebAssemblyExecutableType;
105
    }
101
    bool isProgramExecutable()
106
    bool isProgramExecutable()
102
    {
107
    {
103
        return type() == ProgramExecutableType;
108
        return type() == ProgramExecutableType;
Lines 678-683 private: a/Source/JavaScriptCore/runtime/Executable.h_sec3
678
    WriteBarrier<InferredValue> m_singletonFunction;
683
    WriteBarrier<InferredValue> m_singletonFunction;
679
};
684
};
680
685
686
class WebAssemblyExecutable final : public ScriptExecutable {
687
    friend class JIT;
688
    friend class LLIntOffsetsExtractor;
689
public:
690
    typedef ScriptExecutable Base;
691
    static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
692
693
    static WebAssemblyExecutable* create(VM& vm, const SourceCode& source)
694
    {
695
        WebAssemblyExecutable* executable = new (NotNull, allocateCell<WebAssemblyExecutable>(vm.heap)) WebAssemblyExecutable(vm, source);
696
        executable->finishCreation(vm);
697
        return executable;
698
    }
699
    // static WebAssemblyExecutable* fromGlobalCode(const Identifier& name, ExecState&, const SourceCode&, JSObject*& exception, int overrideLineNumber);
700
701
    static void destroy(JSCell*);
702
        
703
    bool isGeneratedForCall() const
704
    {
705
        return m_codeBlockForCall;
706
    }
707
708
    WebAssemblyCodeBlock* codeBlockForCall()
709
    {
710
        return m_codeBlockForCall.get();
711
    }
712
713
    bool isGeneratedForConstruct() const
714
    {
715
        return false;
716
    }
717
718
    WebAssemblyCodeBlock* codeBlockForConstruct()
719
    {
720
        return nullptr;
721
    }
722
        
723
    bool isGeneratedFor(CodeSpecializationKind kind)
724
    {
725
        if (kind == CodeForCall)
726
            return isGeneratedForCall();
727
        ASSERT(kind == CodeForConstruct);
728
        return isGeneratedForConstruct();
729
    }
730
        
731
    WebAssemblyCodeBlock* codeBlockFor(CodeSpecializationKind kind)
732
    {
733
        if (kind == CodeForCall)
734
            return codeBlockForCall();
735
        ASSERT(kind == CodeForConstruct);
736
        return codeBlockForConstruct();
737
    }
738
739
    WebAssemblyCodeBlock* baselineCodeBlockFor(CodeSpecializationKind);
740
        
741
    WebAssemblyCodeBlock* profiledCodeBlockFor(CodeSpecializationKind kind)
742
    {
743
        return baselineCodeBlockFor(kind);
744
    }
745
746
    RefPtr<TypeSet> returnStatementTypeSet() 
747
    {
748
        if (!m_returnStatementTypeSet)
749
            m_returnStatementTypeSet = TypeSet::create();
750
751
        return m_returnStatementTypeSet;
752
    }
753
        
754
    // FunctionMode functionMode() { return m_unlinkedExecutable->functionMode(); }
755
    // bool isBuiltinFunction() const { return m_unlinkedExecutable->isBuiltinFunction(); }
756
    // bool isClassConstructorFunction() const { return m_unlinkedExecutable->isClassConstructorFunction(); }
757
    // const Identifier& name() { return m_unlinkedExecutable->name(); }
758
    // const Identifier& inferredName() { return m_unlinkedExecutable->inferredName(); }
759
    // JSString* nameValue() const { return m_unlinkedExecutable->nameValue(); }
760
    // size_t parameterCount() const { return m_unlinkedExecutable->parameterCount(); } // Excluding 'this'!
761
    SymbolTable* symbolTable(CodeSpecializationKind);
762
763
    static void visitChildren(JSCell*, SlotVisitor&);
764
    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
765
    {
766
        return Structure::create(vm, globalObject, proto, TypeInfo(WebAssemblyExecutableType, StructureFlags), info());
767
    }
768
769
    unsigned parametersStartOffset() const { return m_parametersStartOffset; }
770
771
    /*
772
    void overrideParameterAndTypeProfilingStartEndOffsets(unsigned parametersStartOffset, unsigned typeProfilingStartOffset, unsigned typeProfilingEndOffset)
773
    {
774
        m_parametersStartOffset = parametersStartOffset;
775
        m_typeProfilingStartOffset = typeProfilingStartOffset;
776
        m_typeProfilingEndOffset = typeProfilingEndOffset;
777
    }
778
    */
779
780
    DECLARE_INFO;
781
        
782
    void unlinkCalls();
783
784
    void clearCode();
785
    
786
    InferredValue* singletonFunction() { return m_singletonFunction.get(); }
787
788
private:
789
    WebAssemblyExecutable(VM&, const SourceCode&);
790
    
791
    void finishCreation(VM&);
792
793
    friend class ScriptExecutable;
794
795
    RefPtr<WebAssemblyCodeBlock> m_codeBlockForCall;
796
    RefPtr<TypeSet> m_returnStatementTypeSet;
797
    unsigned m_parametersStartOffset;
798
    WriteBarrier<InferredValue> m_singletonFunction;
799
};
800
681
inline void ExecutableBase::clearCodeVirtual(ExecutableBase* executable)
801
inline void ExecutableBase::clearCodeVirtual(ExecutableBase* executable)
682
{
802
{
683
    switch (executable->type()) {
803
    switch (executable->type()) {
Lines 687-692 inline void ExecutableBase::clearCodeVirtual(ExecutableBase* executable) a/Source/JavaScriptCore/runtime/Executable.h_sec4
687
        return jsCast<ProgramExecutable*>(executable)->clearCode();
807
        return jsCast<ProgramExecutable*>(executable)->clearCode();
688
    case FunctionExecutableType:
808
    case FunctionExecutableType:
689
        return jsCast<FunctionExecutable*>(executable)->clearCode();
809
        return jsCast<FunctionExecutable*>(executable)->clearCode();
810
    case WebAssemblyExecutableType:
811
        return jsCast<WebAssemblyExecutable*>(executable)->clearCode();
690
    default:
812
    default:
691
        return jsCast<NativeExecutable*>(executable)->clearCode();
813
        return jsCast<NativeExecutable*>(executable)->clearCode();
692
    }
814
    }
- a/Source/JavaScriptCore/runtime/JSFunction.cpp -2 / +3 lines
Lines 60-69 bool JSFunction::isHostFunctionNonInline() const a/Source/JavaScriptCore/runtime/JSFunction.cpp_sec1
60
    return isHostFunction();
60
    return isHostFunction();
61
}
61
}
62
62
63
JSFunction* JSFunction::create(VM& vm, FunctionExecutable* executable, JSScope* scope)
63
JSFunction* JSFunction::create(VM& vm, ExecutableBase* executable, JSScope* scope)
64
{
64
{
65
    JSFunction* result = createImpl(vm, executable, scope);
65
    JSFunction* result = createImpl(vm, executable, scope);
66
    executable->singletonFunction()->notifyWrite(vm, result, "Allocating a function");
66
    if (executable->isFunctionExecutable())
67
        static_cast<FunctionExecutable*>(executable)->singletonFunction()->notifyWrite(vm, result, "Allocating a function");
67
    return result;
68
    return result;
68
}
69
}
69
70
- a/Source/JavaScriptCore/runtime/JSFunction.h -3 / +3 lines
Lines 72-78 public: a/Source/JavaScriptCore/runtime/JSFunction.h_sec1
72
    static JSFunction* createWithInvalidatedReallocationWatchpoint(VM&, FunctionExecutable*, JSScope*);
72
    static JSFunction* createWithInvalidatedReallocationWatchpoint(VM&, FunctionExecutable*, JSScope*);
73
    JS_EXPORT_PRIVATE static JSFunction* create(VM&, JSGlobalObject*, int length, const String& name, NativeStdFunction&&, Intrinsic = NoIntrinsic, NativeFunction nativeConstructor = callHostFunctionAsConstructor);
73
    JS_EXPORT_PRIVATE static JSFunction* create(VM&, JSGlobalObject*, int length, const String& name, NativeStdFunction&&, Intrinsic = NoIntrinsic, NativeFunction nativeConstructor = callHostFunctionAsConstructor);
74
74
75
    static JSFunction* create(VM&, FunctionExecutable*, JSScope*);
75
    static JSFunction* create(VM&, ExecutableBase*, JSScope*);
76
76
77
    static JSFunction* createBuiltinFunction(VM&, FunctionExecutable*, JSGlobalObject*);
77
    static JSFunction* createBuiltinFunction(VM&, FunctionExecutable*, JSGlobalObject*);
78
    static JSFunction* createBuiltinFunction(VM&, FunctionExecutable*, JSGlobalObject*, const String& name);
78
    static JSFunction* createBuiltinFunction(VM&, FunctionExecutable*, JSGlobalObject*, const String& name);
Lines 140-146 public: a/Source/JavaScriptCore/runtime/JSFunction.h_sec2
140
140
141
protected:
141
protected:
142
    JS_EXPORT_PRIVATE JSFunction(VM&, JSGlobalObject*, Structure*);
142
    JS_EXPORT_PRIVATE JSFunction(VM&, JSGlobalObject*, Structure*);
143
    JSFunction(VM&, FunctionExecutable*, JSScope*);
143
    JSFunction(VM&, ExecutableBase*, JSScope*);
144
144
145
    void finishCreation(VM&, NativeExecutable*, int length, const String& name);
145
    void finishCreation(VM&, NativeExecutable*, int length, const String& name);
146
    using Base::finishCreation;
146
    using Base::finishCreation;
Lines 159-165 protected: a/Source/JavaScriptCore/runtime/JSFunction.h_sec3
159
    static void visitChildren(JSCell*, SlotVisitor&);
159
    static void visitChildren(JSCell*, SlotVisitor&);
160
160
161
private:
161
private:
162
    static JSFunction* createImpl(VM& vm, FunctionExecutable* executable, JSScope* scope)
162
    static JSFunction* createImpl(VM& vm, ExecutableBase* executable, JSScope* scope)
163
    {
163
    {
164
        JSFunction* function = new (NotNull, allocateCell<JSFunction>(vm.heap)) JSFunction(vm, executable, scope);
164
        JSFunction* function = new (NotNull, allocateCell<JSFunction>(vm.heap)) JSFunction(vm, executable, scope);
165
        ASSERT(function->structure()->globalObject());
165
        ASSERT(function->structure()->globalObject());
- a/Source/JavaScriptCore/runtime/JSFunctionInlines.h -1 / +3 lines
Lines 38-44 inline JSFunction* JSFunction::createWithInvalidatedReallocationWatchpoint( a/Source/JavaScriptCore/runtime/JSFunctionInlines.h_sec1
38
    return createImpl(vm, executable, scope);
38
    return createImpl(vm, executable, scope);
39
}
39
}
40
40
41
inline JSFunction::JSFunction(VM& vm, FunctionExecutable* executable, JSScope* scope)
41
inline JSFunction::JSFunction(VM& vm, ExecutableBase* executable, JSScope* scope)
42
    : Base(vm, scope, scope->globalObject()->functionStructure())
42
    : Base(vm, scope, scope->globalObject()->functionStructure())
43
    , m_executable(vm, this, executable)
43
    , m_executable(vm, this, executable)
44
    , m_rareData()
44
    , m_rareData()
Lines 54-59 inline FunctionExecutable* JSFunction::jsExecutable() const a/Source/JavaScriptCore/runtime/JSFunctionInlines.h_sec2
54
inline bool JSFunction::isHostFunction() const
54
inline bool JSFunction::isHostFunction() const
55
{
55
{
56
    ASSERT(m_executable);
56
    ASSERT(m_executable);
57
    if (m_executable->isWebAssemblyExecutable()) // FIXME: hacky
58
        return true;
57
    return m_executable->isHostFunction();
59
    return m_executable->isHostFunction();
58
}
60
}
59
61
- a/Source/JavaScriptCore/runtime/JSType.h +2 lines
Lines 74-79 enum JSType : uint8_t { a/Source/JavaScriptCore/runtime/JSType.h_sec1
74
74
75
    NameScopeObjectType,
75
    NameScopeObjectType,
76
76
77
    WebAssemblyExecutableType, // FIXME: Move it above.
78
77
    GlobalObjectType,
79
    GlobalObjectType,
78
    ActivationObjectType,
80
    ActivationObjectType,
79
81
- a/Source/JavaScriptCore/runtime/VM.cpp +1 lines
Lines 220-225 VM::VM(VMType vmType, HeapType heapType) a/Source/JavaScriptCore/runtime/VM.cpp_sec1
220
    evalExecutableStructure.set(*this, EvalExecutable::createStructure(*this, 0, jsNull()));
220
    evalExecutableStructure.set(*this, EvalExecutable::createStructure(*this, 0, jsNull()));
221
    programExecutableStructure.set(*this, ProgramExecutable::createStructure(*this, 0, jsNull()));
221
    programExecutableStructure.set(*this, ProgramExecutable::createStructure(*this, 0, jsNull()));
222
    functionExecutableStructure.set(*this, FunctionExecutable::createStructure(*this, 0, jsNull()));
222
    functionExecutableStructure.set(*this, FunctionExecutable::createStructure(*this, 0, jsNull()));
223
    webAssemblyExecutableStructure.set(*this, WebAssemblyExecutable::createStructure(*this, 0, jsNull()));
223
    regExpStructure.set(*this, RegExp::createStructure(*this, 0, jsNull()));
224
    regExpStructure.set(*this, RegExp::createStructure(*this, 0, jsNull()));
224
    symbolStructure.set(*this, Symbol::createStructure(*this, 0, jsNull()));
225
    symbolStructure.set(*this, Symbol::createStructure(*this, 0, jsNull()));
225
    symbolTableStructure.set(*this, SymbolTable::createStructure(*this, 0, jsNull()));
226
    symbolTableStructure.set(*this, SymbolTable::createStructure(*this, 0, jsNull()));
- a/Source/JavaScriptCore/runtime/VM.h +1 lines
Lines 259-264 public: a/Source/JavaScriptCore/runtime/VM.h_sec1
259
    Strong<Structure> evalExecutableStructure;
259
    Strong<Structure> evalExecutableStructure;
260
    Strong<Structure> programExecutableStructure;
260
    Strong<Structure> programExecutableStructure;
261
    Strong<Structure> functionExecutableStructure;
261
    Strong<Structure> functionExecutableStructure;
262
    Strong<Structure> webAssemblyExecutableStructure;
262
    Strong<Structure> regExpStructure;
263
    Strong<Structure> regExpStructure;
263
    Strong<Structure> symbolStructure;
264
    Strong<Structure> symbolStructure;
264
    Strong<Structure> symbolTableStructure;
265
    Strong<Structure> symbolTableStructure;
- a/Source/JavaScriptCore/wasm/WasmJITCompiler.cpp +1138 lines
Line 0 a/Source/JavaScriptCore/wasm/WasmJITCompiler.cpp_sec1
1
/*
2
 * Copyright (C) 2015 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
/*
27
 Licensed under the Apache License, Version 2.0 (the "License");
28
 you may not use this file except in compliance with the License.
29
 You may obtain a copy of the License at
30
31
 http://www.apache.org/licenses/LICENSE-2.0
32
33
 Unless required by applicable law or agreed to in writing, software
34
 distributed under the License is distributed on an "AS IS" BASIS,
35
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
36
 See the License for the specific language governing permissions and
37
 limitations under the License.
38
*/
39
40
#include "config.h"
41
#include "WasmJITCompiler.h"
42
43
#include "JITCode.h"
44
#include "JSCJSValueInlines.h"
45
#include "LinkBuffer.h"
46
#include "MaxFrameExtentForSlowPathCall.h"
47
#include "Register.h"
48
49
namespace JSC {
50
51
namespace Wasm {
52
53
class JumpScope {
54
public:
55
    JumpScope(MacroAssembler* macroAssembler)
56
        : m_macroAssembler(macroAssembler)
57
        , m_linked(false)
58
    {
59
    }
60
61
    JumpScope(MacroAssembler* macroAssembler, const MacroAssembler::Label& label)
62
        : m_macroAssembler(macroAssembler)
63
        , m_linked(true)
64
        , m_label(label)
65
    {
66
    }
67
68
    void jump()
69
    {
70
        if (m_linked)
71
            m_macroAssembler->jump(m_label);
72
        else
73
            m_jumpList.append(m_macroAssembler->jump());
74
    }
75
76
    void link()
77
    {
78
        ASSERT(!m_linked);
79
        m_jumpList.link(m_macroAssembler);
80
    }
81
82
private:
83
    MacroAssembler* m_macroAssembler;
84
    bool m_linked;
85
    MacroAssembler::Label m_label;
86
    MacroAssembler::JumpList m_jumpList;
87
};
88
89
RefPtr<JITCode> JITCompiler::compileFunction(VM& vm, size_t functionIndex)
90
{
91
    emitFunctionPrologue();
92
    emitPutImmediateToCallFrameHeader(m_codeBlock, JSStack::CodeBlock);
93
94
    const Signature& signature = m_module->m_signatures[m_module->m_funcSignatures[functionIndex]];
95
    m_currentReturnType = signature.returnType;
96
    parseArguments(signature);
97
98
    // FIXME: Calculate the actual height. (Be careful about calls.)
99
    m_stackHeight = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), signature.arguments.size() + 8) * sizeof(Register);
100
    allocateSpaceOnStack();
101
102
    parseVars();
103
    parseStmtList();
104
105
    // FIXME: Skip these if the last statement is a return statement.
106
    move(TrustedImm64(JSValue::encode(jsUndefined())), GPRInfo::regT0); // FIXME: Should we return undefined?
107
    deallocateSpaceOnStack();
108
    emitFunctionEpilogue();
109
    ret();
110
111
    LinkBuffer patchBuffer(vm, *this, 0, JITCompilationMustSucceed);
112
    MacroAssemblerCodePtr withArityCheck;
113
    CodeRef result = FINALIZE_CODE(patchBuffer, ("Baseline JIT code for WebAssembly"));
114
    return adoptRef(new DirectJITCode(result, withArityCheck, JITCode::BaselineJIT));
115
}
116
117
void JITCompiler::allocateSpaceOnStack()
118
{
119
    addPtr(TrustedImm32(-m_stackHeight), stackPointerRegister);
120
}
121
122
void JITCompiler::deallocateSpaceOnStack()
123
{
124
    addPtr(TrustedImm32(m_stackHeight), stackPointerRegister);
125
}
126
127
void JITCompiler::parseArguments(const Signature& signature)
128
{
129
    size_t argumentCount = signature.arguments.size();
130
    for (uint32_t argIndex = 0; argIndex < argumentCount; ++argIndex) {
131
        Type type = signature.arguments[argIndex];
132
        m_currentLocalTypes.append(type);
133
        switch (type) {
134
        case Type::I32:
135
            load32(Address(GPRInfo::callFrameRegister, (argIndex + 1 + CallFrame::thisArgumentOffset()) * sizeof(Register)), GPRInfo::regT0);
136
            store32(GPRInfo::regT0, stackAddress(argIndex));
137
            break;
138
        case Type::F32:
139
            RELEASE_ASSERT_NOT_REACHED();
140
        case Type::F64:
141
            load64(Address(GPRInfo::callFrameRegister, (argIndex + 1 + CallFrame::thisArgumentOffset()) * sizeof(Register)), GPRInfo::regT0);
142
            unboxDoubleWithoutAssertions(GPRInfo::regT0, FPRInfo::fpRegT0);
143
            storeDouble(FPRInfo::fpRegT0, stackAddress(argIndex));
144
            break;
145
        default:
146
            RELEASE_ASSERT_NOT_REACHED();
147
        }
148
    }
149
}
150
151
void JITCompiler::parseVars()
152
{
153
    uint32_t numberOfI32Vars = 0;
154
    uint32_t numberOfF32Vars = 0;
155
    uint32_t numberOfF64Vars = 0;
156
157
    VarTypes varTypes;
158
    VarTypesWithImm varTypesWithImm;
159
    uint8_t imm;
160
    if (m_module->m_reader.code(&varTypes, &varTypesWithImm, &imm)) {
161
        if (varTypes & VarTypes::I32)
162
            numberOfI32Vars = m_module->m_reader.immU32();
163
        if (varTypes & VarTypes::F32)
164
            numberOfF32Vars = m_module->m_reader.immU32();
165
        if (varTypes & VarTypes::F64)
166
            numberOfF64Vars = m_module->m_reader.immU32();
167
    } else
168
        numberOfI32Vars = imm;
169
170
    uint32_t numberOfVars = numberOfI32Vars + numberOfF32Vars + numberOfF64Vars;
171
    if (numberOfVars > 0) {
172
        uint32_t localIndex = m_currentLocalTypes.size();
173
        for (uint32_t i = 0; i < numberOfI32Vars; ++i) {
174
            m_currentLocalTypes.append(Type::I32);
175
            store32(TrustedImm32(0), stackAddress(localIndex++));
176
        }
177
        for (uint32_t i = 0; i < numberOfF32Vars; ++i) {
178
            m_currentLocalTypes.append(Type::F32);
179
            store32(TrustedImm32(0), stackAddress(localIndex++));
180
        }
181
        for (uint32_t i = 0; i < numberOfF64Vars; ++i) {
182
            m_currentLocalTypes.append(Type::F64);
183
            store64(TrustedImm64(0), stackAddress(localIndex++));
184
        }
185
    }
186
}
187
188
void JITCompiler::parseStmt()
189
{
190
    Stmt stmt;
191
    StmtWithImm stmtWithImm;
192
    uint8_t imm;
193
    if (m_module->m_reader.code(&stmt, &stmtWithImm, &imm)) {
194
        switch (stmt) {
195
        case Stmt::SetLoc:
196
            parseSetLocal(0);
197
            break;
198
        case Stmt::SetGlo:
199
        case Stmt::I32Store8:
200
        case Stmt::I32StoreOff8:
201
        case Stmt::I32Store16:
202
        case Stmt::I32StoreOff16:
203
        case Stmt::I32Store32:
204
        case Stmt::I32StoreOff32:
205
        case Stmt::F32Store:
206
        case Stmt::F32StoreOff:
207
        case Stmt::F64Store:
208
        case Stmt::F64StoreOff:
209
        case Stmt::CallInt:
210
        case Stmt::CallInd:
211
            RELEASE_ASSERT_NOT_REACHED();
212
        case Stmt::CallImp:
213
            parseCallImport(ReturnType::Void, 0); // FIXME: Is it really Void?
214
            break;
215
        case Stmt::Ret:
216
            parseReturnStmt();
217
            return;
218
        case Stmt::Block:
219
            parseBlockStmt();
220
            return;
221
        case Stmt::IfThen:
222
            parseIfStmt();
223
            return;
224
        case Stmt::IfElse:
225
            parseIfElseStmt();
226
            return;
227
        case Stmt::While:
228
            parseWhileStmt();
229
            return;
230
        case Stmt::Do:
231
            parseDoStmt();
232
            return;
233
        case Stmt::Label:
234
            parseLabelStmt();
235
            return;
236
        case Stmt::Break:
237
            parseBreakStmt();
238
            return;
239
        case Stmt::BreakLabel:
240
            parseBreakLabelStmt();
241
            return;
242
        case Stmt::Continue:
243
            parseContinueStmt();
244
            break;
245
        case Stmt::ContinueLabel:
246
            parseContinueLabelStmt();
247
            return;
248
        case Stmt::Switch:
249
            parseSwitchStmt();
250
            break;
251
        default:
252
            RELEASE_ASSERT_NOT_REACHED();
253
        }
254
    } else {
255
        switch (stmtWithImm) {
256
        case StmtWithImm::SetLoc:
257
            parseSetLocal(imm, 0);
258
            break;
259
        case StmtWithImm::SetGlo:
260
        default:
261
            RELEASE_ASSERT_NOT_REACHED();
262
        }
263
    }
264
}
265
266
void JITCompiler::parseGetLocal(int dst)
267
{
268
    uint32_t imm = m_module->m_reader.immU32();
269
    switch (m_currentLocalTypes[imm]) {
270
    case Type::I32:
271
    case Type::F32:
272
        load32(stackAddress(imm), GPRInfo::regT0);
273
        store32(GPRInfo::regT0, temporaryAddress(dst));
274
        break;
275
    case Type::F64:
276
        load64(stackAddress(imm), GPRInfo::regT0);
277
        store64(GPRInfo::regT0, temporaryAddress(dst));
278
        break;
279
    default:
280
        RELEASE_ASSERT_NOT_REACHED();
281
    }
282
}
283
284
void JITCompiler::parseSetLocal(uint32_t imm, int dst)
285
{
286
    Type type = m_currentLocalTypes[imm];
287
    parseExpr(ReturnType(type), dst);
288
    switch (type) {
289
    case Type::I32:
290
    case Type::F32:
291
        load32(temporaryAddress(dst), GPRInfo::regT0);
292
        store32(GPRInfo::regT0, stackAddress(imm));
293
        break;
294
    case Type::F64:
295
        load64(temporaryAddress(dst), GPRInfo::regT0);
296
        store64(GPRInfo::regT0, stackAddress(imm));
297
        break;
298
    default:
299
        RELEASE_ASSERT_NOT_REACHED();
300
    }
301
}
302
303
void JITCompiler::parseSetLocal(int dst)
304
{
305
    parseSetLocal(m_module->m_reader.immU32(), dst);
306
}
307
308
static const void* JSC_HOST_CALL getArrayBufferData(ExecState*, Module* module)
309
{
310
    // FIXME: Do we really have to do this?
311
    // TODO: Use these two lines?
312
    // VM* vm = exec->vm();
313
    // NativeCallFrameTracer tracer(vm, exec);
314
    
315
    return module->arrayBufferData();
316
}
317
318
void JITCompiler::parseLoad(ReturnType returnType, bool hasOffset, int dst)
319
{
320
    // TODO: Check for out-of-bounds access.
321
    uint32_t offset = hasOffset ? m_module->m_reader.immU32() : 0;
322
    uint32_t u32;
323
    if (m_module->m_reader.ifI32Lit(m_module->m_constantI32s, &u32))
324
        store32(TrustedImm32(u32 + offset), temporaryAddress(dst));
325
    else {
326
        parseExpr(ReturnType::I32, dst);
327
        load32(temporaryAddress(dst), GPRInfo::regT0);
328
        if (offset)
329
            add32(TrustedImm32(offset), GPRInfo::regT0);
330
        store32(GPRInfo::regT0, temporaryAddress(dst));
331
    }
332
333
    if (maxFrameExtentForSlowPathCall)
334
        addPtr(TrustedImm32(-maxFrameExtentForSlowPathCall), stackPointerRegister);
335
    setupArgumentsWithExecState(TrustedImmPtr(m_module));
336
    move(TrustedImmPtr(bitwise_cast<void*>(getArrayBufferData)), GPRInfo::nonArgGPR0);
337
    call(GPRInfo::nonArgGPR0);
338
    if (maxFrameExtentForSlowPathCall)
339
        addPtr(TrustedImm32(maxFrameExtentForSlowPathCall), stackPointerRegister);
340
341
    load32(temporaryAddress(dst), GPRInfo::regT1);
342
    BaseIndex address = BaseIndex(GPRInfo::returnValueGPR, GPRInfo::regT1, TimesOne);
343
344
    switch (returnType) {
345
    case ReturnType::I32:
346
        load32(address, GPRInfo::regT0);
347
        store32(GPRInfo::regT0, temporaryAddress(dst));
348
        break;
349
    case ReturnType::F64:
350
        load64(address, GPRInfo::regT0);
351
        store64(GPRInfo::regT0, temporaryAddress(dst));
352
        break;
353
    default:
354
        RELEASE_ASSERT_NOT_REACHED();
355
    }
356
}
357
358
void JITCompiler::parseReturnStmt()
359
{
360
    switch (m_currentReturnType) {
361
    case ReturnType::I32:
362
        parseExpr(ReturnType::I32, 0);
363
        load32(temporaryAddress(0), GPRInfo::returnValueGPR);
364
        or64(GPRInfo::tagTypeNumberRegister, GPRInfo::returnValueGPR);
365
        break;
366
    case ReturnType::F32:
367
        parseExpr(ReturnType::F32, 0);
368
        loadDouble(temporaryAddress(0), FPRInfo::fpRegT0); // FIXME: This loads 64 bits!
369
        convertFloatToDouble(FPRInfo::fpRegT0, FPRInfo::fpRegT0);
370
        boxDouble(FPRInfo::fpRegT0, GPRInfo::returnValueGPR);
371
        break;
372
    case ReturnType::F64:
373
        parseExpr(ReturnType::F64, 0);
374
        loadDouble(temporaryAddress(0), FPRInfo::fpRegT0);
375
        boxDouble(FPRInfo::fpRegT0, GPRInfo::returnValueGPR);
376
        break;
377
    case ReturnType::Void:
378
        break;
379
    }
380
381
    deallocateSpaceOnStack();
382
    emitFunctionEpilogue();
383
    ret();
384
}
385
386
void JITCompiler::parseStmtList()
387
{
388
    uint32_t numberOfStmts = m_module->m_reader.immU32();
389
    for (uint32_t i = 0; i < numberOfStmts; ++i)
390
        parseStmt();
391
}
392
393
void JITCompiler::parseBlockStmt()
394
{
395
    parseStmtList();
396
}
397
398
void JITCompiler::parseIfStmt()
399
{
400
    parseExpr(ReturnType::I32, 0);
401
    load32(temporaryAddress(0), GPRInfo::regT0);
402
    Jump end = branchTest32(Zero, GPRInfo::regT0);
403
    parseStmt();
404
    end.link(this);
405
}
406
407
void JITCompiler::parseIfElseStmt()
408
{
409
    parseExpr(ReturnType::I32, 0);
410
    load32(temporaryAddress(0), GPRInfo::regT0);
411
    Jump els = branchTest32(Zero, GPRInfo::regT0);
412
    parseStmt();
413
    Jump end = jump();
414
    els.link(this);
415
    parseStmt();
416
    end.link(this);
417
}
418
419
void JITCompiler::parseWhileStmt()
420
{
421
    JumpScope continueJumpScope(this, label());
422
    pushContinueJumpScope(&continueJumpScope);
423
424
    JumpList breakJumpList;
425
    pushBreakJumpList(&breakJumpList);
426
427
    parseExpr(ReturnType::I32, 0);
428
    load32(temporaryAddress(0), GPRInfo::regT0);
429
    Jump end = branchTest32(Zero, GPRInfo::regT0);
430
    parseStmt();
431
    continueJumpScope.jump();
432
    end.link(this);
433
    breakJumpList.link(this);
434
435
    popBreakJumpList();
436
437
    popContinueJumpScope();
438
}
439
440
void JITCompiler::parseDoStmt()
441
{
442
    JumpScope continueJumpScope(this);
443
    pushContinueJumpScope(&continueJumpScope);
444
445
    JumpList breakJumpList;
446
    pushBreakJumpList(&breakJumpList);
447
448
    Label start = label();
449
    parseStmt();
450
    continueJumpScope.link();
451
    parseExpr(ReturnType::I32, 0);
452
    load32(temporaryAddress(0), GPRInfo::regT0);
453
    Jump jumpToStart = branchTest32(NonZero, GPRInfo::regT0);
454
    jumpToStart.linkTo(start, this);
455
    breakJumpList.link(this);
456
457
    popBreakJumpList();
458
459
    popContinueJumpScope();
460
}
461
462
void JITCompiler::parseLabelStmt()
463
{
464
    Label continueLabel = label();
465
    JumpList breakJumpList;
466
    pushContinueLabelLabel(&continueLabel);
467
    pushBreakLabelJumpList(&breakJumpList);
468
    parseStmt();
469
    breakJumpList.link(this);
470
    popBreakLabelJumpList();
471
    popContinueLabelLabel();
472
}
473
474
void JITCompiler::parseBreakStmt()
475
{
476
    topBreakJumpList()->append(jump());
477
}
478
479
void JITCompiler::parseBreakLabelStmt()
480
{
481
    uint32_t index = m_module->m_reader.immU32();
482
    breakLabelJumpList(index)->append(jump());
483
}
484
485
void JITCompiler::parseContinueStmt()
486
{
487
    topContinueJumpScope()->jump();
488
}
489
490
void JITCompiler::parseContinueLabelStmt()
491
{
492
    uint32_t index = m_module->m_reader.immU32();
493
    jump(*continueLabelLabel(index));
494
}
495
496
void JITCompiler::parseSwitchStmt()
497
{
498
    JumpList breakJumpList;
499
    pushBreakJumpList(&breakJumpList);
500
501
    uint32_t numberOfCases = m_module->m_reader.immU32();
502
    parseExpr(ReturnType::I32, 0);
503
    load32(temporaryAddress(0), GPRInfo::regT0);
504
505
    Jump table = jump();
506
507
    Vector<Label> labels;
508
    Vector<int32_t> imms;
509
    Label defaultLabel;
510
    bool hasDefault = false;
511
512
    for (uint32_t i = 0; i < numberOfCases; ++i) {
513
        switch (m_module->m_reader.switchCase()) {
514
        case SwitchCase::Case0:
515
            labels.append(label());
516
            imms.append(m_module->m_reader.immS32());
517
            break;
518
        case SwitchCase::Case1:
519
            labels.append(label());
520
            imms.append(m_module->m_reader.immS32());
521
            parseStmt();
522
            break;
523
        case SwitchCase::CaseN:
524
            labels.append(label());
525
            imms.append(m_module->m_reader.immS32());
526
            parseStmtList();
527
            break;
528
        case SwitchCase::Default0:
529
            defaultLabel = label();
530
            hasDefault = true;
531
            break;
532
        case SwitchCase::Default1:
533
            defaultLabel = label();
534
            hasDefault = true;
535
            parseStmt();
536
            break;
537
        case SwitchCase::DefaultN:
538
            defaultLabel = label();
539
            hasDefault = true;
540
            parseStmtList();
541
            break;
542
        default:
543
            RELEASE_ASSERT_NOT_REACHED();
544
        }
545
    }
546
547
    Jump end = jump();
548
    table.link(this);
549
550
    for (size_t i = 0; i < labels.size(); ++i) {
551
        Jump jmp = branch32(Equal, GPRInfo::regT0, TrustedImm32(imms[i]));
552
        jmp.linkTo(labels[i], this);
553
    }
554
    if (hasDefault)
555
        jump(defaultLabel);
556
557
    end.link(this);
558
559
    breakJumpList.link(this);
560
    popBreakJumpList();
561
}
562
563
void JITCompiler::parseExpr(ReturnType returnType, int dst)
564
{
565
    switch (returnType) {
566
    case ReturnType::I32:
567
        parseExprI32(dst);
568
        break;
569
    case ReturnType::F64:
570
        parseExprF64(dst);
571
        break;
572
    case ReturnType::Void:
573
        parseExprVoid(dst);
574
        break;
575
    default:
576
        RELEASE_ASSERT_NOT_REACHED();
577
    }
578
}
579
580
void JITCompiler::parseExprI32(int dst)
581
{
582
    I32 i32;
583
    I32WithImm i32WithImm;
584
    uint8_t imm;
585
586
    if (m_module->m_reader.code(&i32, &i32WithImm, &imm)) {
587
        switch (i32) {
588
        case I32::LitImm:
589
            store32(TrustedImm32(m_module->m_reader.immU32()), temporaryAddress(dst));
590
            break;
591
        case I32::LitPool:
592
        case I32::GetLoc:
593
            parseGetLocal(dst);
594
            break;
595
        case I32::GetGlo:
596
            RELEASE_ASSERT_NOT_REACHED();
597
        case I32::SetLoc:
598
            parseSetLocal(dst);
599
            break;
600
        case I32::SetGlo:
601
        case I32::SLoad8:
602
        case I32::SLoadOff8:
603
        case I32::ULoad8:
604
        case I32::ULoadOff8:
605
        case I32::SLoad16:
606
        case I32::SLoadOff16:
607
        case I32::ULoad16:
608
        case I32::ULoadOff16:
609
        case I32::Load32:
610
            parseLoad(ReturnType::I32, false, dst);
611
            break;
612
        case I32::LoadOff32:
613
            parseLoad(ReturnType::I32, true, dst);
614
            break;
615
        case I32::Store8:
616
        case I32::StoreOff8:
617
        case I32::Store16:
618
        case I32::StoreOff16:
619
        case I32::Store32:
620
        case I32::StoreOff32:
621
            RELEASE_ASSERT_NOT_REACHED();
622
        case I32::CallInt:
623
            parseCallInternal(ReturnType::I32, dst);
624
            break;
625
        case I32::CallInd:
626
            RELEASE_ASSERT_NOT_REACHED();
627
        case I32::CallImp:
628
            parseCallImport(ReturnType::I32, dst);
629
            break;
630
        case I32::Cond:
631
            parseCond(ReturnType::I32, dst);
632
            break;
633
        case I32::Comma:
634
            parseComma(ReturnType::I32, dst);
635
            break;
636
        case I32::FromF32:
637
            RELEASE_ASSERT_NOT_REACHED();
638
        case I32::FromF64:
639
            parseExprF64(dst);
640
            loadDouble(temporaryAddress(dst), FPRInfo::fpRegT0);
641
            truncateDoubleToInt32(FPRInfo::fpRegT0, GPRInfo::regT0);
642
            store32(GPRInfo::regT0, temporaryAddress(dst));
643
            break;
644
        case I32::Neg:
645
            parseUnaryOp(static_cast<uint8_t>(i32), ReturnType::I32, dst);
646
            break;
647
        case I32::Add:
648
        case I32::Sub:
649
        case I32::Mul:
650
        case I32::SDiv:
651
            parseBinaryOp(static_cast<uint8_t>(i32), ReturnType::I32, dst);
652
            break;
653
        case I32::UDiv:
654
            RELEASE_ASSERT_NOT_REACHED();
655
        case I32::SMod:
656
            parseBinaryOp(static_cast<uint8_t>(i32), ReturnType::I32, dst);
657
            break;
658
        case I32::UMod:
659
            RELEASE_ASSERT_NOT_REACHED();
660
        case I32::BitNot:
661
            parseUnaryOp(static_cast<uint8_t>(i32), ReturnType::I32, dst);
662
            break;
663
        case I32::BitOr:
664
        case I32::BitAnd:
665
        case I32::BitXor:
666
        case I32::Lsh:
667
        case I32::ArithRsh:
668
        case I32::LogicRsh:
669
            parseBinaryOp(static_cast<uint8_t>(i32), ReturnType::I32, dst);
670
            break;
671
        case I32::Clz:
672
            parseUnaryOp(static_cast<uint8_t>(i32), ReturnType::I32, dst);
673
            break;
674
        case I32::LogicNot:
675
            RELEASE_ASSERT_NOT_REACHED();
676
        case I32::EqI32:
677
            parseRelationalOpI32(Equal, dst);
678
            break;
679
        case I32::EqF32:
680
            RELEASE_ASSERT_NOT_REACHED();
681
        case I32::EqF64:
682
            parseRelationalOpF64(DoubleEqual, dst);
683
            break;
684
        case I32::NEqI32:
685
            parseRelationalOpI32(NotEqual, dst);
686
            break;
687
        case I32::NEqF32:
688
            RELEASE_ASSERT_NOT_REACHED();
689
        case I32::NEqF64:
690
            parseRelationalOpF64(DoubleNotEqual, dst);
691
            break;
692
        case I32::SLeThI32:
693
            parseRelationalOpI32(LessThan, dst);
694
            break;
695
        case I32::ULeThI32:
696
            parseRelationalOpI32(Below, dst);
697
            break;
698
        case I32::LeThF32:
699
            RELEASE_ASSERT_NOT_REACHED();
700
        case I32::LeThF64:
701
            parseRelationalOpF64(DoubleLessThan, dst);
702
            break;
703
        case I32::SLeEqI32:
704
            parseRelationalOpI32(LessThanOrEqual, dst);
705
            break;
706
        case I32::ULeEqI32:
707
            parseRelationalOpI32(BelowOrEqual, dst);
708
            break;
709
        case I32::LeEqF32:
710
            RELEASE_ASSERT_NOT_REACHED();
711
        case I32::LeEqF64:
712
            parseRelationalOpF64(DoubleLessThanOrEqual, dst);
713
            break;
714
        case I32::SGrThI32:
715
            parseRelationalOpI32(GreaterThan, dst);
716
            break;
717
        case I32::UGrThI32:
718
            parseRelationalOpI32(Above, dst);
719
            break;
720
        case I32::GrThF32:
721
            RELEASE_ASSERT_NOT_REACHED();
722
        case I32::GrThF64:
723
            parseRelationalOpF64(DoubleGreaterThan, dst);
724
            break;
725
        case I32::SGrEqI32:
726
            parseRelationalOpI32(GreaterThanOrEqual, dst);
727
            break;
728
        case I32::UGrEqI32:
729
            parseRelationalOpI32(AboveOrEqual, dst);
730
            break;
731
        case I32::GrEqF32:
732
            RELEASE_ASSERT_NOT_REACHED();
733
        case I32::GrEqF64:
734
            parseRelationalOpF64(DoubleGreaterThanOrEqual, dst);
735
            break;
736
        case I32::SMin:
737
        case I32::UMin:
738
        case I32::SMax:
739
        case I32::UMax:
740
        case I32::Abs:
741
        default:
742
            RELEASE_ASSERT_NOT_REACHED();
743
        }
744
    } else {
745
        switch (i32WithImm) {
746
        case I32WithImm::LitImm:
747
            store32(TrustedImm32(imm), temporaryAddress(dst));
748
            break;
749
        case I32WithImm::LitPool:
750
            store32(TrustedImm32(m_module->m_constantI32s[imm]), temporaryAddress(dst));
751
            break;
752
        case I32WithImm::GetLoc:
753
            load32(stackAddress(imm), GPRInfo::regT0);
754
            store32(GPRInfo::regT0, temporaryAddress(dst));
755
            break;
756
        default:
757
            RELEASE_ASSERT_NOT_REACHED();
758
        }
759
    }
760
}
761
762
void JITCompiler::parseExprF64(int dst)
763
{
764
    F64 f64;
765
    F64WithImm f64WithImm;
766
    uint8_t imm;
767
768
    if (m_module->m_reader.code(&f64, &f64WithImm, &imm)) {
769
        switch (f64) {
770
        case F64::LitImm:
771
            store64(TrustedImm64(reinterpretDoubleToInt64(m_module->m_reader.fixedWidth<double>())), temporaryAddress(dst));
772
            break;
773
        case F64::Load:
774
            parseLoad(ReturnType::F64, false, dst);
775
            break;
776
        case F64::LoadOff:
777
            parseLoad(ReturnType::F64, true, dst);
778
            break;
779
        case F64::Neg:
780
            parseUnaryOp(static_cast<uint8_t>(f64), ReturnType::F64, dst);
781
            break;
782
        case F64::Add:
783
        case F64::Sub:
784
        case F64::Mul:
785
        case F64::Div:
786
            parseBinaryOp(static_cast<uint8_t>(f64), ReturnType::F64, dst);
787
            break;
788
        case F64::Sqrt:
789
            parseUnaryOp(static_cast<uint8_t>(f64), ReturnType::F64, dst);
790
            break;
791
        case F64::CallInt:
792
            parseCallInternal(ReturnType::F64, dst);
793
            break;
794
        case F64::CallImp:
795
            parseCallImport(ReturnType::F64, dst);
796
            break;
797
        default:
798
            RELEASE_ASSERT_NOT_REACHED();
799
        }
800
    } else {
801
        switch (f64WithImm) {
802
        case F64WithImm::LitPool:
803
            store64(TrustedImm64(reinterpretDoubleToInt64(m_module->m_constantF64s[imm])), temporaryAddress(dst));
804
            break;
805
        case F64WithImm::GetLoc:
806
            // FIXME: loadDouble/storeDouble?
807
            load64(stackAddress(imm), GPRInfo::regT0);
808
            store64(GPRInfo::regT0, temporaryAddress(dst));
809
            break;
810
        default:
811
            RELEASE_ASSERT_NOT_REACHED();
812
        }
813
    }
814
}
815
816
void JITCompiler::parseExprVoid(int dst)
817
{
818
    switch (m_module->m_reader.voidExpr()) {
819
    case Void::CallInt:
820
        parseCallInternal(ReturnType::Void, dst);
821
        break;
822
    case Void::CallInd:
823
        RELEASE_ASSERT_NOT_REACHED();
824
    case Void::CallImp:
825
        parseCallImport(ReturnType::Void, dst);
826
        break;
827
    default:
828
        RELEASE_ASSERT_NOT_REACHED();
829
    }
830
}
831
832
static EncodedJSValue JSC_HOST_CALL getInternalFunction(ExecState*, Module* module, uint32_t functionIndex)
833
{
834
    // TODO: Use these two lines?
835
    // VM* vm = exec->vm();
836
    // NativeCallFrameTracer tracer(vm, exec);
837
838
    return JSValue::encode(module->internalFunction(functionIndex));
839
}
840
841
void JITCompiler::parseCallInternal(ReturnType returnType, int dst)
842
{
843
    uint32_t functionIndex = m_module->m_reader.immU32();
844
    const Signature& signature = m_module->m_signatures[m_module->m_funcSignatures[functionIndex]];
845
    const Vector<Type>& arguments = signature.arguments;
846
    size_t argumentCount = arguments.size();
847
    // FIXME: returnType is redundant with signature.returnType
848
849
    parseCallArguments(arguments, dst);
850
851
    store32(TrustedImm32(argumentCount + 1), Address(stackPointerRegister, JSStack::ArgumentCount * static_cast<int>(sizeof(Register)) + PayloadOffset - sizeof(CallerFrameAndPC)));
852
853
    if (maxFrameExtentForSlowPathCall)
854
        addPtr(TrustedImm32(-maxFrameExtentForSlowPathCall), stackPointerRegister);
855
    setupArgumentsWithExecState(TrustedImmPtr(m_module), TrustedImm32(functionIndex));
856
    move(TrustedImmPtr(bitwise_cast<void*>(getInternalFunction)), GPRInfo::nonArgGPR0);
857
    call(GPRInfo::nonArgGPR0);
858
    if (maxFrameExtentForSlowPathCall)
859
        addPtr(TrustedImm32(maxFrameExtentForSlowPathCall), stackPointerRegister);
860
861
    move(GPRInfo::returnValueGPR, GPRInfo::regT0); // regT0 holds callee.
862
    store64(GPRInfo::regT0, Address(stackPointerRegister, JSStack::Callee * static_cast<int>(sizeof(Register)) - sizeof(CallerFrameAndPC)));
863
864
    callFunctionSlowCase(returnType, dst);
865
}
866
867
static EncodedJSValue JSC_HOST_CALL getImportedFunction(ExecState* exec, Module* module, uint32_t funcImportIndex)
868
{
869
    // TODO: Use these two lines?
870
    // VM* vm = exec->vm();
871
    // NativeCallFrameTracer tracer(vm, exec);
872
873
    const String& functionImportName = module->functionImportName(funcImportIndex);
874
875
    JSGlobalObject* globalObject = exec->lexicalGlobalObject();
876
    Identifier identifier = Identifier::fromString(&exec->vm(), functionImportName);
877
    PropertySlot slot(globalObject);
878
879
    if (!globalObject->getPropertySlot(exec, identifier, slot)) {
880
        // TODO: Do something!
881
        fprintf(stderr, "Can't find a function named \"%s\".\n", functionImportName.utf8().data());
882
        abort();
883
    }
884
885
    JSValue value = slot.getValue(exec, identifier);
886
    if (!value.isFunction()) {
887
        fprintf(stderr, "\"%s\" is not a function.\n", functionImportName.utf8().data());
888
        abort();
889
    }
890
891
    return JSValue::encode(value);
892
}
893
894
void JITCompiler::parseCallImport(ReturnType returnType, int dst)
895
{
896
    uint32_t funcImportSignatureIndex = m_module->m_reader.immU32();
897
    const Module::FuncImportSignature& funcImportSignature = m_module->m_funcImportSignatures[funcImportSignatureIndex];
898
    const Signature& signature = m_module->m_signatures[funcImportSignature.signatureIndex];
899
    const Vector<Type>& arguments = signature.arguments;
900
    size_t argumentCount = arguments.size();
901
    // FIXME: returnType is redundant with signature.returnType
902
903
    parseCallArguments(arguments, dst);
904
905
    store32(TrustedImm32(argumentCount + 1), Address(stackPointerRegister, JSStack::ArgumentCount * static_cast<int>(sizeof(Register)) + PayloadOffset - sizeof(CallerFrameAndPC)));
906
907
    if (maxFrameExtentForSlowPathCall)
908
        addPtr(TrustedImm32(-maxFrameExtentForSlowPathCall), stackPointerRegister);
909
    setupArgumentsWithExecState(TrustedImmPtr(m_module), TrustedImm32(funcImportSignature.funcImportIndex));
910
    move(TrustedImmPtr(bitwise_cast<void*>(getImportedFunction)), GPRInfo::nonArgGPR0);
911
    call(GPRInfo::nonArgGPR0);
912
    if (maxFrameExtentForSlowPathCall)
913
        addPtr(TrustedImm32(maxFrameExtentForSlowPathCall), stackPointerRegister);
914
915
    move(GPRInfo::returnValueGPR, GPRInfo::regT0); // regT0 holds callee.
916
    store64(GPRInfo::regT0, Address(stackPointerRegister, JSStack::Callee * static_cast<int>(sizeof(Register)) - sizeof(CallerFrameAndPC)));
917
918
    callFunctionSlowCase(returnType, dst);
919
}
920
921
void JITCompiler::callFunctionSlowCase(ReturnType returnType, int dst)
922
{
923
    ThunkGenerator generator = linkThunkGeneratorFor(CodeForCall, RegisterPreservationNotRequired);
924
925
    move(TrustedImmPtr(nullptr), GPRInfo::regT2); // TODO: Use CallLinkInfo
926
927
    CodePtr ptr = m_vm->getCTIStub(generator).code();
928
929
    move(TrustedImmPtr(ptr.executableAddress()), GPRInfo::nonArgGPR0);
930
931
    call(GPRInfo::nonArgGPR0);
932
933
    addPtr(TrustedImm32(-m_stackHeight), GPRInfo::callFrameRegister, stackPointerRegister); // FIXME: hacky
934
935
    // FIXME: Can we really use returnValueGPR?
936
    switch (returnType) {
937
    case ReturnType::I32:
938
        store32(GPRInfo::returnValueGPR, temporaryAddress(dst));
939
        break;
940
    case ReturnType::F64:
941
        unboxDoubleWithoutAssertions(GPRInfo::returnValueGPR, FPRInfo::fpRegT0);
942
        storeDouble(FPRInfo::fpRegT0, temporaryAddress(dst));
943
        break;
944
    case ReturnType::Void:
945
        break; // TODO: Sure?
946
    default:
947
        ASSERT_NOT_REACHED();
948
    }
949
}
950
951
void JITCompiler::parseCallArguments(const Vector<Type>& arguments, int dst)
952
{
953
    size_t argumentCount = arguments.size();
954
    size_t offset = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), dst + argumentCount + m_currentLocalTypes.size()) - m_currentLocalTypes.size(); // FIXME: Better name
955
956
    for (size_t i = 0; i < argumentCount; ++i) {
957
        switch (arguments[i]) {
958
        case Type::I32:
959
            parseExpr(ReturnType::I32, offset);
960
            load32(temporaryAddress(offset), GPRInfo::regT0);
961
            or64(GPRInfo::tagTypeNumberRegister, GPRInfo::regT0);
962
            store64(GPRInfo::regT0, temporaryAddress(offset - i - 1));
963
            break;
964
        case Type::F64:
965
            parseExpr(ReturnType::F64, offset);
966
            loadDouble(temporaryAddress(offset), FPRInfo::fpRegT0);
967
            boxDouble(FPRInfo::fpRegT0, GPRInfo::regT0);
968
            store64(GPRInfo::regT0, temporaryAddress(offset - i - 1));
969
            break;
970
        default:
971
            ASSERT_NOT_REACHED();
972
        }
973
    }
974
975
    addPtr(TrustedImm32(-(offset + m_currentLocalTypes.size() + 3) * 8 - 8), GPRInfo::callFrameRegister, stackPointerRegister); // FIXME: hacky
976
}
977
978
void JITCompiler::parseUnaryOp(uint8_t op, ReturnType returnType, int dst)
979
{
980
    parseExpr(returnType, dst);
981
    switch (returnType) {
982
    case ReturnType::I32:
983
        load32(temporaryAddress(dst), GPRInfo::regT0);
984
        switch (static_cast<I32>(op)) {
985
        case I32::Neg:
986
            neg32(GPRInfo::regT0);
987
            break;
988
        case I32::BitNot:
989
            xor32(TrustedImm32(-1), GPRInfo::regT0);
990
            break;
991
        case I32::Clz:
992
            countLeadingZeros32(GPRInfo::regT0, GPRInfo::regT0);
993
            break;
994
        default:
995
            ASSERT_NOT_REACHED();
996
        }
997
        store32(GPRInfo::regT0, temporaryAddress(dst));
998
        break;
999
    case ReturnType::F64:
1000
        loadDouble(temporaryAddress(dst), FPRInfo::fpRegT0);
1001
        switch (static_cast<F64>(op)) {
1002
        case F64::Neg:
1003
            negateDouble(FPRInfo::fpRegT0, FPRInfo::fpRegT1);
1004
            break;
1005
        case F64::Sqrt:
1006
            sqrtDouble(FPRInfo::fpRegT0, FPRInfo::fpRegT1);
1007
            break;
1008
        default:
1009
            ASSERT_NOT_REACHED();
1010
        }
1011
        storeDouble(FPRInfo::fpRegT1, temporaryAddress(dst));
1012
        break;
1013
    default:
1014
        RELEASE_ASSERT_NOT_REACHED();
1015
    }
1016
}
1017
1018
void JITCompiler::parseBinaryOp(uint8_t op, ReturnType returnType, int dst)
1019
{
1020
    parseExpr(returnType, dst);
1021
    parseExpr(returnType, dst + 1);
1022
    switch (returnType) {
1023
    case ReturnType::I32:
1024
        load32(temporaryAddress(dst), GPRInfo::regT0);
1025
        load32(temporaryAddress(dst + 1), GPRInfo::regT1);
1026
        switch (static_cast<I32>(op)) {
1027
        case I32::Add:
1028
            add32(GPRInfo::regT1, GPRInfo::regT0);
1029
            break;
1030
        case I32::Sub:
1031
            sub32(GPRInfo::regT1, GPRInfo::regT0);
1032
            break;
1033
        case I32::Mul:
1034
            mul32(GPRInfo::regT1, GPRInfo::regT0);
1035
            break;
1036
        case I32::SDiv:
1037
            move(GPRInfo::regT1, GPRInfo::regT2);
1038
            m_assembler.cdq();
1039
            m_assembler.idivl_r(GPRInfo::regT2);
1040
            break;
1041
        case I32::SMod:
1042
            move(GPRInfo::regT1, GPRInfo::regT2);
1043
            m_assembler.cdq();
1044
            m_assembler.idivl_r(GPRInfo::regT2);
1045
            move(GPRInfo::regT1, GPRInfo::regT0);
1046
            break;
1047
        case I32::BitOr:
1048
            or32(GPRInfo::regT1, GPRInfo::regT0);
1049
            break;
1050
        case I32::BitAnd:
1051
            and32(GPRInfo::regT1, GPRInfo::regT0);
1052
            break;
1053
        case I32::BitXor:
1054
            xor32(GPRInfo::regT1, GPRInfo::regT0);
1055
            break;
1056
        case I32::Lsh:
1057
            lshift32(GPRInfo::regT1, GPRInfo::regT0);
1058
            break;
1059
        case I32::ArithRsh:
1060
            rshift32(GPRInfo::regT1, GPRInfo::regT0);
1061
            break;
1062
        case I32::LogicRsh:
1063
            urshift32(GPRInfo::regT1, GPRInfo::regT0);
1064
            break;
1065
        default:
1066
            ASSERT_NOT_REACHED();
1067
        }
1068
        store32(GPRInfo::regT0, temporaryAddress(dst));
1069
        break;
1070
    case ReturnType::F64:
1071
        loadDouble(temporaryAddress(dst), FPRInfo::fpRegT0);
1072
        loadDouble(temporaryAddress(dst + 1), FPRInfo::fpRegT1);
1073
        switch (static_cast<F64>(op)) {
1074
        case F64::Add:
1075
            addDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
1076
            break;
1077
        case F64::Sub:
1078
            subDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
1079
            break;
1080
        case F64::Mul:
1081
            mulDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
1082
            break;
1083
        case F64::Div:
1084
            divDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
1085
            break;
1086
        default:
1087
            ASSERT_NOT_REACHED();
1088
        }
1089
        storeDouble(FPRInfo::fpRegT0, temporaryAddress(dst));
1090
        break;
1091
    default:
1092
        RELEASE_ASSERT_NOT_REACHED();
1093
    }
1094
}
1095
1096
void JITCompiler::parseRelationalOpI32(RelationalCondition condition, int dst)
1097
{
1098
    parseExpr(ReturnType::I32, dst);
1099
    parseExpr(ReturnType::I32, dst + 1);
1100
    load32(temporaryAddress(dst), GPRInfo::regT0);
1101
    load32(temporaryAddress(dst + 1), GPRInfo::regT1);
1102
    compare32(condition, GPRInfo::regT0, GPRInfo::regT1, GPRInfo::regT0);
1103
    store32(GPRInfo::regT0, temporaryAddress(dst));
1104
}
1105
1106
void JITCompiler::parseRelationalOpF64(DoubleCondition condition, int dst)
1107
{
1108
    parseExpr(ReturnType::F64, dst);
1109
    parseExpr(ReturnType::F64, dst + 1);
1110
    loadDouble(temporaryAddress(dst), FPRInfo::fpRegT0);
1111
    loadDouble(temporaryAddress(dst + 1), FPRInfo::fpRegT1);
1112
    Jump trueCase = branchDouble(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT1);
1113
    store32(TrustedImm32(0), temporaryAddress(dst));
1114
    Jump end = jump();
1115
    trueCase.link(this);
1116
    store32(TrustedImm32(1), temporaryAddress(dst));
1117
    end.link(this);
1118
}
1119
1120
void JITCompiler::parseComma(ReturnType returnType, int dst)
1121
{
1122
    parseExpr(m_module->m_reader.returnType(), dst);
1123
    parseExpr(returnType, dst);
1124
}
1125
1126
void JITCompiler::parseCond(ReturnType returnType, int dst)
1127
{
1128
    parseExpr(ReturnType::I32, dst);
1129
    load32(temporaryAddress(dst), GPRInfo::regT0);
1130
    Jump els = branchTest32(Zero, GPRInfo::regT0);
1131
    parseExpr(returnType, dst);
1132
    Jump end = jump();
1133
    els.link(this);
1134
    parseExpr(returnType, dst);
1135
    end.link(this);
1136
}
1137
1138
} } // namespace JSC::Wasm
- a/Source/JavaScriptCore/wasm/WasmJITCompiler.h +148 lines
Line 0 a/Source/JavaScriptCore/wasm/WasmJITCompiler.h_sec1
1
/*
2
 * Copyright (C) 2015 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
/*
27
 Licensed under the Apache License, Version 2.0 (the "License");
28
 you may not use this file except in compliance with the License.
29
 You may obtain a copy of the License at
30
31
 http://www.apache.org/licenses/LICENSE-2.0
32
33
 Unless required by applicable law or agreed to in writing, software
34
 distributed under the License is distributed on an "AS IS" BASIS,
35
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
36
 See the License for the specific language governing permissions and
37
 limitations under the License.
38
*/
39
40
#ifndef WasmJITCompiler_h
41
#define WasmJITCompiler_h
42
43
#include "CCallHelpers.h"
44
#include "WasmModule.h"
45
46
namespace JSC {
47
48
class ExecState;
49
class JITCode;
50
class VM;
51
52
namespace Wasm {
53
54
class JumpScope;
55
56
class JITCompiler : private CCallHelpers {
57
public:
58
    JITCompiler(VM* vm, CodeBlock* codeBlock, Module* module)
59
        : CCallHelpers(vm, codeBlock)
60
        , m_module(module)
61
    {
62
    }
63
64
    RefPtr<JITCode> compileFunction(VM&, size_t functionIndex);
65
66
private:
67
    void allocateSpaceOnStack();
68
    void deallocateSpaceOnStack();
69
70
    void parseArguments(const Signature&);
71
    void parseVars();
72
73
    void parseStmt();
74
    void parseGetLocal(int dst);
75
    void parseSetLocal(uint32_t imm, int dst);
76
    void parseSetLocal(int dst);
77
    void parseLoad(ReturnType, bool hasOffset, int dst);
78
    void parseReturnStmt();
79
    void parseBlockStmt();
80
    void parseStmtList();
81
    void parseIfStmt();
82
    void parseIfElseStmt();
83
    void parseWhileStmt();
84
    void parseDoStmt();
85
    void parseLabelStmt();
86
    void parseBreakStmt();
87
    void parseBreakLabelStmt();
88
    void parseContinueStmt();
89
    void parseContinueLabelStmt();
90
    void parseSwitchStmt();
91
92
    void parseExpr(ReturnType, int dst);
93
    void parseExprI32(int dst);
94
    void parseExprF64(int dst);
95
    void parseExprVoid(int dst);
96
    void parseCallInternal(ReturnType, int dst);
97
    void parseCallImport(ReturnType, int dst);
98
    void callFunctionSlowCase(ReturnType, int dst);
99
    void parseCallArguments(const Vector<Type>& arguments, int dst);
100
    void parseUnaryOp(uint8_t op, ReturnType, int dst);
101
    void parseBinaryOp(uint8_t op, ReturnType, int dst);
102
    void parseRelationalOpI32(RelationalCondition, int dst);
103
    void parseRelationalOpF64(DoubleCondition, int dst);
104
    void parseComma(ReturnType, int dst);
105
    void parseCond(ReturnType, int dst);
106
107
    Address stackAddress(int i) const // FIXME: Is this correct?
108
    {
109
        return Address(GPRInfo::callFrameRegister, -i * 8 - 8);
110
    }
111
112
    Address temporaryAddress(int i) const // FIXME: Is this correct?
113
    {
114
        return Address(GPRInfo::callFrameRegister, -(i + m_currentLocalTypes.size()) * 8 - 8);
115
    }
116
117
    void pushContinueLabelLabel(Label* label) { m_continueLabelLabels.append(label); }
118
    void popContinueLabelLabel() { m_continueLabelLabels.removeLast(); }
119
    Label* continueLabelLabel(size_t i) const { return m_continueLabelLabels[i]; }
120
    void pushBreakLabelJumpList(JumpList* jumpList) { m_breakLabelJumpLists.append(jumpList); }
121
    void popBreakLabelJumpList() { m_breakLabelJumpLists.removeLast(); }
122
    JumpList* breakLabelJumpList(size_t i) const { return m_breakLabelJumpLists[i]; }
123
124
    void pushContinueJumpScope(JumpScope* jumpScope) { m_continueJumpScopes.append(jumpScope); }
125
    void popContinueJumpScope() { m_continueJumpScopes.removeLast(); }
126
    JumpScope* topContinueJumpScope() const { return m_continueJumpScopes.last(); }
127
128
    void pushBreakJumpList(JumpList* jumpList) { m_breakJumpLists.append(jumpList); }
129
    void popBreakJumpList() { m_breakJumpLists.removeLast(); }
130
    JumpList* topBreakJumpList() const { return m_breakJumpLists.last(); }
131
132
    Module* m_module;
133
134
    uint32_t m_stackHeight; // FIXME: This caused a 'segmentation fault' heisenbug when I added "size_t m_stackHeight". Something must be wrong.
135
136
    ReturnType m_currentReturnType;
137
    Vector<Type> m_currentLocalTypes;
138
139
    Vector<MacroAssembler::Label*> m_continueLabelLabels;
140
    Vector<MacroAssembler::JumpList*> m_breakLabelJumpLists;
141
142
    Vector<JumpScope*> m_continueJumpScopes;
143
    Vector<MacroAssembler::JumpList*> m_breakJumpLists;
144
};
145
146
} } // namespace JSC::Wasm
147
148
#endif // WasmJITCompiler_h
- a/Source/JavaScriptCore/wasm/WasmModule.cpp +336 lines
Line 0 a/Source/JavaScriptCore/wasm/WasmModule.cpp_sec1
1
/*
2
 * Copyright (C) 2015 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
/*
27
 Licensed under the Apache License, Version 2.0 (the "License");
28
 you may not use this file except in compliance with the License.
29
 You may obtain a copy of the License at
30
31
 http://www.apache.org/licenses/LICENSE-2.0
32
33
 Unless required by applicable law or agreed to in writing, software
34
 distributed under the License is distributed on an "AS IS" BASIS,
35
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
36
 See the License for the specific language governing permissions and
37
 limitations under the License.
38
*/
39
40
#include "config.h"
41
#include "WasmModule.h"
42
43
#include "JITCode.h"
44
#include "JSArrayBuffer.h"
45
#include "JSCellInlines.h"
46
#include "Reject.h"
47
#include "SlotVisitorInlines.h"
48
#include "WasmJITCompiler.h"
49
#include <wtf/text/StringBuilder.h>
50
51
namespace JSC {
52
53
namespace Wasm {
54
55
const ClassInfo Module::s_info = { "Module", &Base::s_info, 0, CREATE_METHOD_TABLE(Module) };
56
57
void Module::compile(ExecState* exec, const Vector<char>& buffer)
58
{
59
    m_reader = Reader(reinterpret_cast<const uint8_t*>(buffer.data()));
60
    if (m_reader.fixedWidth<uint32_t>() != MagicNumber)
61
        abort();
62
    m_reader.fixedWidth<uint32_t>(); // output size in asm.js format
63
64
    initializeArrayBuffer(exec);
65
66
    parseConstantPoolSection();
67
    parseSignatureSection();
68
    parseFunctionImportSection();
69
    parseGlobalSection();
70
    parseFunctionDeclarationSection();
71
    parseFunctionPointerTables();
72
    parseFunctionDefinitionSection(exec);
73
    parseExportSection(exec->vm());
74
}
75
76
void Module::initializeArrayBuffer(ExecState* exec)
77
{
78
    // TODO: Make this less hacky
79
    VM& vm = exec->vm();
80
    RefPtr<ArrayBuffer> arrayBuffer = ArrayBuffer::create(1024, 1);
81
    JSArrayBuffer* jsArrayBuffer = JSArrayBuffer::create(vm, exec->lexicalGlobalObject()->arrayBufferStructure(), arrayBuffer.release());
82
    m_arrayBuffer.set(vm, this, jsArrayBuffer);
83
}
84
85
void Module::parseConstantPoolSection()
86
{
87
    uint32_t numberOfI32s = m_reader.immU32();
88
    uint32_t numberOfF32s = m_reader.immU32();
89
    uint32_t numberOfF64s = m_reader.immU32();
90
91
    Vector<uint32_t> constantI32s(numberOfI32s);
92
    for (uint32_t i = 0; i < numberOfI32s; ++i)
93
        constantI32s[i] = m_reader.immU32();
94
95
    Vector<float> constantF32s(numberOfF32s);
96
    for (uint32_t i = 0; i < numberOfF32s; ++i)
97
        constantF32s[i] = m_reader.fixedWidth<float>();
98
99
    Vector<double> constantF64s(numberOfF64s);
100
    for (uint32_t i = 0; i < numberOfF64s; ++i)
101
        constantF64s[i] = m_reader.fixedWidth<double>();
102
103
    m_constantI32s = WTF::move(constantI32s);
104
    m_constantF32s = WTF::move(constantF32s);
105
    m_constantF64s = WTF::move(constantF64s);
106
}
107
108
void Module::parseSignatureSection()
109
{
110
    uint32_t numberOfSignatures = m_reader.immU32();
111
    Vector<Signature> signatures(numberOfSignatures);
112
    for (uint32_t signatureIndex = 0; signatureIndex < numberOfSignatures; ++signatureIndex) {
113
        ReturnType returnType = m_reader.returnType();
114
        uint32_t argumentCount = m_reader.immU32();
115
        Signature signature(returnType, argumentCount);
116
        for (uint32_t argumentIndex = 0; argumentIndex < argumentCount; ++argumentIndex)
117
            signature.arguments[argumentIndex] = m_reader.type();
118
        signatures[signatureIndex] = WTF::move(signature);
119
    }
120
121
    m_signatures = WTF::move(signatures);
122
}
123
124
void Module::parseFunctionImportSection()
125
{
126
    uint32_t numberOfFuncImports = m_reader.immU32();
127
    uint32_t numberOfFuncImportSignatures = m_reader.immU32();
128
129
    m_functionImportNames.reserveCapacity(numberOfFuncImports);
130
131
    Vector<FuncImportSignature> funcImportSignatures(numberOfFuncImportSignatures);
132
    FuncImportSignature* funcImportSignature = funcImportSignatures.data();
133
    for (uint32_t funcImportIndex = 0; funcImportIndex < numberOfFuncImports; ++funcImportIndex) {
134
        StringBuilder builder;
135
        while (char c = m_reader.singleChar())
136
            builder.append(c);
137
        m_functionImportNames.append(builder.toString());
138
139
        uint32_t numberOfSignatures = m_reader.immU32();
140
        for (uint32_t i = 0; i < numberOfSignatures; ++i) {
141
            funcImportSignature->signatureIndex = m_reader.immU32();
142
            funcImportSignature->funcImportIndex = funcImportIndex;
143
            funcImportSignature++;
144
        }
145
    }
146
    assert(funcImportSignature == funcImportSignatures.data() + numberOfFuncImportSignatures);
147
148
    m_funcImportSignatures = WTF::move(funcImportSignatures);
149
}
150
151
void Module::parseGlobalSection()
152
{
153
    uint32_t numberOfI32Zero = m_reader.immU32();
154
    uint32_t numberOfF32Zero = m_reader.immU32();
155
    uint32_t numberOfF64Zero = m_reader.immU32();
156
    uint32_t numberOfI32Import = m_reader.immU32();
157
    uint32_t numberOfF32Import = m_reader.immU32();
158
    uint32_t numberOfF64Import = m_reader.immU32();
159
    uint32_t numberOfGlobalVars = numberOfI32Zero + numberOfF32Zero + numberOfF64Zero + numberOfI32Import + numberOfF32Import + numberOfF64Import;
160
161
    Vector<Type> globalTypes(numberOfGlobalVars);
162
    size_t globalTypeIndex = 0;
163
    for (uint32_t i = 0; i < numberOfI32Zero; ++i)
164
        globalTypes[globalTypeIndex++] = Type::I32;
165
    for (uint32_t i = 0; i < numberOfF32Zero; ++i)
166
        globalTypes[globalTypeIndex++] = Type::F32;
167
    for (uint32_t i = 0; i < numberOfF64Zero; ++i)
168
        globalTypes[globalTypeIndex++] = Type::F64;
169
    for (uint32_t i = 0; i < numberOfI32Import; ++i) {
170
        while (m_reader.singleChar()) { }
171
        globalTypes[globalTypeIndex++] = Type::I32;
172
    }
173
    for (uint32_t i = 0; i < numberOfF32Import; ++i) {
174
        while (m_reader.singleChar()) { }
175
        globalTypes[globalTypeIndex++] = Type::F32;
176
    }
177
    for (uint32_t i = 0; i < numberOfF64Import; ++i) {
178
        while (m_reader.singleChar()) { }
179
        globalTypes[globalTypeIndex++] = Type::F64;
180
    }
181
    m_globalTypes = WTF::move(globalTypes);
182
}
183
184
void Module::parseFunctionDeclarationSection()
185
{
186
    uint32_t numberOfFunctions = m_reader.immU32();
187
    Vector<uint32_t> funcSignatures(numberOfFunctions);
188
    for (uint32_t i = 0; i < numberOfFunctions; ++i)
189
        funcSignatures[i] = m_reader.immU32();
190
191
    m_funcSignatures = WTF::move(funcSignatures);
192
}
193
194
void Module::parseFunctionPointerTables()
195
{
196
    uint32_t numberOfFuncPtrTables = m_reader.immU32();
197
    Vector<FuncPtrTable> funcPtrTables(numberOfFuncPtrTables);
198
    for (uint32_t i = 0; i < numberOfFuncPtrTables; ++i) {
199
        funcPtrTables[i].signatureIndex = m_reader.immU32();
200
        uint32_t numElements = m_reader.immU32();
201
        Vector<uint32_t> elements(numElements);
202
        for (uint32_t j = 0; j < numElements; ++j)
203
            elements[j] = m_reader.immU32();
204
        funcPtrTables[i].elements = WTF::move(elements);
205
    }
206
207
    m_funcPtrTables = WTF::move(funcPtrTables);
208
}
209
210
void Module::parseFunctionDefinitionSection(ExecState* exec)
211
{
212
    for (size_t i = 0; i < m_funcSignatures.size(); ++i)
213
        parseFunctionDefinition(exec, i);
214
}
215
216
void Module::parseExportSection(VM& vm)
217
{
218
    switch (m_reader.exportFormat()) {
219
    case ExportFormat::Default: {
220
        uint32_t functionIndex = m_reader.immU32();
221
        Identifier identifier = Identifier::fromString(&vm, "default"); // TODO: Use other names
222
        putDirect(vm, identifier, m_functions[functionIndex].get());
223
        break;
224
    }
225
    case ExportFormat::Record: {
226
        uint32_t numberOfExports = m_reader.immU32();
227
        for (uint32_t exportIndex = 0; exportIndex < numberOfExports; ++exportIndex) {
228
            StringBuilder builder;
229
            while (char c = m_reader.singleChar())
230
                builder.append(c);
231
            uint32_t functionIndex = m_reader.immU32();
232
            Identifier identifier = Identifier::fromString(&vm, builder.toString());
233
            putDirect(vm, identifier, m_functions[functionIndex].get());
234
        }
235
        break;
236
    }
237
    default:
238
        RELEASE_ASSERT_NOT_REACHED();
239
    }
240
}
241
242
void Module::parseFunctionDefinition(ExecState* exec, size_t functionIndex)
243
{
244
    VM& vm = exec->vm();
245
    JSGlobalObject* globalObject = exec->lexicalGlobalObject(); // FIXME: should it be 'this'?
246
247
    WebAssemblyExecutable* executable = WebAssemblyExecutable::create(vm, SourceCode());
248
    {
249
        DeferGC deferGC(vm.heap);
250
        RefPtr<WebAssemblyCodeBlock> codeBlock = adoptRef(new WebAssemblyCodeBlock(executable, globalObject));
251
        JITCompiler jitCompiler(&vm, codeBlock.get(), this);
252
        codeBlock->setJITCode(jitCompiler.compileFunction(vm, functionIndex));
253
        executable->installCode(codeBlock.get());
254
    }
255
256
    JSFunction* jsFunction = JSFunction::create(vm, executable, globalObject);
257
    m_functions.append(WriteBarrier<JSFunction>(vm, this, jsFunction));
258
}
259
260
JSFunction* Module::internalFunction(size_t functionIndex) const
261
{
262
    return m_functions[functionIndex].get();
263
}
264
265
const void* Module::arrayBufferData() const
266
{
267
    return m_arrayBuffer->impl()->data();
268
}
269
270
void Module::visitChildren(JSCell* cell, SlotVisitor& visitor)
271
{
272
    Module* thisObject = static_cast<Module*>(cell);
273
    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
274
    Base::visitChildren(thisObject, visitor);
275
    for (auto function : thisObject->m_functions)
276
        visitor.append(&function);
277
    visitor.append(&thisObject->m_arrayBuffer);
278
}
279
280
bool Module::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
281
{
282
    Module* thisObject = jsCast<Module*>(object);
283
    if (propertyName == exec->propertyNames().buffer) {
284
        slot.setValue(thisObject, DontDelete | ReadOnly, thisObject->m_arrayBuffer.get());
285
        return true;
286
    }
287
288
    return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
289
}
290
291
void Module::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
292
{
293
    Module* thisObject = jsCast<Module*>(cell);
294
    if (propertyName == exec->propertyNames().buffer) {
295
        reject(exec, slot.isStrictMode(), "Attempting to write to a read-only array buffer property.");
296
        return;
297
    }
298
299
    Base::put(thisObject, exec, propertyName, value, slot);
300
}
301
302
bool Module::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool shouldThrow)
303
{
304
    Module* thisObject = jsCast<Module*>(object);
305
    if (propertyName == exec->propertyNames().buffer)
306
        return reject(exec, shouldThrow, "Attempting to define read-only array buffer property.");
307
308
    return Base::defineOwnProperty(thisObject, exec, propertyName, descriptor, shouldThrow);
309
}
310
311
bool Module::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName)
312
{
313
    Module* thisObject = jsCast<Module*>(cell);
314
    if (propertyName == exec->propertyNames().buffer)
315
        return false;
316
    
317
    return Base::deleteProperty(thisObject, exec, propertyName);
318
}
319
320
void Module::getOwnNonIndexPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& array, EnumerationMode mode)
321
{
322
    Module* thisObject = jsCast<Module*>(object);
323
    if (mode.includeDontEnumProperties())
324
        array.add(exec->propertyNames().buffer);
325
    
326
    Base::getOwnNonIndexPropertyNames(thisObject, exec, array, mode);
327
}
328
329
Module* compile(ExecState* exec, const Vector<char>& buffer)
330
{
331
    Module* module = Module::create(exec->vm(), exec->lexicalGlobalObject());
332
    module->compile(exec, buffer);
333
    return module;
334
}
335
336
} } // namespace JSC::Wasm
- a/Source/JavaScriptCore/wasm/WasmModule.h +136 lines
Line 0 a/Source/JavaScriptCore/wasm/WasmModule.h_sec1
1
/*
2
 * Copyright (C) 2015 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
/*
27
 Licensed under the Apache License, Version 2.0 (the "License");
28
 you may not use this file except in compliance with the License.
29
 You may obtain a copy of the License at
30
31
 http://www.apache.org/licenses/LICENSE-2.0
32
33
 Unless required by applicable law or agreed to in writing, software
34
 distributed under the License is distributed on an "AS IS" BASIS,
35
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
36
 See the License for the specific language governing permissions and
37
 limitations under the License.
38
*/
39
40
#ifndef WasmModule_h
41
#define WasmModule_h
42
43
#include "JSGlobalObject.h"
44
#include "WasmOpcodes.h"
45
46
namespace JSC {
47
48
class JITCompiler;
49
50
namespace Wasm {
51
52
class Module : public JSGlobalObject {
53
public:
54
    typedef JSGlobalObject Base;
55
    static const unsigned StructureFlags = Base::StructureFlags | OverridesGetPropertyNames | OverridesGetOwnPropertySlot;
56
57
    static Module* create(VM& vm, JSGlobalObject* globalObject)
58
    {
59
        Structure* structure = createStructure(vm, globalObject); // FIXME: is this right?
60
        Module* module = new (NotNull, allocateCell<Module>(vm.heap)) Module(vm, structure);
61
        module->finishCreation(vm);
62
        return module;
63
    }
64
65
    DECLARE_INFO;
66
67
    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject)
68
    {
69
        return Structure::create(vm, globalObject, jsNull(), TypeInfo(GlobalObjectType, StructureFlags), info());
70
    }
71
72
    void compile(ExecState*, const Vector<char>& buffer);
73
    JSFunction* internalFunction(size_t functionIndex) const;
74
    const String& functionImportName(size_t functionImportIndex) const { return m_functionImportNames[functionImportIndex]; }
75
    const void* arrayBufferData() const;
76
77
    static void visitChildren(JSCell*, SlotVisitor&);
78
79
private:
80
    friend class JITCompiler;
81
82
    struct FuncImportSignature {
83
        uint32_t signatureIndex;
84
        uint32_t funcImportIndex;
85
    };
86
    
87
    struct FuncPtrTable {
88
        uint32_t signatureIndex;
89
        Vector<uint32_t> elements;
90
    };
91
92
    Module(VM& vm, Structure* structure)
93
        : Base(vm, structure)
94
    {
95
    }
96
97
    void initializeArrayBuffer(ExecState*);
98
99
    void parseConstantPoolSection();
100
    void parseSignatureSection();
101
    void parseFunctionImportSection();
102
    void parseGlobalSection();
103
    void parseFunctionDeclarationSection();
104
    void parseFunctionPointerTables();
105
    void parseFunctionDefinitionSection(ExecState*);
106
    void parseExportSection(VM&);
107
108
    void parseFunctionDefinition(ExecState*, size_t functionIndex);
109
110
    static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&);
111
    static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&);
112
    static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&, bool shouldThrow);
113
    static bool deleteProperty(JSCell*, ExecState*, PropertyName);
114
    static void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
115
116
    Reader m_reader;
117
118
    Vector<Signature> m_signatures;
119
    Vector<uint32_t> m_constantI32s;
120
    Vector<float> m_constantF32s;
121
    Vector<double> m_constantF64s;
122
    Vector<String> m_functionImportNames;
123
    Vector<FuncImportSignature> m_funcImportSignatures;
124
    Vector<Type> m_globalTypes;
125
    Vector<uint32_t> m_funcSignatures;
126
    Vector<FuncPtrTable> m_funcPtrTables;
127
128
    Vector<WriteBarrier<JSFunction>> m_functions;
129
    WriteBarrier<JSArrayBuffer> m_arrayBuffer;
130
};
131
132
JS_EXPORT_PRIVATE Module* compile(ExecState*, const Vector<char>& buffer);
133
134
} } // namespace JSC::Wasm
135
136
#endif // WasmModule_h
- a/Source/JavaScriptCore/wasm/WasmOpcodes.h +591 lines
Line 0 a/Source/JavaScriptCore/wasm/WasmOpcodes.h_sec1
1
/*
2
 * Copyright (C) 2015 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
/*
27
 Licensed under the Apache License, Version 2.0 (the "License");
28
 you may not use this file except in compliance with the License.
29
 You may obtain a copy of the License at
30
31
 http://www.apache.org/licenses/LICENSE-2.0
32
33
 Unless required by applicable law or agreed to in writing, software
34
 distributed under the License is distributed on an "AS IS" BASIS,
35
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
36
 See the License for the specific language governing permissions and
37
 limitations under the License.
38
*/
39
40
#ifndef WasmOpcodes_h
41
#define WasmOpcodes_h
42
43
#include <wtf/Vector.h>
44
45
namespace JSC {
46
47
namespace Wasm {
48
49
static const uint32_t MagicNumber = 0x6d736177;
50
51
enum class Stmt : uint8_t {
52
    SetLoc,
53
    SetGlo,
54
    I32Store8,
55
    I32StoreOff8,
56
    I32Store16,
57
    I32StoreOff16,
58
    I32Store32,
59
    I32StoreOff32,
60
    F32Store,
61
    F32StoreOff,
62
    F64Store,
63
    F64StoreOff,
64
    CallInt,
65
    CallInd,
66
    CallImp,
67
    Ret,
68
    Block,
69
    IfThen,
70
    IfElse,
71
    While,
72
    Do,
73
    Label,
74
    Break,
75
    BreakLabel,
76
    Continue,
77
    ContinueLabel,
78
    Switch,
79
80
    Bad
81
};
82
83
enum class StmtWithImm : uint8_t {
84
    SetLoc,
85
    SetGlo,
86
    Reseved1,
87
    Reseved2,
88
89
    Bad
90
};
91
92
enum class SwitchCase : uint8_t {
93
    Case0,
94
    Case1,
95
    CaseN,
96
    Default0,
97
    Default1,
98
    DefaultN
99
};
100
101
enum class I32 : uint8_t {
102
    LitPool,
103
    LitImm,
104
    GetLoc,
105
    GetGlo,
106
    SetLoc,
107
    SetGlo,
108
    SLoad8,
109
    SLoadOff8,
110
    ULoad8,
111
    ULoadOff8,
112
    SLoad16,
113
    SLoadOff16,
114
    ULoad16,
115
    ULoadOff16,
116
    Load32,
117
    LoadOff32,
118
    Store8,
119
    StoreOff8,
120
    Store16,
121
    StoreOff16,
122
    Store32,
123
    StoreOff32,
124
    CallInt,
125
    CallInd,
126
    CallImp,
127
    Cond,
128
    Comma,
129
    FromF32,
130
    FromF64,
131
    Neg,
132
    Add,
133
    Sub,
134
    Mul,
135
    SDiv,
136
    UDiv,
137
    SMod,
138
    UMod,
139
    BitNot,
140
    BitOr,
141
    BitAnd,
142
    BitXor,
143
    Lsh,
144
    ArithRsh,
145
    LogicRsh,
146
    Clz,
147
    LogicNot,
148
    EqI32,
149
    EqF32,
150
    EqF64,
151
    NEqI32,
152
    NEqF32,
153
    NEqF64,
154
    SLeThI32,
155
    ULeThI32,
156
    LeThF32,
157
    LeThF64,
158
    SLeEqI32,
159
    ULeEqI32,
160
    LeEqF32,
161
    LeEqF64,
162
    SGrThI32,
163
    UGrThI32,
164
    GrThF32,
165
    GrThF64,
166
    SGrEqI32,
167
    UGrEqI32,
168
    GrEqF32,
169
    GrEqF64,
170
    SMin,
171
    UMin,
172
    SMax,
173
    UMax,
174
    Abs,
175
176
    Bad
177
};
178
179
enum class I32WithImm : uint8_t {
180
    LitPool,
181
    LitImm,
182
    GetLoc,
183
    Reserved,
184
185
    Bad
186
};
187
188
enum class F32 : uint8_t {
189
    LitPool,
190
    LitImm,
191
    GetLoc,
192
    GetGlo,
193
    SetLoc,
194
    SetGlo,
195
    Load,
196
    LoadOff,
197
    Store,
198
    StoreOff,
199
    CallInt,
200
    CallInd,
201
    Cond,
202
    Comma,
203
    FromS32,
204
    FromU32,
205
    FromF64,
206
    Neg,
207
    Add,
208
    Sub,
209
    Mul,
210
    Div,
211
    Abs,
212
    Ceil,
213
    Floor,
214
    Sqrt,
215
216
    Bad
217
};
218
219
enum class F32WithImm : uint8_t {
220
    LitPool,
221
    GetLoc,
222
    Reserved0,
223
    Reserved1,
224
225
    Bad
226
};
227
228
enum class F64 : uint8_t {
229
    LitPool,
230
    LitImm,
231
    GetLoc,
232
    GetGlo,
233
    SetLoc,
234
    SetGlo,
235
    Load,
236
    LoadOff,
237
    Store,
238
    StoreOff,
239
    CallInt,
240
    CallInd,
241
    CallImp,
242
    Cond,
243
    Comma,
244
    FromS32,
245
    FromU32,
246
    FromF32,
247
    Neg,
248
    Add,
249
    Sub,
250
    Mul,
251
    Div,
252
    Mod,
253
    Min,
254
    Max,
255
    Abs,
256
    Ceil,
257
    Floor,
258
    Sqrt,
259
    Cos,
260
    Sin,
261
    Tan,
262
    ACos,
263
    ASin,
264
    ATan,
265
    ATan2,
266
    Exp,
267
    Ln,
268
    Pow,
269
270
    Bad
271
};
272
273
enum class F64WithImm : uint8_t {
274
    LitPool,
275
    GetLoc,
276
    Reserved0,
277
    Reserved1,
278
279
    Bad
280
};
281
282
enum class Void : uint8_t {
283
    CallInt,
284
    CallInd,
285
    CallImp,
286
287
    Bad
288
};
289
290
enum class Type : uint8_t {
291
    I32,
292
    F32,
293
    F64
294
};
295
296
enum class VarTypes : uint8_t {
297
    I32 = 0x1,
298
    F32 = 0x2,
299
    F64 = 0x4,
300
};
301
302
inline VarTypes operator| (VarTypes lhs, VarTypes rhs) { return VarTypes(uint8_t(lhs) | uint8_t(rhs)); }
303
inline bool operator&(VarTypes lhs, VarTypes rhs) { return bool(uint8_t(lhs) & uint8_t(rhs)); }
304
305
enum class VarTypesWithImm : uint8_t {
306
    OnlyI32,
307
    Reserved0,
308
    Reserved1,
309
    Reserved2
310
};
311
312
enum class ReturnType : uint8_t {
313
    I32 = uint8_t(Type::I32),
314
    F32 = uint8_t(Type::F32),
315
    F64 = uint8_t(Type::F64),
316
    Void
317
};
318
319
class Expr {
320
public:
321
    Expr()
322
    : m_type(ReturnType(-1)), u { }
323
    {
324
    }
325
    Expr(I32 i32) : m_type(ReturnType::I32) { u.i32 = i32; }
326
    Expr(F32 f32) : m_type(ReturnType::F32) { u.f32 = f32; }
327
    Expr(F64 f64) : m_type(ReturnType::F64) { u.f64 = f64; }
328
    Expr(Void v) : m_type(ReturnType::Void) { u.v = v; }
329
330
    ReturnType type() const { return m_type; }
331
    I32 i32() const { return u.i32; }
332
    F32 f32() const { return u.f32; }
333
    F64 f64() const { return u.f64; }
334
335
    bool operator==(Expr rhs) const { return m_type == rhs.m_type && u.raw == rhs.u.raw; }
336
    bool operator!=(Expr rhs) const { return !(*this == rhs); }
337
338
private:
339
    ReturnType m_type;
340
    union U {
341
        I32 i32;
342
        F32 f32;
343
        F64 f64;
344
        Void v;
345
        uint8_t raw;
346
    } u;
347
348
    static_assert(sizeof(U) == sizeof(uint8_t), "Exact overlay of raw_");
349
};
350
351
static const uint8_t HasImmFlag = 0x80;
352
static_assert(uint8_t(I32::Bad) <= HasImmFlag, "MSB reserved to distinguish I32 from I32WithImm");
353
static_assert(uint8_t(F32::Bad) <= HasImmFlag, "MSB reserved to distinguish F32 from F32WithImm");
354
static_assert(uint8_t(F64::Bad) <= HasImmFlag, "MSB reserved to distinguish F64 from F64WithImm");
355
356
static const unsigned OpWithImmBits = 2;
357
static const uint32_t OpWithImmLimit = 1 << OpWithImmBits;
358
static_assert(uint8_t(I32WithImm::Bad) <= OpWithImmLimit, "I32WithImm op fits");
359
static_assert(uint8_t(F32WithImm::Bad) <= OpWithImmLimit, "F32WithImm op fits");
360
static_assert(uint8_t(F64WithImm::Bad) <= OpWithImmLimit, "F64WithImm op fits");
361
362
static const unsigned ImmBits = 5;
363
static const uint32_t ImmLimit = 1 << ImmBits;
364
static_assert((1 + OpWithImmBits + ImmBits) == 8, "Bits of immediate op should add up to a byte");
365
366
static inline uint8_t PackOpWithImm(uint8_t op, uint8_t imm)
367
{
368
    assert(op < OpWithImmLimit);
369
    assert(imm < ImmLimit);
370
    return HasImmFlag | (uint8_t(op) << ImmBits) | imm;
371
}
372
373
template <class TWithImm>
374
static inline void UnpackOpWithImm(uint8_t byte, TWithImm* op, uint8_t *imm)
375
{
376
    assert(byte & HasImmFlag);
377
    *op = TWithImm((byte >> ImmBits) & (OpWithImmLimit - 1));
378
    *imm = byte & (ImmLimit - 1);
379
}
380
381
class ExprWithImm {
382
public:
383
    ExprWithImm()
384
        : m_type(Type(-1))
385
    {
386
    }
387
    ExprWithImm(I32WithImm i32) : m_type(Type::I32) { u.i32 = i32; }
388
    ExprWithImm(F32WithImm f32) : m_type(Type::F32) { u.f32 = f32; }
389
    ExprWithImm(F64WithImm f64) : m_type(Type::F64) { u.f64 = f64; }
390
391
    Type type() const { return m_type; }
392
    I32WithImm i32() const { return u.i32; }
393
    F32WithImm f32() const { return u.f32; }
394
    F64WithImm f64() const { return u.f64; }
395
396
private:
397
    Type m_type;
398
    union U {
399
        I32WithImm i32;
400
        F32WithImm f32;
401
        F64WithImm f64;
402
        uint8_t raw;
403
    } u;
404
405
    static_assert(sizeof(U) == sizeof(uint8_t), "Exact overlay of raw_");
406
};
407
408
enum class ExportFormat : uint8_t {
409
    Default,
410
    Record
411
};
412
413
struct Signature {
414
    ReturnType returnType;
415
    Vector<Type> arguments;
416
417
    Signature() { }
418
    Signature(ReturnType returnType)
419
        : returnType(returnType) { }
420
    Signature(ReturnType returnType, uint32_t argumentCount)
421
        : returnType(returnType)
422
        , arguments(argumentCount) { }
423
    Signature(ReturnType returnType, Vector<Type>&& arguments)
424
        : returnType(returnType)
425
        , arguments(WTF::move(arguments)) { }
426
427
    bool operator==(const Signature& rhs) const { return returnType == rhs.returnType && arguments == rhs.arguments; }
428
    bool operator!=(const Signature& rhs) const { return !(*this == rhs); }
429
430
    struct Hash {
431
        bool operator()(const Signature &signature) const
432
        {
433
            static_assert(sizeof(Type) == 1 && sizeof(ReturnType) == 1, "Shift more");
434
            uint32_t h = uint8_t(signature.returnType);
435
            for (Type t : signature.arguments)
436
                h = ((h << 2) | uint8_t(t)) ^ (h >> 30);
437
            return h;
438
        }
439
    };
440
};
441
442
class Reader {
443
public:
444
    Reader() { }
445
    Reader(const uint8_t* begin)
446
        : m_cursor(begin)
447
    {
448
    }
449
450
    template <class T> T fixedWidth();
451
    Stmt stmt() { return u8<Stmt>(); }
452
    SwitchCase switchCase() { return u8<SwitchCase>(); }
453
    template<class T, class TWithImm> inline bool code(T*, TWithImm*, uint8_t*);
454
    Void voidExpr() { return u8<Void>(); }
455
    ExportFormat exportFormat() { return u8<ExportFormat>(); }
456
    Type type() { return u8<Type>(); }
457
    ReturnType returnType() { return u8<ReturnType>(); }
458
    inline uint32_t immU32();
459
    inline int32_t immS32();
460
    char singleChar() { return *m_cursor++; }
461
462
    inline bool ifI32Lit(const Vector<uint32_t>& i32s, uint32_t*);
463
464
private:
465
    template <class T> T u8() { return T(*m_cursor++); }
466
467
    const uint8_t* m_cursor;
468
};
469
470
template <>
471
inline uint32_t Reader::fixedWidth<uint32_t>()
472
{
473
    uint32_t u32 = m_cursor[0] | m_cursor[1] << 8 | m_cursor[2] << 16 | m_cursor[3] << 24;
474
    m_cursor += 4;
475
    return u32;
476
}
477
478
template <>
479
inline float Reader::fixedWidth<float>()
480
{
481
    union {
482
        uint8_t arr[4];
483
        float f;
484
    } u = { { m_cursor[0], m_cursor[1], m_cursor[2], m_cursor[3] } };
485
    m_cursor += 4;
486
    return u.f;
487
}
488
489
template <>
490
inline double Reader::fixedWidth<double>()
491
{
492
    union {
493
        uint8_t arr[8];
494
        double d;
495
    } u = { { m_cursor[0], m_cursor[1], m_cursor[2], m_cursor[3], m_cursor[4], m_cursor[5], m_cursor[6], m_cursor[7] } };
496
    m_cursor += 8;
497
    return u.d;
498
}
499
500
template <class T, class TWithImm>
501
bool Reader::code(T* t, TWithImm* tWithImm, uint8_t* imm)
502
{
503
    uint8_t byte = *m_cursor++;
504
    if (!(byte & HasImmFlag)) {
505
        *t = T(byte);
506
        return true;
507
    }
508
509
    UnpackOpWithImm(byte, tWithImm, imm);
510
    return false;
511
}
512
513
inline uint32_t Reader::immU32()
514
{
515
    uint32_t u32 = *m_cursor++;
516
    if (u32 < 0x80)
517
        return u32;
518
519
    u32 &= 0x7f;
520
521
    for (unsigned shift = 7; true; shift += 7) {
522
        uint32_t b = *m_cursor++;
523
        if (b < 0x80)
524
            return u32 | (b << shift);
525
        u32 |= (b & 0x7f) << shift;
526
    }
527
}
528
529
inline int32_t Reader::immS32()
530
{
531
    uint32_t u32 = *m_cursor++;
532
    if (u32 < 0x80)
533
        return int32_t(u32) << (32-7) >> (32-7);
534
535
    u32 &= 0x7f;
536
537
    for (unsigned shift = 7; true; shift += 7) {
538
        uint32_t b = *m_cursor++;
539
        if (b < 0x80) {
540
            u32 |= b << shift;
541
            int signExtend = (32-7) - shift;
542
            if (signExtend > 0)
543
                return int32_t(u32) << signExtend >> signExtend;
544
            return int32_t(u32);
545
        }
546
        u32 |= (b & 0x7f) << shift;
547
    }
548
}
549
550
inline bool Reader::ifI32Lit(const Vector<uint32_t>& i32s, uint32_t* u32)
551
{
552
    uint8_t byte = *m_cursor;
553
554
    if (byte & HasImmFlag) {
555
        I32WithImm i32WithImm;
556
        uint8_t imm;
557
        UnpackOpWithImm(byte, &i32WithImm, &imm);
558
559
        if (i32WithImm == I32WithImm::LitImm) {
560
            m_cursor++;
561
            *u32 = imm;
562
            return true;
563
        }
564
565
        if (i32WithImm == I32WithImm::LitPool) {
566
            m_cursor++;
567
            *u32 = i32s[imm];
568
            return true;
569
        }
570
571
        return false;
572
    }
573
574
    if (I32(byte) == I32::LitImm) {
575
        m_cursor++;
576
        *u32 = immU32();
577
        return true;
578
    }
579
580
    if (I32(byte) == I32::LitPool) {
581
        m_cursor++;
582
        *u32 = i32s[immU32()];
583
        return true;
584
    }
585
586
    return false;
587
}
588
589
} } // namespace JSC::Wasm
590
591
#endif // WasmOpcodes_h

Return to Bug 146064