| Differences between
and this patch
- a/Source/JavaScriptCore/ChangeLog +108 lines
Lines 1-3 a/Source/JavaScriptCore/ChangeLog_sec1
1
2015-07-02  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
        * jsc.cpp:
10
        (GlobalObject::finishCreation):
11
        (functionLoadWebAssembly):
12
        * wasm/WasmJITCompiler.cpp: Added.
13
        (JSC::Wasm::JumpScope::JumpScope):
14
        (JSC::Wasm::JumpScope::jump):
15
        (JSC::Wasm::JumpScope::link):
16
        (JSC::Wasm::JITCompiler::compileAndRun):
17
        (JSC::Wasm::JITCompiler::compile):
18
        (JSC::Wasm::JITCompiler::unpack):
19
        (JSC::Wasm::JITCompiler::readSignatureSection):
20
        (JSC::Wasm::JITCompiler::readFunctionImportSection):
21
        (JSC::Wasm::JITCompiler::readGlobalSection):
22
        (JSC::Wasm::JITCompiler::readConstantPoolSection):
23
        (JSC::Wasm::JITCompiler::readFunctionDeclarationSection):
24
        (JSC::Wasm::JITCompiler::readFunctionPointerTables):
25
        (JSC::Wasm::JITCompiler::readFunctionDefinitionSection):
26
        (JSC::Wasm::JITCompiler::readExportSection):
27
        (JSC::Wasm::JITCompiler::readFunctionDefinition):
28
        (JSC::Wasm::JITCompiler::readArgs):
29
        (JSC::Wasm::JITCompiler::readVars):
30
        (JSC::Wasm::JITCompiler::stmt):
31
        (JSC::Wasm::JITCompiler::get_local):
32
        (JSC::Wasm::JITCompiler::set_local):
33
        (JSC::Wasm::JITCompiler::return_stmt):
34
        (JSC::Wasm::JITCompiler::stmt_list):
35
        (JSC::Wasm::JITCompiler::block_stmt):
36
        (JSC::Wasm::JITCompiler::if_stmt):
37
        (JSC::Wasm::JITCompiler::if_else_stmt):
38
        (JSC::Wasm::JITCompiler::while_stmt):
39
        (JSC::Wasm::JITCompiler::do_stmt):
40
        (JSC::Wasm::JITCompiler::label_stmt):
41
        (JSC::Wasm::JITCompiler::break_label_stmt):
42
        (JSC::Wasm::JITCompiler::continue_label_stmt):
43
        (JSC::Wasm::JITCompiler::switch_stmt):
44
        (JSC::Wasm::JITCompiler::expr):
45
        (JSC::Wasm::JITCompiler::signed_expr):
46
        (JSC::Wasm::JITCompiler::add_sub):
47
        (JSC::Wasm::JITCompiler::mul_i32):
48
        (JSC::Wasm::JITCompiler::rel_i32):
49
        (JSC::Wasm::JITCompiler::comma):
50
        (JSC::Wasm::JITCompiler::cond):
51
        (JSC::Wasm::compileAndRun):
52
        * wasm/WasmJITCompiler.h: Added.
53
        (JSC::Wasm::JITCompiler::JITCompiler):
54
        (JSC::Wasm::JITCompiler::stackAddress):
55
        (JSC::Wasm::JITCompiler::temporaryAddress):
56
        (JSC::Wasm::JITCompiler::pushContinueLabelLabel):
57
        (JSC::Wasm::JITCompiler::popContinueLabelLabel):
58
        (JSC::Wasm::JITCompiler::continueLabelLabel):
59
        (JSC::Wasm::JITCompiler::pushBreakLabelJumpList):
60
        (JSC::Wasm::JITCompiler::popBreakLabelJumpList):
61
        (JSC::Wasm::JITCompiler::breakLabelJumpList):
62
        (JSC::Wasm::JITCompiler::pushContinueJumpScope):
63
        (JSC::Wasm::JITCompiler::popContinueJumpScope):
64
        (JSC::Wasm::JITCompiler::topContinueJumpScope):
65
        (JSC::Wasm::JITCompiler::pushBreakJumpList):
66
        (JSC::Wasm::JITCompiler::popBreakJumpList):
67
        (JSC::Wasm::JITCompiler::topBreakJumpList):
68
        * wasm/WasmOpcodes.h: Added.
69
        (JSC::Wasm::operator|):
70
        (JSC::Wasm::operator&):
71
        (JSC::Wasm::Expr::Expr):
72
        (JSC::Wasm::Expr::Bad):
73
        (JSC::Wasm::Expr::is_bad):
74
        (JSC::Wasm::Expr::type):
75
        (JSC::Wasm::Expr::i32):
76
        (JSC::Wasm::Expr::f32):
77
        (JSC::Wasm::Expr::f64):
78
        (JSC::Wasm::Expr::operator==):
79
        (JSC::Wasm::Expr::operator!=):
80
        (JSC::Wasm::PackOpWithImm):
81
        (JSC::Wasm::UnpackOpWithImm):
82
        (JSC::Wasm::ExprWithImm::ExprWithImm):
83
        (JSC::Wasm::ExprWithImm::is_bad):
84
        (JSC::Wasm::ExprWithImm::type):
85
        (JSC::Wasm::ExprWithImm::i32):
86
        (JSC::Wasm::ExprWithImm::f32):
87
        (JSC::Wasm::ExprWithImm::f64):
88
        (JSC::Wasm::Signature::Signature):
89
        (JSC::Wasm::Signature::operator==):
90
        (JSC::Wasm::Signature::operator!=):
91
        (JSC::Wasm::Signature::Hash::operator()):
92
        (JSC::Wasm::In::In):
93
        (JSC::Wasm::In::stmt):
94
        (JSC::Wasm::In::switchCase):
95
        (JSC::Wasm::In::voidExpr):
96
        (JSC::Wasm::In::exportFormat):
97
        (JSC::Wasm::In::type):
98
        (JSC::Wasm::In::rtype):
99
        (JSC::Wasm::In::singleChar):
100
        (JSC::Wasm::In::u8):
101
        (JSC::Wasm::In::fixedWidth<uint32_t>):
102
        (JSC::Wasm::In::fixedWidth<float>):
103
        (JSC::Wasm::In::fixedWidth<double>):
104
        (JSC::Wasm::In::code):
105
        (JSC::Wasm::In::immU32):
106
        (JSC::Wasm::In::immS32):
107
        (JSC::Wasm::In::ifI32Lit):
108
1
2015-06-20  Yusuke Suzuki  <utatane.tea@gmail.com>
109
2015-06-20  Yusuke Suzuki  <utatane.tea@gmail.com>
2
110
3
        [ES6] Destructuring assignment need to accept iterables
111
        [ES6] Destructuring assignment need to accept iterables
- a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj +20 lines
Lines 1016-1021 a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec1
1016
		70ECA6071AFDBEA200449739 /* TemplateRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 70ECA6021AFDBEA200449739 /* TemplateRegistry.cpp */; };
1016
		70ECA6071AFDBEA200449739 /* TemplateRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 70ECA6021AFDBEA200449739 /* TemplateRegistry.cpp */; };
1017
		70ECA6081AFDBEA200449739 /* TemplateRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = 70ECA6031AFDBEA200449739 /* TemplateRegistry.h */; settings = {ATTRIBUTES = (Private, ); }; };
1017
		70ECA6081AFDBEA200449739 /* TemplateRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = 70ECA6031AFDBEA200449739 /* TemplateRegistry.h */; settings = {ATTRIBUTES = (Private, ); }; };
1018
		70ECA6091AFDBEA200449739 /* TemplateRegistryKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 70ECA6041AFDBEA200449739 /* TemplateRegistryKey.h */; settings = {ATTRIBUTES = (Private, ); }; };
1018
		70ECA6091AFDBEA200449739 /* TemplateRegistryKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 70ECA6041AFDBEA200449739 /* TemplateRegistryKey.h */; settings = {ATTRIBUTES = (Private, ); }; };
1019
		7B545E501B4605C70029390E /* WasmJITCompiler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7B545E4D1B4605C30029390E /* WasmJITCompiler.cpp */; };
1020
		7B545E511B4605D30029390E /* WasmJITCompiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B545E4E1B4605C30029390E /* WasmJITCompiler.h */; settings = {ATTRIBUTES = (Private, ); }; };
1021
		7B545E521B4605D80029390E /* WasmOpcodes.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B545E4F1B4605C30029390E /* WasmOpcodes.h */; settings = {ATTRIBUTES = (Private, ); }; };
1019
		7C008CD2186F8A9300955C24 /* JSPromiseFunctions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C008CD0186F8A9300955C24 /* JSPromiseFunctions.cpp */; };
1022
		7C008CD2186F8A9300955C24 /* JSPromiseFunctions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C008CD0186F8A9300955C24 /* JSPromiseFunctions.cpp */; };
1020
		7C008CD3186F8A9300955C24 /* JSPromiseFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C008CD1186F8A9300955C24 /* JSPromiseFunctions.h */; settings = {ATTRIBUTES = (Private, ); }; };
1023
		7C008CD3186F8A9300955C24 /* JSPromiseFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C008CD1186F8A9300955C24 /* JSPromiseFunctions.h */; settings = {ATTRIBUTES = (Private, ); }; };
1021
		7C008CDA187124BB00955C24 /* JSPromiseDeferred.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C008CD8187124BB00955C24 /* JSPromiseDeferred.cpp */; };
1024
		7C008CDA187124BB00955C24 /* JSPromiseDeferred.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C008CD8187124BB00955C24 /* JSPromiseDeferred.cpp */; };
Lines 2758-2763 a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec2
2758
		70ECA6021AFDBEA200449739 /* TemplateRegistry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TemplateRegistry.cpp; sourceTree = "<group>"; };
2761
		70ECA6021AFDBEA200449739 /* TemplateRegistry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TemplateRegistry.cpp; sourceTree = "<group>"; };
2759
		70ECA6031AFDBEA200449739 /* TemplateRegistry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TemplateRegistry.h; sourceTree = "<group>"; };
2762
		70ECA6031AFDBEA200449739 /* TemplateRegistry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TemplateRegistry.h; sourceTree = "<group>"; };
2760
		70ECA6041AFDBEA200449739 /* TemplateRegistryKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TemplateRegistryKey.h; sourceTree = "<group>"; };
2763
		70ECA6041AFDBEA200449739 /* TemplateRegistryKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TemplateRegistryKey.h; sourceTree = "<group>"; };
2764
		7B545E4D1B4605C30029390E /* WasmJITCompiler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmJITCompiler.cpp; sourceTree = "<group>"; };
2765
		7B545E4E1B4605C30029390E /* WasmJITCompiler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmJITCompiler.h; sourceTree = "<group>"; };
2766
		7B545E4F1B4605C30029390E /* WasmOpcodes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmOpcodes.h; sourceTree = "<group>"; };
2761
		7C008CD0186F8A9300955C24 /* JSPromiseFunctions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = JSPromiseFunctions.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
2767
		7C008CD0186F8A9300955C24 /* JSPromiseFunctions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = JSPromiseFunctions.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
2762
		7C008CD1186F8A9300955C24 /* JSPromiseFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSPromiseFunctions.h; sourceTree = "<group>"; };
2768
		7C008CD1186F8A9300955C24 /* JSPromiseFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSPromiseFunctions.h; sourceTree = "<group>"; };
2763
		7C008CD8187124BB00955C24 /* JSPromiseDeferred.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPromiseDeferred.cpp; sourceTree = "<group>"; };
2769
		7C008CD8187124BB00955C24 /* JSPromiseDeferred.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPromiseDeferred.cpp; sourceTree = "<group>"; };
Lines 3617-3622 a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec3
3617
				7EF6E0BB0EB7A1EC0079AFAF /* runtime */,
3623
				7EF6E0BB0EB7A1EC0079AFAF /* runtime */,
3618
				141211000A48772600480255 /* tests */,
3624
				141211000A48772600480255 /* tests */,
3619
				8603CEF014C753EF00AE59E3 /* tools */,
3625
				8603CEF014C753EF00AE59E3 /* tools */,
3626
				7B545E4C1B4605A30029390E /* wasm */,
3620
				86EAC48C0F93E8B9008EC948 /* yarr */,
3627
				86EAC48C0F93E8B9008EC948 /* yarr */,
3621
			);
3628
			);
3622
			name = JavaScriptCore;
3629
			name = JavaScriptCore;
Lines 4280-4285 a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec4
4280
			path = disassembler/ARMv7;
4287
			path = disassembler/ARMv7;
4281
			sourceTree = "<group>";
4288
			sourceTree = "<group>";
4282
		};
4289
		};
4290
		7B545E4C1B4605A30029390E /* wasm */ = {
4291
			isa = PBXGroup;
4292
			children = (
4293
				7B545E4D1B4605C30029390E /* WasmJITCompiler.cpp */,
4294
				7B545E4E1B4605C30029390E /* WasmJITCompiler.h */,
4295
				7B545E4F1B4605C30029390E /* WasmOpcodes.h */,
4296
			);
4297
			path = wasm;
4298
			sourceTree = "<group>";
4299
		};
4283
		7E39D81D0EC38EFA003AF11A /* bytecompiler */ = {
4300
		7E39D81D0EC38EFA003AF11A /* bytecompiler */ = {
4284
			isa = PBXGroup;
4301
			isa = PBXGroup;
4285
			children = (
4302
			children = (
Lines 6043-6048 a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec5
6043
				BC18C40F0E16F5CD00B34460 /* Identifier.h in Headers */,
6060
				BC18C40F0E16F5CD00B34460 /* Identifier.h in Headers */,
6044
				A5FD0076189B038C00633231 /* IdentifiersFactory.h in Headers */,
6061
				A5FD0076189B038C00633231 /* IdentifiersFactory.h in Headers */,
6045
				996231E918D1804200C03FDA /* InspectorBackendCommands.js in Headers */,
6062
				996231E918D1804200C03FDA /* InspectorBackendCommands.js in Headers */,
6063
				7B545E521B4605D80029390E /* WasmOpcodes.h in Headers */,
6046
				C25F8BCE157544A900245B71 /* IncrementalSweeper.h in Headers */,
6064
				C25F8BCE157544A900245B71 /* IncrementalSweeper.h in Headers */,
6047
				0FB7F39915ED8E4600F167B2 /* IndexingHeader.h in Headers */,
6065
				0FB7F39915ED8E4600F167B2 /* IndexingHeader.h in Headers */,
6048
				0FB7F39A15ED8E4600F167B2 /* IndexingHeaderInlines.h in Headers */,
6066
				0FB7F39A15ED8E4600F167B2 /* IndexingHeaderInlines.h in Headers */,
Lines 6145-6150 a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec6
6145
				86E3C613167BABD7006D760A /* JSContext.h in Headers */,
6163
				86E3C613167BABD7006D760A /* JSContext.h in Headers */,
6146
				86E3C617167BABEE006D760A /* JSContextInternal.h in Headers */,
6164
				86E3C617167BABEE006D760A /* JSContextInternal.h in Headers */,
6147
				BC18C41E0E16F5CD00B34460 /* JSContextRef.h in Headers */,
6165
				BC18C41E0E16F5CD00B34460 /* JSContextRef.h in Headers */,
6166
				7B545E511B4605D30029390E /* WasmJITCompiler.h in Headers */,
6148
				148CD1D8108CF902008163C6 /* JSContextRefPrivate.h in Headers */,
6167
				148CD1D8108CF902008163C6 /* JSContextRefPrivate.h in Headers */,
6149
				A72028B81797601E0098028C /* JSCTestRunnerUtils.h in Headers */,
6168
				A72028B81797601E0098028C /* JSCTestRunnerUtils.h in Headers */,
6150
				0F7576D318E1FEE9002EF4CD /* AccessorCallJITStubRoutine.h in Headers */,
6169
				0F7576D318E1FEE9002EF4CD /* AccessorCallJITStubRoutine.h in Headers */,
Lines 7167-7172 a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec7
7167
				0FF0F19C16B72A03005DF95B /* DFGNode.cpp in Sources */,
7186
				0FF0F19C16B72A03005DF95B /* DFGNode.cpp in Sources */,
7168
				0FA581BA150E952C00B9A2D9 /* DFGNodeFlags.cpp in Sources */,
7187
				0FA581BA150E952C00B9A2D9 /* DFGNodeFlags.cpp in Sources */,
7169
				86EC9DCF1328DF82002B2AD7 /* DFGOperations.cpp in Sources */,
7188
				86EC9DCF1328DF82002B2AD7 /* DFGOperations.cpp in Sources */,
7189
				7B545E501B4605C70029390E /* WasmJITCompiler.cpp in Sources */,
7170
				A7D89CFD17A0B8CC00773AD8 /* DFGOSRAvailabilityAnalysisPhase.cpp in Sources */,
7190
				A7D89CFD17A0B8CC00773AD8 /* DFGOSRAvailabilityAnalysisPhase.cpp in Sources */,
7171
				0FD82E56141DAF0800179C94 /* DFGOSREntry.cpp in Sources */,
7191
				0FD82E56141DAF0800179C94 /* DFGOSREntry.cpp in Sources */,
7172
				0FD8A32517D51F5700CA2C40 /* DFGOSREntrypointCreationPhase.cpp in Sources */,
7192
				0FD8A32517D51F5700CA2C40 /* DFGOSREntrypointCreationPhase.cpp in Sources */,
- 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 490-495 static EncodedJSValue JSC_HOST_CALL functionReturnTypeFor(ExecState*); a/Source/JavaScriptCore/jsc.cpp_sec2
490
static EncodedJSValue JSC_HOST_CALL functionDumpBasicBlockExecutionRanges(ExecState*);
491
static EncodedJSValue JSC_HOST_CALL functionDumpBasicBlockExecutionRanges(ExecState*);
491
static EncodedJSValue JSC_HOST_CALL functionHasBasicBlockExecuted(ExecState*);
492
static EncodedJSValue JSC_HOST_CALL functionHasBasicBlockExecuted(ExecState*);
492
static EncodedJSValue JSC_HOST_CALL functionEnableExceptionFuzz(ExecState*);
493
static EncodedJSValue JSC_HOST_CALL functionEnableExceptionFuzz(ExecState*);
494
static EncodedJSValue JSC_HOST_CALL functionLoadWebAssembly(ExecState*);
493
495
494
#if ENABLE(SAMPLING_FLAGS)
496
#if ENABLE(SAMPLING_FLAGS)
495
static EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState*);
497
static EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState*);
Lines 651-656 protected: a/Source/JavaScriptCore/jsc.cpp_sec3
651
        addFunction(vm, "hasBasicBlockExecuted", functionHasBasicBlockExecuted, 2);
653
        addFunction(vm, "hasBasicBlockExecuted", functionHasBasicBlockExecuted, 2);
652
654
653
        addFunction(vm, "enableExceptionFuzz", functionEnableExceptionFuzz, 0);
655
        addFunction(vm, "enableExceptionFuzz", functionEnableExceptionFuzz, 0);
656
657
        addFunction(vm, "loadWebAssembly", functionLoadWebAssembly, 1);
654
        
658
        
655
        JSArray* array = constructEmptyArray(globalExec(), 0);
659
        JSArray* array = constructEmptyArray(globalExec(), 0);
656
        for (size_t i = 0; i < arguments.size(); ++i)
660
        for (size_t i = 0; i < arguments.size(); ++i)
Lines 1165-1170 EncodedJSValue JSC_HOST_CALL functionEnableExceptionFuzz(ExecState*) a/Source/JavaScriptCore/jsc.cpp_sec4
1165
    return JSValue::encode(jsUndefined());
1169
    return JSValue::encode(jsUndefined());
1166
}
1170
}
1167
1171
1172
EncodedJSValue JSC_HOST_CALL functionLoadWebAssembly(ExecState* exec)
1173
{
1174
    String fileName = exec->argument(0).toString(exec)->value(exec);
1175
    Vector<char> buffer;
1176
    if (!fillBufferWithContentsOfFile(fileName, buffer))
1177
        return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Could not open file."))));
1178
    JSValue result = Wasm::compileAndRun(exec, buffer);
1179
    return JSValue::encode(result);
1180
}
1181
1168
// Use SEH for Release builds only to get rid of the crash report dialog
1182
// Use SEH for Release builds only to get rid of the crash report dialog
1169
// (luckily the same tests fail in Release and Debug builds so far). Need to
1183
// (luckily the same tests fail in Release and Debug builds so far). Need to
1170
// be in a separate main function because the jscmain function requires object
1184
// be in a separate main function because the jscmain function requires object
- a/Source/JavaScriptCore/wasm/WasmJITCompiler.cpp +884 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
#include "config.h"
27
#include "WasmJITCompiler.h"
28
29
#include "JITCode.h"
30
#include "JSCallee.h"
31
#include "LinkBuffer.h"
32
#include "ProtoCallFrame.h"
33
34
namespace JSC {
35
36
namespace Wasm {
37
38
class JumpScope {
39
public:
40
    JumpScope(MacroAssembler* macroAssembler)
41
    : m_macroAssembler(macroAssembler)
42
    , m_linked(false)
43
    {
44
    }
45
46
    JumpScope(MacroAssembler* macroAssembler, const MacroAssembler::Label& label)
47
    : m_macroAssembler(macroAssembler)
48
    , m_linked(true)
49
    , m_label(label)
50
    {
51
    }
52
53
    void jump()
54
    {
55
        if (m_linked)
56
            m_macroAssembler->jump(m_label);
57
        else
58
            m_jumpList.append(m_macroAssembler->jump());
59
    }
60
61
    void link()
62
    {
63
        ASSERT(!m_linked);
64
        m_jumpList.link(m_macroAssembler);
65
    }
66
67
private:
68
    MacroAssembler* m_macroAssembler;
69
    bool m_linked;
70
    MacroAssembler::Label m_label;
71
    MacroAssembler::JumpList m_jumpList;
72
};
73
74
JSValue JITCompiler::compileAndRun(ExecState* exec, const Vector<char>& buffer)
75
{
76
    VM& vm = exec->vm();
77
    RefPtr<JITCode> jitCode = compile(vm, buffer);
78
79
    ProtoCallFrame protoCallFrame;
80
    protoCallFrame.init(0, JSCallee::create(vm, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()), jsUndefined(), 1);
81
82
    return jitCode->execute(&vm, &protoCallFrame);
83
}
84
85
RefPtr<JITCode> JITCompiler::compile(VM& vm, const Vector<char>& buffer)
86
{
87
    emitFunctionPrologue();
88
89
    m_read = In(reinterpret_cast<const uint8_t*>(buffer.data()));
90
    if (m_read.fixedWidth<uint32_t>() != MagicNumber)
91
        abort();
92
    m_read.fixedWidth<uint32_t>(); // out_size
93
    unpack();
94
95
    boxInt52(GPRInfo::returnValueGPR, GPRInfo::returnValueGPR, GPRInfo::regT0, FPRInfo::fpRegT0);
96
    emitFunctionEpilogue();
97
    ret();
98
99
    JITCompilationEffort effort = JITCompilationMustSucceed;
100
    LinkBuffer patchBuffer(vm, *this, 0, effort);
101
102
    MacroAssemblerCodePtr withArityCheck;
103
    CodeRef result = FINALIZE_CODE(patchBuffer, ("Baseline JIT code for WebAssembly"));
104
105
    // TODO: should create a new jitType
106
    return adoptRef(new DirectJITCode(result, withArityCheck, JITCode::BaselineJIT));
107
}
108
109
void JITCompiler::unpack()
110
{
111
    readConstantPoolSection();
112
    readSignatureSection();
113
    readFunctionImportSection();
114
    readGlobalSection();
115
    readFunctionDeclarationSection();
116
    readFunctionPointerTables();
117
    readFunctionDefinitionSection();
118
    readExportSection();
119
}
120
121
void JITCompiler::readSignatureSection()
122
{
123
    uint32_t numSignatures = m_read.immU32();
124
    Vector<Signature> signatures(numSignatures);
125
    for (uint32_t signatureIndex = 0; signatureIndex < numSignatures; signatureIndex++) {
126
        RType ret = m_read.rtype();
127
        uint32_t numArgs = m_read.immU32();
128
        Signature signature(ret, numArgs);
129
        for (uint32_t argumentIndex = 0; argumentIndex < numArgs; argumentIndex++)
130
            signature.args[argumentIndex] = m_read.type();
131
        signatures[signatureIndex] = WTF::move(signature);
132
    }
133
134
    m_signatures = WTF::move(signatures);
135
}
136
137
void JITCompiler::readFunctionImportSection()
138
{
139
    uint32_t numFuncImps = m_read.immU32();
140
    uint32_t numFuncImportSignatures = m_read.immU32();
141
142
    Vector<FuncImportSignature> funcImportSignatures(numFuncImportSignatures);
143
    FuncImportSignature* funcImportSignature = funcImportSignatures.data();
144
    for (uint32_t func_imp_i = 0; func_imp_i < numFuncImps; func_imp_i++) {
145
        while (m_read.singleChar()) { }
146
147
        uint32_t numSigs = m_read.immU32();
148
        for (uint32_t i = 0; i < numSigs; i++) {
149
            funcImportSignature->signatureIndex = m_read.immU32();
150
            funcImportSignature->funcImportIndex = func_imp_i;
151
            funcImportSignature++;
152
        }
153
    }
154
    assert(funcImportSignature == funcImportSignatures.data() + numFuncImportSignatures);
155
156
    m_funcImportSignatures = WTF::move(funcImportSignatures);
157
}
158
159
void JITCompiler::readGlobalSection()
160
{
161
    uint32_t num_i32_zero = m_read.immU32();
162
    uint32_t num_f32_zero = m_read.immU32();
163
    uint32_t num_f64_zero = m_read.immU32();
164
    uint32_t num_i32_import = m_read.immU32();
165
    uint32_t num_f32_import = m_read.immU32();
166
    uint32_t num_f64_import = m_read.immU32();
167
168
    uint32_t numGlobalVars = num_i32_zero + num_f32_zero + num_f64_zero + num_i32_import + num_f32_import + num_f64_import;
169
170
    Vector<Type> globalTypes(numGlobalVars);
171
    size_t globalTypeIndex = 0;
172
    for (uint32_t i = 0; i < num_i32_zero; i++) {
173
        globalTypes[globalTypeIndex++] = Type::I32;
174
    }
175
    for (uint32_t i = 0; i < num_f32_zero; i++) {
176
        globalTypes[globalTypeIndex++] = Type::F32;
177
    }
178
    for (uint32_t i = 0; i < num_f64_zero; i++) {
179
        globalTypes[globalTypeIndex++] = Type::F64;
180
    }
181
    for (uint32_t i = 0; i < num_i32_import; i++) {
182
        while (m_read.singleChar()) { }
183
        globalTypes[globalTypeIndex++] = Type::I32;
184
    }
185
    for (uint32_t i = 0; i < num_f32_import; i++) {
186
        while (m_read.singleChar()) { }
187
        globalTypes[globalTypeIndex++] = Type::F32;
188
    }
189
    for (uint32_t i = 0; i < num_f64_import; i++) {
190
        while (m_read.singleChar()) { }
191
        globalTypes[globalTypeIndex++] = Type::F64;
192
    }
193
    m_globalTypes = WTF::move(globalTypes);
194
}
195
196
void JITCompiler::readConstantPoolSection()
197
{
198
    uint32_t numI32s = m_read.immU32();
199
    uint32_t numF32s = m_read.immU32();
200
    uint32_t numF64s = m_read.immU32();
201
202
    Vector<uint32_t> i32s(numI32s);
203
    for (uint32_t i = 0; i < numI32s; i++)
204
        i32s[i] = m_read.immU32();
205
206
    Vector<float> f32s(numF32s);
207
    for (uint32_t i = 0; i < numF32s; i++)
208
        f32s[i] = m_read.fixedWidth<float>();
209
210
    Vector<double> f64s(numF64s);
211
    for (uint32_t i = 0; i < numF64s; i++)
212
        f64s[i] = m_read.fixedWidth<double>();
213
214
    m_i32s = WTF::move(i32s);
215
    m_f32s = WTF::move(f32s);
216
    m_f64s = WTF::move(f64s);
217
}
218
219
void JITCompiler::readFunctionDeclarationSection()
220
{
221
    uint32_t numFuncs = m_read.immU32();
222
    Vector<uint32_t> funcSigs(numFuncs);
223
    for (uint32_t i = 0; i != numFuncs; i++)
224
        funcSigs[i] = m_read.immU32();
225
226
    m_funcSigs = WTF::move(funcSigs);
227
}
228
229
void JITCompiler::readFunctionPointerTables()
230
{
231
    uint32_t numFuncPtrTables = m_read.immU32();
232
    Vector<FuncPtrTable> funcPtrTables(numFuncPtrTables);
233
    for (uint32_t i = 0; i != numFuncPtrTables; i++) {
234
        funcPtrTables[i].signatureIndex = m_read.immU32();
235
        uint32_t num_elements = m_read.immU32();
236
        Vector<uint32_t> elements(num_elements);
237
        for (uint32_t j = 0; j != num_elements; j++)
238
            elements[j] = m_read.immU32();
239
        funcPtrTables[i].elements = WTF::move(elements);
240
    }
241
242
    m_funcPtrTables = WTF::move(funcPtrTables);
243
}
244
245
void JITCompiler::readFunctionDefinitionSection()
246
{
247
    for (size_t i = 0; i < m_funcSigs.size(); i++)
248
        readFunctionDefinition(i);
249
}
250
251
void JITCompiler::readExportSection()
252
{
253
    switch (m_read.exportFormat()) {
254
        case ExportFormat::Default:
255
            m_read.immU32();
256
            break;
257
        case ExportFormat::Record:
258
            if (uint32_t num_exports = m_read.immU32()) {
259
                for (uint32_t export_index = 0;;) {
260
                    while (m_read.singleChar()) { }
261
                    m_read.immU32();
262
                    if (++export_index == num_exports)
263
                        break;
264
                }
265
            }
266
            break;
267
        default:
268
            RELEASE_ASSERT_NOT_REACHED();
269
    }
270
}
271
272
void JITCompiler::readFunctionDefinition(size_t funcIndex)
273
{
274
    const Signature& signature = m_signatures[m_funcSigs[funcIndex]];
275
    m_currentReturnType = signature.ret;
276
    m_currentLocalTypes.clear();
277
    readArgs(signature);
278
    readVars();
279
    stmt_list(0);
280
}
281
282
void JITCompiler::readArgs(const Signature& signature)
283
{
284
    size_t numArgs = signature.args.size();
285
    for (uint32_t argIndex = 0; argIndex < numArgs; argIndex++) {
286
        Type type = signature.args[argIndex];
287
        m_currentLocalTypes.append(type);
288
        switch (type) {
289
            case Type::I32:
290
            case Type::F32:
291
            case Type::F64:
292
                break;
293
            default:
294
                RELEASE_ASSERT_NOT_REACHED();
295
        }
296
    }
297
}
298
299
void JITCompiler::readVars()
300
{
301
    uint32_t numI32Vars = 0;
302
    uint32_t numF32Vars = 0;
303
    uint32_t numF64Vars = 0;
304
305
    VarTypes varTypes;
306
    VarTypesWithImm varTypesWithImm;
307
    uint8_t imm;
308
    if (m_read.code(&varTypes, &varTypesWithImm, &imm)) {
309
        if (varTypes & VarTypes::I32)
310
            numI32Vars = m_read.immU32();
311
        if (varTypes & VarTypes::F32)
312
            numF32Vars = m_read.immU32();
313
        if (varTypes & VarTypes::F64)
314
            numF64Vars = m_read.immU32();
315
    } else {
316
        numI32Vars = imm;
317
    }
318
319
    // FIXME: we need to initialize these to zeroes
320
321
    uint32_t num_vars = numI32Vars + numF32Vars + numF64Vars;
322
    if (num_vars > 0) {
323
        uint32_t localIndex = m_currentLocalTypes.size();
324
        for (uint32_t i = 0; i < numI32Vars; i++) {
325
            m_currentLocalTypes.append(Type::I32);
326
            store32(TrustedImm32(0), stackAddress(localIndex++));
327
        }
328
        for (uint32_t i = 0; i < numF32Vars; i++) {
329
            m_currentLocalTypes.append(Type::F32);
330
            store32(TrustedImm32(0), stackAddress(localIndex++)); // FIXME: float?
331
        }
332
        for (uint32_t i = 0; i < numF64Vars; i++) {
333
            m_currentLocalTypes.append(Type::F64);
334
            store64(TrustedImm64(0), stackAddress(localIndex++)); // FIXME: float?
335
        }
336
    }
337
}
338
339
void JITCompiler::stmt(int dst)
340
{
341
    Stmt stmt;
342
    StmtWithImm stmtWithImm;
343
    uint8_t imm;
344
    if (m_read.code(&stmt, &stmtWithImm, &imm)) {
345
        switch (stmt) {
346
        case Stmt::SetLoc:
347
            set_local(dst);
348
            break;
349
        case Stmt::SetGlo:
350
        case Stmt::I32Store8:
351
        case Stmt::I32StoreOff8:
352
        case Stmt::I32Store16:
353
        case Stmt::I32StoreOff16:
354
        case Stmt::I32Store32:
355
        case Stmt::I32StoreOff32:
356
        case Stmt::F32Store:
357
        case Stmt::F32StoreOff:
358
        case Stmt::F64Store:
359
        case Stmt::F64StoreOff:
360
        case Stmt::CallInt:
361
        case Stmt::CallInd:
362
        case Stmt::CallImp:
363
            RELEASE_ASSERT_NOT_REACHED();
364
        case Stmt::Ret:
365
            return_stmt();
366
            return;
367
        case Stmt::Block:
368
            block_stmt(dst); return;
369
        case Stmt::IfThen:
370
            if_stmt(dst);
371
            return;
372
        case Stmt::IfElse:
373
            if_else_stmt(dst);
374
            return;
375
        case Stmt::While:
376
            while_stmt(dst);
377
            return;
378
        case Stmt::Do:
379
            do_stmt(dst);
380
            return;
381
        case Stmt::Label:
382
            label_stmt(dst);
383
            return;
384
        case Stmt::Break:
385
            topBreakJumpList()->append(jump());
386
            return;
387
        case Stmt::BreakLabel:
388
            break_label_stmt();
389
            return;
390
        case Stmt::Continue:
391
            topContinueJumpScope()->jump();
392
            break;
393
        case Stmt::ContinueLabel:
394
            continue_label_stmt();
395
            return;
396
        case Stmt::Switch:
397
            switch_stmt(dst);
398
            break;
399
        default:
400
            RELEASE_ASSERT_NOT_REACHED();
401
        }
402
    } else {
403
        switch (stmtWithImm) {
404
        case StmtWithImm::SetLoc:
405
            set_local(imm, dst);
406
            break;
407
        case StmtWithImm::SetGlo:
408
        default:
409
            RELEASE_ASSERT_NOT_REACHED();
410
        }
411
    }
412
}
413
414
void JITCompiler::get_local(int dst)
415
{
416
    // FIXME: type
417
    uint32_t imm = m_read.immU32();
418
    load32(stackAddress(imm), GPRInfo::regT0);
419
    store32(GPRInfo::regT0, temporaryAddress(dst));
420
}
421
422
void JITCompiler::set_local(uint32_t imm, int dst)
423
{
424
    Type type = m_currentLocalTypes[imm]; // FIXME: Should we receive the Type from the parent?
425
426
    expr(RType(type), dst);
427
428
    switch (type) {
429
        case Type::I32: {
430
            load32(temporaryAddress(dst), GPRInfo::regT0);
431
            store32(GPRInfo::regT0, stackAddress(imm));
432
            break;
433
        }
434
        case Type::F32:
435
        case Type::F64:
436
        default:
437
            RELEASE_ASSERT_NOT_REACHED();
438
    }
439
}
440
441
void JITCompiler::set_local(int dst)
442
{
443
    set_local(m_read.immU32(), dst);
444
}
445
446
void JITCompiler::return_stmt()
447
{
448
    // FIXME: hacky
449
    switch (m_currentReturnType) {
450
        case RType::I32:
451
            signed_expr(Signedness::Signed, 0);
452
            load32(temporaryAddress(0), GPRInfo::returnValueGPR);
453
            break;
454
        case RType::F32:
455
            expr(RType::F32, 0);
456
            load32(temporaryAddress(0), GPRInfo::returnValueGPR);
457
            break;
458
        case RType::F64:
459
            expr(RType::F64, 0);
460
            load64(temporaryAddress(0), GPRInfo::returnValueGPR);
461
            break;
462
        case RType::Void:
463
            break;
464
    }
465
}
466
467
void JITCompiler::stmt_list(int dst)
468
{
469
    uint32_t num_stmts = m_read.immU32();
470
    for (uint32_t i = 0; i < num_stmts; i++)
471
        stmt(dst);
472
}
473
474
void JITCompiler::block_stmt(int dst)
475
{
476
    stmt_list(dst);
477
}
478
479
void JITCompiler::if_stmt(int dst)
480
{
481
    expr(RType::I32, dst);
482
    load32(temporaryAddress(dst), GPRInfo::regT0);
483
    Jump end = branchTest32(Zero, GPRInfo::regT0);
484
    stmt(dst);
485
    end.link(this);
486
}
487
488
void JITCompiler::if_else_stmt(int dst)
489
{
490
    expr(RType::I32, dst);
491
    load32(temporaryAddress(dst), GPRInfo::regT0);
492
    Jump els = branchTest32(Zero, GPRInfo::regT0);
493
    stmt(dst);
494
    Jump end = jump();
495
    els.link(this);
496
    stmt(dst);
497
    end.link(this);
498
}
499
500
void JITCompiler::while_stmt(int dst)
501
{
502
    JumpScope continueJumpScope(this, label());
503
    pushContinueJumpScope(&continueJumpScope);
504
505
    JumpList breakJumpList;
506
    pushBreakJumpList(&breakJumpList);
507
508
    expr(RType::I32, dst);
509
    load32(temporaryAddress(dst), GPRInfo::regT0);
510
    Jump end = branchTest32(Zero, GPRInfo::regT0);
511
    stmt(dst);
512
    continueJumpScope.jump();
513
    end.link(this);
514
    breakJumpList.link(this);
515
516
    popBreakJumpList();
517
518
    popContinueJumpScope();
519
}
520
521
void JITCompiler::do_stmt(int dst)
522
{
523
    JumpScope continueJumpScope(this);
524
    pushContinueJumpScope(&continueJumpScope);
525
526
    JumpList breakJumpList;
527
    pushBreakJumpList(&breakJumpList);
528
529
    Label start = label();
530
    stmt(dst);
531
    continueJumpScope.link();
532
    expr(RType::I32, dst);
533
    load32(temporaryAddress(dst), GPRInfo::regT0);
534
    Jump jumpToStart = branchTest32(NonZero, GPRInfo::regT0);
535
    jumpToStart.linkTo(start, this);
536
    breakJumpList.link(this);
537
538
    popBreakJumpList();
539
540
    popContinueJumpScope();
541
}
542
543
void JITCompiler::label_stmt(int dst)
544
{
545
    Label continueLabel = label();
546
    JumpList breakJumpList;
547
    pushContinueLabelLabel(&continueLabel);
548
    pushBreakLabelJumpList(&breakJumpList);
549
    stmt(dst);
550
    breakJumpList.link(this);
551
    popBreakLabelJumpList();
552
    popContinueLabelLabel();
553
}
554
555
void JITCompiler::break_label_stmt()
556
{
557
    uint32_t index = m_read.immU32();
558
    breakLabelJumpList(index)->append(jump());
559
}
560
561
void JITCompiler::continue_label_stmt()
562
{
563
    uint32_t index = m_read.immU32();
564
    jump(*continueLabelLabel(index));
565
}
566
567
void JITCompiler::switch_stmt(int dst)
568
{
569
    JumpList breakJumpList;
570
    pushBreakJumpList(&breakJumpList);
571
572
    uint32_t numCases = m_read.immU32();
573
    signed_expr(Signedness::Signed, dst);
574
    load32(temporaryAddress(dst), GPRInfo::regT0);
575
576
    Jump table = jump();
577
578
    Vector<Label> labels;
579
    Vector<int32_t> imms;
580
    Label defaultLabel;
581
    bool hasDefault = false;
582
583
    for (uint32_t i = 0; i < numCases; i++) {
584
        switch (m_read.switchCase()) {
585
            case SwitchCase::Case0:
586
                imms.append(m_read.immS32());
587
                labels.append(label());
588
                break;
589
            case SwitchCase::Case1:
590
                imms.append(m_read.immS32());
591
                labels.append(label());
592
                stmt(dst);
593
                break;
594
            case SwitchCase::CaseN:
595
                imms.append(m_read.immS32());
596
                labels.append(label());
597
                stmt_list(dst);
598
                break;
599
            case SwitchCase::Default0:
600
                defaultLabel = label();
601
                hasDefault = true;
602
                break;
603
            case SwitchCase::Default1:
604
                defaultLabel = label();
605
                hasDefault = true;
606
                stmt(dst);
607
                break;
608
            case SwitchCase::DefaultN:
609
                defaultLabel = label();
610
                hasDefault = true;
611
                stmt_list(dst);
612
                break;
613
            default:
614
                abort();
615
        }
616
    }
617
618
    Jump end = jump();
619
    table.link(this);
620
621
    for (size_t i = 0; i < labels.size(); ++i) {
622
        Jump j = branch32(Equal, GPRInfo::regT0, TrustedImm32(imms[i]));
623
        j.linkTo(labels[i], this);
624
    }
625
    if (hasDefault) {
626
        jump(defaultLabel);
627
    }
628
629
    end.link(this);
630
631
    breakJumpList.link(this);
632
    popBreakJumpList();
633
}
634
635
void JITCompiler::expr(RType rType, int dst)
636
{
637
    I32 i32;
638
    I32WithImm i32_with_imm;
639
    uint8_t imm;
640
641
    if (rType != RType::I32) {
642
        RELEASE_ASSERT_NOT_REACHED();
643
    }
644
645
    if (m_read.code(&i32, &i32_with_imm, &imm)) {
646
        switch (i32) {
647
            case I32::LitImm:
648
                store32(TrustedImm32(m_read.immU32()), temporaryAddress(dst));
649
                break;
650
            case I32::LitPool:
651
            case I32::GetLoc:
652
                get_local(dst); // TODO: should pass I32 as RType
653
                break;
654
            case I32::GetGlo:
655
                RELEASE_ASSERT_NOT_REACHED();
656
            case I32::SetLoc:
657
                set_local(dst); // TODO: should pass I32 as RType
658
                break;
659
            case I32::SetGlo:
660
            case I32::SLoad8:
661
            case I32::SLoadOff8:
662
            case I32::ULoad8:
663
            case I32::ULoadOff8:
664
            case I32::SLoad16:
665
            case I32::SLoadOff16:
666
            case I32::ULoad16:
667
            case I32::ULoadOff16:
668
            case I32::Load32:
669
            case I32::LoadOff32:
670
            case I32::Store8:
671
            case I32::StoreOff8:
672
            case I32::Store16:
673
            case I32::StoreOff16:
674
            case I32::Store32:
675
            case I32::StoreOff32:
676
            case I32::CallInt:
677
            case I32::CallInd:
678
            case I32::CallImp:
679
                RELEASE_ASSERT_NOT_REACHED();
680
            case I32::Cond:
681
                cond(RType::I32, dst);
682
                break;
683
            case I32::Comma:
684
                comma(RType::I32, dst);
685
                break;
686
            case I32::FromF32:
687
            case I32::FromF64:
688
            case I32::Neg:
689
                RELEASE_ASSERT_NOT_REACHED();
690
            case I32::Add:
691
                add_sub('+', RType::I32, dst);
692
                break;
693
            case I32::Sub:
694
                add_sub('-', RType::I32, dst);
695
                break;
696
            case I32::Mul:
697
                mul_i32(dst);
698
                break;
699
            case I32::SDiv:
700
            case I32::UDiv:
701
            case I32::SMod:
702
            case I32::UMod:
703
            case I32::BitNot:
704
            case I32::BitOr:
705
            case I32::BitAnd:
706
            case I32::BitXor:
707
            case I32::Lsh:
708
            case I32::ArithRsh:
709
            case I32::LogicRsh:
710
            case I32::Clz:
711
            case I32::LogicNot:
712
                RELEASE_ASSERT_NOT_REACHED();
713
            case I32::EqI32:
714
                rel_i32(Signedness::Signed, "==", dst);
715
                break;
716
            case I32::EqF32:
717
            case I32::EqF64:
718
                RELEASE_ASSERT_NOT_REACHED();
719
            case I32::NEqI32:
720
                rel_i32(Signedness::Signed, "!=", dst);
721
                break;
722
            case I32::NEqF32:
723
            case I32::NEqF64:
724
                RELEASE_ASSERT_NOT_REACHED();
725
            case I32::SLeThI32:
726
                rel_i32(Signedness::Signed, "<", dst);
727
                break;
728
            case I32::ULeThI32:
729
                rel_i32(Signedness::Unsigned, "<", dst);
730
                break;
731
            case I32::LeThF32:
732
            case I32::LeThF64:
733
                RELEASE_ASSERT_NOT_REACHED();
734
            case I32::SLeEqI32:
735
                rel_i32(Signedness::Signed, "<=", dst);
736
                break;
737
            case I32::ULeEqI32:
738
                rel_i32(Signedness::Unsigned, "<=", dst);
739
                break;
740
            case I32::LeEqF32:
741
            case I32::LeEqF64:
742
                RELEASE_ASSERT_NOT_REACHED();
743
            case I32::SGrThI32:
744
                rel_i32(Signedness::Signed, ">", dst);
745
                break;
746
            case I32::UGrThI32:
747
                rel_i32(Signedness::Unsigned, ">", dst);
748
                break;
749
            case I32::GrThF32:
750
            case I32::GrThF64:
751
                RELEASE_ASSERT_NOT_REACHED();
752
            case I32::SGrEqI32:
753
                rel_i32(Signedness::Signed, ">=", dst);
754
                break;
755
            case I32::UGrEqI32:
756
                rel_i32(Signedness::Unsigned, ">=", dst);
757
                break;
758
            case I32::GrEqF32:
759
            case I32::GrEqF64:
760
            case I32::SMin:
761
            case I32::UMin:
762
            case I32::SMax:
763
            case I32::UMax:
764
            case I32::Abs:
765
            default:
766
                RELEASE_ASSERT_NOT_REACHED();
767
        }
768
    } else {
769
        switch (i32_with_imm) {
770
            case I32WithImm::LitImm:
771
                store32(TrustedImm32(imm), temporaryAddress(dst));
772
                break;
773
            case I32WithImm::LitPool:
774
                store32(TrustedImm32(m_i32s[imm]), temporaryAddress(dst));
775
                break;
776
            case I32WithImm::GetLoc:
777
                load32(stackAddress(imm), GPRInfo::regT0);
778
                store32(GPRInfo::regT0, temporaryAddress(dst));
779
                break;
780
            default:
781
                RELEASE_ASSERT_NOT_REACHED();
782
        }
783
    }
784
}
785
786
void JITCompiler::signed_expr(Signedness signedness, int dst)
787
{
788
    uint32_t u32;
789
    if (m_read.ifI32Lit(m_i32s, &u32)) {
790
        if (signedness == Signedness::Signed) {
791
            store32(TrustedImm32(u32), temporaryAddress(dst));
792
        } else {
793
            store32(TrustedImm32(u32), temporaryAddress(dst)); // FIXME: unsigned
794
            //RELEASE_ASSERT_NOT_REACHED();
795
        }
796
    } else if (signedness == Signedness::Signed) {
797
        //expr<RType::I32>(Ctx::ToI32);
798
        //s.write().ascii("|0");
799
        expr(RType::I32, dst);
800
    } else {
801
        //expr<RType::I32>(Ctx::ToI32);
802
        //s.write().ascii(">>>0");
803
        expr(RType::I32, dst); // FIXME: unsigned
804
    }
805
}
806
807
void JITCompiler::add_sub(char op, RType rType, int dst)
808
{
809
    expr(rType, dst);
810
    expr(rType, dst + 1);
811
    if (op == '+') {
812
        load32(temporaryAddress(dst), GPRInfo::regT0);
813
        load32(temporaryAddress(dst + 1), GPRInfo::regT1);
814
        add32(GPRInfo::regT1, GPRInfo::regT0);
815
        store32(GPRInfo::regT0, temporaryAddress(dst));
816
    } else {
817
        load32(temporaryAddress(dst), GPRInfo::regT0);
818
        load32(temporaryAddress(dst + 1), GPRInfo::regT1);
819
        sub32(GPRInfo::regT1, GPRInfo::regT0);
820
        store32(GPRInfo::regT0, temporaryAddress(dst));
821
    }
822
}
823
824
void JITCompiler::mul_i32(int dst)
825
{
826
    expr(RType::I32, dst);
827
    expr(RType::I32, dst + 1);
828
    load32(temporaryAddress(dst), GPRInfo::regT0);
829
    load32(temporaryAddress(dst + 1), GPRInfo::regT1);
830
    mul32(GPRInfo::regT1, GPRInfo::regT0);
831
    store32(GPRInfo::regT0, temporaryAddress(dst));
832
}
833
834
void JITCompiler::rel_i32(Signedness signedness, const char* op, int dst)
835
{
836
    signed_expr(signedness, dst);
837
    signed_expr(signedness, dst + 1);
838
    load32(temporaryAddress(dst), GPRInfo::regT0);
839
    load32(temporaryAddress(dst + 1), GPRInfo::regT1);
840
    RelationalCondition condition;
841
    if (op[0] == '=' && op[1] == '=' && op[2] == 0) {
842
        condition = Equal;
843
    } else if (op[0] == '!' && op[1] == '=' && op[2] == 0) {
844
        condition = NotEqual;
845
    } else if (op[0] == '>' && op[1] == 0) {
846
        condition = GreaterThan;
847
    } else if (op[0] == '<' && op[1] == 0) {
848
        condition = LessThan;
849
    } else if (op[0] == '>' && op[1] == '=' && op[2] == 0) {
850
        condition = GreaterThanOrEqual;
851
    } else if (op[0] == '<' && op[1] == '=' && op[2] == 0) {
852
        condition = LessThanOrEqual;
853
    } else {
854
        RELEASE_ASSERT_NOT_REACHED();
855
    }
856
    compare32(condition, GPRInfo::regT0, GPRInfo::regT1, GPRInfo::regT0);
857
    store32(GPRInfo::regT0, temporaryAddress(dst));
858
}
859
860
void JITCompiler::comma(RType rType, int dst)
861
{
862
    expr(m_read.rtype(), dst);
863
    expr(rType, dst);
864
}
865
866
void JITCompiler::cond(RType rType, int dst)
867
{
868
    expr(RType::I32, dst);
869
    load32(temporaryAddress(dst), GPRInfo::regT0);
870
    Jump els = branchTest32(Zero, GPRInfo::regT0);
871
    expr(rType, dst);
872
    Jump end = jump();
873
    els.link(this);
874
    expr(rType, dst);
875
    end.link(this);
876
}
877
878
JSValue compileAndRun(ExecState* exec, const Vector<char>& buffer)
879
{
880
    JITCompiler compiler(&exec->vm());
881
    return compiler.compileAndRun(exec, buffer);
882
}
883
884
} } // namespace JSC::Wasm
- a/Source/JavaScriptCore/wasm/WasmJITCompiler.h +145 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
#ifndef WasmJITCompiler_h
27
#define WasmJITCompiler_h
28
29
#include "AssemblyHelpers.h"
30
#include "WasmOpcodes.h"
31
32
namespace JSC {
33
34
class ExecState;
35
class JITCode;
36
class VM;
37
38
namespace Wasm {
39
40
class JumpScope;
41
42
class JITCompiler : private AssemblyHelpers {
43
public:
44
    JITCompiler(VM* vm) : AssemblyHelpers(vm, 0) { }
45
    JSValue compileAndRun(ExecState*, const Vector<char>& buffer);
46
47
private:
48
    struct FuncImportSignature {
49
        uint32_t signatureIndex;
50
        uint32_t funcImportIndex;
51
    };
52
53
    struct FuncPtrTable {
54
        uint32_t signatureIndex;
55
        Vector<uint32_t> elements;
56
    };
57
58
    RefPtr<JITCode> compile(VM&, const Vector<char>& buffer);
59
    void unpack();
60
    void readConstantPoolSection();
61
    void readSignatureSection();
62
    void readFunctionImportSection();
63
    void readGlobalSection();
64
    void readFunctionDeclarationSection();
65
    void readFunctionPointerTables();
66
    void readFunctionDefinitionSection();
67
    void readExportSection();
68
69
    void readFunctionDefinition(size_t funcIndex);
70
    void readArgs(const Signature&);
71
    void readVars();
72
73
    void stmt(int dst);
74
    void get_local(int dst);
75
    void set_local(uint32_t imm, int dst);
76
    void set_local(int dst);
77
    void return_stmt();
78
    void block_stmt(int dst);
79
    void stmt_list(int dst);
80
    void if_stmt(int dst);
81
    void if_else_stmt(int dst);
82
    void while_stmt(int dst);
83
    void do_stmt(int dst);
84
    void label_stmt(int dst);
85
    void break_label_stmt();
86
    void continue_label_stmt();
87
    void switch_stmt(int dst);
88
89
    void expr(RType rType, int dst);
90
    void signed_expr(Signedness, int dst);
91
    void add_sub(char op, RType, int dst);
92
    void mul_i32(int dst);
93
    void rel_i32(Signedness, const char* op, int dst);
94
    void comma(RType, int dst);
95
    void cond(RType, int dst);
96
97
    Address stackAddress(int i) { // FIXME:
98
        return Address(GPRInfo::callFrameRegister, -i * 8 - 8);
99
    }
100
101
    Address temporaryAddress(int i) { // FIXME:
102
        return Address(GPRInfo::callFrameRegister, -(i + m_currentLocalTypes.size()) * 8 - 8);
103
    }
104
105
    void pushContinueLabelLabel(Label* label) { m_continueLabelLabels.append(label); }
106
    void popContinueLabelLabel() { m_continueLabelLabels.removeLast(); }
107
    Label* continueLabelLabel(size_t i) const { return m_continueLabelLabels[i]; }
108
    void pushBreakLabelJumpList(JumpList* jumpList) { m_breakLabelJumpLists.append(jumpList); }
109
    void popBreakLabelJumpList() { m_breakLabelJumpLists.removeLast(); }
110
    JumpList* breakLabelJumpList(size_t i) const { return m_breakLabelJumpLists[i]; }
111
112
    void pushContinueJumpScope(JumpScope* jumpScope) { m_continueJumpScopes.append(jumpScope); }
113
    void popContinueJumpScope() { m_continueJumpScopes.removeLast(); }
114
    JumpScope* topContinueJumpScope() const { return m_continueJumpScopes.last(); }
115
116
    void pushBreakJumpList(JumpList* jumpList) { m_breakJumpLists.append(jumpList); }
117
    void popBreakJumpList() { m_breakJumpLists.removeLast(); }
118
    JumpList* topBreakJumpList() const { return m_breakJumpLists.last(); }
119
120
    In m_read;
121
122
    Vector<Signature> m_signatures;
123
    Vector<uint32_t> m_i32s;
124
    Vector<float> m_f32s;
125
    Vector<double> m_f64s;
126
    Vector<FuncImportSignature> m_funcImportSignatures;
127
    Vector<Type> m_globalTypes;
128
    Vector<uint32_t> m_funcSigs;
129
    Vector<FuncPtrTable> m_funcPtrTables;
130
131
    RType m_currentReturnType;
132
    Vector<Type> m_currentLocalTypes;
133
134
    Vector<MacroAssembler::Label*> m_continueLabelLabels;
135
    Vector<MacroAssembler::JumpList*> m_breakLabelJumpLists;
136
137
    Vector<JumpScope*> m_continueJumpScopes;
138
    Vector<MacroAssembler::JumpList*> m_breakJumpLists;
139
};
140
141
JS_EXPORT_PRIVATE JSValue compileAndRun(ExecState*, const Vector<char>& buffer);
142
143
} } // namespace JSC::Wasm
144
145
#endif // WasmJITCompiler_h
- a/Source/JavaScriptCore/wasm/WasmOpcodes.h +565 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
#ifndef WasmOpcodes_h
27
#define WasmOpcodes_h
28
29
namespace JSC {
30
31
namespace Wasm {
32
33
static const uint32_t MagicNumber = 0x6d736177;
34
35
enum class Stmt : uint8_t {
36
    SetLoc,
37
    SetGlo,
38
    I32Store8,
39
    I32StoreOff8,
40
    I32Store16,
41
    I32StoreOff16,
42
    I32Store32,
43
    I32StoreOff32,
44
    F32Store,
45
    F32StoreOff,
46
    F64Store,
47
    F64StoreOff,
48
    CallInt,
49
    CallInd,
50
    CallImp,
51
    Ret,
52
    Block,
53
    IfThen,
54
    IfElse,
55
    While,
56
    Do,
57
    Label,
58
    Break,
59
    BreakLabel,
60
    Continue,
61
    ContinueLabel,
62
    Switch,
63
64
    Bad
65
};
66
67
enum class StmtWithImm : uint8_t {
68
    SetLoc,
69
    SetGlo,
70
    Reseved1,
71
    Reseved2,
72
73
    Bad
74
};
75
76
enum class SwitchCase : uint8_t {
77
    Case0,
78
    Case1,
79
    CaseN,
80
    Default0,
81
    Default1,
82
    DefaultN
83
};
84
85
enum class I32 : uint8_t {
86
    LitPool,
87
    LitImm,
88
    GetLoc,
89
    GetGlo,
90
    SetLoc,
91
    SetGlo,
92
    SLoad8,
93
    SLoadOff8,
94
    ULoad8,
95
    ULoadOff8,
96
    SLoad16,
97
    SLoadOff16,
98
    ULoad16,
99
    ULoadOff16,
100
    Load32,
101
    LoadOff32,
102
    Store8,
103
    StoreOff8,
104
    Store16,
105
    StoreOff16,
106
    Store32,
107
    StoreOff32,
108
    CallInt,
109
    CallInd,
110
    CallImp,
111
    Cond,
112
    Comma,
113
    FromF32,
114
    FromF64,
115
    Neg,
116
    Add,
117
    Sub,
118
    Mul,
119
    SDiv,
120
    UDiv,
121
    SMod,
122
    UMod,
123
    BitNot,
124
    BitOr,
125
    BitAnd,
126
    BitXor,
127
    Lsh,
128
    ArithRsh,
129
    LogicRsh,
130
    Clz,
131
    LogicNot,
132
    EqI32,
133
    EqF32,
134
    EqF64,
135
    NEqI32,
136
    NEqF32,
137
    NEqF64,
138
    SLeThI32,
139
    ULeThI32,
140
    LeThF32,
141
    LeThF64,
142
    SLeEqI32,
143
    ULeEqI32,
144
    LeEqF32,
145
    LeEqF64,
146
    SGrThI32,
147
    UGrThI32,
148
    GrThF32,
149
    GrThF64,
150
    SGrEqI32,
151
    UGrEqI32,
152
    GrEqF32,
153
    GrEqF64,
154
    SMin,
155
    UMin,
156
    SMax,
157
    UMax,
158
    Abs,
159
160
    Bad
161
};
162
163
enum class I32WithImm : uint8_t {
164
    LitPool,
165
    LitImm,
166
    GetLoc,
167
    Reserved,
168
169
    Bad
170
};
171
172
enum class F32 : uint8_t {
173
    LitPool,
174
    LitImm,
175
    GetLoc,
176
    GetGlo,
177
    SetLoc,
178
    SetGlo,
179
    Load,
180
    LoadOff,
181
    Store,
182
    StoreOff,
183
    CallInt,
184
    CallInd,
185
    Cond,
186
    Comma,
187
    FromS32,
188
    FromU32,
189
    FromF64,
190
    Neg,
191
    Add,
192
    Sub,
193
    Mul,
194
    Div,
195
    Abs,
196
    Ceil,
197
    Floor,
198
    Sqrt,
199
200
    Bad
201
};
202
203
enum class F32WithImm : uint8_t {
204
    LitPool,
205
    GetLoc,
206
    Reserved0,
207
    Reserved1,
208
209
    Bad
210
};
211
212
enum class F64 : uint8_t {
213
    LitPool,
214
    LitImm,
215
    GetLoc,
216
    GetGlo,
217
    SetLoc,
218
    SetGlo,
219
    Load,
220
    LoadOff,
221
    Store,
222
    StoreOff,
223
    CallInt,
224
    CallInd,
225
    CallImp,
226
    Cond,
227
    Comma,
228
    FromS32,
229
    FromU32,
230
    FromF32,
231
    Neg,
232
    Add,
233
    Sub,
234
    Mul,
235
    Div,
236
    Mod,
237
    Min,
238
    Max,
239
    Abs,
240
    Ceil,
241
    Floor,
242
    Sqrt,
243
    Cos,
244
    Sin,
245
    Tan,
246
    ACos,
247
    ASin,
248
    ATan,
249
    ATan2,
250
    Exp,
251
    Ln,
252
    Pow,
253
254
    Bad
255
};
256
257
enum class F64WithImm : uint8_t {
258
    LitPool,
259
    GetLoc,
260
    Reserved0,
261
    Reserved1,
262
263
    Bad
264
};
265
266
enum class Void : uint8_t {
267
    CallInt,
268
    CallInd,
269
    CallImp,
270
271
    Bad
272
};
273
274
enum class Type : uint8_t {
275
    I32,
276
    F32,
277
    F64
278
};
279
280
enum class VarTypes : uint8_t {
281
    I32 = 0x1,
282
    F32 = 0x2,
283
    F64 = 0x4,
284
};
285
286
inline VarTypes operator|(VarTypes lhs, VarTypes rhs) { return VarTypes(uint8_t(lhs) | uint8_t(rhs)); }
287
inline bool operator&(VarTypes lhs, VarTypes rhs) { return bool(uint8_t(lhs) & uint8_t(rhs)); }
288
289
enum class VarTypesWithImm : uint8_t {
290
    OnlyI32,
291
    Reserved0,
292
    Reserved1,
293
    Reserved2
294
};
295
296
enum class RType : uint8_t {
297
    I32 = uint8_t(Type::I32),
298
    F32 = uint8_t(Type::F32),
299
    F64 = uint8_t(Type::F64),
300
    Void
301
};
302
303
class Expr {
304
public:
305
    Expr() : m_type(RType(-1)), u{} {}
306
    static Expr Bad() { return Expr(); }
307
    Expr(I32 i32) : m_type(RType::I32) { assert(i32 < I32::Bad); u.i32 = i32; }
308
    Expr(F32 f32) : m_type(RType::F32) { assert(f32 < F32::Bad); u.f32 = f32; }
309
    Expr(F64 f64) : m_type(RType::F64) { assert(f64 < F64::Bad); u.f64 = f64; }
310
    Expr(Void v) : m_type(RType::Void) { assert(v < Void::Bad); u.v = v; }
311
312
    bool is_bad() const { return m_type == RType(-1); }
313
    RType type() const { assert(!is_bad()); return m_type; }
314
    I32 i32() const { assert(m_type == RType::I32); return u.i32; }
315
    F32 f32() const { assert(m_type == RType::F32); return u.f32; }
316
    F64 f64() const { assert(m_type == RType::F64); return u.f64; }
317
318
    bool operator==(Expr rhs) const { return m_type == rhs.m_type && u.raw == rhs.u.raw; }
319
    bool operator!=(Expr rhs) const { return !(*this == rhs); }
320
321
private:
322
    RType m_type;
323
    union U {
324
        I32 i32;
325
        F32 f32;
326
        F64 f64;
327
        Void v;
328
        uint8_t raw;
329
    } u;
330
331
    static_assert(sizeof(U) == sizeof(uint8_t), "Exact overlay of raw_");
332
};
333
334
static const uint8_t HasImmFlag = 0x80;
335
static_assert(uint8_t(I32::Bad) <= HasImmFlag, "MSB reserved to distinguish I32 from I32WithImm");
336
static_assert(uint8_t(F32::Bad) <= HasImmFlag, "MSB reserved to distinguish F32 from F32WithImm");
337
static_assert(uint8_t(F64::Bad) <= HasImmFlag, "MSB reserved to distinguish F64 from F64WithImm");
338
339
static const unsigned OpWithImmBits = 2;
340
static const uint32_t OpWithImmLimit = 1 << OpWithImmBits;
341
static_assert(uint8_t(I32WithImm::Bad) <= OpWithImmLimit, "I32WithImm op fits");
342
static_assert(uint8_t(F32WithImm::Bad) <= OpWithImmLimit, "F32WithImm op fits");
343
static_assert(uint8_t(F64WithImm::Bad) <= OpWithImmLimit, "F64WithImm op fits");
344
345
static const unsigned ImmBits = 5;
346
static const uint32_t ImmLimit = 1 << ImmBits;
347
static_assert(1 + OpWithImmBits + ImmBits == 8, "Bits of immediate op should add up to a byte");
348
349
static inline uint8_t PackOpWithImm(uint8_t op, uint8_t imm)
350
{
351
    assert(op < OpWithImmLimit);
352
    assert(imm < ImmLimit);
353
    return HasImmFlag | (uint8_t(op) << ImmBits) | imm;
354
}
355
356
template <class TWithImm>
357
static inline void UnpackOpWithImm(uint8_t byte, TWithImm* op, uint8_t *imm)
358
{
359
    assert(byte & HasImmFlag);
360
    *op = TWithImm((byte >> ImmBits) & (OpWithImmLimit - 1));
361
    *imm = byte & (ImmLimit - 1);
362
}
363
364
class ExprWithImm {
365
public:
366
    ExprWithImm() : m_type(Type(-1)) {}
367
    ExprWithImm(I32WithImm i32) : m_type(Type::I32) { assert(i32 < I32WithImm::Bad); u.i32 = i32; }
368
    ExprWithImm(F32WithImm f32) : m_type(Type::F32) { assert(f32 < F32WithImm::Bad); u.f32 = f32; }
369
    ExprWithImm(F64WithImm f64) : m_type(Type::F64) { assert(f64 < F64WithImm::Bad); u.f64 = f64; }
370
371
    bool is_bad() const { return m_type == Type(-1); }
372
    Type type() const { return m_type; }
373
    I32WithImm i32() const { assert(m_type == Type::I32); return u.i32; }
374
    F32WithImm f32() const { assert(m_type == Type::F32); return u.f32; }
375
    F64WithImm f64() const { assert(m_type == Type::F64); return u.f64; }
376
377
private:
378
    Type m_type;
379
    union U {
380
        I32WithImm i32;
381
        F32WithImm f32;
382
        F64WithImm f64;
383
        uint8_t raw;
384
    } u;
385
386
    static_assert(sizeof(U) == sizeof(uint8_t), "Exact overlay of raw_");
387
};
388
389
enum class ExportFormat : uint8_t {
390
    Default,
391
    Record
392
};
393
394
enum class Signedness { Signed, Unsigned };
395
396
struct Signature {
397
    RType ret;
398
    Vector<Type> args;
399
400
    Signature() {}
401
    Signature(RType ret) : ret(ret) {}
402
    Signature(RType ret, uint32_t numArgs) : ret(ret), args(numArgs) {}
403
    Signature(RType ret, Vector<Type>&& args) : ret(ret), args(WTF::move(args)) {}
404
405
    bool operator==(const Signature& rhs) const { return ret == rhs.ret && args == rhs.args; }
406
    bool operator!=(const Signature& rhs) const { return !(*this == rhs); }
407
408
    struct Hash {
409
        bool operator()(const Signature &sig) const {
410
            static_assert(sizeof(Type) == 1 && sizeof(RType) == 1, "Shift more");
411
            uint32_t h = uint8_t(sig.ret);
412
            for (Type t : sig.args)
413
                h = ((h << 2) | uint8_t(t)) ^ (h >> 30);
414
            return h;
415
        }
416
    };
417
};
418
419
class In {
420
public:
421
    In() { }
422
    In(const uint8_t* begin) : m_cursor(begin) { }
423
424
    template <class T> T fixedWidth();
425
    Stmt stmt() { return u8<Stmt>(); }
426
    SwitchCase switchCase() { return u8<SwitchCase>(); }
427
    template<class T, class TWithImm> inline bool code(T*, TWithImm*, uint8_t*);
428
    Void voidExpr() { return u8<Void>(); }
429
    ExportFormat exportFormat() { return u8<ExportFormat>(); }
430
    Type type() { return u8<Type>(); }
431
    RType rtype() { return u8<RType>(); }
432
    inline uint32_t immU32();
433
    inline int32_t immS32();
434
    char singleChar() { return *m_cursor++; }
435
436
    inline bool ifI32Lit(const Vector<uint32_t>& i32s, uint32_t* u32);
437
438
private:
439
    template <class T> T u8() { return T(*m_cursor++); }
440
441
    const uint8_t* m_cursor;
442
};
443
444
template <>
445
inline uint32_t In::fixedWidth<uint32_t>()
446
{
447
    uint32_t u32 = m_cursor[0] | m_cursor[1] << 8 | m_cursor[2] << 16 | m_cursor[3] << 24;
448
    m_cursor += 4;
449
    return u32;
450
}
451
452
template <>
453
inline float In::fixedWidth<float>()
454
{
455
    union {
456
        uint8_t arr[4];
457
        float f;
458
    } u = { { m_cursor[0], m_cursor[1], m_cursor[2], m_cursor[3] } };
459
    m_cursor += 4;
460
    return u.f;
461
}
462
463
template <>
464
inline double In::fixedWidth<double>()
465
{
466
    union {
467
        uint8_t arr[8];
468
        double d;
469
    } 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] } };
470
    m_cursor += 8;
471
    return u.d;
472
}
473
474
template <class T, class TWithImm>
475
bool In::code(T* t, TWithImm* tWithImm, uint8_t* imm)
476
{
477
    uint8_t byte = *m_cursor++;
478
    if (!(byte & HasImmFlag)) {
479
        *t = T(byte);
480
        return true;
481
    }
482
483
    UnpackOpWithImm(byte, tWithImm, imm);
484
    return false;
485
}
486
487
inline uint32_t In::immU32()
488
{
489
    uint32_t u32 = *m_cursor++;
490
    if (u32 < 0x80)
491
        return u32;
492
493
    u32 &= 0x7f;
494
495
    for (unsigned shift = 7; true; shift += 7) {
496
        uint32_t b = *m_cursor++;
497
        if (b < 0x80)
498
            return u32 | (b << shift);
499
        u32 |= (b & 0x7f) << shift;
500
    }
501
}
502
503
inline int32_t In::immS32()
504
{
505
    uint32_t u32 = *m_cursor++;
506
    if (u32 < 0x80)
507
        return int32_t(u32) << (32-7) >> (32-7);
508
509
    u32 &= 0x7f;
510
511
    for (unsigned shift = 7; true; shift += 7) {
512
        uint32_t b = *m_cursor++;
513
        if (b < 0x80) {
514
            u32 |= b << shift;
515
            int sign_extend = (32-7) - shift;
516
            if (sign_extend > 0)
517
                return int32_t(u32) << sign_extend >> sign_extend;
518
            return int32_t(u32);
519
        }
520
        u32 |= (b & 0x7f) << shift;
521
    }
522
}
523
524
inline bool In::ifI32Lit(const Vector<uint32_t>& i32s, uint32_t* u32)
525
{
526
    uint8_t byte = *m_cursor;
527
528
    if (byte & HasImmFlag) {
529
        I32WithImm i32WithImm;
530
        uint8_t imm;
531
        UnpackOpWithImm(byte, &i32WithImm, &imm);
532
533
        if (i32WithImm == I32WithImm::LitImm) {
534
            m_cursor++;
535
            *u32 = imm;
536
            return true;
537
        }
538
539
        if (i32WithImm == I32WithImm::LitPool) {
540
            m_cursor++;
541
            *u32 = i32s[imm];
542
            return true;
543
        }
544
545
        return false;
546
    }
547
548
    if (I32(byte) == I32::LitImm) {
549
        m_cursor++;
550
        *u32 = immU32();
551
        return true;
552
    }
553
554
    if (I32(byte) == I32::LitPool) {
555
        m_cursor++;
556
        *u32 = i32s[immU32()];
557
        return true;
558
    }
559
560
    return false;
561
}
562
563
} } // namespace JSC::Wasm
564
565
#endif // WasmOpcodes_h

Return to Bug 146064