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"
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"
35 # error "Unknown architecture!"
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
,
96 #ifdef CHECK_OSIPOINT_REGISTERS
97 void resetOsiPointRegs(LSafepoint
* safepoint
);
98 bool shouldVerifyOsiPointRegs(LSafepoint
* safepoint
);
99 void verifyOsiPointRegs(LSafepoint
* safepoint
);
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
);
120 CodeGenerator(MIRGenerator
* gen
, LIRGraph
* graph
,
121 MacroAssembler
* masm
= nullptr);
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
,
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
,
209 wasm::BytecodeOffset bytecodeOffset
);
210 void visitOutOfLineWasmNewArray(OutOfLineWasmNewArray
* ool
);
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
,
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
);
288 void emitAssertArgumentsSliceBounds(const RegisterOrInt32
& begin
,
289 const RegisterOrInt32
& count
,
290 Register numActualArgs
);
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
,
303 void emitInstanceOf(LInstruction
* ins
, Register protoReg
);
305 void loadJSScriptForBlock(MBasicBlock
* block
, Register reg
);
306 void loadOutermostJSScript(Register reg
);
309 void emitAssertResultV(const ValueOperand output
, const MDefinition
* mir
);
310 void emitAssertGCThingResult(Register input
, const MDefinition
* mir
);
314 void emitDebugForceBailing(LInstruction
* lir
);
317 IonScriptCounts
* extractScriptCounts() {
318 IonScriptCounts
* counts
= scriptCounts_
;
319 scriptCounts_
= nullptr; // prevent delete in dtor
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
,
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
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
380 void testObjectEmulatesUndefinedKernel(Register objreg
,
381 Label
* ifEmulatesUndefined
,
382 Label
* ifDoesntEmulateUndefined
,
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
,
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
,
416 void maybeEmitGlobalBarrierCheck(const LAllocation
* maybeGlobal
,
419 void incrementWarmUpCounter(AbsoluteAddress warmUpCount
, JSScript
* script
,
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
{
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
);
437 void emitDebugResultChecks(LInstruction
* ins
);
438 void emitGCThingResultChecks(LInstruction
* lir
, MDefinition
* mir
);
439 void emitValueResultChecks(LInstruction
* lir
, MDefinition
* mir
);
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
,
453 void emitFuzzilliHashObject(LInstruction
* lir
, Register obj
, Register output
);
454 void emitFuzzilliHashBigInt(Register bigInt
, Register output
);
457 #define LIR_OP(op) void visit##op(L##op* ins);
458 LIR_OPCODE_LIST(LIR_OP
)
461 // In debug mode, we need to validate that we've not made a mistake with the
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
,
491 // Return true if the fuse is intact, andd if the fuse is intact note the
493 bool hasSeenObjectEmulateUndefinedFuseIntactAndDependencyNoted() {
494 if (!JS::Prefs::use_emulates_undefined_fuse()) {
495 // if we're not active, simply pretend the fuse is popped.
499 bool intact
= gen
->outerInfo().hasSeenObjectEmulateUndefinedFuseIntact();
501 addHasSeenObjectEmulateUndefinedFuseDependency();
507 class OutOfLineResumableWasmTrap
: public OutOfLineCodeBase
<CodeGenerator
> {
510 wasm::BytecodeOffset bytecodeOffset_
;
514 OutOfLineResumableWasmTrap(LInstruction
* lir
, size_t framePushed
,
515 wasm::BytecodeOffset bytecodeOffset
,
518 framePushed_(framePushed
),
519 bytecodeOffset_(bytecodeOffset
),
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_
;
536 OutOfLineAbortingWasmTrap(wasm::BytecodeOffset bytecodeOffset
,
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_
; }
550 #endif /* jit_CodeGenerator_h */