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