| Differences between
and this patch
- a/Source/JavaScriptCore/ChangeLog +174 lines
Lines 1-3 a/Source/JavaScriptCore/ChangeLog_sec1
1
2015-07-14  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::inferredName):
11
        (JSC::CodeBlock::CodeBlock):
12
        (JSC::WebAssemblyCodeBlock::replacement):
13
        (JSC::WebAssemblyCodeBlock::capabilityLevelInternal):
14
        * bytecode/CodeBlock.h:
15
        (JSC::CodeBlock::codeType):
16
        (JSC::WebAssemblyCodeBlock::WebAssemblyCodeBlock):
17
        * jit/JITOperations.cpp:
18
        * jsc.cpp:
19
        (GlobalObject::finishCreation):
20
        (functionLoadWebAssembly):
21
        * llint/LLIntSlowPaths.cpp:
22
        (JSC::LLInt::setUpCall):
23
        * runtime/Executable.cpp:
24
        (JSC::ScriptExecutable::installCode):
25
        (JSC::ScriptExecutable::newCodeBlockFor):
26
        (JSC::ScriptExecutable::prepareForExecutionImpl):
27
        (JSC::WebAssemblyExecutable::WebAssemblyExecutable):
28
        (JSC::WebAssemblyExecutable::finishCreation):
29
        (JSC::WebAssemblyExecutable::destroy):
30
        (JSC::WebAssemblyExecutable::baselineCodeBlockFor):
31
        (JSC::WebAssemblyExecutable::visitChildren):
32
        (JSC::WebAssemblyExecutable::symbolTable):
33
        (JSC::WebAssemblyExecutable::clearCode):
34
        (JSC::WebAssemblyExecutable::unlinkCalls):
35
        * runtime/Executable.h:
36
        (JSC::ExecutableBase::isWebAssemblyExecutable):
37
        (JSC::ExecutableBase::clearCodeVirtual):
38
        * runtime/JSFunction.cpp:
39
        (JSC::JSFunction::create):
40
        * runtime/JSFunction.h:
41
        (JSC::JSFunction::createImpl):
42
        * runtime/JSFunctionInlines.h:
43
        (JSC::JSFunction::JSFunction):
44
        (JSC::JSFunction::isHostFunction):
45
        * runtime/JSType.h:
46
        * runtime/VM.cpp:
47
        (JSC::VM::VM):
48
        * runtime/VM.h:
49
        * wasm/WasmJITCompiler.cpp: Added.
50
        (JSC::Wasm::JumpScope::JumpScope):
51
        (JSC::Wasm::JumpScope::jump):
52
        (JSC::Wasm::JumpScope::link):
53
        (JSC::Wasm::JITCompiler::compileFunction):
54
        (JSC::Wasm::JITCompiler::allocateSpaceOnStack):
55
        (JSC::Wasm::JITCompiler::deallocateSpaceOnStack):
56
        (JSC::Wasm::JITCompiler::parseArguments):
57
        (JSC::Wasm::JITCompiler::parseVars):
58
        (JSC::Wasm::JITCompiler::parseStmt):
59
        (JSC::Wasm::JITCompiler::parseGetLocal):
60
        (JSC::Wasm::JITCompiler::parseSetLocal):
61
        (JSC::Wasm::getArrayBufferData):
62
        (JSC::Wasm::JITCompiler::parseArrayBufferOffset):
63
        (JSC::Wasm::JITCompiler::parseLoad):
64
        (JSC::Wasm::JITCompiler::parseStore):
65
        (JSC::Wasm::JITCompiler::parseReturnStmt):
66
        (JSC::Wasm::JITCompiler::parseStmtList):
67
        (JSC::Wasm::JITCompiler::parseBlockStmt):
68
        (JSC::Wasm::JITCompiler::parseIfStmt):
69
        (JSC::Wasm::JITCompiler::parseIfElseStmt):
70
        (JSC::Wasm::JITCompiler::parseWhileStmt):
71
        (JSC::Wasm::JITCompiler::parseDoStmt):
72
        (JSC::Wasm::JITCompiler::parseLabelStmt):
73
        (JSC::Wasm::JITCompiler::parseBreakStmt):
74
        (JSC::Wasm::JITCompiler::parseBreakLabelStmt):
75
        (JSC::Wasm::JITCompiler::parseContinueStmt):
76
        (JSC::Wasm::JITCompiler::parseContinueLabelStmt):
77
        (JSC::Wasm::JITCompiler::parseSwitchStmt):
78
        (JSC::Wasm::JITCompiler::parseExpr):
79
        (JSC::Wasm::JITCompiler::parseExprI32):
80
        (JSC::Wasm::JITCompiler::parseExprF64):
81
        (JSC::Wasm::JITCompiler::parseExprVoid):
82
        (JSC::Wasm::getInternalFunction):
83
        (JSC::Wasm::JITCompiler::parseCallInternal):
84
        (JSC::Wasm::getImportedFunction):
85
        (JSC::Wasm::JITCompiler::parseCallImport):
86
        (JSC::Wasm::JITCompiler::callFunctionSlowCase):
87
        (JSC::Wasm::JITCompiler::parseCallArguments):
88
        (JSC::Wasm::JITCompiler::callDoubleFunction):
89
        (JSC::Wasm::JITCompiler::parseUnaryOp):
90
        (JSC::Wasm::JITCompiler::parseBinaryOp):
91
        (JSC::Wasm::JITCompiler::parseRelationalOpI32):
92
        (JSC::Wasm::JITCompiler::parseRelationalOpF64):
93
        (JSC::Wasm::JITCompiler::parseComma):
94
        (JSC::Wasm::JITCompiler::parseCond):
95
        (JSC::Wasm::JITCompiler::parseMinMaxI32):
96
        * wasm/WasmJITCompiler.h: Added.
97
        (JSC::Wasm::JITCompiler::JITCompiler):
98
        (JSC::Wasm::JITCompiler::stackAddress):
99
        (JSC::Wasm::JITCompiler::temporaryAddress):
100
        (JSC::Wasm::JITCompiler::pushContinueLabelLabel):
101
        (JSC::Wasm::JITCompiler::popContinueLabelLabel):
102
        (JSC::Wasm::JITCompiler::continueLabelLabel):
103
        (JSC::Wasm::JITCompiler::pushBreakLabelJumpList):
104
        (JSC::Wasm::JITCompiler::popBreakLabelJumpList):
105
        (JSC::Wasm::JITCompiler::breakLabelJumpList):
106
        (JSC::Wasm::JITCompiler::pushContinueJumpScope):
107
        (JSC::Wasm::JITCompiler::popContinueJumpScope):
108
        (JSC::Wasm::JITCompiler::topContinueJumpScope):
109
        (JSC::Wasm::JITCompiler::pushBreakJumpList):
110
        (JSC::Wasm::JITCompiler::popBreakJumpList):
111
        (JSC::Wasm::JITCompiler::topBreakJumpList):
112
        * wasm/WasmModule.cpp: Added.
113
        (JSC::Wasm::Module::finishCreation):
114
        (JSC::Wasm::Module::parseConstantPoolSection):
115
        (JSC::Wasm::Module::parseSignatureSection):
116
        (JSC::Wasm::Module::parseFunctionImportSection):
117
        (JSC::Wasm::Module::parseGlobalSection):
118
        (JSC::Wasm::Module::parseFunctionDeclarationSection):
119
        (JSC::Wasm::Module::parseFunctionPointerTables):
120
        (JSC::Wasm::Module::parseFunctionDefinitionSection):
121
        (JSC::Wasm::Module::parseExportSection):
122
        (JSC::Wasm::Module::parseFunctionDefinition):
123
        (JSC::Wasm::Module::function):
124
        (JSC::Wasm::Module::arrayBufferData):
125
        (JSC::Wasm::Module::visitChildren):
126
        (JSC::Wasm::Module::getOwnPropertySlot):
127
        (JSC::Wasm::Module::put):
128
        (JSC::Wasm::Module::defineOwnProperty):
129
        (JSC::Wasm::Module::deleteProperty):
130
        (JSC::Wasm::Module::getOwnNonIndexPropertyNames):
131
        (JSC::Wasm::compile):
132
        * wasm/WasmModule.h: Added.
133
        (JSC::Wasm::Module::create):
134
        (JSC::Wasm::Module::createStructure):
135
        (JSC::Wasm::Module::functionImportName):
136
        (JSC::Wasm::Module::Module):
137
        * wasm/WasmOpcodes.h: Added.
138
        (JSC::Wasm::operator| ):
139
        (JSC::Wasm::operator&):
140
        (JSC::Wasm::Expr::Expr):
141
        (JSC::Wasm::Expr::type):
142
        (JSC::Wasm::Expr::i32):
143
        (JSC::Wasm::Expr::f32):
144
        (JSC::Wasm::Expr::f64):
145
        (JSC::Wasm::Expr::operator==):
146
        (JSC::Wasm::Expr::operator!=):
147
        (JSC::Wasm::PackOpWithImm):
148
        (JSC::Wasm::UnpackOpWithImm):
149
        (JSC::Wasm::ExprWithImm::ExprWithImm):
150
        (JSC::Wasm::ExprWithImm::type):
151
        (JSC::Wasm::ExprWithImm::i32):
152
        (JSC::Wasm::ExprWithImm::f32):
153
        (JSC::Wasm::ExprWithImm::f64):
154
        (JSC::Wasm::Signature::Signature):
155
        (JSC::Wasm::Signature::operator==):
156
        (JSC::Wasm::Signature::operator!=):
157
        (JSC::Wasm::Signature::Hash::operator()):
158
        (JSC::Wasm::Reader::Reader):
159
        (JSC::Wasm::Reader::stmt):
160
        (JSC::Wasm::Reader::switchCase):
161
        (JSC::Wasm::Reader::voidExpr):
162
        (JSC::Wasm::Reader::exportFormat):
163
        (JSC::Wasm::Reader::type):
164
        (JSC::Wasm::Reader::returnType):
165
        (JSC::Wasm::Reader::singleChar):
166
        (JSC::Wasm::Reader::u8):
167
        (JSC::Wasm::Reader::fixedWidth<uint32_t>):
168
        (JSC::Wasm::Reader::fixedWidth<float>):
169
        (JSC::Wasm::Reader::fixedWidth<double>):
170
        (JSC::Wasm::Reader::code):
171
        (JSC::Wasm::Reader::immU32):
172
        (JSC::Wasm::Reader::immS32):
173
        (JSC::Wasm::Reader::ifI32Lit):
174
1
2015-07-08  Joseph Pecoraro  <pecoraro@apple.com>
175
2015-07-08  Joseph Pecoraro  <pecoraro@apple.com>
2
176
3
        Fix grammar issue in TypeError attempting to change an unconfigurable property
177
        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 +1395 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
enum class LinearMemoryType : unsigned {
90
    I8,
91
    S8,
92
    U8,
93
    I16,
94
    S16,
95
    U16,
96
    I32,
97
    F32,
98
    F64
99
};
100
101
RefPtr<JITCode> JITCompiler::compileFunction(VM& vm, size_t functionIndex)
102
{
103
    emitFunctionPrologue();
104
    emitPutImmediateToCallFrameHeader(m_codeBlock, JSStack::CodeBlock);
105
106
    const Signature& signature = m_module->m_signatures[m_module->m_funcSignatures[functionIndex]];
107
    m_currentReturnType = signature.returnType;
108
    parseArguments(signature);
109
110
    // FIXME: Calculate the actual height. (Be careful about calls.)
111
    m_stackHeight = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), signature.arguments.size() + 8) * sizeof(Register);
112
    allocateSpaceOnStack();
113
114
    parseVars();
115
    parseStmtList();
116
117
    // FIXME: Skip these if the last statement is a return statement.
118
    move(TrustedImm64(JSValue::encode(jsUndefined())), GPRInfo::regT0); // FIXME: Should we return undefined?
119
    deallocateSpaceOnStack();
120
    emitFunctionEpilogue();
121
    ret();
122
123
    LinkBuffer patchBuffer(vm, *this, 0, JITCompilationMustSucceed);
124
    MacroAssemblerCodePtr withArityCheck;
125
    CodeRef result = FINALIZE_CODE(patchBuffer, ("Baseline JIT code for WebAssembly"));
126
    return adoptRef(new DirectJITCode(result, withArityCheck, JITCode::BaselineJIT));
127
}
128
129
void JITCompiler::allocateSpaceOnStack()
130
{
131
    addPtr(TrustedImm32(-m_stackHeight), stackPointerRegister);
132
}
133
134
void JITCompiler::deallocateSpaceOnStack()
135
{
136
    addPtr(TrustedImm32(m_stackHeight), stackPointerRegister);
137
}
138
139
void JITCompiler::parseArguments(const Signature& signature)
140
{
141
    size_t argumentCount = signature.arguments.size();
142
    for (uint32_t argIndex = 0; argIndex < argumentCount; ++argIndex) {
143
        Type type = signature.arguments[argIndex];
144
        m_currentLocalTypes.append(type);
145
        switch (type) {
146
        case Type::I32:
147
            load32(Address(GPRInfo::callFrameRegister, (argIndex + 1 + CallFrame::thisArgumentOffset()) * sizeof(Register)), GPRInfo::regT0);
148
            store32(GPRInfo::regT0, stackAddress(argIndex));
149
            break;
150
        case Type::F32:
151
            RELEASE_ASSERT_NOT_REACHED();
152
        case Type::F64:
153
            load64(Address(GPRInfo::callFrameRegister, (argIndex + 1 + CallFrame::thisArgumentOffset()) * sizeof(Register)), GPRInfo::regT0);
154
            unboxDoubleWithoutAssertions(GPRInfo::regT0, FPRInfo::fpRegT0);
155
            storeDouble(FPRInfo::fpRegT0, stackAddress(argIndex));
156
            break;
157
        default:
158
            RELEASE_ASSERT_NOT_REACHED();
159
        }
160
    }
161
}
162
163
void JITCompiler::parseVars()
164
{
165
    uint32_t numberOfI32Vars = 0;
166
    uint32_t numberOfF32Vars = 0;
167
    uint32_t numberOfF64Vars = 0;
168
169
    VarTypes varTypes;
170
    VarTypesWithImm varTypesWithImm;
171
    uint8_t imm;
172
    if (m_module->m_reader.code(&varTypes, &varTypesWithImm, &imm)) {
173
        if (varTypes & VarTypes::I32)
174
            numberOfI32Vars = m_module->m_reader.immU32();
175
        if (varTypes & VarTypes::F32)
176
            numberOfF32Vars = m_module->m_reader.immU32();
177
        if (varTypes & VarTypes::F64)
178
            numberOfF64Vars = m_module->m_reader.immU32();
179
    } else
180
        numberOfI32Vars = imm;
181
182
    uint32_t numberOfVars = numberOfI32Vars + numberOfF32Vars + numberOfF64Vars;
183
    if (numberOfVars > 0) {
184
        uint32_t localIndex = m_currentLocalTypes.size();
185
        for (uint32_t i = 0; i < numberOfI32Vars; ++i) {
186
            m_currentLocalTypes.append(Type::I32);
187
            store32(TrustedImm32(0), stackAddress(localIndex++));
188
        }
189
        for (uint32_t i = 0; i < numberOfF32Vars; ++i) {
190
            m_currentLocalTypes.append(Type::F32);
191
            store32(TrustedImm32(0), stackAddress(localIndex++));
192
        }
193
        for (uint32_t i = 0; i < numberOfF64Vars; ++i) {
194
            m_currentLocalTypes.append(Type::F64);
195
            store64(TrustedImm64(0), stackAddress(localIndex++));
196
        }
197
    }
198
}
199
200
void JITCompiler::parseStmt()
201
{
202
    Stmt stmt;
203
    StmtWithImm stmtWithImm;
204
    uint8_t imm;
205
    if (m_module->m_reader.code(&stmt, &stmtWithImm, &imm)) {
206
        switch (stmt) {
207
        case Stmt::SetLoc:
208
            parseSetLocal(0);
209
            break;
210
        case Stmt::SetGlo:
211
            RELEASE_ASSERT_NOT_REACHED();
212
        case Stmt::I32Store8:
213
            parseStore(ReturnType::I32, LinearMemoryType::I8, false, 0);
214
            break;
215
        case Stmt::I32StoreOff8:
216
            parseStore(ReturnType::I32, LinearMemoryType::I8, true, 0);
217
            break;
218
        case Stmt::I32Store16:
219
            parseStore(ReturnType::I32, LinearMemoryType::I16, false, 0);
220
            break;
221
        case Stmt::I32StoreOff16:
222
            parseStore(ReturnType::I32, LinearMemoryType::I16, true, 0);
223
            break;
224
        case Stmt::I32Store32:
225
            parseStore(ReturnType::I32, LinearMemoryType::I32, false, 0);
226
            break;
227
        case Stmt::I32StoreOff32:
228
            parseStore(ReturnType::I32, LinearMemoryType::I32, true, 0);
229
            break;
230
        case Stmt::F32Store:
231
            parseStore(ReturnType::F32, LinearMemoryType::F32, false, 0);
232
            break;
233
        case Stmt::F32StoreOff:
234
            parseStore(ReturnType::F32, LinearMemoryType::F32, true, 0);
235
            break;
236
        case Stmt::F64Store:
237
            parseStore(ReturnType::F64, LinearMemoryType::F64, false, 0);
238
            break;
239
        case Stmt::F64StoreOff:
240
            parseStore(ReturnType::F64, LinearMemoryType::F64, true, 0);
241
            break;
242
        case Stmt::CallInt:
243
            parseCallInternal(ReturnType::Void, 0);
244
            break;
245
        case Stmt::CallInd:
246
            RELEASE_ASSERT_NOT_REACHED();
247
        case Stmt::CallImp:
248
            parseCallImport(ReturnType::Void, 0); // FIXME: Is it really Void?
249
            break;
250
        case Stmt::Ret:
251
            parseReturnStmt();
252
            return;
253
        case Stmt::Block:
254
            parseBlockStmt();
255
            return;
256
        case Stmt::IfThen:
257
            parseIfStmt();
258
            return;
259
        case Stmt::IfElse:
260
            parseIfElseStmt();
261
            return;
262
        case Stmt::While:
263
            parseWhileStmt();
264
            return;
265
        case Stmt::Do:
266
            parseDoStmt();
267
            return;
268
        case Stmt::Label:
269
            parseLabelStmt();
270
            return;
271
        case Stmt::Break:
272
            parseBreakStmt();
273
            return;
274
        case Stmt::BreakLabel:
275
            parseBreakLabelStmt();
276
            return;
277
        case Stmt::Continue:
278
            parseContinueStmt();
279
            break;
280
        case Stmt::ContinueLabel:
281
            parseContinueLabelStmt();
282
            return;
283
        case Stmt::Switch:
284
            parseSwitchStmt();
285
            break;
286
        default:
287
            RELEASE_ASSERT_NOT_REACHED();
288
        }
289
    } else {
290
        switch (stmtWithImm) {
291
        case StmtWithImm::SetLoc:
292
            parseSetLocal(imm, 0);
293
            break;
294
        case StmtWithImm::SetGlo:
295
        default:
296
            RELEASE_ASSERT_NOT_REACHED();
297
        }
298
    }
299
}
300
301
void JITCompiler::parseGetLocal(int dst)
302
{
303
    uint32_t imm = m_module->m_reader.immU32();
304
    switch (m_currentLocalTypes[imm]) {
305
    case Type::I32:
306
    case Type::F32:
307
        load32(stackAddress(imm), GPRInfo::regT0);
308
        store32(GPRInfo::regT0, temporaryAddress(dst));
309
        break;
310
    case Type::F64:
311
        load64(stackAddress(imm), GPRInfo::regT0);
312
        store64(GPRInfo::regT0, temporaryAddress(dst));
313
        break;
314
    default:
315
        RELEASE_ASSERT_NOT_REACHED();
316
    }
317
}
318
319
void JITCompiler::parseSetLocal(uint32_t imm, int dst)
320
{
321
    Type type = m_currentLocalTypes[imm];
322
    parseExpr(ReturnType(type), dst);
323
    switch (type) {
324
    case Type::I32:
325
    case Type::F32:
326
        load32(temporaryAddress(dst), GPRInfo::regT0);
327
        store32(GPRInfo::regT0, stackAddress(imm));
328
        break;
329
    case Type::F64:
330
        load64(temporaryAddress(dst), GPRInfo::regT0);
331
        store64(GPRInfo::regT0, stackAddress(imm));
332
        break;
333
    default:
334
        RELEASE_ASSERT_NOT_REACHED();
335
    }
336
}
337
338
void JITCompiler::parseSetLocal(int dst)
339
{
340
    parseSetLocal(m_module->m_reader.immU32(), dst);
341
}
342
343
static const void* JSC_HOST_CALL getArrayBufferData(Module* module)
344
{
345
    // FIXME: Do we really have to do this?
346
    return module->arrayBufferData();
347
}
348
349
void JITCompiler::parseArrayBufferOffset(bool hasOffset, int dst)
350
{
351
    // TODO: Check for out-of-bounds access.
352
    uint32_t offset = hasOffset ? m_module->m_reader.immU32() : 0;
353
    uint32_t u32;
354
    if (m_module->m_reader.ifI32Lit(m_module->m_constantI32s, &u32))
355
        store32(TrustedImm32(u32 + offset), temporaryAddress(dst));
356
    else {
357
        parseExpr(ReturnType::I32, dst);
358
        load32(temporaryAddress(dst), GPRInfo::regT0);
359
        if (offset)
360
            add32(TrustedImm32(offset), GPRInfo::regT0);
361
        store32(GPRInfo::regT0, temporaryAddress(dst));
362
    }
363
364
    if (maxFrameExtentForSlowPathCall)
365
        addPtr(TrustedImm32(-maxFrameExtentForSlowPathCall), stackPointerRegister);
366
    setupArguments(TrustedImmPtr(m_module));
367
    move(TrustedImmPtr(bitwise_cast<void*>(getArrayBufferData)), GPRInfo::nonArgGPR0);
368
    call(GPRInfo::nonArgGPR0);
369
    if (maxFrameExtentForSlowPathCall)
370
        addPtr(TrustedImm32(maxFrameExtentForSlowPathCall), stackPointerRegister);
371
}
372
    
373
void JITCompiler::parseLoad(ReturnType returnType, LinearMemoryType linearMemoryType, bool hasOffset, int dst)
374
{
375
    parseArrayBufferOffset(hasOffset, dst);
376
    load32(temporaryAddress(dst), GPRInfo::regT1);
377
    BaseIndex address = BaseIndex(GPRInfo::returnValueGPR, GPRInfo::regT1, TimesOne);
378
379
    switch (returnType) {
380
    case ReturnType::I32:
381
        switch (linearMemoryType) {
382
        case LinearMemoryType::S8:
383
            load8SignedExtendTo32(address, GPRInfo::regT0);
384
            break;
385
        case LinearMemoryType::U8:
386
            load8(address, GPRInfo::regT0);
387
            break;
388
        case LinearMemoryType::S16:
389
            load16SignedExtendTo32(address, GPRInfo::regT0);
390
            break;
391
        case LinearMemoryType::U16:
392
            load16(address, GPRInfo::regT0);
393
            break;
394
        case LinearMemoryType::I32:
395
            load32(address, GPRInfo::regT0);
396
            break;
397
        default:
398
            ASSERT_NOT_REACHED();
399
        }
400
        store32(GPRInfo::regT0, temporaryAddress(dst));
401
        break;
402
    case ReturnType::F32:
403
        load32(address, GPRInfo::regT0);
404
        store32(GPRInfo::regT0, temporaryAddress(dst));
405
        break;
406
    case ReturnType::F64:
407
        load64(address, GPRInfo::regT0);
408
        store64(GPRInfo::regT0, temporaryAddress(dst));
409
        break;
410
    default:
411
        RELEASE_ASSERT_NOT_REACHED();
412
    }
413
}
414
415
void JITCompiler::parseStore(ReturnType returnType, LinearMemoryType linearMemoryType, bool hasOffset, int dst)
416
{
417
    parseArrayBufferOffset(hasOffset, dst + 1);
418
    storePtr(GPRInfo::returnValueGPR, temporaryAddress(dst));
419
420
    parseExpr(returnType, dst + 2);
421
422
    loadPtr(temporaryAddress(dst), GPRInfo::regT1);
423
    load32(temporaryAddress(dst + 1), GPRInfo::regT2);
424
    BaseIndex address = BaseIndex(GPRInfo::regT1, GPRInfo::regT2, TimesOne);
425
426
    switch (returnType) {
427
    case ReturnType::I32:
428
        load32(temporaryAddress(dst + 2), GPRInfo::regT0);
429
        switch (linearMemoryType) {
430
        case LinearMemoryType::I8:
431
            store8(GPRInfo::regT0, address);
432
            break;
433
        case LinearMemoryType::I16:
434
            store16(GPRInfo::regT0, address);
435
            break;
436
        case LinearMemoryType::I32:
437
            store32(GPRInfo::regT0, address);
438
            break;
439
        default:
440
            ASSERT_NOT_REACHED();
441
        }
442
        store32(GPRInfo::regT0, temporaryAddress(dst));
443
        break;
444
    case ReturnType::F32:
445
        load32(temporaryAddress(dst + 2), GPRInfo::regT0);
446
        store32(GPRInfo::regT0, address);
447
        store32(GPRInfo::regT0, temporaryAddress(dst));
448
        break;
449
    case ReturnType::F64:
450
        load64(temporaryAddress(dst + 2), GPRInfo::regT0);
451
        store64(GPRInfo::regT0, address);
452
        store64(GPRInfo::regT0, temporaryAddress(dst));
453
        break;
454
    default:
455
        RELEASE_ASSERT_NOT_REACHED();
456
    }
457
}
458
459
void JITCompiler::parseReturnStmt()
460
{
461
    switch (m_currentReturnType) {
462
    case ReturnType::I32:
463
        parseExpr(ReturnType::I32, 0);
464
        load32(temporaryAddress(0), GPRInfo::returnValueGPR);
465
        or64(GPRInfo::tagTypeNumberRegister, GPRInfo::returnValueGPR);
466
        break;
467
    case ReturnType::F32:
468
        parseExpr(ReturnType::F32, 0);
469
        loadDouble(temporaryAddress(0), FPRInfo::fpRegT0); // FIXME: This loads 64 bits!
470
        convertFloatToDouble(FPRInfo::fpRegT0, FPRInfo::fpRegT0);
471
        boxDouble(FPRInfo::fpRegT0, GPRInfo::returnValueGPR);
472
        break;
473
    case ReturnType::F64:
474
        parseExpr(ReturnType::F64, 0);
475
        loadDouble(temporaryAddress(0), FPRInfo::fpRegT0);
476
        boxDouble(FPRInfo::fpRegT0, GPRInfo::returnValueGPR);
477
        break;
478
    case ReturnType::Void:
479
        break;
480
    }
481
482
    deallocateSpaceOnStack();
483
    emitFunctionEpilogue();
484
    ret();
485
}
486
487
void JITCompiler::parseStmtList()
488
{
489
    uint32_t numberOfStmts = m_module->m_reader.immU32();
490
    for (uint32_t i = 0; i < numberOfStmts; ++i)
491
        parseStmt();
492
}
493
494
void JITCompiler::parseBlockStmt()
495
{
496
    parseStmtList();
497
}
498
499
void JITCompiler::parseIfStmt()
500
{
501
    parseExpr(ReturnType::I32, 0);
502
    load32(temporaryAddress(0), GPRInfo::regT0);
503
    Jump end = branchTest32(Zero, GPRInfo::regT0);
504
    parseStmt();
505
    end.link(this);
506
}
507
508
void JITCompiler::parseIfElseStmt()
509
{
510
    parseExpr(ReturnType::I32, 0);
511
    load32(temporaryAddress(0), GPRInfo::regT0);
512
    Jump els = branchTest32(Zero, GPRInfo::regT0);
513
    parseStmt();
514
    Jump end = jump();
515
    els.link(this);
516
    parseStmt();
517
    end.link(this);
518
}
519
520
void JITCompiler::parseWhileStmt()
521
{
522
    JumpScope continueJumpScope(this, label());
523
    pushContinueJumpScope(&continueJumpScope);
524
525
    JumpList breakJumpList;
526
    pushBreakJumpList(&breakJumpList);
527
528
    parseExpr(ReturnType::I32, 0);
529
    load32(temporaryAddress(0), GPRInfo::regT0);
530
    Jump end = branchTest32(Zero, GPRInfo::regT0);
531
    parseStmt();
532
    continueJumpScope.jump();
533
    end.link(this);
534
    breakJumpList.link(this);
535
536
    popBreakJumpList();
537
538
    popContinueJumpScope();
539
}
540
541
void JITCompiler::parseDoStmt()
542
{
543
    JumpScope continueJumpScope(this);
544
    pushContinueJumpScope(&continueJumpScope);
545
546
    JumpList breakJumpList;
547
    pushBreakJumpList(&breakJumpList);
548
549
    Label start = label();
550
    parseStmt();
551
    continueJumpScope.link();
552
    parseExpr(ReturnType::I32, 0);
553
    load32(temporaryAddress(0), GPRInfo::regT0);
554
    Jump jumpToStart = branchTest32(NonZero, GPRInfo::regT0);
555
    jumpToStart.linkTo(start, this);
556
    breakJumpList.link(this);
557
558
    popBreakJumpList();
559
560
    popContinueJumpScope();
561
}
562
563
void JITCompiler::parseLabelStmt()
564
{
565
    Label continueLabel = label();
566
    JumpList breakJumpList;
567
    pushContinueLabelLabel(&continueLabel);
568
    pushBreakLabelJumpList(&breakJumpList);
569
    parseStmt();
570
    breakJumpList.link(this);
571
    popBreakLabelJumpList();
572
    popContinueLabelLabel();
573
}
574
575
void JITCompiler::parseBreakStmt()
576
{
577
    topBreakJumpList()->append(jump());
578
}
579
580
void JITCompiler::parseBreakLabelStmt()
581
{
582
    uint32_t index = m_module->m_reader.immU32();
583
    breakLabelJumpList(index)->append(jump());
584
}
585
586
void JITCompiler::parseContinueStmt()
587
{
588
    topContinueJumpScope()->jump();
589
}
590
591
void JITCompiler::parseContinueLabelStmt()
592
{
593
    uint32_t index = m_module->m_reader.immU32();
594
    jump(*continueLabelLabel(index));
595
}
596
597
void JITCompiler::parseSwitchStmt()
598
{
599
    JumpList breakJumpList;
600
    pushBreakJumpList(&breakJumpList);
601
602
    uint32_t numberOfCases = m_module->m_reader.immU32();
603
    parseExpr(ReturnType::I32, 0);
604
    load32(temporaryAddress(0), GPRInfo::regT0);
605
606
    Jump table = jump();
607
608
    Vector<Label> labels;
609
    Vector<int32_t> imms;
610
    Label defaultLabel;
611
    bool hasDefault = false;
612
613
    for (uint32_t i = 0; i < numberOfCases; ++i) {
614
        switch (m_module->m_reader.switchCase()) {
615
        case SwitchCase::Case0:
616
            labels.append(label());
617
            imms.append(m_module->m_reader.immS32());
618
            break;
619
        case SwitchCase::Case1:
620
            labels.append(label());
621
            imms.append(m_module->m_reader.immS32());
622
            parseStmt();
623
            break;
624
        case SwitchCase::CaseN:
625
            labels.append(label());
626
            imms.append(m_module->m_reader.immS32());
627
            parseStmtList();
628
            break;
629
        case SwitchCase::Default0:
630
            defaultLabel = label();
631
            hasDefault = true;
632
            break;
633
        case SwitchCase::Default1:
634
            defaultLabel = label();
635
            hasDefault = true;
636
            parseStmt();
637
            break;
638
        case SwitchCase::DefaultN:
639
            defaultLabel = label();
640
            hasDefault = true;
641
            parseStmtList();
642
            break;
643
        default:
644
            RELEASE_ASSERT_NOT_REACHED();
645
        }
646
    }
647
648
    Jump end = jump();
649
    table.link(this);
650
651
    for (size_t i = 0; i < labels.size(); ++i) {
652
        Jump jmp = branch32(Equal, GPRInfo::regT0, TrustedImm32(imms[i]));
653
        jmp.linkTo(labels[i], this);
654
    }
655
    if (hasDefault)
656
        jump(defaultLabel);
657
658
    end.link(this);
659
660
    breakJumpList.link(this);
661
    popBreakJumpList();
662
}
663
664
void JITCompiler::parseExpr(ReturnType returnType, int dst)
665
{
666
    switch (returnType) {
667
    case ReturnType::I32:
668
        parseExprI32(dst);
669
        break;
670
    case ReturnType::F64:
671
        parseExprF64(dst);
672
        break;
673
    case ReturnType::Void:
674
        parseExprVoid(dst);
675
        break;
676
    default:
677
        RELEASE_ASSERT_NOT_REACHED();
678
    }
679
}
680
681
void JITCompiler::parseExprI32(int dst)
682
{
683
    I32 i32;
684
    I32WithImm i32WithImm;
685
    uint8_t imm;
686
687
    if (m_module->m_reader.code(&i32, &i32WithImm, &imm)) {
688
        switch (i32) {
689
        case I32::LitPool:
690
            store32(TrustedImm32(m_module->m_constantI32s[m_module->m_reader.immU32()]), temporaryAddress(dst));
691
            break;
692
        case I32::LitImm:
693
            store32(TrustedImm32(m_module->m_reader.immU32()), temporaryAddress(dst));
694
            break;
695
        case I32::GetLoc:
696
            parseGetLocal(dst);
697
            break;
698
        case I32::GetGlo:
699
            RELEASE_ASSERT_NOT_REACHED();
700
        case I32::SetLoc:
701
            parseSetLocal(dst);
702
            break;
703
        case I32::SetGlo:
704
            RELEASE_ASSERT_NOT_REACHED();
705
        case I32::SLoad8:
706
            parseLoad(ReturnType::I32, LinearMemoryType::S8, false, dst);
707
            break;
708
        case I32::SLoadOff8:
709
            parseLoad(ReturnType::I32, LinearMemoryType::S8, true, dst);
710
            break;
711
        case I32::ULoad8:
712
            parseLoad(ReturnType::I32, LinearMemoryType::U8, false, dst);
713
            break;
714
        case I32::ULoadOff8:
715
            parseLoad(ReturnType::I32, LinearMemoryType::U8, true, dst);
716
            break;
717
        case I32::SLoad16:
718
            parseLoad(ReturnType::I32, LinearMemoryType::S16, false, dst);
719
            break;
720
        case I32::SLoadOff16:
721
            parseLoad(ReturnType::I32, LinearMemoryType::S16, true, dst);
722
            break;
723
        case I32::ULoad16:
724
            parseLoad(ReturnType::I32, LinearMemoryType::U16, false, dst);
725
            break;
726
        case I32::ULoadOff16:
727
            parseLoad(ReturnType::I32, LinearMemoryType::U16, true, dst);
728
            break;
729
        case I32::Load32:
730
            parseLoad(ReturnType::I32, LinearMemoryType::I32, false, dst);
731
            break;
732
        case I32::LoadOff32:
733
            parseLoad(ReturnType::I32, LinearMemoryType::I32, true, dst);
734
            break;
735
        case I32::Store8:
736
            parseStore(ReturnType::I32, LinearMemoryType::I8, false, dst);
737
            break;
738
        case I32::StoreOff8:
739
            parseStore(ReturnType::I32, LinearMemoryType::I8, true, dst);
740
            break;
741
        case I32::Store16:
742
            parseStore(ReturnType::I32, LinearMemoryType::I16, false, dst);
743
            break;
744
        case I32::StoreOff16:
745
            parseStore(ReturnType::I32, LinearMemoryType::I16, true, dst);
746
            break;
747
        case I32::Store32:
748
            parseStore(ReturnType::I32, LinearMemoryType::I32, false, dst);
749
            break;
750
        case I32::StoreOff32:
751
            parseStore(ReturnType::I32, LinearMemoryType::I32, true, dst);
752
            break;
753
        case I32::CallInt:
754
            parseCallInternal(ReturnType::I32, dst);
755
            break;
756
        case I32::CallInd:
757
            RELEASE_ASSERT_NOT_REACHED();
758
        case I32::CallImp:
759
            parseCallImport(ReturnType::I32, dst);
760
            break;
761
        case I32::Cond:
762
            parseCond(ReturnType::I32, dst);
763
            break;
764
        case I32::Comma:
765
            parseComma(ReturnType::I32, dst);
766
            break;
767
        case I32::FromF32:
768
            RELEASE_ASSERT_NOT_REACHED();
769
        case I32::FromF64:
770
            parseExprF64(dst);
771
            loadDouble(temporaryAddress(dst), FPRInfo::fpRegT0);
772
            truncateDoubleToInt32(FPRInfo::fpRegT0, GPRInfo::regT0);
773
            store32(GPRInfo::regT0, temporaryAddress(dst));
774
            break;
775
        case I32::Neg:
776
        case I32::BitNot:
777
        case I32::Clz:
778
        case I32::Abs:
779
            parseUnaryOp(static_cast<uint8_t>(i32), ReturnType::I32, dst);
780
            break;
781
        case I32::Add:
782
        case I32::Sub:
783
        case I32::Mul:
784
        case I32::SDiv:
785
        case I32::SMod:
786
        case I32::BitOr:
787
        case I32::BitAnd:
788
        case I32::BitXor:
789
        case I32::Lsh:
790
        case I32::ArithRsh:
791
        case I32::LogicRsh:
792
            parseBinaryOp(static_cast<uint8_t>(i32), ReturnType::I32, dst);
793
            break;
794
        case I32::UDiv:
795
        case I32::UMod:
796
        case I32::LogicNot:
797
            RELEASE_ASSERT_NOT_REACHED();
798
        case I32::EqI32:
799
            parseRelationalOpI32(Equal, dst);
800
            break;
801
        case I32::EqF32:
802
            RELEASE_ASSERT_NOT_REACHED();
803
        case I32::EqF64:
804
            parseRelationalOpF64(DoubleEqual, dst);
805
            break;
806
        case I32::NEqI32:
807
            parseRelationalOpI32(NotEqual, dst);
808
            break;
809
        case I32::NEqF32:
810
            RELEASE_ASSERT_NOT_REACHED();
811
        case I32::NEqF64:
812
            parseRelationalOpF64(DoubleNotEqual, dst);
813
            break;
814
        case I32::SLeThI32:
815
            parseRelationalOpI32(LessThan, dst);
816
            break;
817
        case I32::ULeThI32:
818
            parseRelationalOpI32(Below, dst);
819
            break;
820
        case I32::LeThF32:
821
            RELEASE_ASSERT_NOT_REACHED();
822
        case I32::LeThF64:
823
            parseRelationalOpF64(DoubleLessThan, dst);
824
            break;
825
        case I32::SLeEqI32:
826
            parseRelationalOpI32(LessThanOrEqual, dst);
827
            break;
828
        case I32::ULeEqI32:
829
            parseRelationalOpI32(BelowOrEqual, dst);
830
            break;
831
        case I32::LeEqF32:
832
            RELEASE_ASSERT_NOT_REACHED();
833
        case I32::LeEqF64:
834
            parseRelationalOpF64(DoubleLessThanOrEqual, dst);
835
            break;
836
        case I32::SGrThI32:
837
            parseRelationalOpI32(GreaterThan, dst);
838
            break;
839
        case I32::UGrThI32:
840
            parseRelationalOpI32(Above, dst);
841
            break;
842
        case I32::GrThF32:
843
            RELEASE_ASSERT_NOT_REACHED();
844
        case I32::GrThF64:
845
            parseRelationalOpF64(DoubleGreaterThan, dst);
846
            break;
847
        case I32::SGrEqI32:
848
            parseRelationalOpI32(GreaterThanOrEqual, dst);
849
            break;
850
        case I32::UGrEqI32:
851
            parseRelationalOpI32(AboveOrEqual, dst);
852
            break;
853
        case I32::GrEqF32:
854
            RELEASE_ASSERT_NOT_REACHED();
855
        case I32::GrEqF64:
856
            parseRelationalOpF64(DoubleGreaterThanOrEqual, dst);
857
            break;
858
        case I32::SMin:
859
            parseMinMaxI32(LessThanOrEqual, dst);
860
            break;
861
        case I32::UMin:
862
            parseMinMaxI32(BelowOrEqual, dst);
863
            break;
864
        case I32::SMax:
865
            parseMinMaxI32(GreaterThanOrEqual, dst);
866
            break;
867
        case I32::UMax:
868
            parseMinMaxI32(AboveOrEqual, dst);
869
            break;
870
        default:
871
            RELEASE_ASSERT_NOT_REACHED();
872
        }
873
    } else {
874
        switch (i32WithImm) {
875
        case I32WithImm::LitImm:
876
            store32(TrustedImm32(imm), temporaryAddress(dst));
877
            break;
878
        case I32WithImm::LitPool:
879
            store32(TrustedImm32(m_module->m_constantI32s[imm]), temporaryAddress(dst));
880
            break;
881
        case I32WithImm::GetLoc:
882
            load32(stackAddress(imm), GPRInfo::regT0);
883
            store32(GPRInfo::regT0, temporaryAddress(dst));
884
            break;
885
        default:
886
            RELEASE_ASSERT_NOT_REACHED();
887
        }
888
    }
889
}
890
891
void JITCompiler::parseExprF64(int dst)
892
{
893
    F64 f64;
894
    F64WithImm f64WithImm;
895
    uint8_t imm;
896
897
    if (m_module->m_reader.code(&f64, &f64WithImm, &imm)) {
898
        switch (f64) {
899
        case F64::LitPool:
900
            store64(TrustedImm64(reinterpretDoubleToInt64(m_module->m_constantF64s[m_module->m_reader.immU32()])), temporaryAddress(dst));
901
            break;
902
        case F64::LitImm:
903
            store64(TrustedImm64(reinterpretDoubleToInt64(m_module->m_reader.fixedWidth<double>())), temporaryAddress(dst));
904
            break;
905
        case F64::Load:
906
            parseLoad(ReturnType::F64, LinearMemoryType::F64, false, dst);
907
            break;
908
        case F64::LoadOff:
909
            parseLoad(ReturnType::F64, LinearMemoryType::F64, true, dst);
910
            break;
911
        case F64::Store:
912
            parseStore(ReturnType::F64, LinearMemoryType::F64, false, dst);
913
            break;
914
        case F64::StoreOff:
915
            parseStore(ReturnType::F64, LinearMemoryType::F64, true, dst);
916
            break;
917
        case F64::CallInt:
918
            parseCallInternal(ReturnType::F64, dst);
919
            break;
920
        case F64::CallImp:
921
            parseCallImport(ReturnType::F64, dst);
922
            break;
923
        case F64::Cond:
924
            parseCond(ReturnType::F64, dst);
925
            break;
926
        case F64::Comma:
927
            parseComma(ReturnType::F64, dst);
928
            break;
929
        case F64::FromS32:
930
            parseExprI32(dst);
931
            convertInt32ToDouble(temporaryAddress(dst), FPRInfo::fpRegT0);
932
            storeDouble(FPRInfo::fpRegT0, temporaryAddress(dst));
933
            break;
934
        case F64::FromU32:
935
        case F64::FromF32:
936
            RELEASE_ASSERT_NOT_REACHED();
937
        case F64::Neg:
938
        case F64::Abs:
939
        case F64::Ceil:
940
        case F64::Floor:
941
        case F64::Sqrt:
942
        case F64::Cos:
943
        case F64::Sin:
944
        case F64::Tan:
945
        case F64::ACos:
946
        case F64::ASin:
947
        case F64::ATan:
948
        case F64::Exp:
949
        case F64::Ln:
950
            parseUnaryOp(static_cast<uint8_t>(f64), ReturnType::F64, dst);
951
            break;
952
        case F64::Add:
953
        case F64::Sub:
954
        case F64::Mul:
955
        case F64::Div:
956
        case F64::ATan2:
957
        case F64::Pow:
958
            parseBinaryOp(static_cast<uint8_t>(f64), ReturnType::F64, dst);
959
            break;
960
        case F64::Mod:
961
        case F64::Min:
962
        case F64::Max:
963
        default:
964
            RELEASE_ASSERT_NOT_REACHED();
965
        }
966
    } else {
967
        switch (f64WithImm) {
968
        case F64WithImm::LitPool:
969
            store64(TrustedImm64(reinterpretDoubleToInt64(m_module->m_constantF64s[imm])), temporaryAddress(dst));
970
            break;
971
        case F64WithImm::GetLoc:
972
            // FIXME: loadDouble/storeDouble?
973
            load64(stackAddress(imm), GPRInfo::regT0);
974
            store64(GPRInfo::regT0, temporaryAddress(dst));
975
            break;
976
        default:
977
            RELEASE_ASSERT_NOT_REACHED();
978
        }
979
    }
980
}
981
982
void JITCompiler::parseExprVoid(int dst)
983
{
984
    switch (m_module->m_reader.voidExpr()) {
985
    case Void::CallInt:
986
        parseCallInternal(ReturnType::Void, dst);
987
        break;
988
    case Void::CallInd:
989
        RELEASE_ASSERT_NOT_REACHED();
990
    case Void::CallImp:
991
        parseCallImport(ReturnType::Void, dst);
992
        break;
993
    default:
994
        RELEASE_ASSERT_NOT_REACHED();
995
    }
996
}
997
998
static EncodedJSValue JSC_HOST_CALL getInternalFunction(ExecState*, Module* module, uint32_t functionIndex)
999
{
1000
    // TODO: Use these two lines?
1001
    // VM* vm = exec->vm();
1002
    // NativeCallFrameTracer tracer(vm, exec);
1003
1004
    return JSValue::encode(module->function(functionIndex));
1005
}
1006
1007
void JITCompiler::parseCallInternal(ReturnType returnType, int dst)
1008
{
1009
    uint32_t functionIndex = m_module->m_reader.immU32();
1010
    const Signature& signature = m_module->m_signatures[m_module->m_funcSignatures[functionIndex]];
1011
    const Vector<Type>& arguments = signature.arguments;
1012
    size_t argumentCount = arguments.size();
1013
    // FIXME: returnType is redundant with signature.returnType
1014
1015
    parseCallArguments(arguments, dst);
1016
1017
    store32(TrustedImm32(argumentCount + 1), Address(stackPointerRegister, JSStack::ArgumentCount * static_cast<int>(sizeof(Register)) + PayloadOffset - sizeof(CallerFrameAndPC)));
1018
1019
    if (maxFrameExtentForSlowPathCall)
1020
        addPtr(TrustedImm32(-maxFrameExtentForSlowPathCall), stackPointerRegister);
1021
    setupArgumentsWithExecState(TrustedImmPtr(m_module), TrustedImm32(functionIndex));
1022
    move(TrustedImmPtr(bitwise_cast<void*>(getInternalFunction)), GPRInfo::nonArgGPR0);
1023
    call(GPRInfo::nonArgGPR0);
1024
    if (maxFrameExtentForSlowPathCall)
1025
        addPtr(TrustedImm32(maxFrameExtentForSlowPathCall), stackPointerRegister);
1026
1027
    move(GPRInfo::returnValueGPR, GPRInfo::regT0); // regT0 holds callee.
1028
    store64(GPRInfo::regT0, Address(stackPointerRegister, JSStack::Callee * static_cast<int>(sizeof(Register)) - sizeof(CallerFrameAndPC)));
1029
1030
    callFunctionSlowCase(returnType, dst);
1031
}
1032
1033
static EncodedJSValue JSC_HOST_CALL getImportedFunction(ExecState* exec, Module* module, uint32_t funcImportIndex)
1034
{
1035
    // TODO: Use these two lines?
1036
    // VM* vm = exec->vm();
1037
    // NativeCallFrameTracer tracer(vm, exec);
1038
1039
    const String& functionImportName = module->functionImportName(funcImportIndex);
1040
1041
    JSGlobalObject* globalObject = exec->lexicalGlobalObject();
1042
    Identifier identifier = Identifier::fromString(&exec->vm(), functionImportName);
1043
    PropertySlot slot(globalObject);
1044
1045
    if (!globalObject->getPropertySlot(exec, identifier, slot)) {
1046
        // TODO: Do something!
1047
        fprintf(stderr, "Can't find a function named \"%s\".\n", functionImportName.utf8().data());
1048
        abort();
1049
    }
1050
1051
    JSValue value = slot.getValue(exec, identifier);
1052
    if (!value.isFunction()) {
1053
        fprintf(stderr, "\"%s\" is not a function.\n", functionImportName.utf8().data());
1054
        abort();
1055
    }
1056
1057
    return JSValue::encode(value);
1058
}
1059
1060
void JITCompiler::parseCallImport(ReturnType returnType, int dst)
1061
{
1062
    uint32_t funcImportSignatureIndex = m_module->m_reader.immU32();
1063
    const Module::FuncImportSignature& funcImportSignature = m_module->m_funcImportSignatures[funcImportSignatureIndex];
1064
    const Signature& signature = m_module->m_signatures[funcImportSignature.signatureIndex];
1065
    const Vector<Type>& arguments = signature.arguments;
1066
    size_t argumentCount = arguments.size();
1067
    // FIXME: returnType is redundant with signature.returnType
1068
1069
    parseCallArguments(arguments, dst);
1070
1071
    store32(TrustedImm32(argumentCount + 1), Address(stackPointerRegister, JSStack::ArgumentCount * static_cast<int>(sizeof(Register)) + PayloadOffset - sizeof(CallerFrameAndPC)));
1072
1073
    if (maxFrameExtentForSlowPathCall)
1074
        addPtr(TrustedImm32(-maxFrameExtentForSlowPathCall), stackPointerRegister);
1075
    setupArgumentsWithExecState(TrustedImmPtr(m_module), TrustedImm32(funcImportSignature.funcImportIndex));
1076
    move(TrustedImmPtr(bitwise_cast<void*>(getImportedFunction)), GPRInfo::nonArgGPR0);
1077
    call(GPRInfo::nonArgGPR0);
1078
    if (maxFrameExtentForSlowPathCall)
1079
        addPtr(TrustedImm32(maxFrameExtentForSlowPathCall), stackPointerRegister);
1080
1081
    move(GPRInfo::returnValueGPR, GPRInfo::regT0); // regT0 holds callee.
1082
    store64(GPRInfo::regT0, Address(stackPointerRegister, JSStack::Callee * static_cast<int>(sizeof(Register)) - sizeof(CallerFrameAndPC)));
1083
1084
    callFunctionSlowCase(returnType, dst);
1085
}
1086
1087
void JITCompiler::callFunctionSlowCase(ReturnType returnType, int dst)
1088
{
1089
    ThunkGenerator generator = linkThunkGeneratorFor(CodeForCall, RegisterPreservationNotRequired);
1090
1091
    move(TrustedImmPtr(nullptr), GPRInfo::regT2); // TODO: Use CallLinkInfo
1092
1093
    CodePtr ptr = m_vm->getCTIStub(generator).code();
1094
1095
    move(TrustedImmPtr(ptr.executableAddress()), GPRInfo::nonArgGPR0);
1096
1097
    call(GPRInfo::nonArgGPR0);
1098
1099
    addPtr(TrustedImm32(-m_stackHeight), GPRInfo::callFrameRegister, stackPointerRegister); // FIXME: hacky
1100
1101
    // FIXME: Can we really use returnValueGPR?
1102
    switch (returnType) {
1103
    case ReturnType::I32:
1104
        store32(GPRInfo::returnValueGPR, temporaryAddress(dst));
1105
        break;
1106
    case ReturnType::F64:
1107
        unboxDoubleWithoutAssertions(GPRInfo::returnValueGPR, FPRInfo::fpRegT0);
1108
        storeDouble(FPRInfo::fpRegT0, temporaryAddress(dst));
1109
        break;
1110
    case ReturnType::Void:
1111
        break; // TODO: Sure?
1112
    default:
1113
        ASSERT_NOT_REACHED();
1114
    }
1115
}
1116
1117
void JITCompiler::parseCallArguments(const Vector<Type>& arguments, int dst)
1118
{
1119
    size_t argumentCount = arguments.size();
1120
    size_t offset = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), dst + argumentCount + m_currentLocalTypes.size()) - m_currentLocalTypes.size(); // FIXME: Better name
1121
1122
    for (size_t i = 0; i < argumentCount; ++i) {
1123
        switch (arguments[i]) {
1124
        case Type::I32:
1125
            parseExpr(ReturnType::I32, offset);
1126
            load32(temporaryAddress(offset), GPRInfo::regT0);
1127
            or64(GPRInfo::tagTypeNumberRegister, GPRInfo::regT0);
1128
            store64(GPRInfo::regT0, temporaryAddress(offset - i - 1));
1129
            break;
1130
        case Type::F64:
1131
            parseExpr(ReturnType::F64, offset);
1132
            loadDouble(temporaryAddress(offset), FPRInfo::fpRegT0);
1133
            boxDouble(FPRInfo::fpRegT0, GPRInfo::regT0);
1134
            store64(GPRInfo::regT0, temporaryAddress(offset - i - 1));
1135
            break;
1136
        default:
1137
            ASSERT_NOT_REACHED();
1138
        }
1139
    }
1140
1141
    store64(TrustedImm64(JSValue::encode(jsUndefined())), temporaryAddress(offset));
1142
1143
    addPtr(TrustedImm32(-(offset + m_currentLocalTypes.size() + 3) * 8 - 8), GPRInfo::callFrameRegister, stackPointerRegister); // FIXME: hacky
1144
}
1145
1146
void JITCompiler::callDoubleFunction(double (*function)(double), FPRegisterID src, FPRegisterID dst)
1147
{
1148
    if (maxFrameExtentForSlowPathCall)
1149
        addPtr(TrustedImm32(-maxFrameExtentForSlowPathCall), stackPointerRegister);
1150
    setupArguments(src);
1151
    move(TrustedImmPtr(bitwise_cast<void*>(function)), GPRInfo::nonArgGPR0);
1152
    call(GPRInfo::nonArgGPR0);
1153
    if (maxFrameExtentForSlowPathCall)
1154
        addPtr(TrustedImm32(maxFrameExtentForSlowPathCall), stackPointerRegister);
1155
1156
    // FIXME: only works on x86
1157
    moveDouble(FPRInfo::returnValueFPR, dst);
1158
}
1159
1160
void JITCompiler::callDoubleFunction(double (*function)(double, double), FPRegisterID src1, FPRegisterID src2, FPRegisterID dst)
1161
{
1162
    if (maxFrameExtentForSlowPathCall)
1163
        addPtr(TrustedImm32(-maxFrameExtentForSlowPathCall), stackPointerRegister);
1164
    setupArguments(src1, src2);
1165
    move(TrustedImmPtr(bitwise_cast<void*>(function)), GPRInfo::nonArgGPR0);
1166
    call(GPRInfo::nonArgGPR0);
1167
    if (maxFrameExtentForSlowPathCall)
1168
        addPtr(TrustedImm32(maxFrameExtentForSlowPathCall), stackPointerRegister);
1169
1170
    // FIXME: only works on x86
1171
    moveDouble(FPRInfo::returnValueFPR, dst);
1172
}
1173
1174
void JITCompiler::parseUnaryOp(uint8_t op, ReturnType returnType, int dst)
1175
{
1176
    parseExpr(returnType, dst);
1177
    switch (returnType) {
1178
    case ReturnType::I32:
1179
        load32(temporaryAddress(dst), GPRInfo::regT0);
1180
        switch (static_cast<I32>(op)) {
1181
        case I32::Neg:
1182
            neg32(GPRInfo::regT0);
1183
            break;
1184
        case I32::BitNot:
1185
            xor32(TrustedImm32(-1), GPRInfo::regT0);
1186
            break;
1187
        case I32::Clz:
1188
            countLeadingZeros32(GPRInfo::regT0, GPRInfo::regT0);
1189
            break;
1190
        case I32::Abs: {
1191
            Jump end = branchTest32(PositiveOrZero, GPRInfo::regT0);
1192
            neg32(GPRInfo::regT0);
1193
            end.link(this);
1194
            break;
1195
        }
1196
        default:
1197
            ASSERT_NOT_REACHED();
1198
        }
1199
        store32(GPRInfo::regT0, temporaryAddress(dst));
1200
        break;
1201
    case ReturnType::F64:
1202
        loadDouble(temporaryAddress(dst), FPRInfo::fpRegT0);
1203
        switch (static_cast<F64>(op)) {
1204
        case F64::Neg:
1205
            negateDouble(FPRInfo::fpRegT0, FPRInfo::fpRegT1);
1206
            break;
1207
        case F64::Abs:
1208
            absDouble(FPRInfo::fpRegT0, FPRInfo::fpRegT1);
1209
            break;
1210
        case F64::Ceil:
1211
            callDoubleFunction(ceil, FPRInfo::fpRegT0, FPRInfo::fpRegT1);
1212
            break;
1213
        case F64::Floor:
1214
            callDoubleFunction(floor, FPRInfo::fpRegT0, FPRInfo::fpRegT1);
1215
            break;
1216
        case F64::Sqrt:
1217
            sqrtDouble(FPRInfo::fpRegT0, FPRInfo::fpRegT1);
1218
            break;
1219
        case F64::Cos:
1220
            callDoubleFunction(cos, FPRInfo::fpRegT0, FPRInfo::fpRegT1);
1221
            break;
1222
        case F64::Sin:
1223
            callDoubleFunction(sin, FPRInfo::fpRegT0, FPRInfo::fpRegT1);
1224
            break;
1225
        case F64::Tan:
1226
            callDoubleFunction(tan, FPRInfo::fpRegT0, FPRInfo::fpRegT1);
1227
            break;
1228
        case F64::ACos:
1229
            callDoubleFunction(acos, FPRInfo::fpRegT0, FPRInfo::fpRegT1);
1230
            break;
1231
        case F64::ASin:
1232
            callDoubleFunction(asin, FPRInfo::fpRegT0, FPRInfo::fpRegT1);
1233
            break;
1234
        case F64::ATan:
1235
            callDoubleFunction(atan, FPRInfo::fpRegT0, FPRInfo::fpRegT1);
1236
            break;
1237
        case F64::Exp:
1238
            callDoubleFunction(exp, FPRInfo::fpRegT0, FPRInfo::fpRegT1);
1239
            break;
1240
        case F64::Ln:
1241
            callDoubleFunction(log, FPRInfo::fpRegT0, FPRInfo::fpRegT1);
1242
            break;
1243
        default:
1244
            ASSERT_NOT_REACHED();
1245
        }
1246
        storeDouble(FPRInfo::fpRegT1, temporaryAddress(dst));
1247
        break;
1248
    default:
1249
        RELEASE_ASSERT_NOT_REACHED();
1250
    }
1251
}
1252
1253
void JITCompiler::parseBinaryOp(uint8_t op, ReturnType returnType, int dst)
1254
{
1255
    parseExpr(returnType, dst);
1256
    parseExpr(returnType, dst + 1);
1257
    switch (returnType) {
1258
    case ReturnType::I32:
1259
        load32(temporaryAddress(dst), GPRInfo::regT0);
1260
        load32(temporaryAddress(dst + 1), GPRInfo::regT1);
1261
        switch (static_cast<I32>(op)) {
1262
        case I32::Add:
1263
            add32(GPRInfo::regT1, GPRInfo::regT0);
1264
            break;
1265
        case I32::Sub:
1266
            sub32(GPRInfo::regT1, GPRInfo::regT0);
1267
            break;
1268
        case I32::Mul:
1269
            mul32(GPRInfo::regT1, GPRInfo::regT0);
1270
            break;
1271
        case I32::SDiv:
1272
            move(GPRInfo::regT1, GPRInfo::regT2);
1273
            m_assembler.cdq();
1274
            m_assembler.idivl_r(GPRInfo::regT2);
1275
            break;
1276
        case I32::SMod:
1277
            move(GPRInfo::regT1, GPRInfo::regT2);
1278
            m_assembler.cdq();
1279
            m_assembler.idivl_r(GPRInfo::regT2);
1280
            move(GPRInfo::regT1, GPRInfo::regT0);
1281
            break;
1282
        case I32::BitOr:
1283
            or32(GPRInfo::regT1, GPRInfo::regT0);
1284
            break;
1285
        case I32::BitAnd:
1286
            and32(GPRInfo::regT1, GPRInfo::regT0);
1287
            break;
1288
        case I32::BitXor:
1289
            xor32(GPRInfo::regT1, GPRInfo::regT0);
1290
            break;
1291
        case I32::Lsh:
1292
            lshift32(GPRInfo::regT1, GPRInfo::regT0);
1293
            break;
1294
        case I32::ArithRsh:
1295
            rshift32(GPRInfo::regT1, GPRInfo::regT0);
1296
            break;
1297
        case I32::LogicRsh:
1298
            urshift32(GPRInfo::regT1, GPRInfo::regT0);
1299
            break;
1300
        default:
1301
            ASSERT_NOT_REACHED();
1302
        }
1303
        store32(GPRInfo::regT0, temporaryAddress(dst));
1304
        break;
1305
    case ReturnType::F64:
1306
        loadDouble(temporaryAddress(dst), FPRInfo::fpRegT0);
1307
        loadDouble(temporaryAddress(dst + 1), FPRInfo::fpRegT1);
1308
        switch (static_cast<F64>(op)) {
1309
        case F64::Add:
1310
            addDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
1311
            break;
1312
        case F64::Sub:
1313
            subDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
1314
            break;
1315
        case F64::Mul:
1316
            mulDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
1317
            break;
1318
        case F64::Div:
1319
            divDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
1320
            break;
1321
        case F64::ATan2:
1322
            callDoubleFunction(atan2, FPRInfo::fpRegT0, FPRInfo::fpRegT1, FPRInfo::fpRegT0);
1323
            break;
1324
        case F64::Pow:
1325
            callDoubleFunction(pow, FPRInfo::fpRegT0, FPRInfo::fpRegT1, FPRInfo::fpRegT0);
1326
            break;
1327
        default:
1328
            ASSERT_NOT_REACHED();
1329
        }
1330
        storeDouble(FPRInfo::fpRegT0, temporaryAddress(dst));
1331
        break;
1332
    default:
1333
        RELEASE_ASSERT_NOT_REACHED();
1334
    }
1335
}
1336
1337
void JITCompiler::parseRelationalOpI32(RelationalCondition condition, int dst)
1338
{
1339
    parseExpr(ReturnType::I32, dst);
1340
    parseExpr(ReturnType::I32, dst + 1);
1341
    load32(temporaryAddress(dst), GPRInfo::regT0);
1342
    load32(temporaryAddress(dst + 1), GPRInfo::regT1);
1343
    compare32(condition, GPRInfo::regT0, GPRInfo::regT1, GPRInfo::regT0);
1344
    store32(GPRInfo::regT0, temporaryAddress(dst));
1345
}
1346
1347
void JITCompiler::parseRelationalOpF64(DoubleCondition condition, int dst)
1348
{
1349
    parseExpr(ReturnType::F64, dst);
1350
    parseExpr(ReturnType::F64, dst + 1);
1351
    loadDouble(temporaryAddress(dst), FPRInfo::fpRegT0);
1352
    loadDouble(temporaryAddress(dst + 1), FPRInfo::fpRegT1);
1353
    Jump trueCase = branchDouble(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT1);
1354
    store32(TrustedImm32(0), temporaryAddress(dst));
1355
    Jump end = jump();
1356
    trueCase.link(this);
1357
    store32(TrustedImm32(1), temporaryAddress(dst));
1358
    end.link(this);
1359
}
1360
1361
void JITCompiler::parseComma(ReturnType returnType, int dst)
1362
{
1363
    parseExpr(m_module->m_reader.returnType(), dst);
1364
    parseExpr(returnType, dst);
1365
}
1366
1367
void JITCompiler::parseCond(ReturnType returnType, int dst)
1368
{
1369
    parseExpr(ReturnType::I32, dst);
1370
    load32(temporaryAddress(dst), GPRInfo::regT0);
1371
    Jump els = branchTest32(Zero, GPRInfo::regT0);
1372
    parseExpr(returnType, dst);
1373
    Jump end = jump();
1374
    els.link(this);
1375
    parseExpr(returnType, dst);
1376
    end.link(this);
1377
}
1378
1379
void JITCompiler::parseMinMaxI32(RelationalCondition condition, int dst)
1380
{
1381
    uint32_t numberOfArguments = m_module->m_reader.immU32();
1382
    RELEASE_ASSERT(numberOfArguments >= 1);
1383
    parseExpr(ReturnType::I32, dst);
1384
    load32(temporaryAddress(dst), GPRInfo::regT0);
1385
    for (uint32_t i = 1; i < numberOfArguments; ++i) {
1386
        parseExpr(ReturnType::I32, dst);
1387
        load32(temporaryAddress(dst), GPRInfo::regT1);
1388
        Jump end = branch32(condition, GPRInfo::regT0, GPRInfo::regT1);
1389
        move(GPRInfo::regT1, GPRInfo::regT0);
1390
        end.link(this);
1391
    }
1392
    store32(GPRInfo::regT0, temporaryAddress(dst));
1393
}
1394
1395
} } // namespace JSC::Wasm
- a/Source/JavaScriptCore/wasm/WasmJITCompiler.h +154 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
enum class LinearMemoryType : unsigned;
56
57
class JITCompiler : private CCallHelpers {
58
public:
59
    JITCompiler(VM* vm, CodeBlock* codeBlock, Module* module)
60
        : CCallHelpers(vm, codeBlock)
61
        , m_module(module)
62
    {
63
    }
64
65
    RefPtr<JITCode> compileFunction(VM&, size_t functionIndex);
66
67
private:
68
    void allocateSpaceOnStack();
69
    void deallocateSpaceOnStack();
70
71
    void parseArguments(const Signature&);
72
    void parseVars();
73
74
    void parseStmt();
75
    void parseGetLocal(int dst);
76
    void parseSetLocal(uint32_t imm, int dst);
77
    void parseSetLocal(int dst);
78
    void parseArrayBufferOffset(bool hasOffset, int dst);
79
    void parseLoad(ReturnType, LinearMemoryType, bool hasOffset, int dst);
80
    void parseStore(ReturnType, LinearMemoryType, bool hasOffset, int dst);
81
    void parseReturnStmt();
82
    void parseBlockStmt();
83
    void parseStmtList();
84
    void parseIfStmt();
85
    void parseIfElseStmt();
86
    void parseWhileStmt();
87
    void parseDoStmt();
88
    void parseLabelStmt();
89
    void parseBreakStmt();
90
    void parseBreakLabelStmt();
91
    void parseContinueStmt();
92
    void parseContinueLabelStmt();
93
    void parseSwitchStmt();
94
95
    void parseExpr(ReturnType, int dst);
96
    void parseExprI32(int dst);
97
    void parseExprF64(int dst);
98
    void parseExprVoid(int dst);
99
    void parseCallInternal(ReturnType, int dst);
100
    void parseCallImport(ReturnType, int dst);
101
    void callFunctionSlowCase(ReturnType, int dst);
102
    void parseCallArguments(const Vector<Type>& arguments, int dst);
103
    void callDoubleFunction(double (*function)(double), FPRegisterID src, FPRegisterID dst);
104
    void callDoubleFunction(double (*function)(double, double), FPRegisterID src1, FPRegisterID src2, FPRegisterID dst);
105
    void parseUnaryOp(uint8_t op, ReturnType, int dst);
106
    void parseBinaryOp(uint8_t op, ReturnType, int dst);
107
    void parseRelationalOpI32(RelationalCondition, int dst);
108
    void parseRelationalOpF64(DoubleCondition, int dst);
109
    void parseComma(ReturnType, int dst);
110
    void parseCond(ReturnType, int dst);
111
    void parseMinMaxI32(RelationalCondition, int dst);
112
113
    Address stackAddress(int i) const // FIXME: Is this correct?
114
    {
115
        return Address(GPRInfo::callFrameRegister, -i * 8 - 8);
116
    }
117
118
    Address temporaryAddress(int i) const // FIXME: Is this correct?
119
    {
120
        return Address(GPRInfo::callFrameRegister, -(i + m_currentLocalTypes.size()) * 8 - 8);
121
    }
122
123
    void pushContinueLabelLabel(Label* label) { m_continueLabelLabels.append(label); }
124
    void popContinueLabelLabel() { m_continueLabelLabels.removeLast(); }
125
    Label* continueLabelLabel(size_t i) const { return m_continueLabelLabels[i]; }
126
    void pushBreakLabelJumpList(JumpList* jumpList) { m_breakLabelJumpLists.append(jumpList); }
127
    void popBreakLabelJumpList() { m_breakLabelJumpLists.removeLast(); }
128
    JumpList* breakLabelJumpList(size_t i) const { return m_breakLabelJumpLists[i]; }
129
130
    void pushContinueJumpScope(JumpScope* jumpScope) { m_continueJumpScopes.append(jumpScope); }
131
    void popContinueJumpScope() { m_continueJumpScopes.removeLast(); }
132
    JumpScope* topContinueJumpScope() const { return m_continueJumpScopes.last(); }
133
134
    void pushBreakJumpList(JumpList* jumpList) { m_breakJumpLists.append(jumpList); }
135
    void popBreakJumpList() { m_breakJumpLists.removeLast(); }
136
    JumpList* topBreakJumpList() const { return m_breakJumpLists.last(); }
137
138
    Module* m_module;
139
140
    uint32_t m_stackHeight; // FIXME: This caused a 'segmentation fault' heisenbug when I added "size_t m_stackHeight". Something must be wrong.
141
142
    ReturnType m_currentReturnType;
143
    Vector<Type> m_currentLocalTypes;
144
145
    Vector<MacroAssembler::Label*> m_continueLabelLabels;
146
    Vector<MacroAssembler::JumpList*> m_breakLabelJumpLists;
147
148
    Vector<JumpScope*> m_continueJumpScopes;
149
    Vector<MacroAssembler::JumpList*> m_breakJumpLists;
150
};
151
152
} } // namespace JSC::Wasm
153
154
#endif // WasmJITCompiler_h
- a/Source/JavaScriptCore/wasm/WasmModule.cpp +327 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::finishCreation(VM& vm, JSGlobalObject* globalObject, const Vector<char>& buffer)
58
{
59
    Base::finishCreation(vm);
60
61
    m_reader = Reader(reinterpret_cast<const uint8_t*>(buffer.data()));
62
    if (m_reader.fixedWidth<uint32_t>() != MagicNumber)
63
        abort();
64
    m_reader.fixedWidth<uint32_t>(); // output size in asm.js format
65
66
    // TODO: Make this less hacky
67
    RefPtr<ArrayBuffer> arrayBuffer = ArrayBuffer::create(1024, 1);
68
    JSArrayBuffer* jsArrayBuffer = JSArrayBuffer::create(vm, globalObject->arrayBufferStructure(), arrayBuffer.release());
69
    m_arrayBuffer.set(vm, this, jsArrayBuffer);
70
71
    parseConstantPoolSection();
72
    parseSignatureSection();
73
    parseFunctionImportSection();
74
    parseGlobalSection();
75
    parseFunctionDeclarationSection();
76
    parseFunctionPointerTables();
77
    parseFunctionDefinitionSection(vm, globalObject);
78
    parseExportSection(vm);
79
}
80
81
void Module::parseConstantPoolSection()
82
{
83
    uint32_t numberOfI32s = m_reader.immU32();
84
    uint32_t numberOfF32s = m_reader.immU32();
85
    uint32_t numberOfF64s = m_reader.immU32();
86
87
    Vector<uint32_t> constantI32s(numberOfI32s);
88
    for (uint32_t i = 0; i < numberOfI32s; ++i)
89
        constantI32s[i] = m_reader.immU32();
90
91
    Vector<float> constantF32s(numberOfF32s);
92
    for (uint32_t i = 0; i < numberOfF32s; ++i)
93
        constantF32s[i] = m_reader.fixedWidth<float>();
94
95
    Vector<double> constantF64s(numberOfF64s);
96
    for (uint32_t i = 0; i < numberOfF64s; ++i)
97
        constantF64s[i] = m_reader.fixedWidth<double>();
98
99
    m_constantI32s = WTF::move(constantI32s);
100
    m_constantF32s = WTF::move(constantF32s);
101
    m_constantF64s = WTF::move(constantF64s);
102
}
103
104
void Module::parseSignatureSection()
105
{
106
    uint32_t numberOfSignatures = m_reader.immU32();
107
    Vector<Signature> signatures(numberOfSignatures);
108
    for (uint32_t signatureIndex = 0; signatureIndex < numberOfSignatures; ++signatureIndex) {
109
        ReturnType returnType = m_reader.returnType();
110
        uint32_t argumentCount = m_reader.immU32();
111
        Signature signature(returnType, argumentCount);
112
        for (uint32_t argumentIndex = 0; argumentIndex < argumentCount; ++argumentIndex)
113
            signature.arguments[argumentIndex] = m_reader.type();
114
        signatures[signatureIndex] = WTF::move(signature);
115
    }
116
117
    m_signatures = WTF::move(signatures);
118
}
119
120
void Module::parseFunctionImportSection()
121
{
122
    uint32_t numberOfFuncImports = m_reader.immU32();
123
    uint32_t numberOfFuncImportSignatures = m_reader.immU32();
124
125
    m_functionImportNames.reserveCapacity(numberOfFuncImports);
126
127
    Vector<FuncImportSignature> funcImportSignatures(numberOfFuncImportSignatures);
128
    FuncImportSignature* funcImportSignature = funcImportSignatures.data();
129
    for (uint32_t funcImportIndex = 0; funcImportIndex < numberOfFuncImports; ++funcImportIndex) {
130
        StringBuilder builder;
131
        while (char c = m_reader.singleChar())
132
            builder.append(c);
133
        m_functionImportNames.append(builder.toString());
134
135
        uint32_t numberOfSignatures = m_reader.immU32();
136
        for (uint32_t i = 0; i < numberOfSignatures; ++i) {
137
            funcImportSignature->signatureIndex = m_reader.immU32();
138
            funcImportSignature->funcImportIndex = funcImportIndex;
139
            funcImportSignature++;
140
        }
141
    }
142
    assert(funcImportSignature == funcImportSignatures.data() + numberOfFuncImportSignatures);
143
144
    m_funcImportSignatures = WTF::move(funcImportSignatures);
145
}
146
147
void Module::parseGlobalSection()
148
{
149
    uint32_t numberOfI32Zero = m_reader.immU32();
150
    uint32_t numberOfF32Zero = m_reader.immU32();
151
    uint32_t numberOfF64Zero = m_reader.immU32();
152
    uint32_t numberOfI32Import = m_reader.immU32();
153
    uint32_t numberOfF32Import = m_reader.immU32();
154
    uint32_t numberOfF64Import = m_reader.immU32();
155
    uint32_t numberOfGlobalVars = numberOfI32Zero + numberOfF32Zero + numberOfF64Zero + numberOfI32Import + numberOfF32Import + numberOfF64Import;
156
157
    Vector<Type> globalTypes(numberOfGlobalVars);
158
    size_t globalTypeIndex = 0;
159
    for (uint32_t i = 0; i < numberOfI32Zero; ++i)
160
        globalTypes[globalTypeIndex++] = Type::I32;
161
    for (uint32_t i = 0; i < numberOfF32Zero; ++i)
162
        globalTypes[globalTypeIndex++] = Type::F32;
163
    for (uint32_t i = 0; i < numberOfF64Zero; ++i)
164
        globalTypes[globalTypeIndex++] = Type::F64;
165
    for (uint32_t i = 0; i < numberOfI32Import; ++i) {
166
        while (m_reader.singleChar()) { }
167
        globalTypes[globalTypeIndex++] = Type::I32;
168
    }
169
    for (uint32_t i = 0; i < numberOfF32Import; ++i) {
170
        while (m_reader.singleChar()) { }
171
        globalTypes[globalTypeIndex++] = Type::F32;
172
    }
173
    for (uint32_t i = 0; i < numberOfF64Import; ++i) {
174
        while (m_reader.singleChar()) { }
175
        globalTypes[globalTypeIndex++] = Type::F64;
176
    }
177
    m_globalTypes = WTF::move(globalTypes);
178
}
179
180
void Module::parseFunctionDeclarationSection()
181
{
182
    uint32_t numberOfFunctions = m_reader.immU32();
183
    Vector<uint32_t> funcSignatures(numberOfFunctions);
184
    for (uint32_t i = 0; i < numberOfFunctions; ++i)
185
        funcSignatures[i] = m_reader.immU32();
186
187
    m_funcSignatures = WTF::move(funcSignatures);
188
}
189
190
void Module::parseFunctionPointerTables()
191
{
192
    uint32_t numberOfFuncPtrTables = m_reader.immU32();
193
    Vector<FuncPtrTable> funcPtrTables(numberOfFuncPtrTables);
194
    for (uint32_t i = 0; i < numberOfFuncPtrTables; ++i) {
195
        funcPtrTables[i].signatureIndex = m_reader.immU32();
196
        uint32_t numElements = m_reader.immU32();
197
        Vector<uint32_t> elements(numElements);
198
        for (uint32_t j = 0; j < numElements; ++j)
199
            elements[j] = m_reader.immU32();
200
        funcPtrTables[i].elements = WTF::move(elements);
201
    }
202
203
    m_funcPtrTables = WTF::move(funcPtrTables);
204
}
205
206
void Module::parseFunctionDefinitionSection(VM& vm, JSGlobalObject* globalObject)
207
{
208
    for (size_t i = 0; i < m_funcSignatures.size(); ++i)
209
        parseFunctionDefinition(vm, globalObject, i);
210
}
211
212
void Module::parseExportSection(VM& vm)
213
{
214
    switch (m_reader.exportFormat()) {
215
    case ExportFormat::Default: {
216
        uint32_t functionIndex = m_reader.immU32();
217
        Identifier identifier = Identifier::fromString(&vm, "default"); // TODO: Use other names
218
        putDirect(vm, identifier, m_functions[functionIndex].get());
219
        break;
220
    }
221
    case ExportFormat::Record: {
222
        uint32_t numberOfExports = m_reader.immU32();
223
        for (uint32_t exportIndex = 0; exportIndex < numberOfExports; ++exportIndex) {
224
            StringBuilder builder;
225
            while (char c = m_reader.singleChar())
226
                builder.append(c);
227
            uint32_t functionIndex = m_reader.immU32();
228
            Identifier identifier = Identifier::fromString(&vm, builder.toString());
229
            putDirect(vm, identifier, m_functions[functionIndex].get());
230
        }
231
        break;
232
    }
233
    default:
234
        RELEASE_ASSERT_NOT_REACHED();
235
    }
236
}
237
238
void Module::parseFunctionDefinition(VM& vm, JSGlobalObject* globalObject, size_t functionIndex)
239
{
240
    WebAssemblyExecutable* executable = WebAssemblyExecutable::create(vm, SourceCode());
241
    {
242
        DeferGC deferGC(vm.heap);
243
        RefPtr<WebAssemblyCodeBlock> codeBlock = adoptRef(new WebAssemblyCodeBlock(executable, globalObject));
244
        JITCompiler jitCompiler(&vm, codeBlock.get(), this);
245
        codeBlock->setJITCode(jitCompiler.compileFunction(vm, functionIndex));
246
        executable->installCode(codeBlock.get());
247
    }
248
249
    JSFunction* jsFunction = JSFunction::create(vm, executable, globalObject);
250
    m_functions.append(WriteBarrier<JSFunction>(vm, this, jsFunction));
251
}
252
253
JSFunction* Module::function(size_t functionIndex) const
254
{
255
    return m_functions[functionIndex].get();
256
}
257
258
const void* Module::arrayBufferData() const
259
{
260
    return m_arrayBuffer->impl()->data();
261
}
262
263
void Module::visitChildren(JSCell* cell, SlotVisitor& visitor)
264
{
265
    Module* thisObject = static_cast<Module*>(cell);
266
    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
267
    Base::visitChildren(thisObject, visitor);
268
    for (auto function : thisObject->m_functions)
269
        visitor.append(&function);
270
    visitor.append(&thisObject->m_arrayBuffer);
271
}
272
273
bool Module::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
274
{
275
    Module* thisObject = jsCast<Module*>(object);
276
    if (propertyName == exec->propertyNames().buffer) {
277
        slot.setValue(thisObject, DontDelete | ReadOnly, thisObject->m_arrayBuffer.get());
278
        return true;
279
    }
280
281
    return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
282
}
283
284
void Module::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
285
{
286
    Module* thisObject = jsCast<Module*>(cell);
287
    if (propertyName == exec->propertyNames().buffer) {
288
        reject(exec, slot.isStrictMode(), "Attempting to write to a read-only array buffer property.");
289
        return;
290
    }
291
292
    Base::put(thisObject, exec, propertyName, value, slot);
293
}
294
295
bool Module::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool shouldThrow)
296
{
297
    Module* thisObject = jsCast<Module*>(object);
298
    if (propertyName == exec->propertyNames().buffer)
299
        return reject(exec, shouldThrow, "Attempting to define read-only array buffer property.");
300
301
    return Base::defineOwnProperty(thisObject, exec, propertyName, descriptor, shouldThrow);
302
}
303
304
bool Module::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName)
305
{
306
    Module* thisObject = jsCast<Module*>(cell);
307
    if (propertyName == exec->propertyNames().buffer)
308
        return false;
309
    
310
    return Base::deleteProperty(thisObject, exec, propertyName);
311
}
312
313
void Module::getOwnNonIndexPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& array, EnumerationMode mode)
314
{
315
    Module* thisObject = jsCast<Module*>(object);
316
    if (mode.includeDontEnumProperties())
317
        array.add(exec->propertyNames().buffer);
318
    
319
    Base::getOwnNonIndexPropertyNames(thisObject, exec, array, mode);
320
}
321
322
Module* compile(ExecState* exec, const Vector<char>& buffer)
323
{
324
    return Module::create(exec->vm(), exec->lexicalGlobalObject(), buffer);
325
}
326
327
} } // namespace JSC::Wasm
- a/Source/JavaScriptCore/wasm/WasmModule.h +135 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, const Vector<char>& buffer)
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, globalObject, buffer);
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
    JSFunction* function(size_t functionIndex) const;
73
    const String& functionImportName(size_t functionImportIndex) const { return m_functionImportNames[functionImportIndex]; }
74
    const void* arrayBufferData() const;
75
76
    static void visitChildren(JSCell*, SlotVisitor&);
77
78
private:
79
    friend class JITCompiler;
80
81
    struct FuncImportSignature {
82
        uint32_t signatureIndex;
83
        uint32_t funcImportIndex;
84
    };
85
    
86
    struct FuncPtrTable {
87
        uint32_t signatureIndex;
88
        Vector<uint32_t> elements;
89
    };
90
91
    Module(VM& vm, Structure* structure)
92
        : Base(vm, structure)
93
    {
94
    }
95
96
    void finishCreation(VM&, JSGlobalObject*, const Vector<char>& buffer);
97
98
    void parseConstantPoolSection();
99
    void parseSignatureSection();
100
    void parseFunctionImportSection();
101
    void parseGlobalSection();
102
    void parseFunctionDeclarationSection();
103
    void parseFunctionPointerTables();
104
    void parseFunctionDefinitionSection(VM&, JSGlobalObject*);
105
    void parseExportSection(VM&);
106
107
    void parseFunctionDefinition(VM&, JSGlobalObject*, size_t functionIndex);
108
109
    static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&);
110
    static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&);
111
    static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&, bool shouldThrow);
112
    static bool deleteProperty(JSCell*, ExecState*, PropertyName);
113
    static void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
114
115
    Reader m_reader;
116
117
    Vector<Signature> m_signatures;
118
    Vector<uint32_t> m_constantI32s;
119
    Vector<float> m_constantF32s;
120
    Vector<double> m_constantF64s;
121
    Vector<String> m_functionImportNames;
122
    Vector<FuncImportSignature> m_funcImportSignatures;
123
    Vector<Type> m_globalTypes;
124
    Vector<uint32_t> m_funcSignatures;
125
    Vector<FuncPtrTable> m_funcPtrTables;
126
127
    Vector<WriteBarrier<JSFunction>> m_functions;
128
    WriteBarrier<JSArrayBuffer> m_arrayBuffer;
129
};
130
131
JS_EXPORT_PRIVATE Module* compile(ExecState*, const Vector<char>& buffer);
132
133
} } // namespace JSC::Wasm
134
135
#endif // WasmModule_h
- a/Source/JavaScriptCore/wasm/WasmOpcodes.h +593 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
320
321
class Expr {
322
public:
323
    Expr()
324
    : m_type(ReturnType(-1)), u { }
325
    {
326
    }
327
    Expr(I32 i32) : m_type(ReturnType::I32) { u.i32 = i32; }
328
    Expr(F32 f32) : m_type(ReturnType::F32) { u.f32 = f32; }
329
    Expr(F64 f64) : m_type(ReturnType::F64) { u.f64 = f64; }
330
    Expr(Void v) : m_type(ReturnType::Void) { u.v = v; }
331
332
    ReturnType type() const { return m_type; }
333
    I32 i32() const { return u.i32; }
334
    F32 f32() const { return u.f32; }
335
    F64 f64() const { return u.f64; }
336
337
    bool operator==(Expr rhs) const { return m_type == rhs.m_type && u.raw == rhs.u.raw; }
338
    bool operator!=(Expr rhs) const { return !(*this == rhs); }
339
340
private:
341
    ReturnType m_type;
342
    union U {
343
        I32 i32;
344
        F32 f32;
345
        F64 f64;
346
        Void v;
347
        uint8_t raw;
348
    } u;
349
350
    static_assert(sizeof(U) == sizeof(uint8_t), "Exact overlay of raw_");
351
};
352
353
static const uint8_t HasImmFlag = 0x80;
354
static_assert(uint8_t(I32::Bad) <= HasImmFlag, "MSB reserved to distinguish I32 from I32WithImm");
355
static_assert(uint8_t(F32::Bad) <= HasImmFlag, "MSB reserved to distinguish F32 from F32WithImm");
356
static_assert(uint8_t(F64::Bad) <= HasImmFlag, "MSB reserved to distinguish F64 from F64WithImm");
357
358
static const unsigned OpWithImmBits = 2;
359
static const uint32_t OpWithImmLimit = 1 << OpWithImmBits;
360
static_assert(uint8_t(I32WithImm::Bad) <= OpWithImmLimit, "I32WithImm op fits");
361
static_assert(uint8_t(F32WithImm::Bad) <= OpWithImmLimit, "F32WithImm op fits");
362
static_assert(uint8_t(F64WithImm::Bad) <= OpWithImmLimit, "F64WithImm op fits");
363
364
static const unsigned ImmBits = 5;
365
static const uint32_t ImmLimit = 1 << ImmBits;
366
static_assert((1 + OpWithImmBits + ImmBits) == 8, "Bits of immediate op should add up to a byte");
367
368
static inline uint8_t PackOpWithImm(uint8_t op, uint8_t imm)
369
{
370
    assert(op < OpWithImmLimit);
371
    assert(imm < ImmLimit);
372
    return HasImmFlag | (uint8_t(op) << ImmBits) | imm;
373
}
374
375
template <class TWithImm>
376
static inline void UnpackOpWithImm(uint8_t byte, TWithImm* op, uint8_t *imm)
377
{
378
    assert(byte & HasImmFlag);
379
    *op = TWithImm((byte >> ImmBits) & (OpWithImmLimit - 1));
380
    *imm = byte & (ImmLimit - 1);
381
}
382
383
class ExprWithImm {
384
public:
385
    ExprWithImm()
386
        : m_type(Type(-1))
387
    {
388
    }
389
    ExprWithImm(I32WithImm i32) : m_type(Type::I32) { u.i32 = i32; }
390
    ExprWithImm(F32WithImm f32) : m_type(Type::F32) { u.f32 = f32; }
391
    ExprWithImm(F64WithImm f64) : m_type(Type::F64) { u.f64 = f64; }
392
393
    Type type() const { return m_type; }
394
    I32WithImm i32() const { return u.i32; }
395
    F32WithImm f32() const { return u.f32; }
396
    F64WithImm f64() const { return u.f64; }
397
398
private:
399
    Type m_type;
400
    union U {
401
        I32WithImm i32;
402
        F32WithImm f32;
403
        F64WithImm f64;
404
        uint8_t raw;
405
    } u;
406
407
    static_assert(sizeof(U) == sizeof(uint8_t), "Exact overlay of raw_");
408
};
409
410
enum class ExportFormat : uint8_t {
411
    Default,
412
    Record
413
};
414
415
struct Signature {
416
    ReturnType returnType;
417
    Vector<Type> arguments;
418
419
    Signature() { }
420
    Signature(ReturnType returnType)
421
        : returnType(returnType) { }
422
    Signature(ReturnType returnType, uint32_t argumentCount)
423
        : returnType(returnType)
424
        , arguments(argumentCount) { }
425
    Signature(ReturnType returnType, Vector<Type>&& arguments)
426
        : returnType(returnType)
427
        , arguments(WTF::move(arguments)) { }
428
429
    bool operator==(const Signature& rhs) const { return returnType == rhs.returnType && arguments == rhs.arguments; }
430
    bool operator!=(const Signature& rhs) const { return !(*this == rhs); }
431
432
    struct Hash {
433
        bool operator()(const Signature &signature) const
434
        {
435
            static_assert(sizeof(Type) == 1 && sizeof(ReturnType) == 1, "Shift more");
436
            uint32_t h = uint8_t(signature.returnType);
437
            for (Type t : signature.arguments)
438
                h = ((h << 2) | uint8_t(t)) ^ (h >> 30);
439
            return h;
440
        }
441
    };
442
};
443
444
class Reader {
445
public:
446
    Reader() { }
447
    Reader(const uint8_t* begin)
448
        : m_cursor(begin)
449
    {
450
    }
451
452
    template <class T> T fixedWidth();
453
    Stmt stmt() { return u8<Stmt>(); }
454
    SwitchCase switchCase() { return u8<SwitchCase>(); }
455
    template<class T, class TWithImm> inline bool code(T*, TWithImm*, uint8_t*);
456
    Void voidExpr() { return u8<Void>(); }
457
    ExportFormat exportFormat() { return u8<ExportFormat>(); }
458
    Type type() { return u8<Type>(); }
459
    ReturnType returnType() { return u8<ReturnType>(); }
460
    inline uint32_t immU32();
461
    inline int32_t immS32();
462
    char singleChar() { return *m_cursor++; }
463
464
    inline bool ifI32Lit(const Vector<uint32_t>& i32s, uint32_t*);
465
466
private:
467
    template <class T> T u8() { return T(*m_cursor++); }
468
469
    const uint8_t* m_cursor;
470
};
471
472
template <>
473
inline uint32_t Reader::fixedWidth<uint32_t>()
474
{
475
    uint32_t u32 = m_cursor[0] | m_cursor[1] << 8 | m_cursor[2] << 16 | m_cursor[3] << 24;
476
    m_cursor += 4;
477
    return u32;
478
}
479
480
template <>
481
inline float Reader::fixedWidth<float>()
482
{
483
    union {
484
        uint8_t arr[4];
485
        float f;
486
    } u = { { m_cursor[0], m_cursor[1], m_cursor[2], m_cursor[3] } };
487
    m_cursor += 4;
488
    return u.f;
489
}
490
491
template <>
492
inline double Reader::fixedWidth<double>()
493
{
494
    union {
495
        uint8_t arr[8];
496
        double d;
497
    } 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] } };
498
    m_cursor += 8;
499
    return u.d;
500
}
501
502
template <class T, class TWithImm>
503
bool Reader::code(T* t, TWithImm* tWithImm, uint8_t* imm)
504
{
505
    uint8_t byte = *m_cursor++;
506
    if (!(byte & HasImmFlag)) {
507
        *t = T(byte);
508
        return true;
509
    }
510
511
    UnpackOpWithImm(byte, tWithImm, imm);
512
    return false;
513
}
514
515
inline uint32_t Reader::immU32()
516
{
517
    uint32_t u32 = *m_cursor++;
518
    if (u32 < 0x80)
519
        return u32;
520
521
    u32 &= 0x7f;
522
523
    for (unsigned shift = 7; true; shift += 7) {
524
        uint32_t b = *m_cursor++;
525
        if (b < 0x80)
526
            return u32 | (b << shift);
527
        u32 |= (b & 0x7f) << shift;
528
    }
529
}
530
531
inline int32_t Reader::immS32()
532
{
533
    uint32_t u32 = *m_cursor++;
534
    if (u32 < 0x80)
535
        return int32_t(u32) << (32-7) >> (32-7);
536
537
    u32 &= 0x7f;
538
539
    for (unsigned shift = 7; true; shift += 7) {
540
        uint32_t b = *m_cursor++;
541
        if (b < 0x80) {
542
            u32 |= b << shift;
543
            int signExtend = (32-7) - shift;
544
            if (signExtend > 0)
545
                return int32_t(u32) << signExtend >> signExtend;
546
            return int32_t(u32);
547
        }
548
        u32 |= (b & 0x7f) << shift;
549
    }
550
}
551
552
inline bool Reader::ifI32Lit(const Vector<uint32_t>& i32s, uint32_t* u32)
553
{
554
    uint8_t byte = *m_cursor;
555
556
    if (byte & HasImmFlag) {
557
        I32WithImm i32WithImm;
558
        uint8_t imm;
559
        UnpackOpWithImm(byte, &i32WithImm, &imm);
560
561
        if (i32WithImm == I32WithImm::LitImm) {
562
            m_cursor++;
563
            *u32 = imm;
564
            return true;
565
        }
566
567
        if (i32WithImm == I32WithImm::LitPool) {
568
            m_cursor++;
569
            *u32 = i32s[imm];
570
            return true;
571
        }
572
573
        return false;
574
    }
575
576
    if (I32(byte) == I32::LitImm) {
577
        m_cursor++;
578
        *u32 = immU32();
579
        return true;
580
    }
581
582
    if (I32(byte) == I32::LitPool) {
583
        m_cursor++;
584
        *u32 = i32s[immU32()];
585
        return true;
586
    }
587
588
    return false;
589
}
590
591
} } // namespace JSC::Wasm
592
593
#endif // WasmOpcodes_h

Return to Bug 146064