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

Return to Bug 146064