2 * Copyright (C) 2011 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
29 #include <wtf/Platform.h>
33 #include "DFGRegisterBank.h"
34 #include "MacroAssembler.h"
36 namespace JSC
{ namespace DFG
{
38 typedef MacroAssembler::RegisterID GPRReg
;
39 #define InvalidGPRReg ((GPRReg)-1)
45 : m_gpr(InvalidGPRReg
)
49 explicit JSValueRegs(GPRReg gpr
)
54 bool operator!() const { return m_gpr
== InvalidGPRReg
; }
56 GPRReg
gpr() const { return m_gpr
; }
65 : m_offset(notAddress())
66 , m_base(InvalidGPRReg
)
70 JSValueSource(JSValueRegs regs
)
71 : m_offset(notAddress())
76 explicit JSValueSource(GPRReg gpr
)
77 : m_offset(notAddress())
82 JSValueSource(MacroAssembler::Address address
)
83 : m_offset(address
.offset
)
84 , m_base(address
.base
)
86 ASSERT(m_offset
!= notAddress());
87 ASSERT(m_base
!= InvalidGPRReg
);
90 static JSValueSource
unboxedCell(GPRReg payloadGPR
)
92 return JSValueSource(payloadGPR
);
95 bool operator!() const { return m_base
== InvalidGPRReg
; }
97 bool isAddress() const { return m_offset
!= notAddress(); }
99 int32_t offset() const
113 ASSERT(!isAddress());
117 MacroAssembler::Address
asAddress() const { return MacroAssembler::Address(base(), offset()); }
120 static inline int32_t notAddress() { return 0x80000000; }
127 #if USE(JSVALUE32_64)
131 : m_tagGPR(static_cast<int8_t>(InvalidGPRReg
))
132 , m_payloadGPR(static_cast<int8_t>(InvalidGPRReg
))
136 JSValueRegs(GPRReg tagGPR
, GPRReg payloadGPR
)
138 , m_payloadGPR(payloadGPR
)
140 ASSERT((static_cast<GPRReg
>(m_tagGPR
) == InvalidGPRReg
) == (static_cast<GPRReg
>(payloadGPR
) == InvalidGPRReg
));
143 bool operator!() const { return static_cast<GPRReg
>(m_tagGPR
) == InvalidGPRReg
; }
145 GPRReg
tagGPR() const { return static_cast<GPRReg
>(m_tagGPR
); }
146 GPRReg
payloadGPR() const { return static_cast<GPRReg
>(m_payloadGPR
); }
153 class JSValueSource
{
156 : m_offset(notAddress())
157 , m_baseOrTag(static_cast<int8_t>(InvalidGPRReg
))
158 , m_payload(static_cast<int8_t>(InvalidGPRReg
))
163 JSValueSource(JSValueRegs regs
)
164 : m_offset(notAddress())
165 , m_baseOrTag(regs
.tagGPR())
166 , m_payload(regs
.payloadGPR())
171 JSValueSource(GPRReg tagGPR
, GPRReg payloadGPR
)
172 : m_offset(notAddress())
173 , m_baseOrTag(static_cast<int8_t>(tagGPR
))
174 , m_payload(static_cast<int8_t>(payloadGPR
))
179 JSValueSource(MacroAssembler::Address address
)
180 : m_offset(address
.offset
)
181 , m_baseOrTag(static_cast<int8_t>(address
.base
))
182 , m_payload(static_cast<int8_t>(InvalidGPRReg
))
185 ASSERT(m_offset
!= notAddress());
186 ASSERT(static_cast<GPRReg
>(m_baseOrTag
) != InvalidGPRReg
);
189 static JSValueSource
unboxedCell(GPRReg payloadGPR
)
191 JSValueSource result
;
192 result
.m_offset
= notAddress();
193 result
.m_baseOrTag
= static_cast<int8_t>(InvalidGPRReg
);
194 result
.m_payload
= static_cast<int8_t>(payloadGPR
);
195 result
.m_tagType
= static_cast<int8_t>(JSValue::CellTag
);
199 bool operator!() const { return static_cast<GPRReg
>(m_baseOrTag
) == InvalidGPRReg
&& static_cast<GPRReg
>(m_payload
) == InvalidGPRReg
; }
201 bool isAddress() const
204 return m_offset
!= notAddress();
207 int32_t offset() const
216 return static_cast<GPRReg
>(m_baseOrTag
);
219 GPRReg
tagGPR() const
221 ASSERT(!isAddress() && static_cast<GPRReg
>(m_baseOrTag
) != InvalidGPRReg
);
222 return static_cast<GPRReg
>(m_baseOrTag
);
225 GPRReg
payloadGPR() const
227 ASSERT(!isAddress());
228 return static_cast<GPRReg
>(m_payload
);
231 bool hasKnownTag() const
234 ASSERT(!isAddress());
235 return static_cast<GPRReg
>(m_baseOrTag
) == InvalidGPRReg
;
240 return static_cast<int32_t>(m_tagType
);
243 MacroAssembler::Address
asAddress(unsigned additionalOffset
= 0) const { return MacroAssembler::Address(base(), offset() + additionalOffset
); }
246 static inline int32_t notAddress() { return 0x80000000; }
251 int8_t m_tagType
; // Contains the low bits of the tag.
256 #define NUMBER_OF_ARGUMENT_REGISTERS 0
260 typedef GPRReg RegisterType
;
261 static const unsigned numberOfRegisters
= 5;
263 // Temporary registers.
264 static const GPRReg regT0
= X86Registers::eax
;
265 static const GPRReg regT1
= X86Registers::edx
;
266 static const GPRReg regT2
= X86Registers::ecx
;
267 static const GPRReg regT3
= X86Registers::ebx
;
268 static const GPRReg regT4
= X86Registers::esi
;
269 // These registers match the baseline JIT.
270 static const GPRReg cachedResultRegister
= regT0
;
271 static const GPRReg cachedResultRegister2
= regT1
;
272 static const GPRReg callFrameRegister
= X86Registers::edi
;
273 // These constants provide the names for the general purpose argument & return value registers.
274 static const GPRReg argumentGPR0
= X86Registers::ecx
; // regT2
275 static const GPRReg argumentGPR1
= X86Registers::edx
; // regT1
276 static const GPRReg nonArgGPR0
= X86Registers::eax
; // regT0
277 static const GPRReg nonArgGPR1
= X86Registers::ebx
; // regT3
278 static const GPRReg nonArgGPR2
= X86Registers::esi
; // regT4
279 static const GPRReg returnValueGPR
= X86Registers::eax
; // regT0
280 static const GPRReg returnValueGPR2
= X86Registers::edx
; // regT1
281 static const GPRReg nonPreservedNonReturnGPR
= X86Registers::ecx
;
283 static GPRReg
toRegister(unsigned index
)
285 ASSERT(index
< numberOfRegisters
);
286 static const GPRReg registerForIndex
[numberOfRegisters
] = { regT0
, regT1
, regT2
, regT3
, regT4
};
287 return registerForIndex
[index
];
290 static unsigned toIndex(GPRReg reg
)
292 ASSERT(reg
!= InvalidGPRReg
);
293 ASSERT(static_cast<int>(reg
) < 8);
294 static const unsigned indexForRegister
[8] = { 0, 2, 1, 3, InvalidIndex
, InvalidIndex
, 4, InvalidIndex
};
295 unsigned result
= indexForRegister
[reg
];
296 ASSERT(result
!= InvalidIndex
);
300 static const char* debugName(GPRReg reg
)
302 ASSERT(reg
!= InvalidGPRReg
);
303 ASSERT(static_cast<int>(reg
) < 8);
304 static const char* nameForRegister
[8] = {
305 "eax", "ecx", "edx", "ebx",
306 "esp", "ebp", "esi", "edi",
308 return nameForRegister
[reg
];
312 static const unsigned InvalidIndex
= 0xffffffff;
318 #define NUMBER_OF_ARGUMENT_REGISTERS 6
322 typedef GPRReg RegisterType
;
323 static const unsigned numberOfRegisters
= 9;
325 // These registers match the baseline JIT.
326 static const GPRReg cachedResultRegister
= X86Registers::eax
;
327 static const GPRReg callFrameRegister
= X86Registers::r13
;
328 static const GPRReg tagTypeNumberRegister
= X86Registers::r14
;
329 static const GPRReg tagMaskRegister
= X86Registers::r15
;
330 // Temporary registers.
331 static const GPRReg regT0
= X86Registers::eax
;
332 static const GPRReg regT1
= X86Registers::edx
;
333 static const GPRReg regT2
= X86Registers::ecx
;
334 static const GPRReg regT3
= X86Registers::ebx
;
335 static const GPRReg regT4
= X86Registers::edi
;
336 static const GPRReg regT5
= X86Registers::esi
;
337 static const GPRReg regT6
= X86Registers::r8
;
338 static const GPRReg regT7
= X86Registers::r9
;
339 static const GPRReg regT8
= X86Registers::r10
;
340 // These constants provide the names for the general purpose argument & return value registers.
341 static const GPRReg argumentGPR0
= X86Registers::edi
; // regT4
342 static const GPRReg argumentGPR1
= X86Registers::esi
; // regT5
343 static const GPRReg argumentGPR2
= X86Registers::edx
; // regT1
344 static const GPRReg argumentGPR3
= X86Registers::ecx
; // regT2
345 static const GPRReg argumentGPR4
= X86Registers::r8
; // regT6
346 static const GPRReg argumentGPR5
= X86Registers::r9
; // regT7
347 static const GPRReg nonArgGPR0
= X86Registers::eax
; // regT0
348 static const GPRReg nonArgGPR1
= X86Registers::ebx
; // regT3
349 static const GPRReg nonArgGPR2
= X86Registers::r10
; // regT8
350 static const GPRReg returnValueGPR
= X86Registers::eax
; // regT0
351 static const GPRReg returnValueGPR2
= X86Registers::edx
; // regT1
352 static const GPRReg nonPreservedNonReturnGPR
= X86Registers::esi
;
354 static GPRReg
toRegister(unsigned index
)
356 ASSERT(index
< numberOfRegisters
);
357 static const GPRReg registerForIndex
[numberOfRegisters
] = { regT0
, regT1
, regT2
, regT3
, regT4
, regT5
, regT6
, regT7
, regT8
};
358 return registerForIndex
[index
];
361 static unsigned toIndex(GPRReg reg
)
363 ASSERT(reg
!= InvalidGPRReg
);
364 ASSERT(static_cast<int>(reg
) < 16);
365 static const unsigned indexForRegister
[16] = { 0, 2, 1, 3, InvalidIndex
, InvalidIndex
, 5, 4, 6, 7, 8, InvalidIndex
, InvalidIndex
, InvalidIndex
, InvalidIndex
, InvalidIndex
};
366 unsigned result
= indexForRegister
[reg
];
367 ASSERT(result
!= InvalidIndex
);
371 static const char* debugName(GPRReg reg
)
373 ASSERT(reg
!= InvalidGPRReg
);
374 ASSERT(static_cast<int>(reg
) < 16);
375 static const char* nameForRegister
[16] = {
376 "rax", "rcx", "rdx", "rbx",
377 "rsp", "rbp", "rsi", "rdi",
378 "r8", "r9", "r10", "r11",
379 "r12", "r13", "r14", "r15"
381 return nameForRegister
[reg
];
385 static const unsigned InvalidIndex
= 0xffffffff;
391 #define NUMBER_OF_ARGUMENT_REGISTERS 4
395 typedef GPRReg RegisterType
;
396 static const unsigned numberOfRegisters
= 8;
398 // Temporary registers.
399 static const GPRReg regT0
= ARMRegisters::r0
;
400 static const GPRReg regT1
= ARMRegisters::r1
;
401 static const GPRReg regT2
= ARMRegisters::r2
;
402 static const GPRReg regT3
= ARMRegisters::r4
;
403 static const GPRReg regT4
= ARMRegisters::r8
;
404 static const GPRReg regT5
= ARMRegisters::r9
;
405 static const GPRReg regT6
= ARMRegisters::r10
;
406 static const GPRReg regT7
= ARMRegisters::r11
;
407 // These registers match the baseline JIT.
408 static const GPRReg cachedResultRegister
= regT0
;
409 static const GPRReg cachedResultRegister2
= regT1
;
410 static const GPRReg callFrameRegister
= ARMRegisters::r5
;
411 // These constants provide the names for the general purpose argument & return value registers.
412 static const GPRReg argumentGPR0
= ARMRegisters::r0
; // regT0
413 static const GPRReg argumentGPR1
= ARMRegisters::r1
; // regT1
414 static const GPRReg argumentGPR2
= ARMRegisters::r2
; // regT2
415 // FIXME: r3 is currently used be the MacroAssembler as a temporary - it seems
416 // This could threoretically be a problem if this is used in code generation
417 // between the arguments being set up, and the call being made. That said,
418 // any change introducing a problem here is likely to be immediately apparent!
419 static const GPRReg argumentGPR3
= ARMRegisters::r3
; // FIXME!
420 static const GPRReg nonArgGPR0
= ARMRegisters::r4
; // regT3
421 static const GPRReg nonArgGPR1
= ARMRegisters::r8
; // regT4
422 static const GPRReg nonArgGPR2
= ARMRegisters::r9
; // regT5
423 static const GPRReg returnValueGPR
= ARMRegisters::r0
; // regT0
424 static const GPRReg returnValueGPR2
= ARMRegisters::r1
; // regT1
425 static const GPRReg nonPreservedNonReturnGPR
= ARMRegisters::r2
;
427 static GPRReg
toRegister(unsigned index
)
429 ASSERT(index
< numberOfRegisters
);
430 static const GPRReg registerForIndex
[numberOfRegisters
] = { regT0
, regT1
, regT2
, regT3
, regT4
, regT5
, regT6
, regT7
};
431 return registerForIndex
[index
];
434 static unsigned toIndex(GPRReg reg
)
436 ASSERT(static_cast<unsigned>(reg
) != InvalidGPRReg
);
437 ASSERT(static_cast<unsigned>(reg
) < 16);
438 static const unsigned indexForRegister
[16] = { 0, 1, 2, InvalidIndex
, 3, InvalidIndex
, InvalidIndex
, InvalidIndex
, 4, 5, 6, 7, InvalidIndex
, InvalidIndex
, InvalidIndex
, InvalidIndex
};
439 unsigned result
= indexForRegister
[reg
];
440 ASSERT(result
!= InvalidIndex
);
444 static const char* debugName(GPRReg reg
)
446 ASSERT(static_cast<unsigned>(reg
) != InvalidGPRReg
);
447 ASSERT(static_cast<unsigned>(reg
) < 16);
448 static const char* nameForRegister
[16] = {
449 "r0", "r1", "r2", "r3",
450 "r4", "r5", "r6", "r7",
451 "r8", "r9", "r10", "r11",
452 "r12", "r13", "r14", "r15"
454 return nameForRegister
[reg
];
458 static const unsigned InvalidIndex
= 0xffffffff;
464 #define NUMBER_OF_ARGUMENT_REGISTERS 8
468 typedef GPRReg RegisterType
;
469 static const unsigned numberOfRegisters
= 16;
471 // These registers match the baseline JIT.
472 static const GPRReg cachedResultRegister
= ARM64Registers::x0
;
473 static const GPRReg timeoutCheckRegister
= ARM64Registers::x26
;
474 static const GPRReg callFrameRegister
= ARM64Registers::x25
;
475 static const GPRReg tagTypeNumberRegister
= ARM64Registers::x27
;
476 static const GPRReg tagMaskRegister
= ARM64Registers::x28
;
477 // Temporary registers.
478 static const GPRReg regT0
= ARM64Registers::x0
;
479 static const GPRReg regT1
= ARM64Registers::x1
;
480 static const GPRReg regT2
= ARM64Registers::x2
;
481 static const GPRReg regT3
= ARM64Registers::x3
;
482 static const GPRReg regT4
= ARM64Registers::x4
;
483 static const GPRReg regT5
= ARM64Registers::x5
;
484 static const GPRReg regT6
= ARM64Registers::x6
;
485 static const GPRReg regT7
= ARM64Registers::x7
;
486 static const GPRReg regT8
= ARM64Registers::x8
;
487 static const GPRReg regT9
= ARM64Registers::x9
;
488 static const GPRReg regT10
= ARM64Registers::x10
;
489 static const GPRReg regT11
= ARM64Registers::x11
;
490 static const GPRReg regT12
= ARM64Registers::x12
;
491 static const GPRReg regT13
= ARM64Registers::x13
;
492 static const GPRReg regT14
= ARM64Registers::x14
;
493 static const GPRReg regT15
= ARM64Registers::x15
;
494 // These constants provide the names for the general purpose argument & return value registers.
495 static const GPRReg argumentGPR0
= ARM64Registers::x0
; // regT0
496 static const GPRReg argumentGPR1
= ARM64Registers::x1
; // regT1
497 static const GPRReg argumentGPR2
= ARM64Registers::x2
; // regT2
498 static const GPRReg argumentGPR3
= ARM64Registers::x3
; // regT3
499 static const GPRReg argumentGPR4
= ARM64Registers::x4
; // regT4
500 static const GPRReg argumentGPR5
= ARM64Registers::x5
; // regT5
501 static const GPRReg argumentGPR6
= ARM64Registers::x6
; // regT6
502 static const GPRReg argumentGPR7
= ARM64Registers::x7
; // regT7
503 static const GPRReg nonArgGPR0
= ARM64Registers::x8
; // regT8
504 static const GPRReg nonArgGPR1
= ARM64Registers::x9
; // regT9
505 static const GPRReg nonArgGPR2
= ARM64Registers::x10
; // regT10
506 static const GPRReg returnValueGPR
= ARM64Registers::x0
; // regT0
507 static const GPRReg returnValueGPR2
= ARM64Registers::x1
; // regT1
508 static const GPRReg nonPreservedNonReturnGPR
= ARM64Registers::x2
;
510 // GPRReg mapping is direct, the machine regsiter numbers can
511 // be used directly as indices into the GPR RegisterBank.
512 COMPILE_ASSERT(ARM64Registers::q0
== 0, q0_is_0
);
513 COMPILE_ASSERT(ARM64Registers::q1
== 1, q1_is_1
);
514 COMPILE_ASSERT(ARM64Registers::q2
== 2, q2_is_2
);
515 COMPILE_ASSERT(ARM64Registers::q3
== 3, q3_is_3
);
516 COMPILE_ASSERT(ARM64Registers::q4
== 4, q4_is_4
);
517 COMPILE_ASSERT(ARM64Registers::q5
== 5, q5_is_5
);
518 COMPILE_ASSERT(ARM64Registers::q6
== 6, q6_is_6
);
519 COMPILE_ASSERT(ARM64Registers::q7
== 7, q7_is_7
);
520 COMPILE_ASSERT(ARM64Registers::q8
== 8, q8_is_8
);
521 COMPILE_ASSERT(ARM64Registers::q9
== 9, q9_is_9
);
522 COMPILE_ASSERT(ARM64Registers::q10
== 10, q10_is_10
);
523 COMPILE_ASSERT(ARM64Registers::q11
== 11, q11_is_11
);
524 COMPILE_ASSERT(ARM64Registers::q12
== 12, q12_is_12
);
525 COMPILE_ASSERT(ARM64Registers::q13
== 13, q13_is_13
);
526 COMPILE_ASSERT(ARM64Registers::q14
== 14, q14_is_14
);
527 COMPILE_ASSERT(ARM64Registers::q15
== 15, q15_is_15
);
528 static GPRReg
toRegister(unsigned index
)
530 return (GPRReg
)index
;
532 static unsigned toIndex(GPRReg reg
)
534 return (unsigned)reg
;
537 static const char* debugName(GPRReg reg
)
539 ASSERT(static_cast<unsigned>(reg
) != InvalidGPRReg
);
540 ASSERT(static_cast<unsigned>(reg
) < 32);
541 static const char* nameForRegister
[32] = {
542 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
543 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
544 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
545 "r24", "r25", "r26", "r27", "r28", "fp", "lr", "sp"
547 return nameForRegister
[reg
];
551 static const unsigned InvalidIndex
= 0xffffffff;
557 #define NUMBER_OF_ARGUMENT_REGISTERS 4
561 typedef GPRReg RegisterType
;
562 static const unsigned numberOfRegisters
= 6;
564 // Temporary registers.
565 static const GPRReg regT0
= MIPSRegisters::v0
;
566 static const GPRReg regT1
= MIPSRegisters::v1
;
567 static const GPRReg regT2
= MIPSRegisters::t4
;
568 static const GPRReg regT3
= MIPSRegisters::t5
;
569 static const GPRReg regT4
= MIPSRegisters::t6
;
570 static const GPRReg regT5
= MIPSRegisters::t7
;
571 // These registers match the baseline JIT.
572 static const GPRReg cachedResultRegister
= regT0
;
573 static const GPRReg cachedResultRegister2
= regT1
;
574 static const GPRReg callFrameRegister
= MIPSRegisters::s0
;
575 // These constants provide the names for the general purpose argument & return value registers.
576 static const GPRReg argumentGPR0
= MIPSRegisters::a0
;
577 static const GPRReg argumentGPR1
= MIPSRegisters::a1
;
578 static const GPRReg argumentGPR2
= MIPSRegisters::a2
;
579 static const GPRReg argumentGPR3
= MIPSRegisters::a3
;
580 static const GPRReg nonArgGPR0
= regT2
;
581 static const GPRReg nonArgGPR1
= regT3
;
582 static const GPRReg nonArgGPR2
= regT4
;
583 static const GPRReg returnValueGPR
= regT0
;
584 static const GPRReg returnValueGPR2
= regT1
;
585 static const GPRReg nonPreservedNonReturnGPR
= regT5
;
587 static GPRReg
toRegister(unsigned index
)
589 ASSERT(index
< numberOfRegisters
);
590 static const GPRReg registerForIndex
[numberOfRegisters
] = { regT0
, regT1
, regT2
, regT3
, regT4
, regT5
};
591 return registerForIndex
[index
];
594 static unsigned toIndex(GPRReg reg
)
596 ASSERT(reg
!= InvalidGPRReg
);
598 static const unsigned indexForRegister
[16] = { InvalidIndex
, InvalidIndex
, 0, 1, InvalidIndex
, InvalidIndex
, InvalidIndex
, InvalidIndex
, InvalidIndex
, InvalidIndex
, InvalidIndex
, InvalidIndex
, 2, 3, 4, 5 };
599 unsigned result
= indexForRegister
[reg
];
600 ASSERT(result
!= InvalidIndex
);
604 static const char* debugName(GPRReg reg
)
606 ASSERT(reg
!= InvalidGPRReg
);
608 static const char* nameForRegister
[16] = {
609 "zero", "at", "v0", "v1",
610 "a0", "a1", "a2", "a3",
611 "t0", "t1", "t2", "t3",
612 "t4", "t5", "t6", "t7"
614 return nameForRegister
[reg
];
618 static const unsigned InvalidIndex
= 0xffffffff;
623 typedef RegisterBank
<GPRInfo
>::iterator gpr_iterator
;
625 } } // namespace JSC::DFG