]> git.saurik.com Git - apple/javascriptcore.git/blame - llint/LowLevelInterpreter64.asm
JavaScriptCore-7600.1.4.9.tar.gz
[apple/javascriptcore.git] / llint / LowLevelInterpreter64.asm
CommitLineData
81345200 1# Copyright (C) 2011, 2012, 2013, 2014 Apple Inc. All rights reserved.
6fe7ccc8
A
2#
3# Redistribution and use in source and binary forms, with or without
4# modification, are permitted provided that the following conditions
5# are met:
6# 1. Redistributions of source code must retain the above copyright
7# notice, this list of conditions and the following disclaimer.
8# 2. Redistributions in binary form must reproduce the above copyright
9# notice, this list of conditions and the following disclaimer in the
10# documentation and/or other materials provided with the distribution.
11#
12# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
13# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
14# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
15# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
16# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
17# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
18# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
19# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
20# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
21# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
22# THE POSSIBILITY OF SUCH DAMAGE.
23
24
6fe7ccc8 25# Utilities.
93a37866
A
26macro jumpToInstruction()
27 jmp [PB, PC, 8]
28end
29
6fe7ccc8
A
30macro dispatch(advance)
31 addp advance, PC
93a37866 32 jumpToInstruction()
6fe7ccc8
A
33end
34
35macro dispatchInt(advance)
36 addi advance, PC
93a37866
A
37 jumpToInstruction()
38end
39
40macro dispatchIntIndirect(offset)
41 dispatchInt(offset * 8[PB, PC, 8])
6fe7ccc8
A
42end
43
44macro dispatchAfterCall()
45 loadi ArgumentCount + TagOffset[cfr], PC
46 loadp CodeBlock[cfr], PB
47 loadp CodeBlock::m_instructions[PB], PB
81345200
A
48 loadisFromInstruction(1, t1)
49 storeq t0, [cfr, t1, 8]
50 valueProfile(t0, (CallOpCodeSize - 1), t2)
51 dispatch(CallOpCodeSize)
6fe7ccc8
A
52end
53
54macro cCall2(function, arg1, arg2)
81345200 55 checkStackPointerAlignment(t4, 0xbad0c002)
93a37866 56 if X86_64
81345200
A
57 move arg1, t4
58 move arg2, t5
59 call function
60 elsif X86_64_WIN
61 # Note: this implementation is only correct if the return type size is > 8 bytes.
62 # See macro cCall2Void for an implementation when the return type <= 8 bytes.
63 # On Win64, when the return type is larger than 8 bytes, we need to allocate space on the stack for the return value.
64 # On entry rcx (t2), should contain a pointer to this stack space. The other parameters are shifted to the right,
65 # rdx (t1) should contain the first argument, and r8 (t6) should contain the second argument.
66 # On return, rax contains a pointer to this stack value, and we then need to copy the 16 byte return value into rax (t0) and rdx (t1)
67 # since the return value is expected to be split between the two.
68 # See http://msdn.microsoft.com/en-us/library/7572ztz4.aspx
69 move arg1, t1
70 move arg2, t6
71 subp 48, sp
72 move sp, t2
73 addp 32, t2
93a37866 74 call function
81345200
A
75 addp 48, sp
76 move 8[t0], t1
77 move [t0], t0
93a37866
A
78 elsif ARM64
79 move arg1, t0
80 move arg2, t1
81 call function
82 elsif C_LOOP
83 cloopCallSlowPath function, arg1, arg2
84 else
85 error
86 end
6fe7ccc8
A
87end
88
81345200
A
89macro cCall2Void(function, arg1, arg2)
90 if C_LOOP
91 cloopCallSlowPathVoid function, arg1, arg2
92 elsif X86_64_WIN
93 # Note: we cannot use the cCall2 macro for Win64 in this case,
94 # as the Win64 cCall2 implemenation is only correct when the return type size is > 8 bytes.
95 # On Win64, rcx and rdx are used for passing the first two parameters.
96 # We also need to make room on the stack for all four parameter registers.
97 # See http://msdn.microsoft.com/en-us/library/ms235286.aspx
98 move arg2, t1
99 move arg1, t2
100 subp 32, sp
101 call function
102 addp 32, sp
103 else
104 cCall2(function, arg1, arg2)
105 end
106end
107
6fe7ccc8
A
108# This barely works. arg3 and arg4 should probably be immediates.
109macro cCall4(function, arg1, arg2, arg3, arg4)
81345200 110 checkStackPointerAlignment(t4, 0xbad0c004)
93a37866 111 if X86_64
81345200
A
112 move arg1, t4
113 move arg2, t5
93a37866
A
114 move arg3, t1
115 move arg4, t2
116 call function
81345200
A
117 elsif X86_64_WIN
118 # On Win64, rcx, rdx, r8, and r9 are used for passing the first four parameters.
119 # We also need to make room on the stack for all four parameter registers.
120 # See http://msdn.microsoft.com/en-us/library/ms235286.aspx
121 move arg1, t2
122 move arg2, t1
123 move arg3, t6
124 move arg4, t7
125 subp 32, sp
126 call function
127 addp 32, sp
93a37866
A
128 elsif ARM64
129 move arg1, t0
130 move arg2, t1
131 move arg3, t2
132 move arg4, t3
133 call function
134 elsif C_LOOP
135 error
136 else
137 error
138 end
6fe7ccc8
A
139end
140
81345200
A
141macro doCallToJavaScript(makeCall)
142 if X86_64
143 const entry = t4
144 const vm = t5
145 const protoCallFrame = t1
146
147 const previousCFR = t0
148 const previousPC = t6
149 const temp1 = t0
150 const temp2 = t3
151 const temp3 = t6
152 elsif X86_64_WIN
153 const entry = t2
154 const vm = t1
155 const protoCallFrame = t6
156
157 const previousCFR = t0
158 const previousPC = t4
159 const temp1 = t0
160 const temp2 = t3
161 const temp3 = t7
162 elsif ARM64 or C_LOOP
163 const entry = a0
164 const vm = a1
165 const protoCallFrame = a2
166
167 const previousCFR = t5
168 const previousPC = lr
169 const temp1 = t3
170 const temp2 = t4
171 const temp3 = t6
172 end
173
174 callToJavaScriptPrologue()
175
176 if X86_64
177 loadp 7*8[sp], previousPC
178 move 6*8[sp], previousCFR
179 elsif X86_64_WIN
180 # Win64 pushes two more registers
181 loadp 9*8[sp], previousPC
182 move 8*8[sp], previousCFR
183 elsif ARM64
184 move cfr, previousCFR
185 end
186
187 checkStackPointerAlignment(temp2, 0xbad0dc01)
188
189 # The stack reserved zone ensures that we have adequate space for the
190 # VMEntrySentinelFrame. Proceed with allocating and initializing the
191 # sentinel frame.
192 move sp, cfr
193 subp CallFrameHeaderSlots * 8, cfr
194 storep 0, ArgumentCount[cfr]
195 storep vm, Callee[cfr]
196 loadp VM::topCallFrame[vm], temp2
197 storep temp2, ScopeChain[cfr]
198 storep 1, CodeBlock[cfr]
199
200 storep previousPC, ReturnPC[cfr]
201 storep previousCFR, CallerFrame[cfr]
202
203 loadi ProtoCallFrame::paddedArgCount[protoCallFrame], temp2
204 addp CallFrameHeaderSlots, temp2, temp2
205 lshiftp 3, temp2
206 subp cfr, temp2, temp1
207
208 # Ensure that we have enough additional stack capacity for the incoming args,
209 # and the frame for the JS code we're executing. We need to do this check
210 # before we start copying the args from the protoCallFrame below.
211 bpaeq temp1, VM::m_jsStackLimit[vm], .stackHeightOK
212
213 move cfr, sp
214
215 if C_LOOP
216 move entry, temp2
217 move vm, temp3
218 cloopCallSlowPath _llint_stack_check_at_vm_entry, vm, temp1
219 bpeq t0, 0, .stackCheckFailed
220 move temp2, entry
221 move temp3, vm
222 jmp .stackHeightOK
223
224.stackCheckFailed:
225 move temp2, entry
226 move temp3, vm
227 end
228
229 cCall2(_llint_throw_stack_overflow_error, vm, protoCallFrame)
230 callToJavaScriptEpilogue()
231 ret
232
233.stackHeightOK:
234 move temp1, sp
235 move 5, temp1
236
237.copyHeaderLoop:
238 subi 1, temp1
239 loadq [protoCallFrame, temp1, 8], temp3
240 storeq temp3, CodeBlock[sp, temp1, 8]
241 btinz temp1, .copyHeaderLoop
242
243 loadi PayloadOffset + ProtoCallFrame::argCountAndCodeOriginValue[protoCallFrame], temp2
244 subi 1, temp2
245 loadi ProtoCallFrame::paddedArgCount[protoCallFrame], temp3
246 subi 1, temp3
247
248 bieq temp2, temp3, .copyArgs
249 move ValueUndefined, temp1
250.fillExtraArgsLoop:
251 subi 1, temp3
252 storeq temp1, ThisArgumentOffset + 8[sp, temp3, 8]
253 bineq temp2, temp3, .fillExtraArgsLoop
254
255.copyArgs:
256 loadp ProtoCallFrame::args[protoCallFrame], temp1
257
258.copyArgsLoop:
259 btiz temp2, .copyArgsDone
260 subi 1, temp2
261 loadq [temp1, temp2, 8], temp3
262 storeq temp3, ThisArgumentOffset + 8[sp, temp2, 8]
263 jmp .copyArgsLoop
264
265.copyArgsDone:
266 if ARM64
267 move sp, temp2
268 storep temp2, VM::topCallFrame[vm]
269 else
270 storep sp, VM::topCallFrame[vm]
271 end
272
273 move 0xffff000000000000, csr1
274 addp 2, csr1, csr2
275
276 checkStackPointerAlignment(temp3, 0xbad0dc02)
277
278 makeCall(entry, temp1)
279
280 checkStackPointerAlignment(temp3, 0xbad0dc03)
281
282 bpeq CodeBlock[cfr], 1, .calleeFramePopped
283 loadp CallerFrame[cfr], cfr
284
285.calleeFramePopped:
286 loadp Callee[cfr], temp2 # VM
287 loadp ScopeChain[cfr], temp3 # previous topCallFrame
288 storep temp3, VM::topCallFrame[temp2]
289
290 checkStackPointerAlignment(temp3, 0xbad0dc04)
291
292 if X86_64 or X86_64_WIN
293 pop t5
294 end
295 callToJavaScriptEpilogue()
296
297 ret
298end
299
300
301macro makeJavaScriptCall(entry, temp)
302 addp 16, sp
303 if C_LOOP
304 cloopCallJSFunction entry
305 else
306 call entry
307 end
308 subp 16, sp
309end
310
311
312macro makeHostFunctionCall(entry, temp)
313 move entry, temp
314 if X86_64
315 move sp, t4
316 elsif X86_64_WIN
317 move sp, t2
318 elsif ARM64 or C_LOOP
319 move sp, a0
320 end
321 if C_LOOP
322 storep cfr, [sp]
323 storep lr, 8[sp]
324 cloopCallNative temp
325 elsif X86_64_WIN
326 # For a host function call, JIT relies on that the CallerFrame (frame pointer) is put on the stack,
327 # On Win64 we need to manually copy the frame pointer to the stack, since MSVC may not maintain a frame pointer on 64-bit.
328 # See http://msdn.microsoft.com/en-us/library/9z1stfyw.aspx where it's stated that rbp MAY be used as a frame pointer.
329 storep cfr, [sp]
330
331 # We need to allocate 32 bytes on the stack for the shadow space.
332 subp 32, sp
333 call temp
334 addp 32, sp
335 else
336 addp 16, sp
337 call temp
338 subp 16, sp
339 end
340end
341
342
343_handleUncaughtException:
344 loadp ScopeChain[cfr], t3
345 andp MarkedBlockMask, t3
346 loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
347 loadp VM::callFrameForThrow[t3], cfr
348
349 # So far, we've unwound the stack to the frame just below the sentinel frame, except
350 # in the case of stack overflow in the first function called from callToJavaScript.
351 # Check if we need to pop to the sentinel frame and do the necessary clean up for
352 # returning to the caller C frame.
353 bpeq CodeBlock[cfr], 1, .handleUncaughtExceptionAlreadyIsSentinel
354 loadp CallerFrame[cfr], cfr
355.handleUncaughtExceptionAlreadyIsSentinel:
356
357 loadp Callee[cfr], t3 # VM
358 loadp ScopeChain[cfr], t5 # previous topCallFrame
359 storep t5, VM::topCallFrame[t3]
360
361 callToJavaScriptEpilogue()
362 ret
363
364
6fe7ccc8
A
365macro prepareStateForCCall()
366 leap [PB, PC, 8], PC
367 move PB, t3
368end
369
370macro restoreStateAfterCCall()
371 move t0, PC
6fe7ccc8
A
372 move t3, PB
373 subp PB, PC
93a37866 374 rshiftp 3, PC
6fe7ccc8
A
375end
376
377macro callSlowPath(slowPath)
378 prepareStateForCCall()
379 cCall2(slowPath, cfr, PC)
380 restoreStateAfterCCall()
381end
382
383macro traceOperand(fromWhere, operand)
384 prepareStateForCCall()
385 cCall4(_llint_trace_operand, cfr, PC, fromWhere, operand)
386 restoreStateAfterCCall()
387end
388
389macro traceValue(fromWhere, operand)
390 prepareStateForCCall()
391 cCall4(_llint_trace_value, cfr, PC, fromWhere, operand)
392 restoreStateAfterCCall()
393end
394
395# Call a slow path for call call opcodes.
81345200
A
396macro callCallSlowPath(slowPath, action)
397 storei PC, ArgumentCount + TagOffset[cfr]
6fe7ccc8
A
398 prepareStateForCCall()
399 cCall2(slowPath, cfr, PC)
6fe7ccc8
A
400 action(t0)
401end
402
93a37866
A
403macro callWatchdogTimerHandler(throwHandler)
404 storei PC, ArgumentCount + TagOffset[cfr]
405 prepareStateForCCall()
406 cCall2(_llint_slow_path_handle_watchdog_timer, cfr, PC)
93a37866
A
407 btpnz t0, throwHandler
408 move t3, PB
409 loadi ArgumentCount + TagOffset[cfr], PC
410end
411
6fe7ccc8
A
412macro checkSwitchToJITForLoop()
413 checkSwitchToJIT(
414 1,
415 macro()
416 storei PC, ArgumentCount + TagOffset[cfr]
417 prepareStateForCCall()
418 cCall2(_llint_loop_osr, cfr, PC)
6fe7ccc8 419 btpz t0, .recover
81345200 420 move t1, sp
6fe7ccc8
A
421 jmp t0
422 .recover:
423 move t3, PB
424 loadi ArgumentCount + TagOffset[cfr], PC
425 end)
426end
427
81345200
A
428macro loadVariable(operand, value)
429 loadisFromInstruction(operand, value)
430 loadq [cfr, value, 8], value
431end
432
6fe7ccc8
A
433# Index and value must be different registers. Index may be clobbered.
434macro loadConstantOrVariable(index, value)
435 bpgteq index, FirstConstantRegisterIndex, .constant
93a37866 436 loadq [cfr, index, 8], value
6fe7ccc8
A
437 jmp .done
438.constant:
439 loadp CodeBlock[cfr], value
440 loadp CodeBlock::m_constantRegisters + VectorBufferOffset[value], value
441 subp FirstConstantRegisterIndex, index
93a37866 442 loadq [value, index, 8], value
6fe7ccc8
A
443.done:
444end
445
446macro loadConstantOrVariableInt32(index, value, slow)
447 loadConstantOrVariable(index, value)
93a37866 448 bqb value, tagTypeNumber, slow
6fe7ccc8
A
449end
450
451macro loadConstantOrVariableCell(index, value, slow)
452 loadConstantOrVariable(index, value)
93a37866 453 btqnz value, tagMask, slow
6fe7ccc8
A
454end
455
81345200
A
456macro writeBarrierOnOperand(cellOperand)
457 if GGC
458 loadisFromInstruction(cellOperand, t1)
459 loadConstantOrVariableCell(t1, t2, .writeBarrierDone)
460 checkMarkByte(t2, t1, t3,
461 macro(gcData)
462 btbnz gcData, .writeBarrierDone
463 push PB, PC
464 cCall2Void(_llint_write_barrier_slow, cfr, t2)
465 pop PC, PB
466 end
467 )
468 .writeBarrierDone:
469 end
470end
471
472macro writeBarrierOnOperands(cellOperand, valueOperand)
473 if GGC
474 loadisFromInstruction(valueOperand, t1)
475 loadConstantOrVariableCell(t1, t0, .writeBarrierDone)
476 btpz t0, .writeBarrierDone
477
478 writeBarrierOnOperand(cellOperand)
479 .writeBarrierDone:
480 end
6fe7ccc8
A
481end
482
81345200
A
483macro writeBarrierOnGlobalObject(valueOperand)
484 if GGC
485 loadisFromInstruction(valueOperand, t1)
486 loadConstantOrVariableCell(t1, t0, .writeBarrierDone)
487 btpz t0, .writeBarrierDone
488
489 loadp CodeBlock[cfr], t3
490 loadp CodeBlock::m_globalObject[t3], t3
491 checkMarkByte(t3, t1, t2,
492 macro(gcData)
493 btbnz gcData, .writeBarrierDone
494 push PB, PC
495 cCall2Void(_llint_write_barrier_slow, cfr, t3)
496 pop PC, PB
497 end
498 )
499 .writeBarrierDone:
6fe7ccc8
A
500 end
501end
502
81345200
A
503macro valueProfile(value, operand, scratch)
504 loadpFromInstruction(operand, scratch)
505 storeq value, ValueProfile::m_buckets[scratch]
506end
507
508macro loadStructure(cell, structure)
509end
510
511macro loadStructureWithScratch(cell, structure, scratch)
512 loadp CodeBlock[cfr], scratch
513 loadp CodeBlock::m_vm[scratch], scratch
514 loadp VM::heap + Heap::m_structureIDTable + StructureIDTable::m_table[scratch], scratch
515 loadi JSCell::m_structureID[cell], structure
516 loadp [scratch, structure, 8], structure
517end
518
519macro loadStructureAndClobberFirstArg(cell, structure)
520 loadi JSCell::m_structureID[cell], structure
521 loadp CodeBlock[cfr], cell
522 loadp CodeBlock::m_vm[cell], cell
523 loadp VM::heap + Heap::m_structureIDTable + StructureIDTable::m_table[cell], cell
524 loadp [cell, structure, 8], structure
525end
526
527macro storeStructureWithTypeInfo(cell, structure, scratch)
528 loadq Structure::m_blob + StructureIDBlob::u.doubleWord[structure], scratch
529 storeq scratch, JSCell::m_structureID[cell]
530end
6fe7ccc8
A
531
532# Entrypoints into the interpreter.
533
534# Expects that CodeBlock is in t1, which is what prologue() leaves behind.
81345200 535macro functionArityCheck(doneLabel, slowPath)
6fe7ccc8
A
536 loadi PayloadOffset + ArgumentCount[cfr], t0
537 biaeq t0, CodeBlock::m_numParameters[t1], doneLabel
538 prepareStateForCCall()
81345200
A
539 cCall2(slowPath, cfr, PC) # This slowPath has the protocol: t0 = 0 => no error, t0 != 0 => error
540 btiz t0, .noError
541 move t1, cfr # t1 contains caller frame
542 jmp _llint_throw_from_slow_path_trampoline
543
544.noError:
545 # t1 points to ArityCheckData.
546 loadp CommonSlowPaths::ArityCheckData::thunkToCall[t1], t2
547 btpz t2, .proceedInline
548
549 loadp CommonSlowPaths::ArityCheckData::returnPC[t1], t7
550 loadp CommonSlowPaths::ArityCheckData::paddedStackSpace[t1], t0
551 call t2
552 if ASSERT_ENABLED
553 loadp ReturnPC[cfr], t0
554 loadp [t0], t0
555 end
556 jmp .continue
557
558.proceedInline:
559 loadi CommonSlowPaths::ArityCheckData::paddedStackSpace[t1], t1
560 btiz t1, .continue
561
562 // Move frame up "t1 * 2" slots
563 lshiftp 1, t1
564 negq t1
565 move cfr, t3
566 loadi PayloadOffset + ArgumentCount[cfr], t2
567 addi CallFrameHeaderSlots, t2
568.copyLoop:
569 loadq [t3], t0
570 storeq t0, [t3, t1, 8]
571 addp 8, t3
572 bsubinz 1, t2, .copyLoop
573
574 // Fill new slots with JSUndefined
575 move t1, t2
576 move ValueUndefined, t0
577.fillLoop:
578 storeq t0, [t3, t1, 8]
579 addp 8, t3
580 baddinz 1, t2, .fillLoop
581
582 lshiftp 3, t1
583 addp t1, cfr
584 addp t1, sp
585
6fe7ccc8
A
586.continue:
587 # Reload CodeBlock and reset PC, since the slow_path clobbered them.
588 loadp CodeBlock[cfr], t1
589 loadp CodeBlock::m_instructions[t1], PB
590 move 0, PC
591 jmp doneLabel
592end
593
81345200
A
594macro branchIfException(label)
595 loadp ScopeChain[cfr], t3
596 andp MarkedBlockMask, t3
597 loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
598 btqz VM::m_exception[t3], .noException
599 jmp label
600.noException:
601end
602
6fe7ccc8
A
603
604# Instruction implementations
605
606_llint_op_enter:
607 traceExecution()
81345200 608 checkStackPointerAlignment(t2, 0xdead00e1)
93a37866
A
609 loadp CodeBlock[cfr], t2 // t2<CodeBlock> = cfr.CodeBlock
610 loadi CodeBlock::m_numVars[t2], t2 // t2<size_t> = t2<CodeBlock>.m_numVars
6fe7ccc8
A
611 btiz t2, .opEnterDone
612 move ValueUndefined, t0
81345200
A
613 negi t2
614 sxi2q t2, t2
6fe7ccc8 615.opEnterLoop:
93a37866 616 storeq t0, [cfr, t2, 8]
81345200
A
617 addq 1, t2
618 btqnz t2, .opEnterLoop
6fe7ccc8 619.opEnterDone:
81345200 620 callSlowPath(_slow_path_enter)
6fe7ccc8
A
621 dispatch(1)
622
623
624_llint_op_create_activation:
625 traceExecution()
93a37866
A
626 loadisFromInstruction(1, t0)
627 bqneq [cfr, t0, 8], ValueEmpty, .opCreateActivationDone
6fe7ccc8
A
628 callSlowPath(_llint_slow_path_create_activation)
629.opCreateActivationDone:
630 dispatch(2)
631
632
633_llint_op_init_lazy_reg:
634 traceExecution()
93a37866
A
635 loadisFromInstruction(1, t0)
636 storeq ValueEmpty, [cfr, t0, 8]
6fe7ccc8
A
637 dispatch(2)
638
639
640_llint_op_create_arguments:
641 traceExecution()
93a37866
A
642 loadisFromInstruction(1, t0)
643 bqneq [cfr, t0, 8], ValueEmpty, .opCreateArgumentsDone
81345200 644 callSlowPath(_slow_path_create_arguments)
6fe7ccc8
A
645.opCreateArgumentsDone:
646 dispatch(2)
647
648
649_llint_op_create_this:
650 traceExecution()
93a37866 651 loadisFromInstruction(2, t0)
6fe7ccc8 652 loadp [cfr, t0, 8], t0
93a37866
A
653 loadp JSFunction::m_allocationProfile + ObjectAllocationProfile::m_allocator[t0], t1
654 loadp JSFunction::m_allocationProfile + ObjectAllocationProfile::m_structure[t0], t2
655 btpz t1, .opCreateThisSlow
656 allocateJSObject(t1, t2, t0, t3, .opCreateThisSlow)
657 loadisFromInstruction(1, t1)
658 storeq t0, [cfr, t1, 8]
659 dispatch(4)
6fe7ccc8
A
660
661.opCreateThisSlow:
81345200 662 callSlowPath(_slow_path_create_this)
93a37866 663 dispatch(4)
6fe7ccc8
A
664
665
666_llint_op_get_callee:
667 traceExecution()
93a37866 668 loadisFromInstruction(1, t0)
6fe7ccc8 669 loadp Callee[cfr], t1
81345200
A
670 loadpFromInstruction(2, t2)
671 bpneq t1, t2, .opGetCalleeSlow
6fe7ccc8 672 storep t1, [cfr, t0, 8]
93a37866 673 dispatch(3)
6fe7ccc8 674
81345200
A
675.opGetCalleeSlow:
676 callSlowPath(_slow_path_get_callee)
677 dispatch(3)
6fe7ccc8 678
81345200 679_llint_op_to_this:
6fe7ccc8 680 traceExecution()
93a37866
A
681 loadisFromInstruction(1, t0)
682 loadq [cfr, t0, 8], t0
81345200
A
683 btqnz t0, tagMask, .opToThisSlow
684 bbneq JSCell::m_type[t0], FinalObjectType, .opToThisSlow
685 loadStructureWithScratch(t0, t1, t2)
686 loadpFromInstruction(2, t2)
687 bpneq t1, t2, .opToThisSlow
93a37866 688 dispatch(3)
6fe7ccc8 689
81345200
A
690.opToThisSlow:
691 callSlowPath(_slow_path_to_this)
93a37866 692 dispatch(3)
6fe7ccc8
A
693
694
695_llint_op_new_object:
696 traceExecution()
93a37866
A
697 loadpFromInstruction(3, t0)
698 loadp ObjectAllocationProfile::m_allocator[t0], t1
699 loadp ObjectAllocationProfile::m_structure[t0], t2
700 allocateJSObject(t1, t2, t0, t3, .opNewObjectSlow)
701 loadisFromInstruction(1, t1)
702 storeq t0, [cfr, t1, 8]
703 dispatch(4)
6fe7ccc8
A
704
705.opNewObjectSlow:
706 callSlowPath(_llint_slow_path_new_object)
93a37866 707 dispatch(4)
6fe7ccc8
A
708
709
710_llint_op_mov:
711 traceExecution()
93a37866
A
712 loadisFromInstruction(2, t1)
713 loadisFromInstruction(1, t0)
6fe7ccc8 714 loadConstantOrVariable(t1, t2)
93a37866 715 storeq t2, [cfr, t0, 8]
6fe7ccc8
A
716 dispatch(3)
717
718
81345200
A
719macro notifyWrite(set, value, scratch, slow)
720 loadb VariableWatchpointSet::m_state[set], scratch
721 bieq scratch, IsInvalidated, .done
722 bqneq value, VariableWatchpointSet::m_inferredValue[set], slow
723.done:
724end
725
726_llint_op_captured_mov:
727 traceExecution()
728 loadisFromInstruction(2, t1)
729 loadConstantOrVariable(t1, t2)
730 loadpFromInstruction(3, t0)
731 btpz t0, .opCapturedMovReady
732 notifyWrite(t0, t2, t1, .opCapturedMovSlow)
733.opCapturedMovReady:
734 loadisFromInstruction(1, t0)
735 storeq t2, [cfr, t0, 8]
736 dispatch(4)
737
738.opCapturedMovSlow:
739 callSlowPath(_slow_path_captured_mov)
740 dispatch(4)
741
742
6fe7ccc8
A
743_llint_op_not:
744 traceExecution()
93a37866
A
745 loadisFromInstruction(2, t0)
746 loadisFromInstruction(1, t1)
6fe7ccc8 747 loadConstantOrVariable(t0, t2)
93a37866
A
748 xorq ValueFalse, t2
749 btqnz t2, ~1, .opNotSlow
750 xorq ValueTrue, t2
751 storeq t2, [cfr, t1, 8]
6fe7ccc8
A
752 dispatch(3)
753
754.opNotSlow:
81345200 755 callSlowPath(_slow_path_not)
6fe7ccc8
A
756 dispatch(3)
757
758
759macro equalityComparison(integerComparison, slowPath)
760 traceExecution()
93a37866
A
761 loadisFromInstruction(3, t0)
762 loadisFromInstruction(2, t2)
763 loadisFromInstruction(1, t3)
6fe7ccc8
A
764 loadConstantOrVariableInt32(t0, t1, .slow)
765 loadConstantOrVariableInt32(t2, t0, .slow)
766 integerComparison(t0, t1, t0)
93a37866
A
767 orq ValueFalse, t0
768 storeq t0, [cfr, t3, 8]
6fe7ccc8
A
769 dispatch(4)
770
771.slow:
772 callSlowPath(slowPath)
773 dispatch(4)
774end
775
776_llint_op_eq:
777 equalityComparison(
778 macro (left, right, result) cieq left, right, result end,
81345200 779 _slow_path_eq)
6fe7ccc8
A
780
781
782_llint_op_neq:
783 equalityComparison(
784 macro (left, right, result) cineq left, right, result end,
81345200 785 _slow_path_neq)
6fe7ccc8
A
786
787
788macro equalNullComparison()
93a37866
A
789 loadisFromInstruction(2, t0)
790 loadq [cfr, t0, 8], t0
791 btqnz t0, tagMask, .immediate
81345200 792 btbnz JSCell::m_flags[t0], MasqueradesAsUndefined, .masqueradesAsUndefined
93a37866
A
793 move 0, t0
794 jmp .done
795.masqueradesAsUndefined:
81345200 796 loadStructureWithScratch(t0, t2, t1)
93a37866
A
797 loadp CodeBlock[cfr], t0
798 loadp CodeBlock::m_globalObject[t0], t0
799 cpeq Structure::m_globalObject[t2], t0, t0
6fe7ccc8
A
800 jmp .done
801.immediate:
93a37866
A
802 andq ~TagBitUndefined, t0
803 cqeq t0, ValueNull, t0
6fe7ccc8
A
804.done:
805end
806
807_llint_op_eq_null:
808 traceExecution()
809 equalNullComparison()
93a37866
A
810 loadisFromInstruction(1, t1)
811 orq ValueFalse, t0
812 storeq t0, [cfr, t1, 8]
6fe7ccc8
A
813 dispatch(3)
814
815
816_llint_op_neq_null:
817 traceExecution()
818 equalNullComparison()
93a37866
A
819 loadisFromInstruction(1, t1)
820 xorq ValueTrue, t0
821 storeq t0, [cfr, t1, 8]
6fe7ccc8
A
822 dispatch(3)
823
824
825macro strictEq(equalityOperation, slowPath)
826 traceExecution()
93a37866
A
827 loadisFromInstruction(3, t0)
828 loadisFromInstruction(2, t2)
6fe7ccc8
A
829 loadConstantOrVariable(t0, t1)
830 loadConstantOrVariable(t2, t0)
831 move t0, t2
93a37866
A
832 orq t1, t2
833 btqz t2, tagMask, .slow
834 bqaeq t0, tagTypeNumber, .leftOK
835 btqnz t0, tagTypeNumber, .slow
6fe7ccc8 836.leftOK:
93a37866
A
837 bqaeq t1, tagTypeNumber, .rightOK
838 btqnz t1, tagTypeNumber, .slow
6fe7ccc8
A
839.rightOK:
840 equalityOperation(t0, t1, t0)
93a37866
A
841 loadisFromInstruction(1, t1)
842 orq ValueFalse, t0
843 storeq t0, [cfr, t1, 8]
6fe7ccc8
A
844 dispatch(4)
845
846.slow:
847 callSlowPath(slowPath)
848 dispatch(4)
849end
850
851_llint_op_stricteq:
852 strictEq(
93a37866 853 macro (left, right, result) cqeq left, right, result end,
81345200 854 _slow_path_stricteq)
6fe7ccc8
A
855
856
857_llint_op_nstricteq:
858 strictEq(
93a37866 859 macro (left, right, result) cqneq left, right, result end,
81345200 860 _slow_path_nstricteq)
6fe7ccc8
A
861
862
863macro preOp(arithmeticOperation, slowPath)
864 traceExecution()
93a37866
A
865 loadisFromInstruction(1, t0)
866 loadq [cfr, t0, 8], t1
867 bqb t1, tagTypeNumber, .slow
6fe7ccc8 868 arithmeticOperation(t1, .slow)
93a37866
A
869 orq tagTypeNumber, t1
870 storeq t1, [cfr, t0, 8]
6fe7ccc8
A
871 dispatch(2)
872
873.slow:
874 callSlowPath(slowPath)
875 dispatch(2)
876end
877
93a37866 878_llint_op_inc:
6fe7ccc8
A
879 preOp(
880 macro (value, slow) baddio 1, value, slow end,
81345200 881 _slow_path_inc)
6fe7ccc8
A
882
883
93a37866 884_llint_op_dec:
6fe7ccc8
A
885 preOp(
886 macro (value, slow) bsubio 1, value, slow end,
81345200 887 _slow_path_dec)
6fe7ccc8
A
888
889
93a37866 890_llint_op_to_number:
6fe7ccc8 891 traceExecution()
93a37866
A
892 loadisFromInstruction(2, t0)
893 loadisFromInstruction(1, t1)
6fe7ccc8 894 loadConstantOrVariable(t0, t2)
93a37866
A
895 bqaeq t2, tagTypeNumber, .opToNumberIsImmediate
896 btqz t2, tagTypeNumber, .opToNumberSlow
897.opToNumberIsImmediate:
898 storeq t2, [cfr, t1, 8]
6fe7ccc8
A
899 dispatch(3)
900
93a37866 901.opToNumberSlow:
81345200 902 callSlowPath(_slow_path_to_number)
6fe7ccc8
A
903 dispatch(3)
904
905
906_llint_op_negate:
907 traceExecution()
93a37866
A
908 loadisFromInstruction(2, t0)
909 loadisFromInstruction(1, t1)
6fe7ccc8 910 loadConstantOrVariable(t0, t2)
93a37866 911 bqb t2, tagTypeNumber, .opNegateNotInt
6fe7ccc8
A
912 btiz t2, 0x7fffffff, .opNegateSlow
913 negi t2
93a37866
A
914 orq tagTypeNumber, t2
915 storeq t2, [cfr, t1, 8]
6fe7ccc8
A
916 dispatch(3)
917.opNegateNotInt:
93a37866
A
918 btqz t2, tagTypeNumber, .opNegateSlow
919 xorq 0x8000000000000000, t2
920 storeq t2, [cfr, t1, 8]
6fe7ccc8
A
921 dispatch(3)
922
923.opNegateSlow:
81345200 924 callSlowPath(_slow_path_negate)
6fe7ccc8
A
925 dispatch(3)
926
927
928macro binaryOpCustomStore(integerOperationAndStore, doubleOperation, slowPath)
93a37866
A
929 loadisFromInstruction(3, t0)
930 loadisFromInstruction(2, t2)
6fe7ccc8
A
931 loadConstantOrVariable(t0, t1)
932 loadConstantOrVariable(t2, t0)
93a37866
A
933 bqb t0, tagTypeNumber, .op1NotInt
934 bqb t1, tagTypeNumber, .op2NotInt
935 loadisFromInstruction(1, t2)
6fe7ccc8
A
936 integerOperationAndStore(t1, t0, .slow, t2)
937 dispatch(5)
938
939.op1NotInt:
940 # First operand is definitely not an int, the second operand could be anything.
93a37866
A
941 btqz t0, tagTypeNumber, .slow
942 bqaeq t1, tagTypeNumber, .op1NotIntOp2Int
943 btqz t1, tagTypeNumber, .slow
944 addq tagTypeNumber, t1
945 fq2d t1, ft1
6fe7ccc8
A
946 jmp .op1NotIntReady
947.op1NotIntOp2Int:
948 ci2d t1, ft1
949.op1NotIntReady:
93a37866
A
950 loadisFromInstruction(1, t2)
951 addq tagTypeNumber, t0
952 fq2d t0, ft0
6fe7ccc8 953 doubleOperation(ft1, ft0)
93a37866
A
954 fd2q ft0, t0
955 subq tagTypeNumber, t0
956 storeq t0, [cfr, t2, 8]
6fe7ccc8
A
957 dispatch(5)
958
959.op2NotInt:
960 # First operand is definitely an int, the second is definitely not.
93a37866
A
961 loadisFromInstruction(1, t2)
962 btqz t1, tagTypeNumber, .slow
6fe7ccc8 963 ci2d t0, ft0
93a37866
A
964 addq tagTypeNumber, t1
965 fq2d t1, ft1
6fe7ccc8 966 doubleOperation(ft1, ft0)
93a37866
A
967 fd2q ft0, t0
968 subq tagTypeNumber, t0
969 storeq t0, [cfr, t2, 8]
6fe7ccc8
A
970 dispatch(5)
971
972.slow:
973 callSlowPath(slowPath)
974 dispatch(5)
975end
976
977macro binaryOp(integerOperation, doubleOperation, slowPath)
978 binaryOpCustomStore(
979 macro (left, right, slow, index)
980 integerOperation(left, right, slow)
93a37866
A
981 orq tagTypeNumber, right
982 storeq right, [cfr, index, 8]
6fe7ccc8
A
983 end,
984 doubleOperation, slowPath)
985end
986
987_llint_op_add:
988 traceExecution()
989 binaryOp(
990 macro (left, right, slow) baddio left, right, slow end,
991 macro (left, right) addd left, right end,
81345200 992 _slow_path_add)
6fe7ccc8
A
993
994
995_llint_op_mul:
996 traceExecution()
997 binaryOpCustomStore(
998 macro (left, right, slow, index)
999 # Assume t3 is scratchable.
1000 move right, t3
1001 bmulio left, t3, slow
1002 btinz t3, .done
1003 bilt left, 0, slow
1004 bilt right, 0, slow
1005 .done:
93a37866
A
1006 orq tagTypeNumber, t3
1007 storeq t3, [cfr, index, 8]
6fe7ccc8
A
1008 end,
1009 macro (left, right) muld left, right end,
81345200 1010 _slow_path_mul)
6fe7ccc8
A
1011
1012
1013_llint_op_sub:
1014 traceExecution()
1015 binaryOp(
1016 macro (left, right, slow) bsubio left, right, slow end,
1017 macro (left, right) subd left, right end,
81345200 1018 _slow_path_sub)
6fe7ccc8
A
1019
1020
1021_llint_op_div:
1022 traceExecution()
81345200 1023 if X86_64 or X86_64_WIN
93a37866
A
1024 binaryOpCustomStore(
1025 macro (left, right, slow, index)
1026 # Assume t3 is scratchable.
1027 btiz left, slow
1028 bineq left, -1, .notNeg2TwoThe31DivByNeg1
1029 bieq right, -2147483648, .slow
1030 .notNeg2TwoThe31DivByNeg1:
1031 btinz right, .intOK
1032 bilt left, 0, slow
1033 .intOK:
1034 move left, t3
1035 move right, t0
1036 cdqi
1037 idivi t3
1038 btinz t1, slow
1039 orq tagTypeNumber, t0
1040 storeq t0, [cfr, index, 8]
1041 end,
1042 macro (left, right) divd left, right end,
81345200 1043 _slow_path_div)
93a37866 1044 else
81345200 1045 callSlowPath(_slow_path_div)
93a37866
A
1046 dispatch(5)
1047 end
6fe7ccc8
A
1048
1049
1050macro bitOp(operation, slowPath, advance)
93a37866
A
1051 loadisFromInstruction(3, t0)
1052 loadisFromInstruction(2, t2)
1053 loadisFromInstruction(1, t3)
6fe7ccc8
A
1054 loadConstantOrVariable(t0, t1)
1055 loadConstantOrVariable(t2, t0)
93a37866
A
1056 bqb t0, tagTypeNumber, .slow
1057 bqb t1, tagTypeNumber, .slow
81345200 1058 operation(t1, t0)
93a37866
A
1059 orq tagTypeNumber, t0
1060 storeq t0, [cfr, t3, 8]
6fe7ccc8
A
1061 dispatch(advance)
1062
1063.slow:
1064 callSlowPath(slowPath)
1065 dispatch(advance)
1066end
1067
1068_llint_op_lshift:
1069 traceExecution()
1070 bitOp(
81345200
A
1071 macro (left, right) lshifti left, right end,
1072 _slow_path_lshift,
6fe7ccc8
A
1073 4)
1074
1075
1076_llint_op_rshift:
1077 traceExecution()
1078 bitOp(
81345200
A
1079 macro (left, right) rshifti left, right end,
1080 _slow_path_rshift,
6fe7ccc8
A
1081 4)
1082
1083
1084_llint_op_urshift:
1085 traceExecution()
1086 bitOp(
81345200
A
1087 macro (left, right) urshifti left, right end,
1088 _slow_path_urshift,
6fe7ccc8
A
1089 4)
1090
1091
81345200
A
1092_llint_op_unsigned:
1093 traceExecution()
1094 loadisFromInstruction(1, t0)
1095 loadisFromInstruction(2, t1)
1096 loadConstantOrVariable(t1, t2)
1097 bilt t2, 0, .opUnsignedSlow
1098 storeq t2, [cfr, t0, 8]
1099 dispatch(3)
1100.opUnsignedSlow:
1101 callSlowPath(_slow_path_unsigned)
1102 dispatch(3)
1103
1104
6fe7ccc8
A
1105_llint_op_bitand:
1106 traceExecution()
1107 bitOp(
81345200
A
1108 macro (left, right) andi left, right end,
1109 _slow_path_bitand,
6fe7ccc8
A
1110 5)
1111
1112
1113_llint_op_bitxor:
1114 traceExecution()
1115 bitOp(
81345200
A
1116 macro (left, right) xori left, right end,
1117 _slow_path_bitxor,
6fe7ccc8
A
1118 5)
1119
1120
1121_llint_op_bitor:
1122 traceExecution()
1123 bitOp(
81345200
A
1124 macro (left, right) ori left, right end,
1125 _slow_path_bitor,
6fe7ccc8
A
1126 5)
1127
1128
1129_llint_op_check_has_instance:
1130 traceExecution()
93a37866 1131 loadisFromInstruction(3, t1)
6fe7ccc8 1132 loadConstantOrVariableCell(t1, t0, .opCheckHasInstanceSlow)
81345200 1133 btbz JSCell::m_flags[t0], ImplementsDefaultHasInstance, .opCheckHasInstanceSlow
93a37866 1134 dispatch(5)
6fe7ccc8
A
1135
1136.opCheckHasInstanceSlow:
1137 callSlowPath(_llint_slow_path_check_has_instance)
93a37866 1138 dispatch(0)
6fe7ccc8
A
1139
1140
1141_llint_op_instanceof:
1142 traceExecution()
6fe7ccc8 1143 # Actually do the work.
93a37866 1144 loadisFromInstruction(3, t0)
6fe7ccc8 1145 loadConstantOrVariableCell(t0, t1, .opInstanceofSlow)
81345200 1146 bbb JSCell::m_type[t1], ObjectType, .opInstanceofSlow
93a37866 1147 loadisFromInstruction(2, t0)
6fe7ccc8
A
1148 loadConstantOrVariableCell(t0, t2, .opInstanceofSlow)
1149
1150 # Register state: t1 = prototype, t2 = value
1151 move 1, t0
1152.opInstanceofLoop:
81345200
A
1153 loadStructureAndClobberFirstArg(t2, t3)
1154 loadq Structure::m_prototype[t3], t2
93a37866
A
1155 bqeq t2, t1, .opInstanceofDone
1156 btqz t2, tagMask, .opInstanceofLoop
6fe7ccc8
A
1157
1158 move 0, t0
1159.opInstanceofDone:
93a37866 1160 orq ValueFalse, t0
81345200 1161 loadisFromInstruction(1, t3)
93a37866
A
1162 storeq t0, [cfr, t3, 8]
1163 dispatch(4)
6fe7ccc8
A
1164
1165.opInstanceofSlow:
1166 callSlowPath(_llint_slow_path_instanceof)
93a37866 1167 dispatch(4)
6fe7ccc8
A
1168
1169
1170_llint_op_is_undefined:
1171 traceExecution()
93a37866
A
1172 loadisFromInstruction(2, t1)
1173 loadisFromInstruction(1, t2)
6fe7ccc8 1174 loadConstantOrVariable(t1, t0)
93a37866
A
1175 btqz t0, tagMask, .opIsUndefinedCell
1176 cqeq t0, ValueUndefined, t3
1177 orq ValueFalse, t3
1178 storeq t3, [cfr, t2, 8]
6fe7ccc8
A
1179 dispatch(3)
1180.opIsUndefinedCell:
81345200 1181 btbnz JSCell::m_flags[t0], MasqueradesAsUndefined, .masqueradesAsUndefined
93a37866
A
1182 move ValueFalse, t1
1183 storeq t1, [cfr, t2, 8]
1184 dispatch(3)
1185.masqueradesAsUndefined:
81345200 1186 loadStructureWithScratch(t0, t3, t1)
93a37866
A
1187 loadp CodeBlock[cfr], t1
1188 loadp CodeBlock::m_globalObject[t1], t1
81345200
A
1189 cpeq Structure::m_globalObject[t3], t1, t0
1190 orq ValueFalse, t0
1191 storeq t0, [cfr, t2, 8]
6fe7ccc8
A
1192 dispatch(3)
1193
1194
1195_llint_op_is_boolean:
1196 traceExecution()
93a37866
A
1197 loadisFromInstruction(2, t1)
1198 loadisFromInstruction(1, t2)
6fe7ccc8 1199 loadConstantOrVariable(t1, t0)
93a37866
A
1200 xorq ValueFalse, t0
1201 tqz t0, ~1, t0
1202 orq ValueFalse, t0
1203 storeq t0, [cfr, t2, 8]
6fe7ccc8
A
1204 dispatch(3)
1205
1206
1207_llint_op_is_number:
1208 traceExecution()
93a37866
A
1209 loadisFromInstruction(2, t1)
1210 loadisFromInstruction(1, t2)
6fe7ccc8 1211 loadConstantOrVariable(t1, t0)
93a37866
A
1212 tqnz t0, tagTypeNumber, t1
1213 orq ValueFalse, t1
1214 storeq t1, [cfr, t2, 8]
6fe7ccc8
A
1215 dispatch(3)
1216
1217
1218_llint_op_is_string:
1219 traceExecution()
93a37866
A
1220 loadisFromInstruction(2, t1)
1221 loadisFromInstruction(1, t2)
6fe7ccc8 1222 loadConstantOrVariable(t1, t0)
93a37866 1223 btqnz t0, tagMask, .opIsStringNotCell
81345200 1224 cbeq JSCell::m_type[t0], StringType, t1
93a37866
A
1225 orq ValueFalse, t1
1226 storeq t1, [cfr, t2, 8]
6fe7ccc8
A
1227 dispatch(3)
1228.opIsStringNotCell:
93a37866 1229 storeq ValueFalse, [cfr, t2, 8]
6fe7ccc8
A
1230 dispatch(3)
1231
1232
81345200
A
1233macro loadPropertyAtVariableOffset(propertyOffsetAsInt, objectAndStorage, value)
1234 bilt propertyOffsetAsInt, firstOutOfLineOffset, .isInline
93a37866 1235 loadp JSObject::m_butterfly[objectAndStorage], objectAndStorage
81345200
A
1236 negi propertyOffsetAsInt
1237 sxi2q propertyOffsetAsInt, propertyOffsetAsInt
1238 jmp .ready
1239.isInline:
1240 addp sizeof JSObject - (firstOutOfLineOffset - 2) * 8, objectAndStorage
1241.ready:
1242 loadq (firstOutOfLineOffset - 2) * 8[objectAndStorage, propertyOffsetAsInt, 8], value
6fe7ccc8
A
1243end
1244
81345200
A
1245
1246macro storePropertyAtVariableOffset(propertyOffsetAsInt, objectAndStorage, value)
93a37866
A
1247 bilt propertyOffsetAsInt, firstOutOfLineOffset, .isInline
1248 loadp JSObject::m_butterfly[objectAndStorage], objectAndStorage
1249 negi propertyOffsetAsInt
1250 sxi2q propertyOffsetAsInt, propertyOffsetAsInt
1251 jmp .ready
1252.isInline:
1253 addp sizeof JSObject - (firstOutOfLineOffset - 2) * 8, objectAndStorage
1254.ready:
81345200 1255 storeq value, (firstOutOfLineOffset - 2) * 8[objectAndStorage, propertyOffsetAsInt, 8]
6fe7ccc8
A
1256end
1257
93a37866 1258_llint_op_init_global_const:
6fe7ccc8 1259 traceExecution()
81345200 1260 writeBarrierOnGlobalObject(2)
93a37866
A
1261 loadisFromInstruction(2, t1)
1262 loadpFromInstruction(1, t0)
1263 loadConstantOrVariable(t1, t2)
93a37866 1264 storeq t2, [t0]
6fe7ccc8
A
1265 dispatch(5)
1266
1267
93a37866 1268macro getById(getPropertyStorage)
6fe7ccc8
A
1269 traceExecution()
1270 # We only do monomorphic get_by_id caching for now, and we do not modify the
1271 # opcode. We do, however, allow for the cache to change anytime if fails, since
1272 # ping-ponging is free. At best we get lucky and the get_by_id will continue
1273 # to take fast path on the new cache. At worst we take slow path, which is what
1274 # we would have been doing anyway.
93a37866 1275 loadisFromInstruction(2, t0)
6fe7ccc8 1276 loadConstantOrVariableCell(t0, t3, .opGetByIdSlow)
81345200
A
1277 loadStructureWithScratch(t3, t2, t1)
1278 loadpFromInstruction(4, t1)
1279 bpneq t2, t1, .opGetByIdSlow
93a37866
A
1280 getPropertyStorage(
1281 t3,
1282 t0,
1283 macro (propertyStorage, scratch)
81345200 1284 loadisFromInstruction(5, t2)
93a37866
A
1285 loadisFromInstruction(1, t1)
1286 loadq [propertyStorage, t2], scratch
1287 storeq scratch, [cfr, t1, 8]
81345200 1288 valueProfile(scratch, 8, t1)
93a37866
A
1289 dispatch(9)
1290 end)
1291
1292 .opGetByIdSlow:
1293 callSlowPath(_llint_slow_path_get_by_id)
1294 dispatch(9)
1295end
1296
1297_llint_op_get_by_id:
1298 getById(withInlineStorage)
1299
1300
1301_llint_op_get_by_id_out_of_line:
1302 getById(withOutOfLineStorage)
1303
1304
1305_llint_op_get_array_length:
1306 traceExecution()
1307 loadisFromInstruction(2, t0)
1308 loadpFromInstruction(4, t1)
1309 loadConstantOrVariableCell(t0, t3, .opGetArrayLengthSlow)
81345200 1310 move t3, t2
93a37866
A
1311 arrayProfile(t2, t1, t0)
1312 btiz t2, IsArray, .opGetArrayLengthSlow
1313 btiz t2, IndexingShapeMask, .opGetArrayLengthSlow
1314 loadisFromInstruction(1, t1)
93a37866 1315 loadp JSObject::m_butterfly[t3], t0
81345200 1316 loadi -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0], t0
93a37866
A
1317 bilt t0, 0, .opGetArrayLengthSlow
1318 orq tagTypeNumber, t0
81345200 1319 valueProfile(t0, 8, t2)
93a37866 1320 storeq t0, [cfr, t1, 8]
6fe7ccc8
A
1321 dispatch(9)
1322
93a37866 1323.opGetArrayLengthSlow:
6fe7ccc8
A
1324 callSlowPath(_llint_slow_path_get_by_id)
1325 dispatch(9)
1326
1327
1328_llint_op_get_arguments_length:
1329 traceExecution()
93a37866
A
1330 loadisFromInstruction(2, t0)
1331 loadisFromInstruction(1, t1)
1332 btqnz [cfr, t0, 8], .opGetArgumentsLengthSlow
6fe7ccc8
A
1333 loadi ArgumentCount + PayloadOffset[cfr], t2
1334 subi 1, t2
93a37866
A
1335 orq tagTypeNumber, t2
1336 storeq t2, [cfr, t1, 8]
6fe7ccc8
A
1337 dispatch(4)
1338
1339.opGetArgumentsLengthSlow:
1340 callSlowPath(_llint_slow_path_get_arguments_length)
1341 dispatch(4)
1342
1343
93a37866 1344macro putById(getPropertyStorage)
6fe7ccc8 1345 traceExecution()
81345200 1346 writeBarrierOnOperands(1, 3)
93a37866 1347 loadisFromInstruction(1, t3)
6fe7ccc8 1348 loadConstantOrVariableCell(t3, t0, .opPutByIdSlow)
81345200
A
1349 loadStructureWithScratch(t0, t2, t1)
1350 loadpFromInstruction(4, t1)
1351 bpneq t2, t1, .opPutByIdSlow
93a37866
A
1352 getPropertyStorage(
1353 t0,
1354 t3,
1355 macro (propertyStorage, scratch)
93a37866 1356 loadisFromInstruction(5, t1)
81345200 1357 loadisFromInstruction(3, t2)
93a37866 1358 loadConstantOrVariable(t2, scratch)
93a37866
A
1359 storeq scratch, [propertyStorage, t1]
1360 dispatch(9)
1361 end)
1362end
1363
1364_llint_op_put_by_id:
1365 putById(withInlineStorage)
6fe7ccc8
A
1366
1367.opPutByIdSlow:
1368 callSlowPath(_llint_slow_path_put_by_id)
1369 dispatch(9)
1370
1371
93a37866
A
1372_llint_op_put_by_id_out_of_line:
1373 putById(withOutOfLineStorage)
1374
1375
1376macro putByIdTransition(additionalChecks, getPropertyStorage)
6fe7ccc8 1377 traceExecution()
81345200 1378 writeBarrierOnOperand(1)
93a37866
A
1379 loadisFromInstruction(1, t3)
1380 loadpFromInstruction(4, t1)
6fe7ccc8 1381 loadConstantOrVariableCell(t3, t0, .opPutByIdSlow)
81345200
A
1382 loadStructureWithScratch(t0, t2, t3)
1383 bpneq t2, t1, .opPutByIdSlow
1384 additionalChecks(t1, t3, t2)
93a37866 1385 loadisFromInstruction(3, t2)
93a37866
A
1386 loadisFromInstruction(5, t1)
1387 getPropertyStorage(
1388 t0,
1389 t3,
1390 macro (propertyStorage, scratch)
1391 addp t1, propertyStorage, t3
1392 loadConstantOrVariable(t2, t1)
93a37866
A
1393 storeq t1, [t3]
1394 loadpFromInstruction(6, t1)
81345200
A
1395 loadi Structure::m_blob + StructureIDBlob::u.words.word1[t1], t1
1396 storei t1, JSCell::m_structureID[t0]
93a37866
A
1397 dispatch(9)
1398 end)
1399end
1400
81345200 1401macro noAdditionalChecks(oldStructure, scratch, scratch2)
93a37866
A
1402end
1403
81345200 1404macro structureChainChecks(oldStructure, scratch, scratch2)
93a37866
A
1405 const protoCell = oldStructure # Reusing the oldStructure register for the proto
1406 loadpFromInstruction(7, scratch)
1407 assert(macro (ok) btpnz scratch, ok end)
1408 loadp StructureChain::m_vector[scratch], scratch
1409 assert(macro (ok) btpnz scratch, ok end)
1410 bqeq Structure::m_prototype[oldStructure], ValueNull, .done
1411.loop:
1412 loadq Structure::m_prototype[oldStructure], protoCell
81345200
A
1413 loadStructureAndClobberFirstArg(protoCell, scratch2)
1414 move scratch2, oldStructure
93a37866
A
1415 bpneq oldStructure, [scratch], .opPutByIdSlow
1416 addp 8, scratch
1417 bqneq Structure::m_prototype[oldStructure], ValueNull, .loop
1418.done:
6fe7ccc8
A
1419end
1420
1421_llint_op_put_by_id_transition_direct:
93a37866
A
1422 putByIdTransition(noAdditionalChecks, withInlineStorage)
1423
1424
1425_llint_op_put_by_id_transition_direct_out_of_line:
1426 putByIdTransition(noAdditionalChecks, withOutOfLineStorage)
6fe7ccc8
A
1427
1428
1429_llint_op_put_by_id_transition_normal:
93a37866
A
1430 putByIdTransition(structureChainChecks, withInlineStorage)
1431
1432
1433_llint_op_put_by_id_transition_normal_out_of_line:
1434 putByIdTransition(structureChainChecks, withOutOfLineStorage)
6fe7ccc8
A
1435
1436
1437_llint_op_get_by_val:
1438 traceExecution()
93a37866 1439 loadisFromInstruction(2, t2)
6fe7ccc8 1440 loadConstantOrVariableCell(t2, t0, .opGetByValSlow)
93a37866 1441 loadpFromInstruction(4, t3)
81345200 1442 move t0, t2
93a37866
A
1443 arrayProfile(t2, t3, t1)
1444 loadisFromInstruction(3, t3)
6fe7ccc8 1445 loadConstantOrVariableInt32(t3, t1, .opGetByValSlow)
93a37866
A
1446 sxi2q t1, t1
1447 loadp JSObject::m_butterfly[t0], t3
1448 andi IndexingShapeMask, t2
1449 bieq t2, Int32Shape, .opGetByValIsContiguous
1450 bineq t2, ContiguousShape, .opGetByValNotContiguous
1451.opGetByValIsContiguous:
1452
81345200 1453 biaeq t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t3], .opGetByValOutOfBounds
93a37866
A
1454 loadisFromInstruction(1, t0)
1455 loadq [t3, t1, 8], t2
1456 btqz t2, .opGetByValOutOfBounds
1457 jmp .opGetByValDone
1458
1459.opGetByValNotContiguous:
1460 bineq t2, DoubleShape, .opGetByValNotDouble
81345200 1461 biaeq t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t3], .opGetByValOutOfBounds
6fe7ccc8 1462 loadis 8[PB, PC, 8], t0
93a37866
A
1463 loadd [t3, t1, 8], ft0
1464 bdnequn ft0, ft0, .opGetByValOutOfBounds
1465 fd2q ft0, t2
1466 subq tagTypeNumber, t2
1467 jmp .opGetByValDone
1468
1469.opGetByValNotDouble:
1470 subi ArrayStorageShape, t2
1471 bia t2, SlowPutArrayStorageShape - ArrayStorageShape, .opGetByValSlow
81345200 1472 biaeq t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.vectorLength[t3], .opGetByValOutOfBounds
93a37866
A
1473 loadisFromInstruction(1, t0)
1474 loadq ArrayStorage::m_vector[t3, t1, 8], t2
1475 btqz t2, .opGetByValOutOfBounds
1476
1477.opGetByValDone:
1478 storeq t2, [cfr, t0, 8]
81345200 1479 valueProfile(t2, 5, t0)
93a37866 1480 dispatch(6)
6fe7ccc8 1481
93a37866 1482.opGetByValOutOfBounds:
81345200
A
1483 loadpFromInstruction(4, t0)
1484 storeb 1, ArrayProfile::m_outOfBounds[t0]
6fe7ccc8
A
1485.opGetByValSlow:
1486 callSlowPath(_llint_slow_path_get_by_val)
93a37866 1487 dispatch(6)
6fe7ccc8
A
1488
1489
1490_llint_op_get_argument_by_val:
93a37866
A
1491 # FIXME: At some point we should array profile this. Right now it isn't necessary
1492 # since the DFG will never turn a get_argument_by_val into a GetByVal.
6fe7ccc8 1493 traceExecution()
93a37866
A
1494 loadisFromInstruction(2, t0)
1495 loadisFromInstruction(3, t1)
1496 btqnz [cfr, t0, 8], .opGetArgumentByValSlow
6fe7ccc8
A
1497 loadConstantOrVariableInt32(t1, t2, .opGetArgumentByValSlow)
1498 addi 1, t2
1499 loadi ArgumentCount + PayloadOffset[cfr], t1
1500 biaeq t2, t1, .opGetArgumentByValSlow
93a37866
A
1501 loadisFromInstruction(1, t3)
1502 loadpFromInstruction(5, t1)
1503 loadq ThisArgumentOffset[cfr, t2, 8], t0
1504 storeq t0, [cfr, t3, 8]
81345200 1505 valueProfile(t0, 5, t1)
93a37866 1506 dispatch(6)
6fe7ccc8
A
1507
1508.opGetArgumentByValSlow:
1509 callSlowPath(_llint_slow_path_get_argument_by_val)
93a37866 1510 dispatch(6)
6fe7ccc8
A
1511
1512
1513_llint_op_get_by_pname:
1514 traceExecution()
93a37866 1515 loadisFromInstruction(3, t1)
6fe7ccc8 1516 loadConstantOrVariable(t1, t0)
93a37866 1517 loadisFromInstruction(4, t1)
6fe7ccc8 1518 assertNotConstant(t1)
93a37866
A
1519 bqneq t0, [cfr, t1, 8], .opGetByPnameSlow
1520 loadisFromInstruction(2, t2)
1521 loadisFromInstruction(5, t3)
6fe7ccc8
A
1522 loadConstantOrVariableCell(t2, t0, .opGetByPnameSlow)
1523 assertNotConstant(t3)
93a37866 1524 loadq [cfr, t3, 8], t1
81345200 1525 loadStructureWithScratch(t0, t2, t3)
6fe7ccc8 1526 bpneq t2, JSPropertyNameIterator::m_cachedStructure[t1], .opGetByPnameSlow
93a37866 1527 loadisFromInstruction(6, t3)
6fe7ccc8
A
1528 loadi PayloadOffset[cfr, t3, 8], t3
1529 subi 1, t3
1530 biaeq t3, JSPropertyNameIterator::m_numCacheableSlots[t1], .opGetByPnameSlow
93a37866
A
1531 bilt t3, JSPropertyNameIterator::m_cachedStructureInlineCapacity[t1], .opGetByPnameInlineProperty
1532 addi firstOutOfLineOffset, t3
1533 subi JSPropertyNameIterator::m_cachedStructureInlineCapacity[t1], t3
1534.opGetByPnameInlineProperty:
1535 loadPropertyAtVariableOffset(t3, t0, t0)
1536 loadisFromInstruction(1, t1)
1537 storeq t0, [cfr, t1, 8]
6fe7ccc8
A
1538 dispatch(7)
1539
1540.opGetByPnameSlow:
1541 callSlowPath(_llint_slow_path_get_by_pname)
1542 dispatch(7)
1543
1544
93a37866 1545macro contiguousPutByVal(storeCallback)
81345200 1546 biaeq t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0], .outOfBounds
93a37866
A
1547.storeResult:
1548 loadisFromInstruction(3, t2)
1549 storeCallback(t2, t1, [t0, t3, 8])
1550 dispatch(5)
1551
1552.outOfBounds:
81345200
A
1553 biaeq t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.vectorLength[t0], .opPutByValOutOfBounds
1554 loadp 32[PB, PC, 8], t2
1555 storeb 1, ArrayProfile::m_mayStoreToHole[t2]
93a37866 1556 addi 1, t3, t2
81345200 1557 storei t2, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0]
93a37866
A
1558 jmp .storeResult
1559end
1560
81345200 1561macro putByVal(slowPath)
6fe7ccc8 1562 traceExecution()
81345200 1563 writeBarrierOnOperands(1, 3)
93a37866 1564 loadisFromInstruction(1, t0)
6fe7ccc8 1565 loadConstantOrVariableCell(t0, t1, .opPutByValSlow)
93a37866 1566 loadpFromInstruction(4, t3)
81345200 1567 move t1, t2
93a37866
A
1568 arrayProfile(t2, t3, t0)
1569 loadisFromInstruction(2, t0)
1570 loadConstantOrVariableInt32(t0, t3, .opPutByValSlow)
1571 sxi2q t3, t3
1572 loadp JSObject::m_butterfly[t1], t0
1573 andi IndexingShapeMask, t2
1574 bineq t2, Int32Shape, .opPutByValNotInt32
1575 contiguousPutByVal(
1576 macro (operand, scratch, address)
1577 loadConstantOrVariable(operand, scratch)
1578 bpb scratch, tagTypeNumber, .opPutByValSlow
1579 storep scratch, address
1580 end)
1581
1582.opPutByValNotInt32:
1583 bineq t2, DoubleShape, .opPutByValNotDouble
1584 contiguousPutByVal(
1585 macro (operand, scratch, address)
1586 loadConstantOrVariable(operand, scratch)
1587 bqb scratch, tagTypeNumber, .notInt
1588 ci2d scratch, ft0
1589 jmp .ready
1590 .notInt:
1591 addp tagTypeNumber, scratch
1592 fq2d scratch, ft0
1593 bdnequn ft0, ft0, .opPutByValSlow
1594 .ready:
1595 stored ft0, address
1596 end)
1597
1598.opPutByValNotDouble:
1599 bineq t2, ContiguousShape, .opPutByValNotContiguous
1600 contiguousPutByVal(
1601 macro (operand, scratch, address)
1602 loadConstantOrVariable(operand, scratch)
93a37866
A
1603 storep scratch, address
1604 end)
1605
1606.opPutByValNotContiguous:
1607 bineq t2, ArrayStorageShape, .opPutByValSlow
81345200 1608 biaeq t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.vectorLength[t0], .opPutByValOutOfBounds
93a37866
A
1609 btqz ArrayStorage::m_vector[t0, t3, 8], .opPutByValArrayStorageEmpty
1610.opPutByValArrayStorageStoreResult:
1611 loadisFromInstruction(3, t2)
1612 loadConstantOrVariable(t2, t1)
93a37866
A
1613 storeq t1, ArrayStorage::m_vector[t0, t3, 8]
1614 dispatch(5)
6fe7ccc8 1615
93a37866 1616.opPutByValArrayStorageEmpty:
81345200
A
1617 loadpFromInstruction(4, t1)
1618 storeb 1, ArrayProfile::m_mayStoreToHole[t1]
6fe7ccc8 1619 addi 1, ArrayStorage::m_numValuesInVector[t0]
81345200 1620 bib t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0], .opPutByValArrayStorageStoreResult
93a37866 1621 addi 1, t3, t1
81345200 1622 storei t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0]
93a37866 1623 jmp .opPutByValArrayStorageStoreResult
6fe7ccc8 1624
93a37866 1625.opPutByValOutOfBounds:
81345200
A
1626 loadpFromInstruction(4, t0)
1627 storeb 1, ArrayProfile::m_outOfBounds[t0]
6fe7ccc8 1628.opPutByValSlow:
81345200 1629 callSlowPath(slowPath)
93a37866 1630 dispatch(5)
81345200
A
1631end
1632
1633_llint_op_put_by_val:
1634 putByVal(_llint_slow_path_put_by_val)
1635
1636_llint_op_put_by_val_direct:
1637 putByVal(_llint_slow_path_put_by_val_direct)
6fe7ccc8
A
1638
1639
6fe7ccc8
A
1640_llint_op_jmp:
1641 traceExecution()
93a37866 1642 dispatchIntIndirect(1)
6fe7ccc8
A
1643
1644
1645macro jumpTrueOrFalse(conditionOp, slow)
93a37866 1646 loadisFromInstruction(1, t1)
6fe7ccc8 1647 loadConstantOrVariable(t1, t0)
93a37866
A
1648 xorq ValueFalse, t0
1649 btqnz t0, -1, .slow
6fe7ccc8
A
1650 conditionOp(t0, .target)
1651 dispatch(3)
1652
1653.target:
93a37866 1654 dispatchIntIndirect(2)
6fe7ccc8
A
1655
1656.slow:
1657 callSlowPath(slow)
1658 dispatch(0)
1659end
1660
1661
1662macro equalNull(cellHandler, immediateHandler)
93a37866 1663 loadisFromInstruction(1, t0)
6fe7ccc8 1664 assertNotConstant(t0)
93a37866
A
1665 loadq [cfr, t0, 8], t0
1666 btqnz t0, tagMask, .immediate
81345200
A
1667 loadStructureWithScratch(t0, t2, t1)
1668 cellHandler(t2, JSCell::m_flags[t0], .target)
6fe7ccc8
A
1669 dispatch(3)
1670
1671.target:
93a37866 1672 dispatchIntIndirect(2)
6fe7ccc8
A
1673
1674.immediate:
93a37866 1675 andq ~TagBitUndefined, t0
6fe7ccc8
A
1676 immediateHandler(t0, .target)
1677 dispatch(3)
1678end
1679
1680_llint_op_jeq_null:
1681 traceExecution()
1682 equalNull(
93a37866
A
1683 macro (structure, value, target)
1684 btbz value, MasqueradesAsUndefined, .notMasqueradesAsUndefined
1685 loadp CodeBlock[cfr], t0
1686 loadp CodeBlock::m_globalObject[t0], t0
1687 bpeq Structure::m_globalObject[structure], t0, target
1688.notMasqueradesAsUndefined:
1689 end,
1690 macro (value, target) bqeq value, ValueNull, target end)
6fe7ccc8
A
1691
1692
1693_llint_op_jneq_null:
1694 traceExecution()
1695 equalNull(
93a37866
A
1696 macro (structure, value, target)
1697 btbz value, MasqueradesAsUndefined, target
1698 loadp CodeBlock[cfr], t0
1699 loadp CodeBlock::m_globalObject[t0], t0
1700 bpneq Structure::m_globalObject[structure], t0, target
1701 end,
1702 macro (value, target) bqneq value, ValueNull, target end)
6fe7ccc8
A
1703
1704
1705_llint_op_jneq_ptr:
1706 traceExecution()
93a37866
A
1707 loadisFromInstruction(1, t0)
1708 loadisFromInstruction(2, t1)
1709 loadp CodeBlock[cfr], t2
1710 loadp CodeBlock::m_globalObject[t2], t2
1711 loadp JSGlobalObject::m_specialPointers[t2, t1, 8], t1
6fe7ccc8
A
1712 bpneq t1, [cfr, t0, 8], .opJneqPtrTarget
1713 dispatch(4)
1714
1715.opJneqPtrTarget:
93a37866 1716 dispatchIntIndirect(3)
6fe7ccc8
A
1717
1718
1719macro compare(integerCompare, doubleCompare, slowPath)
93a37866
A
1720 loadisFromInstruction(1, t2)
1721 loadisFromInstruction(2, t3)
6fe7ccc8
A
1722 loadConstantOrVariable(t2, t0)
1723 loadConstantOrVariable(t3, t1)
93a37866
A
1724 bqb t0, tagTypeNumber, .op1NotInt
1725 bqb t1, tagTypeNumber, .op2NotInt
6fe7ccc8
A
1726 integerCompare(t0, t1, .jumpTarget)
1727 dispatch(4)
1728
1729.op1NotInt:
93a37866
A
1730 btqz t0, tagTypeNumber, .slow
1731 bqb t1, tagTypeNumber, .op1NotIntOp2NotInt
6fe7ccc8
A
1732 ci2d t1, ft1
1733 jmp .op1NotIntReady
1734.op1NotIntOp2NotInt:
93a37866
A
1735 btqz t1, tagTypeNumber, .slow
1736 addq tagTypeNumber, t1
1737 fq2d t1, ft1
6fe7ccc8 1738.op1NotIntReady:
93a37866
A
1739 addq tagTypeNumber, t0
1740 fq2d t0, ft0
6fe7ccc8
A
1741 doubleCompare(ft0, ft1, .jumpTarget)
1742 dispatch(4)
1743
1744.op2NotInt:
1745 ci2d t0, ft0
93a37866
A
1746 btqz t1, tagTypeNumber, .slow
1747 addq tagTypeNumber, t1
1748 fq2d t1, ft1
6fe7ccc8
A
1749 doubleCompare(ft0, ft1, .jumpTarget)
1750 dispatch(4)
1751
1752.jumpTarget:
93a37866 1753 dispatchIntIndirect(3)
6fe7ccc8
A
1754
1755.slow:
1756 callSlowPath(slowPath)
1757 dispatch(0)
1758end
1759
1760
1761_llint_op_switch_imm:
1762 traceExecution()
93a37866
A
1763 loadisFromInstruction(3, t2)
1764 loadisFromInstruction(1, t3)
6fe7ccc8
A
1765 loadConstantOrVariable(t2, t1)
1766 loadp CodeBlock[cfr], t2
1767 loadp CodeBlock::m_rareData[t2], t2
1768 muli sizeof SimpleJumpTable, t3 # FIXME: would be nice to peephole this!
81345200 1769 loadp CodeBlock::RareData::m_switchJumpTables + VectorBufferOffset[t2], t2
6fe7ccc8 1770 addp t3, t2
93a37866 1771 bqb t1, tagTypeNumber, .opSwitchImmNotInt
6fe7ccc8
A
1772 subi SimpleJumpTable::min[t2], t1
1773 biaeq t1, SimpleJumpTable::branchOffsets + VectorSizeOffset[t2], .opSwitchImmFallThrough
1774 loadp SimpleJumpTable::branchOffsets + VectorBufferOffset[t2], t3
1775 loadis [t3, t1, 4], t1
1776 btiz t1, .opSwitchImmFallThrough
1777 dispatch(t1)
1778
1779.opSwitchImmNotInt:
93a37866 1780 btqnz t1, tagTypeNumber, .opSwitchImmSlow # Go slow if it's a double.
6fe7ccc8 1781.opSwitchImmFallThrough:
93a37866 1782 dispatchIntIndirect(2)
6fe7ccc8
A
1783
1784.opSwitchImmSlow:
1785 callSlowPath(_llint_slow_path_switch_imm)
1786 dispatch(0)
1787
1788
1789_llint_op_switch_char:
1790 traceExecution()
93a37866
A
1791 loadisFromInstruction(3, t2)
1792 loadisFromInstruction(1, t3)
6fe7ccc8
A
1793 loadConstantOrVariable(t2, t1)
1794 loadp CodeBlock[cfr], t2
1795 loadp CodeBlock::m_rareData[t2], t2
1796 muli sizeof SimpleJumpTable, t3
81345200 1797 loadp CodeBlock::RareData::m_switchJumpTables + VectorBufferOffset[t2], t2
6fe7ccc8 1798 addp t3, t2
93a37866 1799 btqnz t1, tagMask, .opSwitchCharFallThrough
81345200 1800 bbneq JSCell::m_type[t1], StringType, .opSwitchCharFallThrough
6fe7ccc8
A
1801 bineq JSString::m_length[t1], 1, .opSwitchCharFallThrough
1802 loadp JSString::m_value[t1], t0
1803 btpz t0, .opSwitchOnRope
1804 loadp StringImpl::m_data8[t0], t1
1805 btinz StringImpl::m_hashAndFlags[t0], HashFlags8BitBuffer, .opSwitchChar8Bit
1806 loadh [t1], t0
1807 jmp .opSwitchCharReady
1808.opSwitchChar8Bit:
1809 loadb [t1], t0
1810.opSwitchCharReady:
1811 subi SimpleJumpTable::min[t2], t0
1812 biaeq t0, SimpleJumpTable::branchOffsets + VectorSizeOffset[t2], .opSwitchCharFallThrough
1813 loadp SimpleJumpTable::branchOffsets + VectorBufferOffset[t2], t2
1814 loadis [t2, t0, 4], t1
1815 btiz t1, .opSwitchCharFallThrough
1816 dispatch(t1)
1817
1818.opSwitchCharFallThrough:
93a37866 1819 dispatchIntIndirect(2)
6fe7ccc8
A
1820
1821.opSwitchOnRope:
1822 callSlowPath(_llint_slow_path_switch_char)
1823 dispatch(0)
1824
1825
1826_llint_op_new_func:
1827 traceExecution()
93a37866
A
1828 loadisFromInstruction(3, t2)
1829 btiz t2, .opNewFuncUnchecked
1830 loadisFromInstruction(1, t1)
1831 btqnz [cfr, t1, 8], .opNewFuncDone
6fe7ccc8
A
1832.opNewFuncUnchecked:
1833 callSlowPath(_llint_slow_path_new_func)
1834.opNewFuncDone:
1835 dispatch(4)
1836
1837
81345200
A
1838_llint_op_new_captured_func:
1839 traceExecution()
1840 callSlowPath(_slow_path_new_captured_func)
1841 dispatch(4)
1842
1843
93a37866 1844macro arrayProfileForCall()
81345200
A
1845 loadisFromInstruction(4, t3)
1846 negp t3
1847 loadq ThisArgumentOffset[cfr, t3, 8], t0
1848 btqnz t0, tagMask, .done
1849 loadpFromInstruction((CallOpCodeSize - 2), t1)
1850 loadi JSCell::m_structureID[t0], t3
1851 storei t3, ArrayProfile::m_lastSeenStructureID[t1]
1852.done:
93a37866
A
1853end
1854
6fe7ccc8 1855macro doCall(slowPath)
81345200
A
1856 loadisFromInstruction(2, t0)
1857 loadpFromInstruction(5, t1)
6fe7ccc8
A
1858 loadp LLIntCallLinkInfo::callee[t1], t2
1859 loadConstantOrVariable(t0, t3)
93a37866 1860 bqneq t3, t2, .opCallSlow
81345200 1861 loadisFromInstruction(4, t3)
6fe7ccc8 1862 lshifti 3, t3
81345200 1863 negp t3
6fe7ccc8 1864 addp cfr, t3
93a37866
A
1865 loadp JSFunction::m_scope[t2], t0
1866 storeq t2, Callee[t3]
1867 storeq t0, ScopeChain[t3]
81345200 1868 loadisFromInstruction(3, t2)
6fe7ccc8 1869 storei PC, ArgumentCount + TagOffset[cfr]
6fe7ccc8 1870 storei t2, ArgumentCount + PayloadOffset[t3]
81345200
A
1871 addp CallerFrameAndPCSize, t3
1872 callTargetFunction(t1, t3)
6fe7ccc8
A
1873
1874.opCallSlow:
81345200 1875 slowPathForCall(slowPath)
6fe7ccc8
A
1876end
1877
1878
1879_llint_op_tear_off_activation:
1880 traceExecution()
93a37866
A
1881 loadisFromInstruction(1, t0)
1882 btqz [cfr, t0, 8], .opTearOffActivationNotCreated
6fe7ccc8
A
1883 callSlowPath(_llint_slow_path_tear_off_activation)
1884.opTearOffActivationNotCreated:
93a37866 1885 dispatch(2)
6fe7ccc8
A
1886
1887
1888_llint_op_tear_off_arguments:
1889 traceExecution()
93a37866 1890 loadisFromInstruction(1, t0)
81345200 1891 addq 1, t0 # Get the unmodifiedArgumentsRegister
93a37866 1892 btqz [cfr, t0, 8], .opTearOffArgumentsNotCreated
6fe7ccc8
A
1893 callSlowPath(_llint_slow_path_tear_off_arguments)
1894.opTearOffArgumentsNotCreated:
93a37866 1895 dispatch(3)
6fe7ccc8
A
1896
1897
1898_llint_op_ret:
1899 traceExecution()
1900 checkSwitchToJITForEpilogue()
93a37866 1901 loadisFromInstruction(1, t2)
6fe7ccc8
A
1902 loadConstantOrVariable(t2, t0)
1903 doReturn()
1904
1905
6fe7ccc8
A
1906_llint_op_ret_object_or_this:
1907 traceExecution()
1908 checkSwitchToJITForEpilogue()
93a37866 1909 loadisFromInstruction(1, t2)
6fe7ccc8 1910 loadConstantOrVariable(t2, t0)
93a37866 1911 btqnz t0, tagMask, .opRetObjectOrThisNotObject
81345200 1912 bbb JSCell::m_type[t0], ObjectType, .opRetObjectOrThisNotObject
6fe7ccc8
A
1913 doReturn()
1914
1915.opRetObjectOrThisNotObject:
93a37866 1916 loadisFromInstruction(2, t2)
6fe7ccc8
A
1917 loadConstantOrVariable(t2, t0)
1918 doReturn()
1919
1920
1921_llint_op_to_primitive:
1922 traceExecution()
93a37866
A
1923 loadisFromInstruction(2, t2)
1924 loadisFromInstruction(1, t3)
6fe7ccc8 1925 loadConstantOrVariable(t2, t0)
93a37866 1926 btqnz t0, tagMask, .opToPrimitiveIsImm
81345200 1927 bbneq JSCell::m_type[t0], StringType, .opToPrimitiveSlowCase
6fe7ccc8 1928.opToPrimitiveIsImm:
93a37866 1929 storeq t0, [cfr, t3, 8]
6fe7ccc8
A
1930 dispatch(3)
1931
1932.opToPrimitiveSlowCase:
81345200 1933 callSlowPath(_slow_path_to_primitive)
6fe7ccc8
A
1934 dispatch(3)
1935
1936
1937_llint_op_next_pname:
1938 traceExecution()
93a37866
A
1939 loadisFromInstruction(3, t1)
1940 loadisFromInstruction(4, t2)
6fe7ccc8
A
1941 assertNotConstant(t1)
1942 assertNotConstant(t2)
1943 loadi PayloadOffset[cfr, t1, 8], t0
1944 bieq t0, PayloadOffset[cfr, t2, 8], .opNextPnameEnd
93a37866 1945 loadisFromInstruction(5, t2)
6fe7ccc8
A
1946 assertNotConstant(t2)
1947 loadp [cfr, t2, 8], t2
1948 loadp JSPropertyNameIterator::m_jsStrings[t2], t3
93a37866 1949 loadq [t3, t0, 8], t3
6fe7ccc8
A
1950 addi 1, t0
1951 storei t0, PayloadOffset[cfr, t1, 8]
93a37866
A
1952 loadisFromInstruction(1, t1)
1953 storeq t3, [cfr, t1, 8]
1954 loadisFromInstruction(2, t3)
6fe7ccc8 1955 assertNotConstant(t3)
93a37866 1956 loadq [cfr, t3, 8], t3
81345200 1957 loadStructureWithScratch(t3, t1, t0)
6fe7ccc8
A
1958 bpneq t1, JSPropertyNameIterator::m_cachedStructure[t2], .opNextPnameSlow
1959 loadp JSPropertyNameIterator::m_cachedPrototypeChain[t2], t0
1960 loadp StructureChain::m_vector[t0], t0
1961 btpz [t0], .opNextPnameTarget
1962.opNextPnameCheckPrototypeLoop:
93a37866
A
1963 bqeq Structure::m_prototype[t1], ValueNull, .opNextPnameSlow
1964 loadq Structure::m_prototype[t1], t2
81345200 1965 loadStructureWithScratch(t2, t1, t3)
6fe7ccc8
A
1966 bpneq t1, [t0], .opNextPnameSlow
1967 addp 8, t0
1968 btpnz [t0], .opNextPnameCheckPrototypeLoop
1969.opNextPnameTarget:
93a37866 1970 dispatchIntIndirect(6)
6fe7ccc8
A
1971
1972.opNextPnameEnd:
1973 dispatch(7)
1974
1975.opNextPnameSlow:
1976 callSlowPath(_llint_slow_path_next_pname) # This either keeps the PC where it was (causing us to loop) or sets it to target.
1977 dispatch(0)
1978
1979
1980_llint_op_catch:
1981 # This is where we end up from the JIT's throw trampoline (because the
1982 # machine code return address will be set to _llint_op_catch), and from
1983 # the interpreter's throw trampoline (see _llint_throw_trampoline).
81345200
A
1984 # The throwing code must have known that we were throwing to the interpreter,
1985 # and have set VM::targetInterpreterPCForThrow.
1986 loadp ScopeChain[cfr], t3
1987 andp MarkedBlockMask, t3
1988 loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
1989 loadp VM::callFrameForThrow[t3], cfr
1990 restoreStackPointerAfterCall()
1991
6fe7ccc8
A
1992 loadp CodeBlock[cfr], PB
1993 loadp CodeBlock::m_instructions[PB], PB
93a37866 1994 loadp VM::targetInterpreterPCForThrow[t3], PC
6fe7ccc8 1995 subp PB, PC
93a37866 1996 rshiftp 3, PC
81345200
A
1997 loadq VM::m_exception[t3], t0
1998 storeq 0, VM::m_exception[t3]
93a37866
A
1999 loadisFromInstruction(1, t2)
2000 storeq t0, [cfr, t2, 8]
6fe7ccc8
A
2001 traceExecution()
2002 dispatch(2)
2003
2004
2005_llint_op_end:
2006 traceExecution()
2007 checkSwitchToJITForEpilogue()
93a37866 2008 loadisFromInstruction(1, t0)
6fe7ccc8 2009 assertNotConstant(t0)
93a37866 2010 loadq [cfr, t0, 8], t0
6fe7ccc8
A
2011 doReturn()
2012
2013
2014_llint_throw_from_slow_path_trampoline:
81345200
A
2015 callSlowPath(_llint_slow_path_handle_exception)
2016
6fe7ccc8
A
2017 # When throwing from the interpreter (i.e. throwing from LLIntSlowPaths), so
2018 # the throw target is not necessarily interpreted code, we come to here.
2019 # This essentially emulates the JIT's throwing protocol.
81345200
A
2020 loadp CodeBlock[cfr], t1
2021 loadp CodeBlock::m_vm[t1], t1
93a37866 2022 jmp VM::targetMachinePCForThrow[t1]
6fe7ccc8
A
2023
2024
2025_llint_throw_during_call_trampoline:
2026 preserveReturnAddressAfterCall(t2)
81345200 2027 jmp _llint_throw_from_slow_path_trampoline
93a37866
A
2028
2029
6fe7ccc8 2030macro nativeCallTrampoline(executableOffsetToFunction)
81345200
A
2031
2032 functionPrologue()
6fe7ccc8 2033 storep 0, CodeBlock[cfr]
81345200
A
2034 if X86_64 or X86_64_WIN
2035 if X86_64
2036 const arg1 = t4 # t4 = rdi
2037 const arg2 = t5 # t5 = rsi
2038 const temp = t1
2039 elsif X86_64_WIN
2040 const arg1 = t2 # t2 = rcx
2041 const arg2 = t1 # t1 = rdx
2042 const temp = t0
2043 end
2044 loadp ScopeChain[cfr], t0
2045 andp MarkedBlockMask, t0
2046 loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t0], t0
93a37866
A
2047 storep cfr, VM::topCallFrame[t0]
2048 loadp CallerFrame[cfr], t0
2049 loadq ScopeChain[t0], t1
2050 storeq t1, ScopeChain[cfr]
81345200
A
2051 move cfr, arg1
2052 loadp Callee[cfr], arg2
2053 loadp JSFunction::m_executable[arg2], temp
2054 checkStackPointerAlignment(t3, 0xdead0001)
2055 if X86_64_WIN
2056 subp 32, sp
2057 end
2058 call executableOffsetToFunction[temp]
2059 if X86_64_WIN
2060 addp 32, sp
2061 end
2062 loadp ScopeChain[cfr], t3
2063 andp MarkedBlockMask, t3
2064 loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
2065 elsif ARM64 or C_LOOP
2066 loadp ScopeChain[cfr], t0
2067 andp MarkedBlockMask, t0
2068 loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t0], t0
93a37866
A
2069 storep cfr, VM::topCallFrame[t0]
2070 loadp CallerFrame[cfr], t2
2071 loadp ScopeChain[t2], t1
2072 storep t1, ScopeChain[cfr]
2073 preserveReturnAddressAfterCall(t3)
2074 storep t3, ReturnPC[cfr]
2075 move cfr, t0
2076 loadp Callee[cfr], t1
2077 loadp JSFunction::m_executable[t1], t1
2078 move t2, cfr # Restore cfr to avoid loading from stack
81345200
A
2079 if C_LOOP
2080 cloopCallNative executableOffsetToFunction[t1]
2081 else
2082 call executableOffsetToFunction[t1]
2083 end
93a37866 2084 restoreReturnAddressBeforeReturn(t3)
81345200
A
2085 loadp ScopeChain[cfr], t3
2086 andp MarkedBlockMask, t3
2087 loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
93a37866
A
2088 else
2089 error
2090 end
2091
81345200
A
2092 functionEpilogue()
2093
2094 btqnz VM::m_exception[t3], .handleException
6fe7ccc8 2095 ret
81345200
A
2096
2097.handleException:
2098 storep cfr, VM::topCallFrame[t3]
2099 restoreStackPointerAfterCall()
6fe7ccc8
A
2100 jmp _llint_throw_from_slow_path_trampoline
2101end
2102
81345200
A
2103
2104macro getGlobalObject(dst)
2105 loadp CodeBlock[cfr], t0
2106 loadp CodeBlock::m_globalObject[t0], t0
2107 loadisFromInstruction(dst, t1)
2108 storeq t0, [cfr, t1, 8]
2109end
2110
2111macro varInjectionCheck(slowPath)
2112 loadp CodeBlock[cfr], t0
2113 loadp CodeBlock::m_globalObject[t0], t0
2114 loadp JSGlobalObject::m_varInjectionWatchpoint[t0], t0
2115 bbeq WatchpointSet::m_state[t0], IsInvalidated, slowPath
2116end
2117
2118macro resolveScope()
2119 loadp CodeBlock[cfr], t0
2120 loadisFromInstruction(4, t2)
2121 btbz CodeBlock::m_needsActivation[t0], .resolveScopeAfterActivationCheck
2122 loadis CodeBlock::m_activationRegister[t0], t1
2123 btpz [cfr, t1, 8], .resolveScopeAfterActivationCheck
2124 addi 1, t2
2125
2126.resolveScopeAfterActivationCheck:
2127 loadp ScopeChain[cfr], t0
2128 btiz t2, .resolveScopeLoopEnd
2129
2130.resolveScopeLoop:
2131 loadp JSScope::m_next[t0], t0
2132 subi 1, t2
2133 btinz t2, .resolveScopeLoop
2134
2135.resolveScopeLoopEnd:
2136 loadisFromInstruction(1, t1)
2137 storeq t0, [cfr, t1, 8]
2138end
2139
2140
2141_llint_op_resolve_scope:
2142 traceExecution()
2143 loadisFromInstruction(3, t0)
2144
2145#rGlobalProperty:
2146 bineq t0, GlobalProperty, .rGlobalVar
2147 getGlobalObject(1)
2148 dispatch(6)
2149
2150.rGlobalVar:
2151 bineq t0, GlobalVar, .rClosureVar
2152 getGlobalObject(1)
2153 dispatch(6)
2154
2155.rClosureVar:
2156 bineq t0, ClosureVar, .rGlobalPropertyWithVarInjectionChecks
2157 resolveScope()
2158 dispatch(6)
2159
2160.rGlobalPropertyWithVarInjectionChecks:
2161 bineq t0, GlobalPropertyWithVarInjectionChecks, .rGlobalVarWithVarInjectionChecks
2162 varInjectionCheck(.rDynamic)
2163 getGlobalObject(1)
2164 dispatch(6)
2165
2166.rGlobalVarWithVarInjectionChecks:
2167 bineq t0, GlobalVarWithVarInjectionChecks, .rClosureVarWithVarInjectionChecks
2168 varInjectionCheck(.rDynamic)
2169 getGlobalObject(1)
2170 dispatch(6)
2171
2172.rClosureVarWithVarInjectionChecks:
2173 bineq t0, ClosureVarWithVarInjectionChecks, .rDynamic
2174 varInjectionCheck(.rDynamic)
2175 resolveScope()
2176 dispatch(6)
2177
2178.rDynamic:
2179 callSlowPath(_llint_slow_path_resolve_scope)
2180 dispatch(6)
2181
2182
2183macro loadWithStructureCheck(operand, slowPath)
2184 loadisFromInstruction(operand, t0)
2185 loadq [cfr, t0, 8], t0
2186 loadStructureWithScratch(t0, t2, t1)
2187 loadpFromInstruction(5, t1)
2188 bpneq t2, t1, slowPath
2189end
2190
2191macro getProperty()
2192 loadisFromInstruction(6, t1)
2193 loadPropertyAtVariableOffset(t1, t0, t2)
2194 valueProfile(t2, 7, t0)
2195 loadisFromInstruction(1, t0)
2196 storeq t2, [cfr, t0, 8]
2197end
2198
2199macro getGlobalVar()
2200 loadpFromInstruction(6, t0)
2201 loadq [t0], t0
2202 valueProfile(t0, 7, t1)
2203 loadisFromInstruction(1, t1)
2204 storeq t0, [cfr, t1, 8]
2205end
2206
2207macro getClosureVar()
2208 loadp JSVariableObject::m_registers[t0], t0
2209 loadisFromInstruction(6, t1)
2210 loadq [t0, t1, 8], t0
2211 valueProfile(t0, 7, t1)
2212 loadisFromInstruction(1, t1)
2213 storeq t0, [cfr, t1, 8]
2214end
2215
2216_llint_op_get_from_scope:
2217 traceExecution()
2218 loadisFromInstruction(4, t0)
2219 andi ResolveModeMask, t0
2220
2221#gGlobalProperty:
2222 bineq t0, GlobalProperty, .gGlobalVar
2223 loadWithStructureCheck(2, .gDynamic)
2224 getProperty()
2225 dispatch(8)
2226
2227.gGlobalVar:
2228 bineq t0, GlobalVar, .gClosureVar
2229 getGlobalVar()
2230 dispatch(8)
2231
2232.gClosureVar:
2233 bineq t0, ClosureVar, .gGlobalPropertyWithVarInjectionChecks
2234 loadVariable(2, t0)
2235 getClosureVar()
2236 dispatch(8)
2237
2238.gGlobalPropertyWithVarInjectionChecks:
2239 bineq t0, GlobalPropertyWithVarInjectionChecks, .gGlobalVarWithVarInjectionChecks
2240 loadWithStructureCheck(2, .gDynamic)
2241 getProperty()
2242 dispatch(8)
2243
2244.gGlobalVarWithVarInjectionChecks:
2245 bineq t0, GlobalVarWithVarInjectionChecks, .gClosureVarWithVarInjectionChecks
2246 varInjectionCheck(.gDynamic)
2247 loadVariable(2, t0)
2248 getGlobalVar()
2249 dispatch(8)
2250
2251.gClosureVarWithVarInjectionChecks:
2252 bineq t0, ClosureVarWithVarInjectionChecks, .gDynamic
2253 varInjectionCheck(.gDynamic)
2254 loadVariable(2, t0)
2255 getClosureVar()
2256 dispatch(8)
2257
2258.gDynamic:
2259 callSlowPath(_llint_slow_path_get_from_scope)
2260 dispatch(8)
2261
2262
2263macro putProperty()
2264 loadisFromInstruction(3, t1)
2265 loadConstantOrVariable(t1, t2)
2266 loadisFromInstruction(6, t1)
2267 storePropertyAtVariableOffset(t1, t0, t2)
2268end
2269
2270macro putGlobalVar()
2271 loadisFromInstruction(3, t0)
2272 loadConstantOrVariable(t0, t1)
2273 loadpFromInstruction(5, t2)
2274 notifyWrite(t2, t1, t0, .pDynamic)
2275 loadpFromInstruction(6, t0)
2276 storeq t1, [t0]
2277end
2278
2279macro putClosureVar()
2280 loadisFromInstruction(3, t1)
2281 loadConstantOrVariable(t1, t2)
2282 loadp JSVariableObject::m_registers[t0], t0
2283 loadisFromInstruction(6, t1)
2284 storeq t2, [t0, t1, 8]
2285end
2286
2287
2288_llint_op_put_to_scope:
2289 traceExecution()
2290 loadisFromInstruction(4, t0)
2291 andi ResolveModeMask, t0
2292
2293#pGlobalProperty:
2294 bineq t0, GlobalProperty, .pGlobalVar
2295 writeBarrierOnOperands(1, 3)
2296 loadWithStructureCheck(1, .pDynamic)
2297 putProperty()
2298 dispatch(7)
2299
2300.pGlobalVar:
2301 bineq t0, GlobalVar, .pClosureVar
2302 writeBarrierOnGlobalObject(3)
2303 putGlobalVar()
2304 dispatch(7)
2305
2306.pClosureVar:
2307 bineq t0, ClosureVar, .pGlobalPropertyWithVarInjectionChecks
2308 writeBarrierOnOperands(1, 3)
2309 loadVariable(1, t0)
2310 putClosureVar()
2311 dispatch(7)
2312
2313.pGlobalPropertyWithVarInjectionChecks:
2314 bineq t0, GlobalPropertyWithVarInjectionChecks, .pGlobalVarWithVarInjectionChecks
2315 writeBarrierOnOperands(1, 3)
2316 loadWithStructureCheck(1, .pDynamic)
2317 putProperty()
2318 dispatch(7)
2319
2320.pGlobalVarWithVarInjectionChecks:
2321 bineq t0, GlobalVarWithVarInjectionChecks, .pClosureVarWithVarInjectionChecks
2322 writeBarrierOnGlobalObject(3)
2323 varInjectionCheck(.pDynamic)
2324 putGlobalVar()
2325 dispatch(7)
2326
2327.pClosureVarWithVarInjectionChecks:
2328 bineq t0, ClosureVarWithVarInjectionChecks, .pDynamic
2329 writeBarrierOnOperands(1, 3)
2330 varInjectionCheck(.pDynamic)
2331 loadVariable(1, t0)
2332 putClosureVar()
2333 dispatch(7)
2334
2335.pDynamic:
2336 callSlowPath(_llint_slow_path_put_to_scope)
2337 dispatch(7)