Bug 1865597 - Add error checking when initializing parallel marking and disable on...
[gecko.git] / js / src / vm / BytecodeLocation.h
blobe5876ed9d2811a139250d28c52ee04d4e1cb3931
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:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef vm_BytecodeLocation_h
8 #define vm_BytecodeLocation_h
10 #include "frontend/NameAnalysisTypes.h"
11 #include "js/TypeDecls.h"
12 #include "vm/AsyncFunctionResolveKind.h"
13 #include "vm/BuiltinObjectKind.h"
14 #include "vm/BytecodeUtil.h"
15 #include "vm/CheckIsObjectKind.h" // CheckIsObjectKind
16 #include "vm/CompletionKind.h" // CompletionKind
17 #include "vm/FunctionPrefixKind.h" // FunctionPrefixKind
18 #include "vm/GeneratorResumeKind.h"
20 namespace js {
22 using RawBytecodeLocationOffset = uint32_t;
24 class PropertyName;
25 class RegExpObject;
27 class BytecodeLocationOffset {
28 RawBytecodeLocationOffset rawOffset_;
30 public:
31 explicit BytecodeLocationOffset(RawBytecodeLocationOffset offset)
32 : rawOffset_(offset) {}
34 RawBytecodeLocationOffset rawOffset() const { return rawOffset_; }
37 using RawBytecode = jsbytecode*;
39 // A immutable representation of a program location
41 class BytecodeLocation {
42 RawBytecode rawBytecode_;
43 #ifdef DEBUG
44 const JSScript* debugOnlyScript_;
45 #endif
47 // Construct a new BytecodeLocation, while borrowing scriptIdentity
48 // from some other BytecodeLocation.
49 BytecodeLocation(const BytecodeLocation& loc, RawBytecode pc)
50 : rawBytecode_(pc)
51 #ifdef DEBUG
53 debugOnlyScript_(loc.debugOnlyScript_)
54 #endif
56 MOZ_ASSERT(isValid());
59 public:
60 // Disallow the creation of an uninitialized location.
61 BytecodeLocation() = delete;
63 BytecodeLocation(const JSScript* script, RawBytecode pc)
64 : rawBytecode_(pc)
65 #ifdef DEBUG
67 debugOnlyScript_(script)
68 #endif
70 MOZ_ASSERT(isValid());
73 RawBytecode toRawBytecode() const { return rawBytecode_; }
75 #ifdef DEBUG
76 // Return true if this bytecode location is valid for the given script.
77 // This includes the location 1-past the end of the bytecode.
78 bool isValid(const JSScript* script) const;
80 // Return true if this bytecode location is within the bounds of the
81 // bytecode for a given script.
82 bool isInBounds(const JSScript* script) const;
84 const JSScript* getDebugOnlyScript() const;
85 #endif
87 inline uint32_t bytecodeToOffset(const JSScript* script) const;
89 inline uint32_t tableSwitchCaseOffset(const JSScript* script,
90 uint32_t caseIndex) const;
92 inline uint32_t getJumpTargetOffset(const JSScript* script) const;
94 inline uint32_t getTableSwitchDefaultOffset(const JSScript* script) const;
96 inline BytecodeLocation getTableSwitchDefaultTarget() const;
97 inline BytecodeLocation getTableSwitchCaseTarget(const JSScript* script,
98 uint32_t caseIndex) const;
100 inline uint32_t useCount() const;
101 inline uint32_t defCount() const;
103 int32_t jumpOffset() const { return GET_JUMP_OFFSET(rawBytecode_); }
105 inline JSAtom* getAtom(const JSScript* script) const;
106 inline JSString* getString(const JSScript* script) const;
107 inline PropertyName* getPropertyName(const JSScript* script) const;
108 inline JS::BigInt* getBigInt(const JSScript* script) const;
109 inline JSObject* getObject(const JSScript* script) const;
110 inline JSFunction* getFunction(const JSScript* script) const;
111 inline js::RegExpObject* getRegExp(const JSScript* script) const;
112 inline js::Scope* getScope(const JSScript* script) const;
114 uint32_t getSymbolIndex() const {
115 MOZ_ASSERT(is(JSOp::Symbol));
116 return GET_UINT8(rawBytecode_);
119 inline Scope* innermostScope(const JSScript* script) const;
121 #ifdef DEBUG
122 bool hasSameScript(const BytecodeLocation& other) const {
123 return debugOnlyScript_ == other.debugOnlyScript_;
125 #endif
127 // Overloaded operators
129 bool operator==(const BytecodeLocation& other) const {
130 MOZ_ASSERT(this->debugOnlyScript_ == other.debugOnlyScript_);
131 return rawBytecode_ == other.rawBytecode_;
134 bool operator!=(const BytecodeLocation& other) const {
135 return !(other == *this);
138 bool operator<(const BytecodeLocation& other) const {
139 MOZ_ASSERT(this->debugOnlyScript_ == other.debugOnlyScript_);
140 return rawBytecode_ < other.rawBytecode_;
143 // It is traditional to represent the rest of the relational operators
144 // using operator<, so we don't need to assert for these.
145 bool operator>(const BytecodeLocation& other) const { return other < *this; }
147 bool operator<=(const BytecodeLocation& other) const {
148 return !(other < *this);
151 bool operator>=(const BytecodeLocation& other) const {
152 return !(*this < other);
155 // Return the next bytecode
156 BytecodeLocation next() const {
157 return BytecodeLocation(*this,
158 rawBytecode_ + GetBytecodeLength(rawBytecode_));
161 // Add an offset.
162 BytecodeLocation operator+(const BytecodeLocationOffset& offset) const {
163 return BytecodeLocation(*this, rawBytecode_ + offset.rawOffset());
166 // Identity Checks
167 bool is(JSOp op) const {
168 MOZ_ASSERT(isInBounds());
169 return getOp() == op;
172 // Accessors:
174 uint32_t length() const { return GetBytecodeLength(rawBytecode_); }
176 bool isJumpTarget() const { return BytecodeIsJumpTarget(getOp()); }
178 bool isJump() const { return IsJumpOpcode(getOp()); }
180 bool isBackedge() const { return IsBackedgePC(rawBytecode_); }
182 bool isBackedgeForLoophead(BytecodeLocation loopHead) const {
183 return IsBackedgeForLoopHead(rawBytecode_, loopHead.rawBytecode_);
186 bool opHasIC() const { return BytecodeOpHasIC(getOp()); }
188 bool fallsThrough() const { return BytecodeFallsThrough(getOp()); }
190 uint32_t icIndex() const { return GET_ICINDEX(rawBytecode_); }
192 uint32_t local() const { return GET_LOCALNO(rawBytecode_); }
194 uint16_t arg() const { return GET_ARGNO(rawBytecode_); }
196 bool isEqualityOp() const { return IsEqualityOp(getOp()); }
198 bool isStrictEqualityOp() const { return IsStrictEqualityOp(getOp()); }
200 bool isStrictSetOp() const { return IsStrictSetPC(rawBytecode_); }
202 bool isNameOp() const { return IsNameOp(getOp()); }
204 bool isSpreadOp() const { return IsSpreadOp(getOp()); }
206 bool isInvokeOp() const { return IsInvokeOp(getOp()); }
208 bool isGetPropOp() const { return IsGetPropOp(getOp()); }
209 bool isGetElemOp() const { return IsGetElemOp(getOp()); }
211 bool isSetPropOp() const { return IsSetPropOp(getOp()); }
212 bool isSetElemOp() const { return IsSetElemOp(getOp()); }
214 AsyncFunctionResolveKind getAsyncFunctionResolveKind() {
215 return AsyncFunctionResolveKind(GET_UINT8(rawBytecode_));
218 bool resultIsPopped() const {
219 MOZ_ASSERT(StackDefs(getOp()) == 1);
220 return BytecodeIsPopped(rawBytecode_);
223 // Accessors:
224 JSOp getOp() const { return JSOp(*rawBytecode_); }
226 BytecodeLocation getJumpTarget() const {
227 MOZ_ASSERT(isJump());
228 return BytecodeLocation(*this,
229 rawBytecode_ + GET_JUMP_OFFSET(rawBytecode_));
232 // Return the 'low' parameter to the tableswitch opcode
233 int32_t getTableSwitchLow() const {
234 MOZ_ASSERT(is(JSOp::TableSwitch));
235 return GET_JUMP_OFFSET(rawBytecode_ + JUMP_OFFSET_LEN);
238 // Return the 'high' parameter to the tableswitch opcode
239 int32_t getTableSwitchHigh() const {
240 MOZ_ASSERT(is(JSOp::TableSwitch));
241 return GET_JUMP_OFFSET(rawBytecode_ + (2 * JUMP_OFFSET_LEN));
244 uint32_t getPopCount() const {
245 MOZ_ASSERT(is(JSOp::PopN));
246 return GET_UINT16(rawBytecode_);
249 uint32_t getDupAtIndex() const {
250 MOZ_ASSERT(is(JSOp::DupAt));
251 return GET_UINT24(rawBytecode_);
254 uint8_t getPickDepth() const {
255 MOZ_ASSERT(is(JSOp::Pick));
256 return GET_UINT8(rawBytecode_);
258 uint8_t getUnpickDepth() const {
259 MOZ_ASSERT(is(JSOp::Unpick));
260 return GET_UINT8(rawBytecode_);
263 uint32_t getEnvCalleeNumHops() const {
264 MOZ_ASSERT(is(JSOp::EnvCallee));
265 return GET_UINT8(rawBytecode_);
268 EnvironmentCoordinate getEnvironmentCoordinate() const {
269 MOZ_ASSERT(JOF_OPTYPE(getOp()) == JOF_ENVCOORD);
270 return EnvironmentCoordinate(rawBytecode_);
273 uint32_t getCallArgc() const {
274 MOZ_ASSERT(JOF_OPTYPE(getOp()) == JOF_ARGC);
275 return GET_ARGC(rawBytecode_);
278 uint32_t getInitElemArrayIndex() const {
279 MOZ_ASSERT(is(JSOp::InitElemArray));
280 uint32_t index = GET_UINT32(rawBytecode_);
281 MOZ_ASSERT(index <= INT32_MAX,
282 "the bytecode emitter must never generate JSOp::InitElemArray "
283 "with an index exceeding int32_t range");
284 return index;
287 FunctionPrefixKind getFunctionPrefixKind() const {
288 MOZ_ASSERT(is(JSOp::SetFunName));
289 return FunctionPrefixKind(GET_UINT8(rawBytecode_));
292 CheckIsObjectKind getCheckIsObjectKind() const {
293 MOZ_ASSERT(is(JSOp::CheckIsObj));
294 return CheckIsObjectKind(GET_UINT8(rawBytecode_));
297 BuiltinObjectKind getBuiltinObjectKind() const {
298 MOZ_ASSERT(is(JSOp::BuiltinObject));
299 return BuiltinObjectKind(GET_UINT8(rawBytecode_));
302 CompletionKind getCompletionKind() const {
303 MOZ_ASSERT(is(JSOp::CloseIter));
304 return CompletionKind(GET_UINT8(rawBytecode_));
307 uint32_t getNewArrayLength() const {
308 MOZ_ASSERT(is(JSOp::NewArray));
309 return GET_UINT32(rawBytecode_);
312 int8_t getInt8() const {
313 MOZ_ASSERT(is(JSOp::Int8));
314 return GET_INT8(rawBytecode_);
316 uint16_t getUint16() const {
317 MOZ_ASSERT(is(JSOp::Uint16));
318 return GET_UINT16(rawBytecode_);
320 uint32_t getUint24() const {
321 MOZ_ASSERT(is(JSOp::Uint24));
322 return GET_UINT24(rawBytecode_);
324 int32_t getInt32() const {
325 MOZ_ASSERT(is(JSOp::Int32));
326 return GET_INT32(rawBytecode_);
328 uint32_t getResumeIndex() const {
329 MOZ_ASSERT(is(JSOp::InitialYield) || is(JSOp::Yield) || is(JSOp::Await));
330 return GET_RESUMEINDEX(rawBytecode_);
332 Value getInlineValue() const {
333 MOZ_ASSERT(is(JSOp::Double));
334 return GET_INLINE_VALUE(rawBytecode_);
337 GeneratorResumeKind resumeKind() { return ResumeKindFromPC(rawBytecode_); }
339 ThrowMsgKind throwMsgKind() {
340 MOZ_ASSERT(is(JSOp::ThrowMsg));
341 return static_cast<ThrowMsgKind>(GET_UINT8(rawBytecode_));
344 #ifdef DEBUG
345 // To ease writing assertions
346 bool isValid() const { return isValid(debugOnlyScript_); }
348 bool isInBounds() const { return isInBounds(debugOnlyScript_); }
349 #endif
352 } // namespace js
354 #endif