Bug 1874684 - Part 29: Update spec fixme notes. r=mgaudet
[gecko.git] / js / src / jit / CodeGenerator.h
blob0b906ac3ee2b65ef49960df2b49fa1fe68029b40
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 jit_CodeGenerator_h
8 #define jit_CodeGenerator_h
10 #include "jit/PerfSpewer.h"
11 #include "js/Prefs.h"
12 #include "js/ScalarType.h" // js::Scalar::Type
14 #if defined(JS_CODEGEN_X86)
15 # include "jit/x86/CodeGenerator-x86.h"
16 #elif defined(JS_CODEGEN_X64)
17 # include "jit/x64/CodeGenerator-x64.h"
18 #elif defined(JS_CODEGEN_ARM)
19 # include "jit/arm/CodeGenerator-arm.h"
20 #elif defined(JS_CODEGEN_ARM64)
21 # include "jit/arm64/CodeGenerator-arm64.h"
22 #elif defined(JS_CODEGEN_MIPS32)
23 # include "jit/mips32/CodeGenerator-mips32.h"
24 #elif defined(JS_CODEGEN_MIPS64)
25 # include "jit/mips64/CodeGenerator-mips64.h"
26 #elif defined(JS_CODEGEN_LOONG64)
27 # include "jit/loong64/CodeGenerator-loong64.h"
28 #elif defined(JS_CODEGEN_RISCV64)
29 # include "jit/riscv64/CodeGenerator-riscv64.h"
30 #elif defined(JS_CODEGEN_WASM32)
31 # include "jit/wasm32/CodeGenerator-wasm32.h"
32 #elif defined(JS_CODEGEN_NONE)
33 # include "jit/none/CodeGenerator-none.h"
34 #else
35 # error "Unknown architecture!"
36 #endif
38 namespace js {
40 namespace wasm {
41 class Decoder;
42 class StackMaps;
43 } // namespace wasm
45 namespace jit {
47 class WarpSnapshot;
49 template <typename Fn, Fn fn, class ArgSeq, class StoreOutputTo>
50 class OutOfLineCallVM;
52 enum class SwitchTableType { Inline, OutOfLine };
54 template <SwitchTableType tableType>
55 class OutOfLineSwitch;
56 class OutOfLineTestObject;
57 class OutOfLineNewArray;
58 class OutOfLineNewObject;
59 class CheckOverRecursedFailure;
60 class OutOfLineUnboxFloatingPoint;
61 class OutOfLineStoreElementHole;
62 class OutOfLineTypeOfV;
63 class OutOfLineTypeOfIsNonPrimitiveV;
64 class OutOfLineTypeOfIsNonPrimitiveO;
65 class OutOfLineUpdateCache;
66 class OutOfLineICFallback;
67 class OutOfLineCallPostWriteBarrier;
68 class OutOfLineCallPostWriteElementBarrier;
69 class OutOfLineElementPostWriteBarrier;
70 class OutOfLineIsCallable;
71 class OutOfLineIsConstructor;
72 class OutOfLineRegExpMatcher;
73 class OutOfLineRegExpSearcher;
74 class OutOfLineRegExpExecMatch;
75 class OutOfLineRegExpExecTest;
76 class OutOfLineRegExpPrototypeOptimizable;
77 class OutOfLineRegExpInstanceOptimizable;
78 class OutOfLineNaNToZero;
79 class OutOfLineResumableWasmTrap;
80 class OutOfLineAbortingWasmTrap;
81 class OutOfLineGuardNumberToIntPtrIndex;
82 class OutOfLineBoxNonStrictThis;
83 class OutOfLineArrayPush;
84 class OutOfLineAtomizeSlot;
85 class OutOfLineWasmCallPostWriteBarrierImmediate;
86 class OutOfLineWasmCallPostWriteBarrierIndex;
87 class OutOfLineWasmNewStruct;
88 class OutOfLineWasmNewArray;
90 class CodeGenerator final : public CodeGeneratorSpecific {
91 [[nodiscard]] bool generateBody();
93 ConstantOrRegister toConstantOrRegister(LInstruction* lir, size_t n,
94 MIRType type);
96 #ifdef CHECK_OSIPOINT_REGISTERS
97 void resetOsiPointRegs(LSafepoint* safepoint);
98 bool shouldVerifyOsiPointRegs(LSafepoint* safepoint);
99 void verifyOsiPointRegs(LSafepoint* safepoint);
100 #endif
102 void callVMInternal(VMFunctionId id, LInstruction* ins);
104 template <typename Fn, Fn fn>
105 void callVM(LInstruction* ins);
107 template <typename Fn, Fn fn, class ArgSeq, class StoreOutputTo>
108 inline OutOfLineCode* oolCallVM(LInstruction* ins, const ArgSeq& args,
109 const StoreOutputTo& out);
111 template <typename LCallIns>
112 void emitCallNative(LCallIns* call, JSNative native, Register argContextReg,
113 Register argUintNReg, Register argVpReg, Register tempReg,
114 uint32_t unusedStack);
116 template <typename LCallIns>
117 void emitCallNative(LCallIns* call, JSNative native);
119 public:
120 CodeGenerator(MIRGenerator* gen, LIRGraph* graph,
121 MacroAssembler* masm = nullptr);
122 ~CodeGenerator();
124 [[nodiscard]] bool generate();
125 [[nodiscard]] bool generateWasm(
126 wasm::CallIndirectId callIndirectId, wasm::BytecodeOffset trapOffset,
127 const wasm::ArgTypeVector& argTys, const RegisterOffsets& trapExitLayout,
128 size_t trapExitLayoutNumWords, wasm::FuncOffsets* offsets,
129 wasm::StackMaps* stackMaps, wasm::Decoder* decoder);
131 [[nodiscard]] bool link(JSContext* cx, const WarpSnapshot* snapshot);
133 void emitOOLTestObject(Register objreg, Label* ifTruthy, Label* ifFalsy,
134 Register scratch);
136 void emitTypeOfCheck(JSValueType type, Register tag, Register output,
137 Label* done, Label* oolObject);
138 void emitTypeOfJSType(JSValueType type, Register output);
139 void emitTypeOfObject(Register obj, Register output, Label* done);
140 void emitTypeOfIsObject(MTypeOfIs* mir, Register obj, Register output,
141 Label* success, Label* fail, Label* slowCheck);
142 void emitTypeOfIsObjectOOL(MTypeOfIs* mir, Register obj, Register output);
144 template <typename Fn, Fn fn, class ArgSeq, class StoreOutputTo>
145 void visitOutOfLineCallVM(
146 OutOfLineCallVM<Fn, fn, ArgSeq, StoreOutputTo>* ool);
148 void visitOutOfLineRegExpMatcher(OutOfLineRegExpMatcher* ool);
149 void visitOutOfLineRegExpSearcher(OutOfLineRegExpSearcher* ool);
150 void visitOutOfLineRegExpExecMatch(OutOfLineRegExpExecMatch* ool);
151 void visitOutOfLineRegExpExecTest(OutOfLineRegExpExecTest* ool);
152 void visitOutOfLineRegExpPrototypeOptimizable(
153 OutOfLineRegExpPrototypeOptimizable* ool);
154 void visitOutOfLineRegExpInstanceOptimizable(
155 OutOfLineRegExpInstanceOptimizable* ool);
157 void visitOutOfLineTypeOfV(OutOfLineTypeOfV* ool);
158 void visitOutOfLineTypeOfIsNonPrimitiveV(OutOfLineTypeOfIsNonPrimitiveV* ool);
159 void visitOutOfLineTypeOfIsNonPrimitiveO(OutOfLineTypeOfIsNonPrimitiveO* ool);
161 template <SwitchTableType tableType>
162 void visitOutOfLineSwitch(OutOfLineSwitch<tableType>* ool);
164 void visitOutOfLineIsCallable(OutOfLineIsCallable* ool);
165 void visitOutOfLineIsConstructor(OutOfLineIsConstructor* ool);
167 void visitOutOfLineNaNToZero(OutOfLineNaNToZero* ool);
169 void visitOutOfLineResumableWasmTrap(OutOfLineResumableWasmTrap* ool);
170 void visitOutOfLineAbortingWasmTrap(OutOfLineAbortingWasmTrap* ool);
171 void visitCheckOverRecursedFailure(CheckOverRecursedFailure* ool);
173 void visitOutOfLineUnboxFloatingPoint(OutOfLineUnboxFloatingPoint* ool);
174 void visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool);
176 void visitOutOfLineBoxNonStrictThis(OutOfLineBoxNonStrictThis* ool);
178 void visitOutOfLineICFallback(OutOfLineICFallback* ool);
180 void visitOutOfLineCallPostWriteBarrier(OutOfLineCallPostWriteBarrier* ool);
181 void visitOutOfLineCallPostWriteElementBarrier(
182 OutOfLineCallPostWriteElementBarrier* ool);
184 void visitOutOfLineElementPostWriteBarrier(
185 OutOfLineElementPostWriteBarrier* ool);
187 void visitOutOfLineNewArray(OutOfLineNewArray* ool);
188 void visitOutOfLineNewObject(OutOfLineNewObject* ool);
190 void visitOutOfLineGuardNumberToIntPtrIndex(
191 OutOfLineGuardNumberToIntPtrIndex* ool);
193 void visitOutOfLineArrayPush(OutOfLineArrayPush* ool);
195 void visitOutOfLineAtomizeSlot(OutOfLineAtomizeSlot* ool);
197 void visitOutOfLineWasmCallPostWriteBarrierImmediate(
198 OutOfLineWasmCallPostWriteBarrierImmediate* ool);
199 void visitOutOfLineWasmCallPostWriteBarrierIndex(
200 OutOfLineWasmCallPostWriteBarrierIndex* ool);
202 void callWasmStructAllocFun(LInstruction* lir, wasm::SymbolicAddress fun,
203 Register typeDefData, Register output);
204 void visitOutOfLineWasmNewStruct(OutOfLineWasmNewStruct* ool);
206 void callWasmArrayAllocFun(LInstruction* lir, wasm::SymbolicAddress fun,
207 Register numElements, Register typeDefData,
208 Register output,
209 wasm::BytecodeOffset bytecodeOffset);
210 void visitOutOfLineWasmNewArray(OutOfLineWasmNewArray* ool);
212 private:
213 void emitPostWriteBarrier(const LAllocation* obj);
214 void emitPostWriteBarrier(Register objreg);
215 void emitPostWriteBarrierS(Address address, Register prev, Register next);
217 void emitElementPostWriteBarrier(MInstruction* mir,
218 const LiveRegisterSet& liveVolatileRegs,
219 Register obj, const LAllocation* index,
220 Register scratch,
221 const ConstantOrRegister& val,
222 int32_t indexDiff = 0);
224 template <class LPostBarrierType, MIRType nurseryType>
225 void visitPostWriteBarrierCommon(LPostBarrierType* lir, OutOfLineCode* ool);
226 template <class LPostBarrierType>
227 void visitPostWriteBarrierCommonV(LPostBarrierType* lir, OutOfLineCode* ool);
229 void emitCallInvokeFunction(LInstruction* call, Register callereg,
230 bool isConstructing, bool ignoresReturnValue,
231 uint32_t argc, uint32_t unusedStack);
232 template <typename T>
233 void emitApplyGeneric(T* apply);
234 template <typename T>
235 void emitCallInvokeFunction(T* apply);
236 void emitAllocateSpaceForApply(Register argcreg, Register scratch);
237 void emitAllocateSpaceForConstructAndPushNewTarget(
238 Register argcreg, Register newTargetAndScratch);
239 void emitCopyValuesForApply(Register argvSrcBase, Register argvIndex,
240 Register copyreg, size_t argvSrcOffset,
241 size_t argvDstOffset);
242 void emitRestoreStackPointerFromFP();
243 void emitPushArguments(Register argcreg, Register scratch, Register copyreg,
244 uint32_t extraFormals);
245 void emitPushArrayAsArguments(Register tmpArgc, Register srcBaseAndArgc,
246 Register scratch, size_t argvSrcOffset);
247 void emitPushArguments(LApplyArgsGeneric* apply);
248 void emitPushArguments(LApplyArgsObj* apply);
249 void emitPushArguments(LApplyArrayGeneric* apply);
250 void emitPushArguments(LConstructArgsGeneric* construct);
251 void emitPushArguments(LConstructArrayGeneric* construct);
253 template <typename T>
254 void emitApplyNative(T* apply);
255 template <typename T>
256 void emitAlignStackForApplyNative(T* apply, Register argc);
257 template <typename T>
258 void emitPushNativeArguments(T* apply);
259 template <typename T>
260 void emitPushArrayAsNativeArguments(T* apply);
261 void emitPushArguments(LApplyArgsNative* apply);
262 void emitPushArguments(LApplyArgsObjNative* apply);
263 void emitPushArguments(LApplyArrayNative* apply);
264 void emitPushArguments(LConstructArgsNative* construct);
265 void emitPushArguments(LConstructArrayNative* construct);
267 template <typename T>
268 void emitApplyArgsGuard(T* apply);
270 template <typename T>
271 void emitApplyArgsObjGuard(T* apply);
273 template <typename T>
274 void emitApplyArrayGuard(T* apply);
276 template <class GetInlinedArgument>
277 void emitGetInlinedArgument(GetInlinedArgument* lir, Register index,
278 ValueOperand output);
280 void emitMaybeAtomizeSlot(LInstruction* ins, Register stringReg,
281 Address slotAddr, TypedOrValueRegister dest);
283 using RegisterOrInt32 = mozilla::Variant<Register, int32_t>;
285 static RegisterOrInt32 ToRegisterOrInt32(const LAllocation* allocation);
287 #ifdef DEBUG
288 void emitAssertArgumentsSliceBounds(const RegisterOrInt32& begin,
289 const RegisterOrInt32& count,
290 Register numActualArgs);
291 #endif
293 template <class ArgumentsSlice>
294 void emitNewArray(ArgumentsSlice* lir, const RegisterOrInt32& count,
295 Register output, Register temp);
297 void visitNewArrayCallVM(LNewArray* lir);
298 void visitNewObjectVMCall(LNewObject* lir);
300 void emitConcat(LInstruction* lir, Register lhs, Register rhs,
301 Register output);
303 void emitInstanceOf(LInstruction* ins, Register protoReg);
305 void loadJSScriptForBlock(MBasicBlock* block, Register reg);
306 void loadOutermostJSScript(Register reg);
308 #ifdef DEBUG
309 void emitAssertResultV(const ValueOperand output, const MDefinition* mir);
310 void emitAssertGCThingResult(Register input, const MDefinition* mir);
311 #endif
313 #ifdef DEBUG
314 void emitDebugForceBailing(LInstruction* lir);
315 #endif
317 IonScriptCounts* extractScriptCounts() {
318 IonScriptCounts* counts = scriptCounts_;
319 scriptCounts_ = nullptr; // prevent delete in dtor
320 return counts;
323 void addGetPropertyCache(LInstruction* ins, LiveRegisterSet liveRegs,
324 TypedOrValueRegister value,
325 const ConstantOrRegister& id, ValueOperand output);
326 void addSetPropertyCache(LInstruction* ins, LiveRegisterSet liveRegs,
327 Register objReg, Register temp,
328 const ConstantOrRegister& id,
329 const ConstantOrRegister& value, bool strict);
331 template <class IteratorObject, class OrderedHashTable>
332 void emitGetNextEntryForIterator(LGetNextEntryForIterator* lir);
334 template <class OrderedHashTable>
335 void emitLoadIteratorValues(Register result, Register temp, Register front);
337 void emitStringToInt64(LInstruction* lir, Register input, Register64 output);
339 OutOfLineCode* createBigIntOutOfLine(LInstruction* lir, Scalar::Type type,
340 Register64 input, Register output);
342 void emitCreateBigInt(LInstruction* lir, Scalar::Type type, Register64 input,
343 Register output, Register maybeTemp);
345 template <size_t NumDefs>
346 void emitIonToWasmCallBase(LIonToWasmCallBase<NumDefs>* lir);
348 IonScriptCounts* maybeCreateScriptCounts();
350 void emitWasmCompareAndSelect(LWasmCompareAndSelect* ins);
352 template <typename InstructionWithMaybeTrapSite, class AddressOrBaseIndex>
353 void emitWasmValueLoad(InstructionWithMaybeTrapSite* ins, MIRType type,
354 MWideningOp wideningOp, AddressOrBaseIndex addr,
355 AnyRegister dst);
356 template <typename InstructionWithMaybeTrapSite, class AddressOrBaseIndex>
357 void emitWasmValueStore(InstructionWithMaybeTrapSite* ins, MIRType type,
358 MNarrowingOp narrowingOp, AnyRegister src,
359 AddressOrBaseIndex addr);
361 void testValueTruthyForType(JSValueType type, ScratchTagScope& tag,
362 const ValueOperand& value, Register tempToUnbox,
363 Register temp, FloatRegister floatTemp,
364 Label* ifTruthy, Label* ifFalsy,
365 OutOfLineTestObject* ool, bool skipTypeTest);
367 // Test whether value is truthy or not and jump to the corresponding label.
368 // The control flow falls through when the object is truthy, as an
369 // optimization.
370 void testValueTruthy(const ValueOperand& value, Register tempToUnbox,
371 Register temp, FloatRegister floatTemp,
372 const TypeDataList& observedTypes, Label* ifTruthy,
373 Label* ifFalsy, OutOfLineTestObject* ool);
375 // This function behaves like testObjectEmulatesUndefined with the exception
376 // that it can choose to let control flow fall through when the object
377 // doesn't emulate undefined, as an optimization. Use the regular
378 // testObjectEmulatesUndefined when it's required to branch to one of the
379 // two labels.
380 void testObjectEmulatesUndefinedKernel(Register objreg,
381 Label* ifEmulatesUndefined,
382 Label* ifDoesntEmulateUndefined,
383 Register scratch,
384 OutOfLineTestObject* ool);
386 // Test whether an object emulates |undefined|. If it does, jump to
387 // |ifEmulatesUndefined|; the caller is responsible for binding this label.
388 // If it doesn't, fall through; the label |ifDoesntEmulateUndefined| (which
389 // must be initially unbound) will be bound at this point.
390 void branchTestObjectEmulatesUndefined(Register objreg,
391 Label* ifEmulatesUndefined,
392 Label* ifDoesntEmulateUndefined,
393 Register scratch,
394 OutOfLineTestObject* ool);
396 // Test whether an object emulates |undefined|, and jump to the
397 // corresponding label.
399 // This method should be used when subsequent code can't be laid out in a
400 // straight line; if it can, branchTest* should be used instead.
401 void testObjectEmulatesUndefined(Register objreg, Label* ifEmulatesUndefined,
402 Label* ifDoesntEmulateUndefined,
403 Register scratch, OutOfLineTestObject* ool);
405 void emitStoreElementTyped(const LAllocation* value, MIRType valueType,
406 Register elements, const LAllocation* index);
408 // Bailout if an element about to be written to is a hole.
409 void emitStoreHoleCheck(Register elements, const LAllocation* index,
410 LSnapshot* snapshot);
412 void emitAssertRangeI(MIRType type, const Range* r, Register input);
413 void emitAssertRangeD(const Range* r, FloatRegister input,
414 FloatRegister temp);
416 void maybeEmitGlobalBarrierCheck(const LAllocation* maybeGlobal,
417 OutOfLineCode* ool);
419 void incrementWarmUpCounter(AbsoluteAddress warmUpCount, JSScript* script,
420 Register tmp);
422 Vector<CodeOffset, 0, JitAllocPolicy> ionScriptLabels_;
424 // Used to bake in a pointer into the IonScript's list of nursery objects, for
425 // MNurseryObject codegen.
426 struct NurseryObjectLabel {
427 CodeOffset offset;
428 uint32_t nurseryIndex;
429 NurseryObjectLabel(CodeOffset offset, uint32_t nurseryIndex)
430 : offset(offset), nurseryIndex(nurseryIndex) {}
432 Vector<NurseryObjectLabel, 0, JitAllocPolicy> ionNurseryObjectLabels_;
434 void branchIfInvalidated(Register temp, Label* invalidated);
436 #ifdef DEBUG
437 void emitDebugResultChecks(LInstruction* ins);
438 void emitGCThingResultChecks(LInstruction* lir, MDefinition* mir);
439 void emitValueResultChecks(LInstruction* lir, MDefinition* mir);
440 #endif
442 // Script counts created during code generation.
443 IonScriptCounts* scriptCounts_;
445 IonPerfSpewer perfSpewer_;
447 // Bit mask of JitZone stubs that are to be read-barriered.
448 uint32_t zoneStubsToReadBarrier_;
450 #ifdef FUZZING_JS_FUZZILLI
451 void emitFuzzilliHashDouble(FloatRegister floatDouble, Register scratch,
452 Register output);
453 void emitFuzzilliHashObject(LInstruction* lir, Register obj, Register output);
454 void emitFuzzilliHashBigInt(Register bigInt, Register output);
455 #endif
457 #define LIR_OP(op) void visit##op(L##op* ins);
458 LIR_OPCODE_LIST(LIR_OP)
459 #undef LIR_OP
461 // In debug mode, we need to validate that we've not made a mistake with the
462 // fuse.
463 void assertObjectDoesNotEmulateUndefined(Register input, Register temp,
464 const MInstruction* mir);
466 // Enumerates the fuses that a code generation can depend on. These will
467 // be mapped to an actual fuse by validateAndRegisterFuseDependencies.
468 enum class FuseDependencyKind {
469 HasSeenObjectEmulateUndefinedFuse,
470 OptimizeGetIteratorFuse,
473 // The set of fuses this code generation depends on.
474 mozilla::EnumSet<FuseDependencyKind> fuseDependencies;
476 // Register a dependency on the HasSeenObjectEmulateUndefined fuse.
477 void addHasSeenObjectEmulateUndefinedFuseDependency() {
478 fuseDependencies += FuseDependencyKind::HasSeenObjectEmulateUndefinedFuse;
481 void addOptimizeGetIteratorFuseDependency() {
482 fuseDependencies += FuseDependencyKind::OptimizeGetIteratorFuse;
485 // Called during linking on main-thread: Ensures that the fuses are still
486 // intact, and registers a script dependency on a specific fuse before
487 // finishing compilation.
488 void validateAndRegisterFuseDependencies(JSContext* cx, HandleScript script,
489 bool* isValid);
491 // Return true if the fuse is intact, andd if the fuse is intact note the
492 // dependency
493 bool hasSeenObjectEmulateUndefinedFuseIntactAndDependencyNoted() {
494 if (!JS::Prefs::use_emulates_undefined_fuse()) {
495 // if we're not active, simply pretend the fuse is popped.
496 return false;
499 bool intact = gen->outerInfo().hasSeenObjectEmulateUndefinedFuseIntact();
500 if (intact) {
501 addHasSeenObjectEmulateUndefinedFuseDependency();
503 return intact;
507 class OutOfLineResumableWasmTrap : public OutOfLineCodeBase<CodeGenerator> {
508 LInstruction* lir_;
509 size_t framePushed_;
510 wasm::BytecodeOffset bytecodeOffset_;
511 wasm::Trap trap_;
513 public:
514 OutOfLineResumableWasmTrap(LInstruction* lir, size_t framePushed,
515 wasm::BytecodeOffset bytecodeOffset,
516 wasm::Trap trap)
517 : lir_(lir),
518 framePushed_(framePushed),
519 bytecodeOffset_(bytecodeOffset),
520 trap_(trap) {}
522 void accept(CodeGenerator* codegen) override {
523 codegen->visitOutOfLineResumableWasmTrap(this);
525 LInstruction* lir() const { return lir_; }
526 size_t framePushed() const { return framePushed_; }
527 wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; }
528 wasm::Trap trap() const { return trap_; }
531 class OutOfLineAbortingWasmTrap : public OutOfLineCodeBase<CodeGenerator> {
532 wasm::BytecodeOffset bytecodeOffset_;
533 wasm::Trap trap_;
535 public:
536 OutOfLineAbortingWasmTrap(wasm::BytecodeOffset bytecodeOffset,
537 wasm::Trap trap)
538 : bytecodeOffset_(bytecodeOffset), trap_(trap) {}
540 void accept(CodeGenerator* codegen) override {
541 codegen->visitOutOfLineAbortingWasmTrap(this);
543 wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; }
544 wasm::Trap trap() const { return trap_; }
547 } // namespace jit
548 } // namespace js
550 #endif /* jit_CodeGenerator_h */