1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
4 * Copyright 2021 Mozilla Foundation
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
19 #include "wasm/WasmCodegenTypes.h"
21 #include "wasm/WasmExprType.h"
22 #include "wasm/WasmStubs.h"
23 #include "wasm/WasmTypeDef.h"
24 #include "wasm/WasmValidate.h"
25 #include "wasm/WasmValue.h"
27 using mozilla::MakeEnumeratedRange
;
28 using mozilla::PodZero
;
31 using namespace js::wasm
;
33 ArgTypeVector::ArgTypeVector(const FuncType
& funcType
)
34 : args_(funcType
.args()),
35 hasStackResults_(ABIResultIter::HasStackResults(
36 ResultType::Vector(funcType
.results()))) {}
38 bool TrapSiteVectorArray::empty() const {
39 for (Trap trap
: MakeEnumeratedRange(Trap::Limit
)) {
40 if (!(*this)[trap
].empty()) {
49 const char* js::wasm::NameOfTrap(Trap trap
) {
51 case Trap::Unreachable
:
53 case Trap::IntegerOverflow
:
54 return "IntegerOverflow";
55 case Trap::InvalidConversionToInteger
:
56 return "InvalidConversionToInteger";
57 case Trap::IntegerDivideByZero
:
58 return "IntegerDivideByZero";
59 case Trap::OutOfBounds
:
61 case Trap::UnalignedAccess
:
62 return "UnalignedAccess";
63 case Trap::IndirectCallToNull
:
64 return "IndirectCallToNull";
65 case Trap::IndirectCallBadSig
:
66 return "IndirectCallBadSig";
67 case Trap::NullPointerDereference
:
68 return "NullPointerDereference";
71 case Trap::StackOverflow
:
72 return "StackOverflow";
73 case Trap::CheckInterrupt
:
74 return "CheckInterrupt";
75 case Trap::ThrowReported
:
76 return "ThrowReported";
80 return "NameOfTrap:unknown";
84 const char* js::wasm::NameOfTrapMachineInsn(TrapMachineInsn tmi
) {
86 case TrapMachineInsn::OfficialUD
:
88 case TrapMachineInsn::Load8
:
90 case TrapMachineInsn::Load16
:
92 case TrapMachineInsn::Load32
:
94 case TrapMachineInsn::Load64
:
96 case TrapMachineInsn::Load128
:
98 case TrapMachineInsn::Store8
:
100 case TrapMachineInsn::Store16
:
102 case TrapMachineInsn::Store32
:
104 case TrapMachineInsn::Store64
:
106 case TrapMachineInsn::Store128
:
108 case TrapMachineInsn::Atomic
:
111 return "NameOfTrapMachineInsn::unknown";
116 void TrapSiteVectorArray::clear() {
117 for (Trap trap
: MakeEnumeratedRange(Trap::Limit
)) {
118 (*this)[trap
].clear();
122 void TrapSiteVectorArray::swap(TrapSiteVectorArray
& rhs
) {
123 for (Trap trap
: MakeEnumeratedRange(Trap::Limit
)) {
124 (*this)[trap
].swap(rhs
[trap
]);
128 void TrapSiteVectorArray::shrinkStorageToFit() {
129 for (Trap trap
: MakeEnumeratedRange(Trap::Limit
)) {
130 (*this)[trap
].shrinkStorageToFit();
134 size_t TrapSiteVectorArray::sumOfLengths() const {
136 for (Trap trap
: MakeEnumeratedRange(Trap::Limit
)) {
137 ret
+= (*this)[trap
].length();
142 size_t TrapSiteVectorArray::sizeOfExcludingThis(
143 MallocSizeOf mallocSizeOf
) const {
145 for (Trap trap
: MakeEnumeratedRange(Trap::Limit
)) {
146 ret
+= (*this)[trap
].sizeOfExcludingThis(mallocSizeOf
);
151 CodeRange::CodeRange(Kind kind
, Offsets offsets
)
152 : begin_(offsets
.begin
), ret_(0), end_(offsets
.end
), kind_(kind
) {
153 MOZ_ASSERT(begin_
<= end_
);
162 MOZ_CRASH("should use more specific constructor");
167 CodeRange::CodeRange(Kind kind
, uint32_t funcIndex
, Offsets offsets
)
168 : begin_(offsets
.begin
), ret_(0), end_(offsets
.end
), kind_(kind
) {
169 u
.funcIndex_
= funcIndex
;
170 u
.func
.lineOrBytecode_
= 0;
171 u
.func
.beginToUncheckedCallEntry_
= 0;
172 u
.func
.beginToTierEntry_
= 0;
173 u
.func
.hasUnwindInfo_
= false;
174 MOZ_ASSERT(isEntry());
175 MOZ_ASSERT(begin_
<= end_
);
178 CodeRange::CodeRange(Kind kind
, CallableOffsets offsets
)
179 : begin_(offsets
.begin
), ret_(offsets
.ret
), end_(offsets
.end
), kind_(kind
) {
180 MOZ_ASSERT(begin_
< ret_
);
181 MOZ_ASSERT(ret_
< end_
);
189 MOZ_CRASH("should use more specific constructor");
194 CodeRange::CodeRange(Kind kind
, uint32_t funcIndex
, CallableOffsets offsets
)
195 : begin_(offsets
.begin
), ret_(offsets
.ret
), end_(offsets
.end
), kind_(kind
) {
196 MOZ_ASSERT(isImportExit() || isJitEntry());
197 MOZ_ASSERT(begin_
< ret_
);
198 MOZ_ASSERT(ret_
< end_
);
199 u
.funcIndex_
= funcIndex
;
200 u
.func
.lineOrBytecode_
= 0;
201 u
.func
.beginToUncheckedCallEntry_
= 0;
202 u
.func
.beginToTierEntry_
= 0;
203 u
.func
.hasUnwindInfo_
= false;
206 CodeRange::CodeRange(uint32_t funcIndex
, uint32_t funcLineOrBytecode
,
207 FuncOffsets offsets
, bool hasUnwindInfo
)
208 : begin_(offsets
.begin
),
212 MOZ_ASSERT(begin_
< ret_
);
213 MOZ_ASSERT(ret_
< end_
);
214 MOZ_ASSERT(offsets
.uncheckedCallEntry
- begin_
<= UINT16_MAX
);
215 MOZ_ASSERT(offsets
.tierEntry
- begin_
<= UINT16_MAX
);
216 u
.funcIndex_
= funcIndex
;
217 u
.func
.lineOrBytecode_
= funcLineOrBytecode
;
218 u
.func
.beginToUncheckedCallEntry_
= offsets
.uncheckedCallEntry
- begin_
;
219 u
.func
.beginToTierEntry_
= offsets
.tierEntry
- begin_
;
220 u
.func
.hasUnwindInfo_
= hasUnwindInfo
;
223 const CodeRange
* wasm::LookupInSorted(const CodeRangeVector
& codeRanges
,
224 CodeRange::OffsetInCode target
) {
225 size_t lowerBound
= 0;
226 size_t upperBound
= codeRanges
.length();
229 if (!BinarySearch(codeRanges
, lowerBound
, upperBound
, target
, &match
)) {
233 return &codeRanges
[match
];
236 CallIndirectId
CallIndirectId::forAsmJSFunc() {
237 return CallIndirectId(CallIndirectIdKind::AsmJS
);
240 CallIndirectId
CallIndirectId::forFunc(const ModuleEnvironment
& moduleEnv
,
241 uint32_t funcIndex
) {
242 // asm.js tables are homogenous and don't require a signature check
243 if (moduleEnv
.isAsmJS()) {
244 return CallIndirectId::forAsmJSFunc();
247 FuncDesc func
= moduleEnv
.funcs
[funcIndex
];
248 if (!func
.canRefFunc()) {
249 return CallIndirectId();
251 return CallIndirectId::forFuncType(moduleEnv
,
252 moduleEnv
.funcs
[funcIndex
].typeIndex
);
255 CallIndirectId
CallIndirectId::forFuncType(const ModuleEnvironment
& moduleEnv
,
256 uint32_t funcTypeIndex
) {
257 // asm.js tables are homogenous and don't require a signature check
258 if (moduleEnv
.isAsmJS()) {
259 return CallIndirectId::forAsmJSFunc();
262 const TypeDef
& typeDef
= moduleEnv
.types
->type(funcTypeIndex
);
263 const FuncType
& funcType
= typeDef
.funcType();
264 CallIndirectId callIndirectId
;
265 if (funcType
.hasImmediateTypeId()) {
266 callIndirectId
.kind_
= CallIndirectIdKind::Immediate
;
267 callIndirectId
.immediate_
= funcType
.immediateTypeId();
269 callIndirectId
.kind_
= CallIndirectIdKind::Global
;
270 callIndirectId
.global_
.instanceDataOffset_
=
271 moduleEnv
.offsetOfTypeDef(funcTypeIndex
);
272 callIndirectId
.global_
.hasSuperType_
= typeDef
.superTypeDef() != nullptr;
274 return callIndirectId
;
277 CalleeDesc
CalleeDesc::function(uint32_t funcIndex
) {
280 c
.u
.funcIndex_
= funcIndex
;
283 CalleeDesc
CalleeDesc::import(uint32_t instanceDataOffset
) {
286 c
.u
.import
.instanceDataOffset_
= instanceDataOffset
;
289 CalleeDesc
CalleeDesc::wasmTable(const ModuleEnvironment
& moduleEnv
,
290 const TableDesc
& desc
, uint32_t tableIndex
,
291 CallIndirectId callIndirectId
) {
293 c
.which_
= WasmTable
;
294 c
.u
.table
.instanceDataOffset_
=
295 moduleEnv
.offsetOfTableInstanceData(tableIndex
);
296 c
.u
.table
.minLength_
= desc
.initialLength
;
297 c
.u
.table
.maxLength_
= desc
.maximumLength
;
298 c
.u
.table
.callIndirectId_
= callIndirectId
;
301 CalleeDesc
CalleeDesc::asmJSTable(const ModuleEnvironment
& moduleEnv
,
302 uint32_t tableIndex
) {
304 c
.which_
= AsmJSTable
;
305 c
.u
.table
.instanceDataOffset_
=
306 moduleEnv
.offsetOfTableInstanceData(tableIndex
);
309 CalleeDesc
CalleeDesc::builtin(SymbolicAddress callee
) {
312 c
.u
.builtin_
= callee
;
315 CalleeDesc
CalleeDesc::builtinInstanceMethod(SymbolicAddress callee
) {
317 c
.which_
= BuiltinInstanceMethod
;
318 c
.u
.builtin_
= callee
;
321 CalleeDesc
CalleeDesc::wasmFuncRef() {