[JSC] Introduce LinkTimeConstant mechanism
[WebKit-https.git] / Source / JavaScriptCore / llint / LowLevelInterpreter32_64.asm
1 # Copyright (C) 2011-2019 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 # Utilities
26 macro nextInstruction()
27     loadb [PC], t0
28     leap _g_opcodeMap, t1
29     jmp [t1, t0, 4], BytecodePtrTag
30 end
31
32 macro nextInstructionWide16()
33     loadh 1[PC], t0
34     leap _g_opcodeMapWide16, t1
35     jmp [t1, t0, 4], BytecodePtrTag
36 end
37
38 macro nextInstructionWide32()
39     loadi 1[PC], t0
40     leap _g_opcodeMapWide32, t1
41     jmp [t1, t0, 4], BytecodePtrTag
42 end
43
44 macro getuOperandNarrow(opcodeStruct, fieldName, dst)
45     loadb constexpr %opcodeStruct%_%fieldName%_index[PC], dst
46 end
47
48 macro getOperandNarrow(opcodeStruct, fieldName, dst)
49     loadbsi constexpr %opcodeStruct%_%fieldName%_index[PC], dst
50 end
51
52 macro getuOperandWide16(opcodeStruct, fieldName, dst)
53     loadh constexpr %opcodeStruct%_%fieldName%_index * 2 + 1[PC], dst
54 end
55
56 macro getOperandWide16(opcodeStruct, fieldName, dst)
57     loadhsi constexpr %opcodeStruct%_%fieldName%_index * 2 + 1[PC], dst
58 end
59
60 macro getuOperandWide32(opcodeStruct, fieldName, dst)
61     loadi constexpr %opcodeStruct%_%fieldName%_index * 4 + 1[PC], dst
62 end
63
64 macro getOperandWide32(opcodeStruct, fieldName, dst)
65     loadis constexpr %opcodeStruct%_%fieldName%_index * 4 + 1[PC], dst
66 end
67
68 macro makeReturn(get, dispatch, fn)
69     fn(macro(tag, payload)
70         move tag, t5
71         move payload, t3
72         get(m_dst, t2)
73         storei t5, TagOffset[cfr, t2, 8]
74         storei t3, PayloadOffset[cfr, t2, 8]
75         dispatch()
76     end)
77 end
78
79 macro makeReturnProfiled(opcodeStruct, get, metadata, dispatch, fn)
80     fn(macro (tag, payload)
81         move tag, t1
82         move payload, t0
83
84         metadata(t5, t2)
85         valueProfile(opcodeStruct, t5, t1, t0)
86         get(m_dst, t2)
87         storei t1, TagOffset[cfr, t2, 8]
88         storei t0, PayloadOffset[cfr, t2, 8]
89         dispatch()
90     end)
91 end
92
93
94 macro dispatchAfterCall(size, opcodeStruct, dispatch)
95     loadi ArgumentCount + TagOffset[cfr], PC
96     get(size, opcodeStruct, m_dst, t3)
97     storei r1, TagOffset[cfr, t3, 8]
98     storei r0, PayloadOffset[cfr, t3, 8]
99     metadata(size, opcodeStruct, t2, t3)
100     valueProfile(opcodeStruct, t2, r1, r0)
101     dispatch()
102 end
103
104 macro cCall2(function)
105     if ARMv7 or MIPS
106         call function
107     elsif X86 or X86_WIN
108         subp 8, sp
109         push a1
110         push a0
111         call function
112         addp 16, sp
113     elsif C_LOOP or C_LOOP_WIN
114         cloopCallSlowPath function, a0, a1
115     else
116         error
117     end
118 end
119
120 macro cCall2Void(function)
121     if C_LOOP or C_LOOP_WIN
122         cloopCallSlowPathVoid function, a0, a1
123     else
124         cCall2(function)
125     end
126 end
127
128 macro cCall4(function)
129     if ARMv7 or MIPS
130         call function
131     elsif X86 or X86_WIN
132         push a3
133         push a2
134         push a1
135         push a0
136         call function
137         addp 16, sp
138     elsif C_LOOP or C_LOOP_WIN
139         error
140     else
141         error
142     end
143 end
144
145 macro callSlowPath(slowPath)
146     move cfr, a0
147     move PC, a1
148     cCall2(slowPath)
149     move r0, PC
150 end
151
152 macro doVMEntry(makeCall)
153     functionPrologue()
154     pushCalleeSaves()
155
156     # x86 needs to load arguments from the stack
157     if X86 or X86_WIN
158         loadp 16[cfr], a2
159         loadp 12[cfr], a1
160         loadp 8[cfr], a0
161     end
162
163     const entry = a0
164     const vm = a1
165     const protoCallFrame = a2
166
167     # We are using t3, t4 and t5 as temporaries through the function.
168     # Since we have the guarantee that tX != aY when X != Y, we are safe from
169     # aliasing problems with our arguments.
170
171     if ARMv7
172         vmEntryRecord(cfr, t3)
173         move t3, sp
174     else
175         vmEntryRecord(cfr, sp)
176     end
177
178     storep vm, VMEntryRecord::m_vm[sp]
179     loadp VM::topCallFrame[vm], t4
180     storep t4, VMEntryRecord::m_prevTopCallFrame[sp]
181     loadp VM::topEntryFrame[vm], t4
182     storep t4, VMEntryRecord::m_prevTopEntryFrame[sp]
183     loadp ProtoCallFrame::calleeValue[protoCallFrame], t4
184     storep t4, VMEntryRecord::m_callee[sp]
185
186     # Align stack pointer
187     if X86_WIN or MIPS
188         addp CallFrameAlignSlots * SlotSize, sp, t3
189         andp ~StackAlignmentMask, t3
190         subp t3, CallFrameAlignSlots * SlotSize, sp
191     elsif ARMv7
192         addp CallFrameAlignSlots * SlotSize, sp, t3
193         clrbp t3, StackAlignmentMask, t3
194         subp t3, CallFrameAlignSlots * SlotSize, t3
195         move t3, sp
196     end
197
198     loadi ProtoCallFrame::paddedArgCount[protoCallFrame], t4
199     addp CallFrameHeaderSlots, t4, t4
200     lshiftp 3, t4
201     subp sp, t4, t3
202     bpa t3, sp, .throwStackOverflow
203
204     # Ensure that we have enough additional stack capacity for the incoming args,
205     # and the frame for the JS code we're executing. We need to do this check
206     # before we start copying the args from the protoCallFrame below.
207     if C_LOOP or C_LOOP_WIN
208         bpaeq t3, VM::m_cloopStackLimit[vm], .stackHeightOK
209         move entry, t4
210         move vm, t5
211         cloopCallSlowPath _llint_stack_check_at_vm_entry, vm, t3
212         bpeq t0, 0, .stackCheckFailed
213         move t4, entry
214         move t5, vm
215         jmp .stackHeightOK
216
217 .stackCheckFailed:
218         move t4, entry
219         move t5, vm
220         jmp .throwStackOverflow
221     else
222         bpb t3, VM::m_softStackLimit[vm], .throwStackOverflow
223     end
224
225 .stackHeightOK:
226     move t3, sp
227     move (constexpr ProtoCallFrame::numberOfRegisters), t3
228
229 .copyHeaderLoop:
230     subi 1, t3
231     loadi TagOffset[protoCallFrame, t3, 8], t5
232     storei t5, TagOffset + CodeBlock[sp, t3, 8]
233     loadi PayloadOffset[protoCallFrame, t3, 8], t5
234     storei t5, PayloadOffset + CodeBlock[sp, t3, 8]
235     btinz t3, .copyHeaderLoop
236
237     loadi PayloadOffset + ProtoCallFrame::argCountAndCodeOriginValue[protoCallFrame], t4
238     subi 1, t4
239     loadi ProtoCallFrame::paddedArgCount[protoCallFrame], t5
240     subi 1, t5
241
242     bieq t4, t5, .copyArgs
243 .fillExtraArgsLoop:
244     subi 1, t5
245     storei UndefinedTag, ThisArgumentOffset + 8 + TagOffset[sp, t5, 8]
246     storei 0, ThisArgumentOffset + 8 + PayloadOffset[sp, t5, 8]
247     bineq t4, t5, .fillExtraArgsLoop
248
249 .copyArgs:
250     loadp ProtoCallFrame::args[protoCallFrame], t3
251
252 .copyArgsLoop:
253     btiz t4, .copyArgsDone
254     subi 1, t4
255     loadi TagOffset[t3, t4, 8], t5
256     storei t5, ThisArgumentOffset + 8 + TagOffset[sp, t4, 8]
257     loadi PayloadOffset[t3, t4, 8], t5
258     storei t5, ThisArgumentOffset + 8 + PayloadOffset[sp, t4, 8]
259     jmp .copyArgsLoop
260
261 .copyArgsDone:
262     storep sp, VM::topCallFrame[vm]
263     storep cfr, VM::topEntryFrame[vm]
264
265     makeCall(entry, protoCallFrame, t3, t4)
266
267     if ARMv7
268         vmEntryRecord(cfr, t3)
269         move t3, sp
270     else
271         vmEntryRecord(cfr, sp)
272     end
273
274     loadp VMEntryRecord::m_vm[sp], t5
275     loadp VMEntryRecord::m_prevTopCallFrame[sp], t4
276     storep t4, VM::topCallFrame[t5]
277     loadp VMEntryRecord::m_prevTopEntryFrame[sp], t4
278     storep t4, VM::topEntryFrame[t5]
279
280     if ARMv7
281         subp cfr, CalleeRegisterSaveSize, t5
282         move t5, sp
283     else
284         subp cfr, CalleeRegisterSaveSize, sp
285     end
286
287     popCalleeSaves()
288     functionEpilogue()
289     ret
290
291 .throwStackOverflow:
292     subp 8, sp # Align stack for cCall2() to make a call.
293     move vm, a0
294     move protoCallFrame, a1
295     cCall2(_llint_throw_stack_overflow_error)
296
297     if ARMv7
298         vmEntryRecord(cfr, t3)
299         move t3, sp
300     else
301         vmEntryRecord(cfr, sp)
302     end
303
304     loadp VMEntryRecord::m_vm[sp], t5
305     loadp VMEntryRecord::m_prevTopCallFrame[sp], t4
306     storep t4, VM::topCallFrame[t5]
307     loadp VMEntryRecord::m_prevTopEntryFrame[sp], t4
308     storep t4, VM::topEntryFrame[t5]
309
310     if ARMv7
311         subp cfr, CalleeRegisterSaveSize, t5
312         move t5, sp
313     else
314         subp cfr, CalleeRegisterSaveSize, sp
315     end
316
317     popCalleeSaves()
318     functionEpilogue()
319     ret
320 end
321
322 # a0, a2, t3, t4
323 macro makeJavaScriptCall(entry, protoCallFrame, temp1, temp2)
324     addp CallerFrameAndPCSize, sp
325     checkStackPointerAlignment(temp1, 0xbad0dc02)
326     if C_LOOP or C_LOOP_WIN
327         cloopCallJSFunction entry
328     else
329         call entry
330     end
331     checkStackPointerAlignment(temp1, 0xbad0dc03)
332     subp CallerFrameAndPCSize, sp
333 end
334
335 # a0, a2, t3, t4
336 macro makeHostFunctionCall(entry, protoCallFrame, temp1, temp2)
337     move entry, temp1
338     storep cfr, [sp]
339     if C_LOOP or C_LOOP_WIN
340         loadp ProtoCallFrame::globalObject[protoCallFrame], a0
341         move sp, a1
342         storep lr, PtrSize[sp]
343         cloopCallNative temp1
344     elsif X86 or X86_WIN
345         # Put callee frame pointer on stack as arg1, also put it in ecx for "fastcall" targets
346         move 0, temp2
347         move temp2, 4[sp] # put 0 in ReturnPC
348         move sp, a1 # a1 is edx
349         loadp ProtoCallFrame::globalObject[protoCallFrame], a0
350         push a1
351         push a0
352         call temp1
353         addp 8, sp
354     else
355         loadp ProtoCallFrame::globalObject[protoCallFrame], a0
356         move sp, a1
357         call temp1
358     end
359 end
360
361 op(handleUncaughtException, macro()
362     loadp Callee + PayloadOffset[cfr], t3
363     convertCalleeToVM(t3)
364     restoreCalleeSavesFromVMEntryFrameCalleeSavesBuffer(t3, t0)
365     storep 0, VM::callFrameForCatch[t3]
366
367     loadp VM::topEntryFrame[t3], cfr
368     if ARMv7
369         vmEntryRecord(cfr, t3)
370         move t3, sp
371     else
372         vmEntryRecord(cfr, sp)
373     end
374
375     loadp VMEntryRecord::m_vm[sp], t3
376     loadp VMEntryRecord::m_prevTopCallFrame[sp], t5
377     storep t5, VM::topCallFrame[t3]
378     loadp VMEntryRecord::m_prevTopEntryFrame[sp], t5
379     storep t5, VM::topEntryFrame[t3]
380
381     if ARMv7
382         subp cfr, CalleeRegisterSaveSize, t3
383         move t3, sp
384     else
385         subp cfr, CalleeRegisterSaveSize, sp
386     end
387
388     popCalleeSaves()
389     functionEpilogue()
390     ret
391 end)
392
393 macro doReturnFromHostFunction(extraStackSpace)
394     functionEpilogue(extraStackSpace)
395     ret
396 end
397
398 # Debugging operation if you'd like to print an operand in the instruction stream. fromWhere
399 # should be an immediate integer - any integer you like; use it to identify the place you're
400 # debugging from. operand should likewise be an immediate, and should identify the operand
401 # in the instruction stream you'd like to print out.
402 macro traceOperand(fromWhere, operand)
403     move fromWhere, a2
404     move operand, a3
405     move cfr, a0
406     move PC, a1
407     cCall4(_llint_trace_operand)
408     move r0, PC
409     move r1, cfr
410 end
411
412 # Debugging operation if you'd like to print the value of an operand in the instruction
413 # stream. Same as traceOperand(), but assumes that the operand is a register, and prints its
414 # value.
415 macro traceValue(fromWhere, operand)
416     move fromWhere, a2
417     move operand, a3
418     move cfr, a0
419     move PC, a1
420     cCall4(_llint_trace_value)
421     move r0, PC
422     move r1, cfr
423 end
424
425 # Call a slowPath for call opcodes.
426 macro callCallSlowPath(slowPath, action)
427     storep PC, ArgumentCount + TagOffset[cfr]
428     move cfr, a0
429     move PC, a1
430     cCall2(slowPath)
431     action(r0, r1)
432 end
433
434 macro callTrapHandler(throwHandler)
435     storei PC, ArgumentCount + TagOffset[cfr]
436     move cfr, a0
437     move PC, a1
438     cCall2(_llint_slow_path_handle_traps)
439     btpnz r0, throwHandler
440     loadi ArgumentCount + TagOffset[cfr], PC
441 end
442
443 macro checkSwitchToJITForLoop()
444     checkSwitchToJIT(
445         1,
446         macro ()
447             storei PC, ArgumentCount + TagOffset[cfr]
448             move cfr, a0
449             move PC, a1
450             cCall2(_llint_loop_osr)
451             btpz r0, .recover
452             move r1, sp
453             jmp r0
454         .recover:
455             loadi ArgumentCount + TagOffset[cfr], PC
456         end)
457 end
458
459 macro loadVariable(get, fieldName, indexReg, tagReg, payloadReg)
460     get(fieldName, indexReg)
461     loadi TagOffset[cfr, indexReg, 8], tagReg
462     loadi PayloadOffset[cfr, indexReg, 8], payloadReg
463 end
464
465 # Index, tag, and payload must be different registers. Index is not
466 # changed.
467 macro loadConstant(size, index, tag, payload)
468     size(FirstConstantRegisterIndexNarrow, FirstConstantRegisterIndexWide16, FirstConstantRegisterIndexWide32, macro (FirstConstantRegisterIndex)
469         loadp CodeBlock[cfr], payload
470         loadp CodeBlock::m_constantRegisters + VectorBufferOffset[payload], payload
471         subp FirstConstantRegisterIndex, index
472         loadp TagOffset[payload, index, 8], tag
473         loadp PayloadOffset[payload, index, 8], payload
474     end)
475 end
476
477 # Index, tag, and payload must be different registers. Index is not
478 # changed.
479 macro loadConstantOrVariable(size, index, tag, payload)
480     size(FirstConstantRegisterIndexNarrow, FirstConstantRegisterIndexWide16, FirstConstantRegisterIndexWide32, macro (FirstConstantRegisterIndex)
481         bigteq index, FirstConstantRegisterIndex, .constant
482         loadi TagOffset[cfr, index, 8], tag
483         loadi PayloadOffset[cfr, index, 8], payload
484         jmp .done
485     .constant:
486         loadConstant(size, index, tag, payload)
487     .done:
488     end)
489 end
490
491 macro loadConstantOrVariableTag(size, index, tag)
492     size(FirstConstantRegisterIndexNarrow, FirstConstantRegisterIndexWide16, FirstConstantRegisterIndexWide32, macro (FirstConstantRegisterIndex)
493         bigteq index, FirstConstantRegisterIndex, .constant
494         loadi TagOffset[cfr, index, 8], tag
495         jmp .done
496     .constant:
497         loadp CodeBlock[cfr], tag
498         loadp CodeBlock::m_constantRegisters + VectorBufferOffset[tag], tag
499         subi FirstConstantRegisterIndex, index
500         loadp TagOffset[tag, index, 8], tag
501     .done:
502     end)
503 end
504
505 # Index and payload may be the same register. Index may be clobbered.
506 macro loadConstantOrVariable2Reg(size, index, tag, payload)
507     size(FirstConstantRegisterIndexNarrow, FirstConstantRegisterIndexWide16, FirstConstantRegisterIndexWide32, macro (FirstConstantRegisterIndex)
508         bigteq index, FirstConstantRegisterIndex, .constant
509         loadi TagOffset[cfr, index, 8], tag
510         loadi PayloadOffset[cfr, index, 8], payload
511         jmp .done
512     .constant:
513         loadp CodeBlock[cfr], tag
514         loadp CodeBlock::m_constantRegisters + VectorBufferOffset[tag], tag
515         subi FirstConstantRegisterIndex, index
516         lshifti 3, index
517         addp index, tag
518         loadp PayloadOffset[tag], payload
519         loadp TagOffset[tag], tag
520     .done:
521     end)
522 end
523
524 macro loadConstantOrVariablePayloadTagCustom(size, index, tagCheck, payload)
525     size(FirstConstantRegisterIndexNarrow, FirstConstantRegisterIndexWide16, FirstConstantRegisterIndexWide32, macro (FirstConstantRegisterIndex)
526         bigteq index, FirstConstantRegisterIndex, .constant
527         tagCheck(TagOffset[cfr, index, 8])
528         loadi PayloadOffset[cfr, index, 8], payload
529         jmp .done
530     .constant:
531         loadp CodeBlock[cfr], payload
532         loadp CodeBlock::m_constantRegisters + VectorBufferOffset[payload], payload
533         subp FirstConstantRegisterIndex, index
534         tagCheck(TagOffset[payload, index, 8])
535         loadp PayloadOffset[payload, index, 8], payload
536     .done:
537     end)
538 end
539
540 # Index and payload must be different registers. Index is not mutated. Use
541 # this if you know what the tag of the variable should be. Doing the tag
542 # test as part of loading the variable reduces register use, but may not
543 # be faster than doing loadConstantOrVariable followed by a branch on the
544 # tag.
545 macro loadConstantOrVariablePayload(size, index, expectedTag, payload, slow)
546     loadConstantOrVariablePayloadTagCustom(
547         size,
548         index,
549         macro (actualTag) bineq actualTag, expectedTag, slow end,
550         payload)
551 end
552
553 macro loadConstantOrVariablePayloadUnchecked(size, index, payload)
554     loadConstantOrVariablePayloadTagCustom(
555         size,
556         index,
557         macro (actualTag) end,
558         payload)
559 end
560
561 macro writeBarrierOnCellWithReload(cell, reloadAfterSlowPath)
562     skipIfIsRememberedOrInEden(
563         cell,
564         macro()
565             push cfr, PC
566             # We make two extra slots because cCall2 will poke.
567             subp 8, sp
568             move cell, a1 # cell can be a0
569             move cfr, a0
570             cCall2Void(_llint_write_barrier_slow)
571             addp 8, sp
572             pop PC, cfr
573             reloadAfterSlowPath()
574         end)
575 end
576
577 macro writeBarrierOnOperand(size, get, cellFieldName)
578     get(cellFieldName, t1)
579     loadConstantOrVariablePayload(size, t1, CellTag, t2, .writeBarrierDone)
580     writeBarrierOnCellWithReload(t2, macro() end)
581 .writeBarrierDone:
582 end
583
584 macro writeBarrierOnOperands(size, get, cellFieldName, valueFieldName)
585     get(valueFieldName, t1)
586     loadConstantOrVariableTag(size, t1, t0)
587     bineq t0, CellTag, .writeBarrierDone
588
589     writeBarrierOnOperand(size, get, cellFieldName)
590 .writeBarrierDone:
591 end
592
593 macro writeBarrierOnGlobal(size, get, valueFieldName, loadMacro)
594     get(valueFieldName, t1)
595     loadConstantOrVariableTag(size, t1, t0)
596     bineq t0, CellTag, .writeBarrierDone
597
598     loadMacro(t3)
599
600     writeBarrierOnCellWithReload(t3, macro() end)
601 .writeBarrierDone:
602 end
603
604 macro writeBarrierOnGlobalObject(size, get, valueFieldName)
605     writeBarrierOnGlobal(size, get, valueFieldName,
606         macro(registerToStoreGlobal)
607             loadp CodeBlock[cfr], registerToStoreGlobal
608             loadp CodeBlock::m_globalObject[registerToStoreGlobal], registerToStoreGlobal
609         end)
610 end
611
612 macro writeBarrierOnGlobalLexicalEnvironment(size, get, valueFieldName)
613     writeBarrierOnGlobal(size, get, valueFieldName,
614         macro(registerToStoreGlobal)
615             loadp CodeBlock[cfr], registerToStoreGlobal
616             loadp CodeBlock::m_globalObject[registerToStoreGlobal], registerToStoreGlobal
617             loadp JSGlobalObject::m_globalLexicalEnvironment[registerToStoreGlobal], registerToStoreGlobal
618         end)
619 end
620
621 macro valueProfile(opcodeStruct, metadata, tag, payload)
622     storei tag, %opcodeStruct%::Metadata::m_profile.m_buckets + TagOffset[metadata]
623     storei payload, %opcodeStruct%::Metadata::m_profile.m_buckets + PayloadOffset[metadata]
624 end
625
626
627 # Entrypoints into the interpreter
628
629 # Expects that CodeBlock is in t1, which is what prologue() leaves behind.
630 macro functionArityCheck(doneLabel, slowPath)
631     loadi PayloadOffset + ArgumentCount[cfr], t0
632     biaeq t0, CodeBlock::m_numParameters[t1], doneLabel
633     move cfr, a0
634     move PC, a1
635     cCall2(slowPath)   # This slowPath has a simple protocol: t0 = 0 => no error, t0 != 0 => error
636     btiz r0, .noError
637
638     # We're throwing before the frame is fully set up. This frame will be
639     # ignored by the unwinder. So, let's restore the callee saves before we
640     # start unwinding. We need to do this before we change the cfr.
641     restoreCalleeSavesUsedByLLInt()
642
643     move r1, cfr   # r1 contains caller frame
644     jmp _llint_throw_from_slow_path_trampoline
645
646 .noError:
647     move r1, t1 # r1 contains slotsToAdd.
648     btiz t1, .continue
649     loadi PayloadOffset + ArgumentCount[cfr], t2
650     addi CallFrameHeaderSlots, t2
651
652     // Check if there are some unaligned slots we can use
653     move t1, t3
654     andi StackAlignmentSlots - 1, t3
655     btiz t3, .noExtraSlot
656 .fillExtraSlots:
657     move 0, t0
658     storei t0, PayloadOffset[cfr, t2, 8]
659     move UndefinedTag, t0
660     storei t0, TagOffset[cfr, t2, 8]
661     addi 1, t2
662     bsubinz 1, t3, .fillExtraSlots
663     andi ~(StackAlignmentSlots - 1), t1
664     btiz t1, .continue
665
666 .noExtraSlot:
667     // Move frame up t1 slots
668     negi t1
669     move cfr, t3
670     subp CalleeSaveSpaceAsVirtualRegisters * SlotSize, t3
671     addi CalleeSaveSpaceAsVirtualRegisters, t2
672     move t1, t0
673     lshiftp 3, t0
674     addp t0, cfr
675     addp t0, sp
676 .copyLoop:
677     loadi PayloadOffset[t3], t0
678     storei t0, PayloadOffset[t3, t1, 8]
679     loadi TagOffset[t3], t0
680     storei t0, TagOffset[t3, t1, 8]
681     addp 8, t3
682     bsubinz 1, t2, .copyLoop
683
684     // Fill new slots with JSUndefined
685     move t1, t2
686 .fillLoop:
687     move 0, t0
688     storei t0, PayloadOffset[t3, t1, 8]
689     move UndefinedTag, t0
690     storei t0, TagOffset[t3, t1, 8]
691     addp 8, t3
692     baddinz 1, t2, .fillLoop
693
694 .continue:
695     # Reload CodeBlock and PC, since the slow_path clobbered it.
696     loadp CodeBlock[cfr], t1
697     loadp CodeBlock::m_instructionsRawPointer[t1], PC
698     jmp doneLabel
699 end
700
701 # Instruction implementations
702
703 _llint_op_enter:
704     traceExecution()
705     checkStackPointerAlignment(t2, 0xdead00e1)
706     loadp CodeBlock[cfr], t2                // t2<CodeBlock> = cfr.CodeBlock
707     loadi CodeBlock::m_numVars[t2], t2      // t2<size_t> = t2<CodeBlock>.m_numVars
708     subi CalleeSaveSpaceAsVirtualRegisters, t2
709     move cfr, t3
710     subp CalleeSaveSpaceAsVirtualRegisters * SlotSize, t3
711     btiz t2, .opEnterDone
712     move UndefinedTag, t0
713     move 0, t1
714     negi t2
715 .opEnterLoop:
716     storei t0, TagOffset[t3, t2, 8]
717     storei t1, PayloadOffset[t3, t2, 8]
718     addi 1, t2
719     btinz t2, .opEnterLoop
720 .opEnterDone:
721     callSlowPath(_slow_path_enter)
722     dispatchOp(narrow, op_enter)
723
724
725 llintOpWithProfile(op_get_argument, OpGetArgument, macro (size, get, dispatch, return)
726     get(m_index, t2)
727     loadi PayloadOffset + ArgumentCount[cfr], t0
728     bilteq t0, t2, .opGetArgumentOutOfBounds
729     loadi ThisArgumentOffset + TagOffset[cfr, t2, 8], t0
730     loadi ThisArgumentOffset + PayloadOffset[cfr, t2, 8], t3
731     return (t0, t3)
732
733 .opGetArgumentOutOfBounds:
734     return (UndefinedTag, 0)
735 end)
736
737
738 llintOpWithReturn(op_argument_count, OpArgumentCount, macro (size, get, dispatch, return)
739     loadi PayloadOffset + ArgumentCount[cfr], t0
740     subi 1, t0
741     return(Int32Tag, t0)
742 end)
743
744
745 llintOpWithReturn(op_get_scope, OpGetScope, macro (size, get, dispatch, return)
746     loadi Callee + PayloadOffset[cfr], t0
747     loadp JSCallee::m_scope[t0], t0
748     return (CellTag, t0)
749 end)
750
751
752 llintOpWithMetadata(op_to_this, OpToThis, macro (size, get, dispatch, metadata, return)
753     get(m_srcDst, t0)
754     bineq TagOffset[cfr, t0, 8], CellTag, .opToThisSlow
755     loadi PayloadOffset[cfr, t0, 8], t0
756     bbneq JSCell::m_type[t0], FinalObjectType, .opToThisSlow
757     metadata(t2, t3)
758     loadi OpToThis::Metadata::m_cachedStructureID[t2], t2
759     bineq JSCell::m_structureID[t0], t2, .opToThisSlow
760     dispatch()
761
762 .opToThisSlow:
763     callSlowPath(_slow_path_to_this)
764     dispatch()
765 end)
766
767
768 llintOp(op_check_tdz, OpCheckTdz, macro (size, get, dispatch)
769     get(m_targetVirtualRegister, t0)
770     loadConstantOrVariableTag(size, t0, t1)
771     bineq t1, EmptyValueTag, .opNotTDZ
772     callSlowPath(_slow_path_throw_tdz_error)
773
774 .opNotTDZ:
775     dispatch()
776 end)
777
778
779 llintOpWithReturn(op_mov, OpMov, macro (size, get, dispatch, return)
780     get(m_src, t1)
781     loadConstantOrVariable(size, t1, t2, t3)
782     return(t2, t3)
783 end)
784
785
786 llintOpWithReturn(op_not, OpNot, macro (size, get, dispatch, return)
787     get(m_operand, t0)
788     loadConstantOrVariable(size, t0, t2, t3)
789     bineq t2, BooleanTag, .opNotSlow
790     xori 1, t3
791     return(t2, t3)
792
793 .opNotSlow:
794     callSlowPath(_slow_path_not)
795     dispatch()
796 end)
797
798
799 macro equalityComparisonOp(opcodeName, opcodeStruct, integerComparison)
800     llintOpWithReturn(op_%opcodeName%, opcodeStruct, macro (size, get, dispatch, return)
801         get(m_rhs, t2)
802         get(m_lhs, t0)
803         loadConstantOrVariable(size, t2, t3, t1)
804         loadConstantOrVariable2Reg(size, t0, t2, t0)
805         bineq t2, t3, .opEqSlow
806         bieq t2, CellTag, .opEqSlow
807         bib t2, LowestTag, .opEqSlow
808         integerComparison(t0, t1, t0)
809         return(BooleanTag, t0)
810
811     .opEqSlow:
812         callSlowPath(_slow_path_%opcodeName%)
813         dispatch()
814     end)
815 end
816
817
818 macro equalityJumpOp(opcodeName, opcodeStruct, integerComparison)
819     llintOpWithJump(op_%opcodeName%, opcodeStruct, macro (size, get, jump, dispatch)
820         get(m_rhs, t2)
821         get(m_lhs, t0)
822         loadConstantOrVariable(size, t2, t3, t1)
823         loadConstantOrVariable2Reg(size, t0, t2, t0)
824         bineq t2, t3, .slow
825         bieq t2, CellTag, .slow
826         bib t2, LowestTag, .slow
827         integerComparison(t0, t1, .jumpTarget)
828         dispatch()
829
830     .jumpTarget:
831         jump(m_targetLabel)
832
833     .slow:
834         callSlowPath(_llint_slow_path_%opcodeName%)
835         nextInstruction()
836     end)
837 end
838
839
840 macro equalNullComparisonOp(opcodeName, opcodeStruct, fn)
841     llintOpWithReturn(opcodeName, opcodeStruct, macro (size, get, dispatch, return)
842         get(m_operand, t0)
843         assertNotConstant(size, t0)
844         loadi TagOffset[cfr, t0, 8], t1
845         loadi PayloadOffset[cfr, t0, 8], t0
846         bineq t1, CellTag, .opEqNullImmediate
847         btbnz JSCell::m_flags[t0], MasqueradesAsUndefined, .opEqNullMasqueradesAsUndefined
848         move 0, t1
849         jmp .opEqNullNotImmediate
850     .opEqNullMasqueradesAsUndefined:
851         loadi JSCell::m_structureID[t0], t1
852         loadp CodeBlock[cfr], t0
853         loadp CodeBlock::m_globalObject[t0], t0
854         cpeq Structure::m_globalObject[t1], t0, t1
855         jmp .opEqNullNotImmediate
856     .opEqNullImmediate:
857         cieq t1, NullTag, t2
858         cieq t1, UndefinedTag, t1
859         ori t2, t1
860     .opEqNullNotImmediate:
861         fn(t1)
862         return(BooleanTag, t1)
863     end)
864 end
865
866 equalNullComparisonOp(op_eq_null, OpEqNull, macro (value) end)
867
868 equalNullComparisonOp(op_neq_null, OpNeqNull,
869     macro (value) xori 1, value end)
870
871
872 llintOpWithReturn(op_is_undefined_or_null, OpIsUndefinedOrNull, macro (size, get, dispatch, return)
873     get(m_operand, t0)
874     loadConstantOrVariableTag(size, t0, t1)
875     ori 1, t1
876     cieq t1, NullTag, t1
877     return(BooleanTag, t1)
878 end)
879
880
881 macro strictEqOp(opcodeName, opcodeStruct, equalityOperation)
882     llintOpWithReturn(op_%opcodeName%, opcodeStruct, macro (size, get, dispatch, return)
883         get(m_rhs, t2)
884         get(m_lhs, t0)
885         loadConstantOrVariable(size, t2, t3, t1)
886         loadConstantOrVariable2Reg(size, t0, t2, t0)
887         bineq t2, t3, .slow
888         bib t2, LowestTag, .slow
889         bineq t2, CellTag, .notStringOrSymbol
890         bbaeq JSCell::m_type[t0], ObjectType, .notStringOrSymbol
891         bbb JSCell::m_type[t1], ObjectType, .slow
892     .notStringOrSymbol:
893         equalityOperation(t0, t1, t0)
894         return(BooleanTag, t0)
895
896     .slow:
897         callSlowPath(_slow_path_%opcodeName%)
898         dispatch()
899     end)
900 end
901
902
903 macro strictEqualityJumpOp(opcodeName, opcodeStruct, equalityOperation)
904     llintOpWithJump(op_%opcodeName%, opcodeStruct, macro (size, get, jump, dispatch)
905         get(m_rhs, t2)
906         get(m_lhs, t0)
907         loadConstantOrVariable(size, t2, t3, t1)
908         loadConstantOrVariable2Reg(size, t0, t2, t0)
909         bineq t2, t3, .slow
910         bib t2, LowestTag, .slow
911         bineq t2, CellTag, .notStringOrSymbol
912         bbaeq JSCell::m_type[t0], ObjectType, .notStringOrSymbol
913         bbb JSCell::m_type[t1], ObjectType, .slow
914     .notStringOrSymbol:
915         equalityOperation(t0, t1, .jumpTarget)
916         dispatch()
917
918     .jumpTarget:
919         jump(m_targetLabel)
920
921     .slow:
922         callSlowPath(_llint_slow_path_%opcodeName%)
923         nextInstruction()
924     end)
925 end
926
927
928 strictEqOp(stricteq, OpStricteq,
929     macro (left, right, result) cieq left, right, result end)
930
931
932 strictEqOp(nstricteq, OpNstricteq,
933     macro (left, right, result) cineq left, right, result end)
934
935
936 strictEqualityJumpOp(jstricteq, OpJstricteq,
937     macro (left, right, target) bieq left, right, target end)
938
939
940 strictEqualityJumpOp(jnstricteq, OpJnstricteq,
941     macro (left, right, target) bineq left, right, target end)
942
943
944 macro preOp(opcodeName, opcodeStruct, operation)
945     llintOp(op_%opcodeName%, opcodeStruct, macro (size, get, dispatch)
946         get(m_srcDst, t0)
947         bineq TagOffset[cfr, t0, 8], Int32Tag, .slow
948         loadi PayloadOffset[cfr, t0, 8], t1
949         operation(t1, .slow)
950         storei t1, PayloadOffset[cfr, t0, 8]
951         dispatch()
952
953     .slow:
954         callSlowPath(_slow_path_%opcodeName%)
955         dispatch()
956     end)
957 end
958
959
960 llintOpWithProfile(op_to_number, OpToNumber, macro (size, get, dispatch, return)
961     get(m_operand, t0)
962     loadConstantOrVariable(size, t0, t2, t3)
963     bieq t2, Int32Tag, .opToNumberIsInt
964     biaeq t2, LowestTag, .opToNumberSlow
965 .opToNumberIsInt:
966     return(t2, t3)
967
968 .opToNumberSlow:
969     callSlowPath(_slow_path_to_number)
970     dispatch()
971 end)
972
973
974 llintOpWithReturn(op_to_string, OpToString, macro (size, get, dispatch, return)
975     get(m_operand, t0)
976     loadConstantOrVariable(size, t0, t2, t3)
977     bineq t2, CellTag, .opToStringSlow
978     bbneq JSCell::m_type[t3], StringType, .opToStringSlow
979 .opToStringIsString:
980     return(t2, t3)
981
982 .opToStringSlow:
983     callSlowPath(_slow_path_to_string)
984     dispatch()
985 end)
986
987
988 llintOpWithProfile(op_to_object, OpToObject, macro (size, get, dispatch, return)
989     get(m_operand, t0)
990     loadConstantOrVariable(size, t0, t2, t3)
991     bineq t2, CellTag, .opToObjectSlow
992     bbb JSCell::m_type[t3], ObjectType, .opToObjectSlow
993     return(t2, t3)
994
995 .opToObjectSlow:
996     callSlowPath(_slow_path_to_object)
997     dispatch()
998 end)
999
1000
1001 llintOpWithMetadata(op_negate, OpNegate, macro (size, get, dispatch, metadata, return)
1002
1003     macro arithProfile(type)
1004         ori type, OpNegate::Metadata::m_arithProfile + ArithProfile::m_bits[t5]
1005     end
1006
1007     metadata(t5, t0)
1008     get(m_operand, t0)
1009     loadConstantOrVariable(size, t0, t1, t2)
1010     bineq t1, Int32Tag, .opNegateSrcNotInt
1011     btiz t2, 0x7fffffff, .opNegateSlow
1012     negi t2
1013     arithProfile(ArithProfileInt)
1014     return (Int32Tag, t2)
1015 .opNegateSrcNotInt:
1016     bia t1, LowestTag, .opNegateSlow
1017     xori 0x80000000, t1
1018     arithProfile(ArithProfileNumber)
1019     return(t1, t2)
1020
1021 .opNegateSlow:
1022     callSlowPath(_slow_path_negate)
1023     dispatch()
1024 end)
1025
1026
1027 macro binaryOpCustomStore(opcodeName, opcodeStruct, integerOperationAndStore, doubleOperation)
1028     llintOpWithMetadata(op_%opcodeName%, opcodeStruct, macro (size, get, dispatch, metadata, return)
1029         macro arithProfile(type)
1030             ori type, %opcodeStruct%::Metadata::m_arithProfile + ArithProfile::m_bits[t5]
1031         end
1032
1033         metadata(t5, t2)
1034         get(m_rhs, t2)
1035         get(m_lhs, t0)
1036         loadConstantOrVariable(size, t2, t3, t1)
1037         loadConstantOrVariable2Reg(size, t0, t2, t0)
1038         bineq t2, Int32Tag, .op1NotInt
1039         bineq t3, Int32Tag, .op2NotInt
1040         arithProfile(ArithProfileIntInt)
1041         get(m_dst, t2)
1042         integerOperationAndStore(t3, t1, t0, .slow, t2)
1043         dispatch()
1044
1045     .op1NotInt:
1046         # First operand is definitely not an int, the second operand could be anything.
1047         bia t2, LowestTag, .slow
1048         bib t3, LowestTag, .op1NotIntOp2Double
1049         bineq t3, Int32Tag, .slow
1050         arithProfile(ArithProfileNumberInt)
1051         ci2ds t1, ft1
1052         jmp .op1NotIntReady
1053     .op1NotIntOp2Double:
1054         fii2d t1, t3, ft1
1055         arithProfile(ArithProfileNumberNumber)
1056     .op1NotIntReady:
1057         get(m_dst, t1)
1058         fii2d t0, t2, ft0
1059         doubleOperation(ft1, ft0)
1060         stored ft0, [cfr, t1, 8]
1061         dispatch()
1062
1063     .op2NotInt:
1064         # First operand is definitely an int, the second operand is definitely not.
1065         get(m_dst, t2)
1066         bia t3, LowestTag, .slow
1067         arithProfile(ArithProfileIntNumber)
1068         ci2ds t0, ft0
1069         fii2d t1, t3, ft1
1070         doubleOperation(ft1, ft0)
1071         stored ft0, [cfr, t2, 8]
1072         dispatch()
1073
1074     .slow:
1075         callSlowPath(_slow_path_%opcodeName%)
1076         dispatch()
1077     end)
1078 end
1079
1080 macro binaryOp(opcodeName, opcodeStruct, integerOperation, doubleOperation)
1081     binaryOpCustomStore(opcodeName, opcodeStruct,
1082         macro (int32Tag, left, right, slow, index)
1083             integerOperation(left, right, slow)
1084             storei int32Tag, TagOffset[cfr, index, 8]
1085             storei right, PayloadOffset[cfr, index, 8]
1086         end,
1087         doubleOperation)
1088 end
1089
1090 binaryOp(add, OpAdd,
1091     macro (left, right, slow) baddio left, right, slow end,
1092     macro (left, right) addd left, right end)
1093
1094
1095 binaryOpCustomStore(mul, OpMul,
1096     macro (int32Tag, left, right, slow, index)
1097         const scratch = int32Tag   # We know that we can reuse the int32Tag register since it has a constant.
1098         move right, scratch
1099         bmulio left, scratch, slow
1100         btinz scratch, .done
1101         bilt left, 0, slow
1102         bilt right, 0, slow
1103     .done:
1104         storei Int32Tag, TagOffset[cfr, index, 8]
1105         storei scratch, PayloadOffset[cfr, index, 8]
1106     end,
1107     macro (left, right) muld left, right end)
1108
1109
1110 binaryOp(sub, OpSub,
1111     macro (left, right, slow) bsubio left, right, slow end,
1112     macro (left, right) subd left, right end)
1113
1114
1115 binaryOpCustomStore(div, OpDiv,
1116     macro (int32Tag, left, right, slow, index)
1117         ci2ds left, ft0
1118         ci2ds right, ft1
1119         divd ft0, ft1
1120         bcd2i ft1, right, .notInt
1121         storei int32Tag, TagOffset[cfr, index, 8]
1122         storei right, PayloadOffset[cfr, index, 8]
1123         jmp .done
1124     .notInt:
1125         stored ft1, [cfr, index, 8]
1126     .done:
1127     end,
1128     macro (left, right) divd left, right end)
1129
1130
1131 llintOpWithReturn(op_unsigned, OpUnsigned, macro (size, get, dispatch, return)
1132     get(m_operand, t1)
1133     loadConstantOrVariablePayload(size, t1, Int32Tag, t2, .opUnsignedSlow)
1134     bilt t2, 0, .opUnsignedSlow
1135     return (Int32Tag, t2)
1136 .opUnsignedSlow:
1137     callSlowPath(_slow_path_unsigned)
1138     dispatch()
1139 end)
1140
1141
1142 macro commonBitOp(opKind, opcodeName, opcodeStruct, operation)
1143     opKind(op_%opcodeName%, opcodeStruct, macro (size, get, dispatch, return)
1144         get(m_rhs, t2)
1145         get(m_lhs, t0)
1146         loadConstantOrVariable(size, t2, t3, t1)
1147         loadConstantOrVariable2Reg(size, t0, t2, t0)
1148         bineq t3, Int32Tag, .slow
1149         bineq t2, Int32Tag, .slow
1150         operation(t1, t0)
1151         return (t3, t0)
1152
1153     .slow:
1154         callSlowPath(_slow_path_%opcodeName%)
1155         dispatch()
1156     end)
1157 end
1158
1159 macro bitOp(opcodeName, opcodeStruct, operation)
1160     commonBitOp(llintOpWithReturn, opcodeName, opcodeStruct, operation)
1161 end
1162
1163 macro bitOpProfiled(opcodeName, opcodeStruct, operation)
1164     commonBitOp(llintOpWithProfile, opcodeName, opcodeStruct, operation)
1165 end
1166
1167
1168 bitOpProfiled(lshift, OpLshift,
1169     macro (left, right) lshifti left, right end)
1170
1171
1172 bitOp(rshift, OpRshift,
1173     macro (left, right) rshifti left, right end)
1174
1175
1176 bitOp(urshift, OpUrshift,
1177     macro (left, right) urshifti left, right end)
1178
1179 bitOpProfiled(bitxor, OpBitxor,
1180     macro (left, right) xori left, right end)
1181
1182 bitOpProfiled(bitand, OpBitand,
1183     macro (left, right) andi left, right end)
1184
1185 bitOpProfiled(bitor, OpBitor,
1186     macro (left, right) ori left, right end)
1187
1188 llintOpWithProfile(op_bitnot, OpBitnot, macro (size, get, dispatch, return)
1189     get(m_operand, t0)
1190     loadConstantOrVariable(size, t0, t2, t3)
1191     bineq t2, Int32Tag, .opBitNotSlow
1192     noti t3
1193     return (Int32Tag, t3)
1194
1195  .opBitNotSlow:
1196     callSlowPath(_slow_path_bitnot)
1197     dispatch()
1198 end)
1199
1200 llintOp(op_overrides_has_instance, OpOverridesHasInstance, macro (size, get, dispatch)
1201     get(m_dst, t3)
1202     storei BooleanTag, TagOffset[cfr, t3, 8]
1203
1204     # First check if hasInstanceValue is the one on Function.prototype[Symbol.hasInstance]
1205     get(m_hasInstanceValue, t0)
1206     loadConstantOrVariablePayload(size, t0, CellTag, t2, .opOverrideshasInstanceValueNotCell)
1207     loadConstantOrVariable(size, t0, t1, t2)
1208     bineq t1, CellTag, .opOverrideshasInstanceValueNotCell
1209
1210     # We don't need hasInstanceValue's tag register anymore.
1211     loadp CodeBlock[cfr], t1
1212     loadp CodeBlock::m_globalObject[t1], t1
1213     loadp JSGlobalObject::m_functionProtoHasInstanceSymbolFunction[t1], t1
1214     bineq t1, t2, .opOverrideshasInstanceValueNotDefault
1215
1216     # We know the constructor is a cell.
1217     get(m_constructor, t0)
1218     loadConstantOrVariablePayloadUnchecked(size, t0, t1)
1219     tbz JSCell::m_flags[t1], ImplementsDefaultHasInstance, t0
1220     storei t0, PayloadOffset[cfr, t3, 8]
1221     dispatch()
1222
1223 .opOverrideshasInstanceValueNotCell:
1224 .opOverrideshasInstanceValueNotDefault:
1225     storei 1, PayloadOffset[cfr, t3, 8]
1226     dispatch()
1227 end)
1228
1229
1230 llintOpWithReturn(op_is_empty, OpIsEmpty, macro (size, get, dispatch, return)
1231     get(m_operand, t1)
1232     loadConstantOrVariable(size, t1, t2, t3)
1233     cieq t2, EmptyValueTag, t3
1234     return(BooleanTag, t3)
1235 end)
1236
1237
1238 llintOpWithReturn(op_is_undefined, OpIsUndefined, macro (size, get, dispatch, return)
1239     get(m_operand, t1)
1240     loadConstantOrVariable(size, t1, t2, t3)
1241     bieq t2, CellTag, .opIsUndefinedCell
1242     cieq t2, UndefinedTag, t3
1243     return(BooleanTag, t3)
1244 .opIsUndefinedCell:
1245     btbnz JSCell::m_flags[t3], MasqueradesAsUndefined, .opIsUndefinedMasqueradesAsUndefined
1246     return(BooleanTag, 0)
1247 .opIsUndefinedMasqueradesAsUndefined:
1248     loadi JSCell::m_structureID[t3], t1
1249     loadp CodeBlock[cfr], t3
1250     loadp CodeBlock::m_globalObject[t3], t3
1251     cpeq Structure::m_globalObject[t1], t3, t1
1252     return(BooleanTag, t1)
1253 end)
1254
1255
1256 llintOpWithReturn(op_is_boolean, OpIsBoolean, macro (size, get, dispatch, return)
1257     get(m_operand, t1)
1258     loadConstantOrVariableTag(size, t1, t0)
1259     cieq t0, BooleanTag, t0
1260     return(BooleanTag, t0)
1261 end)
1262
1263
1264 llintOpWithReturn(op_is_number, OpIsNumber, macro (size, get, dispatch, return)
1265     get(m_operand, t1)
1266     loadConstantOrVariableTag(size, t1, t0)
1267     addi 1, t0
1268     cib t0, LowestTag + 1, t1
1269     return(BooleanTag, t1)
1270 end)
1271
1272
1273 llintOpWithReturn(op_is_cell_with_type, OpIsCellWithType, macro (size, get, dispatch, return)
1274     get(m_operand, t1)
1275     loadConstantOrVariable(size, t1, t0, t3)
1276     bineq t0, CellTag, .notCellCase
1277     getu(size, OpIsCellWithType, m_type, t0)
1278     cbeq JSCell::m_type[t3], t0, t1
1279     return(BooleanTag, t1)
1280 .notCellCase:
1281     return(BooleanTag, 0)
1282 end)
1283
1284
1285 llintOpWithReturn(op_is_object, OpIsObject, macro (size, get, dispatch, return)
1286     get(m_operand, t1)
1287     loadConstantOrVariable(size, t1, t0, t3)
1288     bineq t0, CellTag, .opIsObjectNotCell
1289     cbaeq JSCell::m_type[t3], ObjectType, t1
1290     return(BooleanTag, t1)
1291 .opIsObjectNotCell:
1292     return(BooleanTag, 0)
1293 end)
1294
1295
1296 macro loadPropertyAtVariableOffsetKnownNotInline(propertyOffset, objectAndStorage, tag, payload)
1297     assert(macro (ok) bigteq propertyOffset, firstOutOfLineOffset, ok end)
1298     negi propertyOffset
1299     loadp JSObject::m_butterfly[objectAndStorage], objectAndStorage
1300     loadi TagOffset + (firstOutOfLineOffset - 2) * 8[objectAndStorage, propertyOffset, 8], tag
1301     loadi PayloadOffset + (firstOutOfLineOffset - 2) * 8[objectAndStorage, propertyOffset, 8], payload
1302 end
1303
1304 macro loadPropertyAtVariableOffset(propertyOffset, objectAndStorage, tag, payload)
1305     bilt propertyOffset, firstOutOfLineOffset, .isInline
1306     loadp JSObject::m_butterfly[objectAndStorage], objectAndStorage
1307     negi propertyOffset
1308     jmp .ready
1309 .isInline:
1310     addp sizeof JSObject - (firstOutOfLineOffset - 2) * 8, objectAndStorage
1311 .ready:
1312     loadi TagOffset + (firstOutOfLineOffset - 2) * 8[objectAndStorage, propertyOffset, 8], tag
1313     loadi PayloadOffset + (firstOutOfLineOffset - 2) * 8[objectAndStorage, propertyOffset, 8], payload
1314 end
1315
1316 macro storePropertyAtVariableOffset(propertyOffsetAsInt, objectAndStorage, tag, payload)
1317     bilt propertyOffsetAsInt, firstOutOfLineOffset, .isInline
1318     loadp JSObject::m_butterfly[objectAndStorage], objectAndStorage
1319     negi propertyOffsetAsInt
1320     jmp .ready
1321 .isInline:
1322     addp sizeof JSObject - (firstOutOfLineOffset - 2) * 8, objectAndStorage
1323 .ready:
1324     storei tag, TagOffset + (firstOutOfLineOffset - 2) * 8[objectAndStorage, propertyOffsetAsInt, 8]
1325     storei payload, PayloadOffset + (firstOutOfLineOffset - 2) * 8[objectAndStorage, propertyOffsetAsInt, 8]
1326 end
1327
1328
1329 # We only do monomorphic get_by_id caching for now, and we do not modify the
1330 # opcode for own properties. We also allow for the cache to change anytime it fails,
1331 # since ping-ponging is free. At best we get lucky and the get_by_id will continue
1332 # to take fast path on the new cache. At worst we take slow path, which is what
1333 # we would have been doing anyway. For prototype/unset properties, we will attempt to
1334 # convert opcode into a get_by_id_proto_load/get_by_id_unset, respectively, after an
1335 # execution counter hits zero.
1336
1337 llintOpWithMetadata(op_get_by_id_direct, OpGetByIdDirect, macro (size, get, dispatch, metadata, return)
1338     metadata(t5, t0)
1339     get(m_base, t0)
1340     loadi OpGetByIdDirect::Metadata::m_structureID[t5], t1
1341     loadConstantOrVariablePayload(size, t0, CellTag, t3, .opGetByIdDirectSlow)
1342     loadi OpGetByIdDirect::Metadata::m_offset[t5], t2
1343     bineq JSCell::m_structureID[t3], t1, .opGetByIdDirectSlow
1344     loadPropertyAtVariableOffset(t2, t3, t0, t1)
1345     valueProfile(OpGetByIdDirect, t5, t0, t1)
1346     return(t0, t1)
1347
1348 .opGetByIdDirectSlow:
1349     callSlowPath(_llint_slow_path_get_by_id_direct)
1350     dispatch()
1351 end)
1352
1353
1354 llintOpWithMetadata(op_get_by_id, OpGetById, macro (size, get, dispatch, metadata, return)
1355     metadata(t5, t0)
1356     loadb OpGetById::Metadata::m_modeMetadata.mode[t5], t1
1357     get(m_base, t0)
1358
1359 .opGetByIdProtoLoad:
1360     bbneq t1, constexpr GetByIdMode::ProtoLoad, .opGetByIdArrayLength
1361     loadi OpGetById::Metadata::m_modeMetadata.protoLoadMode.structureID[t5], t1
1362     loadConstantOrVariablePayload(size, t0, CellTag, t3, .opGetByIdSlow)
1363     loadis OpGetById::Metadata::m_modeMetadata.protoLoadMode.cachedOffset[t5], t2
1364     bineq JSCell::m_structureID[t3], t1, .opGetByIdSlow
1365     loadp OpGetById::Metadata::m_modeMetadata.protoLoadMode.cachedSlot[t5], t3
1366     loadPropertyAtVariableOffset(t2, t3, t0, t1)
1367     valueProfile(OpGetById, t5, t0, t1)
1368     return(t0, t1)
1369
1370 .opGetByIdArrayLength:
1371     bbneq t1, constexpr GetByIdMode::ArrayLength, .opGetByIdUnset
1372     loadConstantOrVariablePayload(size, t0, CellTag, t3, .opGetByIdSlow)
1373     move t3, t2
1374     arrayProfile(OpGetById::Metadata::m_modeMetadata.arrayLengthMode.arrayProfile, t2, t5, t0)
1375     btiz t2, IsArray, .opGetByIdSlow
1376     btiz t2, IndexingShapeMask, .opGetByIdSlow
1377     loadp JSObject::m_butterfly[t3], t0
1378     loadi -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0], t0
1379     bilt t0, 0, .opGetByIdSlow
1380     valueProfile(OpGetById, t5, Int32Tag, t0)
1381     return(Int32Tag, t0)
1382
1383 .opGetByIdUnset:
1384     bbneq t1, constexpr GetByIdMode::Unset, .opGetByIdDefault
1385     loadi OpGetById::Metadata::m_modeMetadata.unsetMode.structureID[t5], t1
1386     loadConstantOrVariablePayload(size, t0, CellTag, t3, .opGetByIdSlow)
1387     bineq JSCell::m_structureID[t3], t1, .opGetByIdSlow
1388     valueProfile(OpGetById, t5, UndefinedTag, 0)
1389     return(UndefinedTag, 0)
1390
1391 .opGetByIdDefault:
1392     loadi OpGetById::Metadata::m_modeMetadata.defaultMode.structureID[t5], t1
1393     loadConstantOrVariablePayload(size, t0, CellTag, t3, .opGetByIdSlow)
1394     loadis OpGetById::Metadata::m_modeMetadata.defaultMode.cachedOffset[t5], t2
1395     bineq JSCell::m_structureID[t3], t1, .opGetByIdSlow
1396     loadPropertyAtVariableOffset(t2, t3, t0, t1)
1397     valueProfile(OpGetById, t5, t0, t1)
1398     return(t0, t1)
1399
1400 .opGetByIdSlow:
1401     callSlowPath(_llint_slow_path_get_by_id)
1402     dispatch()
1403
1404 .osrReturnPoint:
1405     getterSetterOSRExitReturnPoint(op_get_by_id, size)
1406     metadata(t2, t3)
1407     valueProfile(OpGetById, t2, r1, r0)
1408     return(r1, r0)
1409
1410 end)
1411
1412
1413 llintOpWithMetadata(op_put_by_id, OpPutById, macro (size, get, dispatch, metadata, return)
1414     writeBarrierOnOperands(size, get, m_base, m_value)
1415     metadata(t5, t3)
1416     get(m_base, t3)
1417     loadConstantOrVariablePayload(size, t3, CellTag, t0, .opPutByIdSlow)
1418     loadi JSCell::m_structureID[t0], t2
1419     bineq t2, OpPutById::Metadata::m_oldStructureID[t5], .opPutByIdSlow
1420
1421     # At this point, we have:
1422     # t5 -> metadata
1423     # t2 -> currentStructureID
1424     # t0 -> object base
1425     # We will lose currentStructureID in the shenanigans below.
1426
1427     loadi OpPutById::Metadata::m_newStructureID[t5], t1
1428
1429     btiz t1, .opPutByIdNotTransition
1430
1431     # This is the transition case. t1 holds the new Structure*. If we have a chain, we need to
1432     # check it. t0 is the base. We may clobber t1 to use it as scratch.
1433     loadp OpPutById::Metadata::m_structureChain[t5], t3
1434     btpz t3, .opPutByIdTransitionDirect
1435
1436     loadi OpPutById::Metadata::m_oldStructureID[t5], t2 # Need old structure again.
1437     loadp StructureChain::m_vector[t3], t3
1438     assert(macro (ok) btpnz t3, ok end)
1439
1440     loadp Structure::m_prototype[t2], t2
1441     btpz t2, .opPutByIdTransitionChainDone
1442 .opPutByIdTransitionChainLoop:
1443     loadp [t3], t1
1444     bineq t1, JSCell::m_structureID[t2], .opPutByIdSlow
1445     addp 4, t3
1446     loadp Structure::m_prototype[t1], t2
1447     btpnz t2, .opPutByIdTransitionChainLoop
1448
1449 .opPutByIdTransitionChainDone:
1450     loadi OpPutById::Metadata::m_newStructureID[t5], t1
1451
1452 .opPutByIdTransitionDirect:
1453     storei t1, JSCell::m_structureID[t0]
1454     get(m_value, t1)
1455     loadConstantOrVariable(size, t1, t2, t3)
1456     loadi OpPutById::Metadata::m_offset[t5], t1
1457     storePropertyAtVariableOffset(t1, t0, t2, t3)
1458     writeBarrierOnOperand(size, get, m_base)
1459     dispatch()
1460
1461 .opPutByIdNotTransition:
1462     # The only thing live right now is t0, which holds the base.
1463     get(m_value, t1)
1464     loadConstantOrVariable(size, t1, t2, t3)
1465     loadi OpPutById::Metadata::m_offset[t5], t1
1466     storePropertyAtVariableOffset(t1, t0, t2, t3)
1467     dispatch()
1468
1469 .opPutByIdSlow:
1470     callSlowPath(_llint_slow_path_put_by_id)
1471     dispatch()
1472
1473 .osrReturnPoint:
1474     getterSetterOSRExitReturnPoint(op_put_by_id, size)
1475     dispatch()
1476
1477 end)
1478
1479
1480 llintOpWithMetadata(op_get_by_val, OpGetByVal, macro (size, get, dispatch, metadata, return)
1481     metadata(t5, t2)
1482     get(m_base, t2)
1483     loadConstantOrVariablePayload(size, t2, CellTag, t0, .opGetByValSlow)
1484     move t0, t2
1485     arrayProfile(OpGetByVal::Metadata::m_arrayProfile, t2, t5, t1)
1486     get(m_property, t3)
1487     loadConstantOrVariablePayload(size, t3, Int32Tag, t1, .opGetByValSlow)
1488     loadp JSObject::m_butterfly[t0], t3
1489     andi IndexingShapeMask, t2
1490     bieq t2, Int32Shape, .opGetByValIsContiguous
1491     bineq t2, ContiguousShape, .opGetByValNotContiguous
1492
1493 .opGetByValIsContiguous:
1494     biaeq t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t3], .opGetByValSlow
1495     loadi TagOffset[t3, t1, 8], t2
1496     loadi PayloadOffset[t3, t1, 8], t1
1497     jmp .opGetByValDone
1498
1499 .opGetByValNotContiguous:
1500     bineq t2, DoubleShape, .opGetByValNotDouble
1501     biaeq t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t3], .opGetByValSlow
1502     loadd [t3, t1, 8], ft0
1503     bdnequn ft0, ft0, .opGetByValSlow
1504     # FIXME: This could be massively optimized.
1505     fd2ii ft0, t1, t2
1506     get(m_dst, t0)
1507     jmp .opGetByValNotEmpty
1508
1509 .opGetByValNotDouble:
1510     subi ArrayStorageShape, t2
1511     bia t2, SlowPutArrayStorageShape - ArrayStorageShape, .opGetByValSlow
1512     biaeq t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.vectorLength[t3], .opGetByValSlow
1513     loadi ArrayStorage::m_vector + TagOffset[t3, t1, 8], t2
1514     loadi ArrayStorage::m_vector + PayloadOffset[t3, t1, 8], t1
1515
1516 .opGetByValDone:
1517     get(m_dst, t0)
1518     bieq t2, EmptyValueTag, .opGetByValSlow
1519 .opGetByValNotEmpty:
1520     storei t2, TagOffset[cfr, t0, 8]
1521     storei t1, PayloadOffset[cfr, t0, 8]
1522     valueProfile(OpGetByVal, t5, t2, t1)
1523     dispatch()
1524
1525 .opGetByValSlow:
1526     callSlowPath(_llint_slow_path_get_by_val)
1527     dispatch()
1528
1529 .osrReturnPoint:
1530     getterSetterOSRExitReturnPoint(op_get_by_val, size)
1531     metadata(t2, t3)
1532     valueProfile(OpGetByVal, t2, r1, r0)
1533     return(r1, r0)
1534
1535 end)
1536
1537
1538 macro putByValOp(opcodeName, opcodeStruct, osrExitPoint)
1539     llintOpWithMetadata(op_%opcodeName%, opcodeStruct, macro (size, get, dispatch, metadata, return)
1540         macro contiguousPutByVal(storeCallback)
1541             biaeq t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0], .outOfBounds
1542         .storeResult:
1543             get(m_value, t2)
1544             storeCallback(t2, t1, t0, t3)
1545             dispatch()
1546
1547         .outOfBounds:
1548             biaeq t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.vectorLength[t0], .opPutByValOutOfBounds
1549             storeb 1, %opcodeStruct%::Metadata::m_arrayProfile.m_mayStoreToHole[t5]
1550             addi 1, t3, t2
1551             storei t2, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0]
1552             jmp .storeResult
1553         end
1554
1555         writeBarrierOnOperands(size, get, m_base, m_value)
1556         metadata(t5, t0)
1557         get(m_base, t0)
1558         loadConstantOrVariablePayload(size, t0, CellTag, t1, .opPutByValSlow)
1559         move t1, t2
1560         arrayProfile(%opcodeStruct%::Metadata::m_arrayProfile, t2, t5, t0)
1561         get(m_property, t0)
1562         loadConstantOrVariablePayload(size, t0, Int32Tag, t3, .opPutByValSlow)
1563         loadp JSObject::m_butterfly[t1], t0
1564         btinz t2, CopyOnWrite, .opPutByValSlow
1565         andi IndexingShapeMask, t2
1566         bineq t2, Int32Shape, .opPutByValNotInt32
1567         contiguousPutByVal(
1568             macro (operand, scratch, base, index)
1569                 loadConstantOrVariablePayload(size, operand, Int32Tag, scratch, .opPutByValSlow)
1570                 storei Int32Tag, TagOffset[base, index, 8]
1571                 storei scratch, PayloadOffset[base, index, 8]
1572             end)
1573
1574     .opPutByValNotInt32:
1575         bineq t2, DoubleShape, .opPutByValNotDouble
1576         contiguousPutByVal(
1577             macro (operand, scratch, base, index)
1578                 const tag = scratch
1579                 const payload = operand
1580                 loadConstantOrVariable2Reg(size, operand, tag, payload)
1581                 bineq tag, Int32Tag, .notInt
1582                 ci2ds payload, ft0
1583                 jmp .ready
1584             .notInt:
1585                 fii2d payload, tag, ft0
1586                 bdnequn ft0, ft0, .opPutByValSlow
1587             .ready:
1588                 stored ft0, [base, index, 8]
1589             end)
1590
1591     .opPutByValNotDouble:
1592         bineq t2, ContiguousShape, .opPutByValNotContiguous
1593         contiguousPutByVal(
1594             macro (operand, scratch, base, index)
1595                 const tag = scratch
1596                 const payload = operand
1597                 loadConstantOrVariable2Reg(size, operand, tag, payload)
1598                 storei tag, TagOffset[base, index, 8]
1599                 storei payload, PayloadOffset[base, index, 8]
1600             end)
1601
1602     .opPutByValNotContiguous:
1603         bineq t2, ArrayStorageShape, .opPutByValSlow
1604         biaeq t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.vectorLength[t0], .opPutByValOutOfBounds
1605         bieq ArrayStorage::m_vector + TagOffset[t0, t3, 8], EmptyValueTag, .opPutByValArrayStorageEmpty
1606     .opPutByValArrayStorageStoreResult:
1607         get(m_value, t2)
1608         loadConstantOrVariable2Reg(size, t2, t1, t2)
1609         storei t1, ArrayStorage::m_vector + TagOffset[t0, t3, 8]
1610         storei t2, ArrayStorage::m_vector + PayloadOffset[t0, t3, 8]
1611         dispatch()
1612
1613     .opPutByValArrayStorageEmpty:
1614         storeb 1, %opcodeStruct%::Metadata::m_arrayProfile.m_mayStoreToHole[t5]
1615         addi 1, ArrayStorage::m_numValuesInVector[t0]
1616         bib t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0], .opPutByValArrayStorageStoreResult
1617         addi 1, t3, t1
1618         storei t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0]
1619         jmp .opPutByValArrayStorageStoreResult
1620
1621     .opPutByValOutOfBounds:
1622         storeb 1, %opcodeStruct%::Metadata::m_arrayProfile.m_outOfBounds[t5]
1623     .opPutByValSlow:
1624         callSlowPath(_llint_slow_path_%opcodeName%)
1625         dispatch()
1626
1627     .osrExitPoint:
1628         osrExitPoint(size, dispatch)
1629     end)
1630 end
1631
1632
1633 putByValOp(put_by_val, OpPutByVal, macro (size, dispatch)
1634 .osrReturnPoint:
1635     getterSetterOSRExitReturnPoint(op_put_by_val, size)
1636     dispatch()
1637 end)
1638
1639 putByValOp(put_by_val_direct, OpPutByValDirect, macro (a, b) end)
1640
1641
1642 macro llintJumpTrueOrFalseOp(opcodeName, opcodeStruct, conditionOp)
1643     llintOpWithJump(op_%opcodeName%, opcodeStruct, macro (size, get, jump, dispatch)
1644         get(m_condition, t1)
1645         loadConstantOrVariablePayload(size, t1, BooleanTag, t0, .slow)
1646         conditionOp(t0, .target)
1647         dispatch()
1648
1649     .target:
1650         jump(m_targetLabel)
1651
1652     .slow:
1653         callSlowPath(_llint_slow_path_%opcodeName%)
1654         nextInstruction()
1655     end)
1656 end
1657
1658
1659 macro equalNullJumpOp(opcodeName, opcodeStruct, cellHandler, immediateHandler)
1660     llintOpWithJump(op_%opcodeName%, opcodeStruct, macro (size, get, jump, dispatch)
1661         get(m_value, t0)
1662         assertNotConstant(size, t0)
1663         loadi TagOffset[cfr, t0, 8], t1
1664         loadi PayloadOffset[cfr, t0, 8], t0
1665         bineq t1, CellTag, .immediate
1666         loadi JSCell::m_structureID[t0], t2
1667         cellHandler(t2, JSCell::m_flags[t0], .target)
1668         dispatch()
1669
1670     .target:
1671         jump(m_targetLabel)
1672
1673     .immediate:
1674         ori 1, t1
1675         immediateHandler(t1, .target)
1676         dispatch()
1677     end)
1678 end
1679
1680 equalNullJumpOp(jeq_null, OpJeqNull,
1681     macro (structure, value, target)
1682         btbz value, MasqueradesAsUndefined, .opJeqNullNotMasqueradesAsUndefined
1683         loadp CodeBlock[cfr], t0
1684         loadp CodeBlock::m_globalObject[t0], t0
1685         bpeq Structure::m_globalObject[structure], t0, target
1686     .opJeqNullNotMasqueradesAsUndefined:
1687     end,
1688     macro (value, target) bieq value, NullTag, target end)
1689     
1690
1691 equalNullJumpOp(jneq_null, OpJneqNull,
1692     macro (structure, value, target)
1693         btbz value, MasqueradesAsUndefined, target
1694         loadp CodeBlock[cfr], t0
1695         loadp CodeBlock::m_globalObject[t0], t0
1696         bpneq Structure::m_globalObject[structure], t0, target
1697     end,
1698     macro (value, target) bineq value, NullTag, target end)
1699
1700 macro undefinedOrNullJumpOp(opcodeName, opcodeStruct, fn)
1701     llintOpWithJump(op_%opcodeName%, opcodeStruct, macro (size, get, jump, dispatch)
1702         get(m_value, t1)
1703         loadConstantOrVariableTag(size, t1, t0)
1704         ori 1, t0
1705         fn(t0, .target)
1706         dispatch()
1707
1708     .target:
1709         jump(m_targetLabel)
1710     end)
1711 end
1712
1713 undefinedOrNullJumpOp(jundefined_or_null, OpJundefinedOrNull,
1714     macro (value, target) bieq value, NullTag, target end)
1715
1716 undefinedOrNullJumpOp(jnundefined_or_null, OpJnundefinedOrNull,
1717     macro (value, target) bineq value, NullTag, target end)
1718
1719 llintOpWithMetadata(op_jneq_ptr, OpJneqPtr, macro (size, get, dispatch, metadata, return)
1720     get(m_value, t0)
1721     get(m_specialPointer, t1)
1722     loadConstant(size, t1, t3, t2)
1723     bineq TagOffset[cfr, t0, 8], CellTag, .opJneqPtrBranch
1724     bpeq PayloadOffset[cfr, t0, 8], t2, .opJneqPtrFallThrough
1725 .opJneqPtrBranch:
1726     metadata(t5, t2)
1727     storeb 1, OpJneqPtr::Metadata::m_hasJumped[t5]
1728     get(m_targetLabel, t0)
1729     jumpImpl(dispatchIndirect, t0)
1730 .opJneqPtrFallThrough:
1731     dispatch()
1732 end)
1733
1734
1735 macro compareUnsignedJumpOp(opcodeName, opcodeStruct, integerCompare)
1736     llintOpWithJump(op_%opcodeName%, opcodeStruct, macro (size, get, jump, dispatch)
1737         get(m_lhs, t2)
1738         get(m_rhs, t3)
1739         loadConstantOrVariable(size, t2, t0, t1)
1740         loadConstantOrVariable2Reg(size, t3, t2, t3)
1741         integerCompare(t1, t3, .jumpTarget)
1742         dispatch()
1743
1744     .jumpTarget:
1745         jump(m_targetLabel)
1746     end)
1747 end
1748
1749
1750 macro compareUnsignedOp(opcodeName, opcodeStruct, integerCompareAndSet)
1751     llintOpWithReturn(op_%opcodeName%, opcodeStruct, macro (size, get, dispatch, return)
1752         get(m_rhs, t2)
1753         get(m_lhs, t0)
1754         loadConstantOrVariable(size, t2, t3, t1)
1755         loadConstantOrVariable2Reg(size, t0, t2, t0)
1756         integerCompareAndSet(t0, t1, t0)
1757         return(BooleanTag, t0)
1758     end)
1759 end
1760
1761
1762 macro compareJumpOp(opcodeName, opcodeStruct, integerCompare, doubleCompare)
1763     llintOpWithJump(op_%opcodeName%, opcodeStruct, macro (size, get, jump, dispatch)
1764         get(m_lhs, t2)
1765         get(m_rhs, t3)
1766         loadConstantOrVariable(size, t2, t0, t1)
1767         loadConstantOrVariable2Reg(size, t3, t2, t3)
1768         bineq t0, Int32Tag, .op1NotInt
1769         bineq t2, Int32Tag, .op2NotInt
1770         integerCompare(t1, t3, .jumpTarget)
1771         dispatch()
1772
1773     .op1NotInt:
1774         bia t0, LowestTag, .slow
1775         bib t2, LowestTag, .op1NotIntOp2Double
1776         bineq t2, Int32Tag, .slow
1777         ci2ds t3, ft1
1778         jmp .op1NotIntReady
1779     .op1NotIntOp2Double:
1780         fii2d t3, t2, ft1
1781     .op1NotIntReady:
1782         fii2d t1, t0, ft0
1783         doubleCompare(ft0, ft1, .jumpTarget)
1784         dispatch()
1785
1786     .op2NotInt:
1787         ci2ds t1, ft0
1788         bia t2, LowestTag, .slow
1789         fii2d t3, t2, ft1
1790         doubleCompare(ft0, ft1, .jumpTarget)
1791         dispatch()
1792
1793     .jumpTarget:
1794         jump(m_targetLabel)
1795
1796     .slow:
1797         callSlowPath(_llint_slow_path_%opcodeName%)
1798         nextInstruction()
1799     end)
1800 end
1801
1802
1803 llintOpWithJump(op_switch_imm, OpSwitchImm, macro (size, get, jump, dispatch)
1804     get(m_scrutinee, t2)
1805     getu(size, OpSwitchImm, m_tableIndex, t3)
1806     loadConstantOrVariable(size, t2, t1, t0)
1807     loadp CodeBlock[cfr], t2
1808     loadp CodeBlock::m_rareData[t2], t2
1809     muli sizeof SimpleJumpTable, t3
1810     loadp CodeBlock::RareData::m_switchJumpTables + VectorBufferOffset[t2], t2
1811     addp t3, t2
1812     bineq t1, Int32Tag, .opSwitchImmNotInt
1813     subi SimpleJumpTable::min[t2], t0
1814     biaeq t0, SimpleJumpTable::branchOffsets + VectorSizeOffset[t2], .opSwitchImmFallThrough
1815     loadp SimpleJumpTable::branchOffsets + VectorBufferOffset[t2], t3
1816     loadi [t3, t0, 4], t1
1817     btiz t1, .opSwitchImmFallThrough
1818     dispatchIndirect(t1)
1819
1820 .opSwitchImmNotInt:
1821     bib t1, LowestTag, .opSwitchImmSlow  # Go to slow path if it's a double.
1822 .opSwitchImmFallThrough:
1823     jump(m_defaultOffset)
1824
1825 .opSwitchImmSlow:
1826     callSlowPath(_llint_slow_path_switch_imm)
1827     nextInstruction()
1828 end)
1829
1830
1831 llintOpWithJump(op_switch_char, OpSwitchChar, macro (size, get, jump, dispatch)
1832     get(m_scrutinee, t2)
1833     getu(size, OpSwitchChar, m_tableIndex, t3)
1834     loadConstantOrVariable(size, t2, t1, t0)
1835     loadp CodeBlock[cfr], t2
1836     loadp CodeBlock::m_rareData[t2], t2
1837     muli sizeof SimpleJumpTable, t3
1838     loadp CodeBlock::RareData::m_switchJumpTables + VectorBufferOffset[t2], t2
1839     addp t3, t2
1840     bineq t1, CellTag, .opSwitchCharFallThrough
1841     bbneq JSCell::m_type[t0], StringType, .opSwitchCharFallThrough
1842     loadp JSString::m_fiber[t0], t1
1843     btpnz t1, isRopeInPointer, .opSwitchOnRope
1844     bineq StringImpl::m_length[t1], 1, .opSwitchCharFallThrough
1845     loadp StringImpl::m_data8[t1], t0
1846     btinz StringImpl::m_hashAndFlags[t1], HashFlags8BitBuffer, .opSwitchChar8Bit
1847     loadh [t0], t0
1848     jmp .opSwitchCharReady
1849 .opSwitchChar8Bit:
1850     loadb [t0], t0
1851 .opSwitchCharReady:
1852     subi SimpleJumpTable::min[t2], t0
1853     biaeq t0, SimpleJumpTable::branchOffsets + VectorSizeOffset[t2], .opSwitchCharFallThrough
1854     loadp SimpleJumpTable::branchOffsets + VectorBufferOffset[t2], t2
1855     loadi [t2, t0, 4], t1
1856     btiz t1, .opSwitchCharFallThrough
1857     dispatchIndirect(t1)
1858
1859 .opSwitchCharFallThrough:
1860     jump(m_defaultOffset)
1861
1862 .opSwitchOnRope:
1863     bineq JSRopeString::m_compactFibers + JSRopeString::CompactFibers::m_length[t0], 1, .opSwitchCharFallThrough
1864
1865 .opSwitchOnRopeChar:
1866     callSlowPath(_llint_slow_path_switch_char)
1867     nextInstruction()
1868 end)
1869
1870
1871 macro arrayProfileForCall(opcodeStruct, getu)
1872     getu(m_argv, t3)
1873     negi t3
1874     bineq ThisArgumentOffset + TagOffset[cfr, t3, 8], CellTag, .done
1875     loadi ThisArgumentOffset + PayloadOffset[cfr, t3, 8], t0
1876     loadi JSCell::m_structureID[t0], t0
1877     storei t0, %opcodeStruct%::Metadata::m_callLinkInfo.m_arrayProfile.m_lastSeenStructureID[t5]
1878 .done:
1879 end
1880
1881 macro commonCallOp(opcodeName, slowPath, opcodeStruct, prepareCall, prologue)
1882     llintOpWithMetadata(opcodeName, opcodeStruct, macro (size, get, dispatch, metadata, return)
1883         metadata(t5, t0)
1884
1885         prologue(macro (fieldName, dst)
1886             getu(size, opcodeStruct, fieldName, dst)
1887         end, metadata)
1888
1889         get(m_callee, t0)
1890         loadp %opcodeStruct%::Metadata::m_callLinkInfo.m_calleeOrLastSeenCalleeWithLinkBit[t5], t2
1891         loadConstantOrVariablePayload(size, t0, CellTag, t3, .opCallSlow)
1892         bineq t3, t2, .opCallSlow
1893         getu(size, opcodeStruct, m_argv, t3)
1894         lshifti 3, t3
1895         negi t3
1896         addp cfr, t3  # t3 contains the new value of cfr
1897         storei t2, Callee + PayloadOffset[t3]
1898         getu(size, opcodeStruct, m_argc, t2)
1899         storei PC, ArgumentCount + TagOffset[cfr]
1900         storei t2, ArgumentCount + PayloadOffset[t3]
1901         storei CellTag, Callee + TagOffset[t3]
1902         move t3, sp
1903         prepareCall(%opcodeStruct%::Metadata::m_callLinkInfo.m_machineCodeTarget[t5], t2, t3, t4, JSEntryPtrTag)
1904         callTargetFunction(opcodeName, size, opcodeStruct, dispatch, %opcodeStruct%::Metadata::m_callLinkInfo.m_machineCodeTarget[t5], JSEntryPtrTag)
1905
1906     .opCallSlow:
1907         slowPathForCall(opcodeName, size, opcodeStruct, dispatch, slowPath, prepareCall)
1908     end)
1909 end
1910
1911 llintOp(op_ret, OpRet, macro (size, get, dispatch)
1912     checkSwitchToJITForEpilogue()
1913     get(m_value, t2)
1914     loadConstantOrVariable(size, t2, t1, t0)
1915     doReturn()
1916 end)
1917
1918
1919 llintOpWithReturn(op_to_primitive, OpToPrimitive, macro (size, get, dispatch, return)
1920     get(m_src, t2)
1921     loadConstantOrVariable(size, t2, t1, t0)
1922     bineq t1, CellTag, .opToPrimitiveIsImm
1923     bbaeq JSCell::m_type[t0], ObjectType, .opToPrimitiveSlowCase
1924 .opToPrimitiveIsImm:
1925     return(t1, t0)
1926
1927 .opToPrimitiveSlowCase:
1928     callSlowPath(_slow_path_to_primitive)
1929     dispatch()
1930 end)
1931
1932
1933 commonOp(llint_op_catch, macro() end, macro (size)
1934     # This is where we end up from the JIT's throw trampoline (because the
1935     # machine code return address will be set to _llint_op_catch), and from
1936     # the interpreter's throw trampoline (see _llint_throw_trampoline).
1937     # The throwing code must have known that we were throwing to the interpreter,
1938     # and have set VM::targetInterpreterPCForThrow.
1939     loadp Callee + PayloadOffset[cfr], t3
1940     convertCalleeToVM(t3)
1941     restoreCalleeSavesFromVMEntryFrameCalleeSavesBuffer(t3, t0)
1942     loadp VM::callFrameForCatch[t3], cfr
1943     storep 0, VM::callFrameForCatch[t3]
1944     restoreStackPointerAfterCall()
1945
1946     # restore metadataTable since we don't restore callee saves for CLoop during unwinding
1947     loadp CodeBlock[cfr], t1
1948     loadp CodeBlock::m_metadata[t1], metadataTable
1949
1950     loadi VM::targetInterpreterPCForThrow[t3], PC
1951
1952     callSlowPath(_llint_slow_path_check_if_exception_is_uncatchable_and_notify_profiler)
1953     bpeq r1, 0, .isCatchableException
1954     jmp _llint_throw_from_slow_path_trampoline
1955
1956 .isCatchableException:
1957     loadp CodeBlock[cfr], t3
1958     loadp CodeBlock::m_vm[t3], t3
1959
1960     loadp VM::m_exception[t3], t0
1961     storep 0, VM::m_exception[t3]
1962     get(size, OpCatch, m_exception, t2)
1963     storei t0, PayloadOffset[cfr, t2, 8]
1964     storei CellTag, TagOffset[cfr, t2, 8]
1965
1966     loadi Exception::m_value + TagOffset[t0], t1
1967     loadi Exception::m_value + PayloadOffset[t0], t0
1968     get(size, OpCatch, m_thrownValue, t2)
1969     storei t0, PayloadOffset[cfr, t2, 8]
1970     storei t1, TagOffset[cfr, t2, 8]
1971
1972     traceExecution()  # This needs to be here because we don't want to clobber t0, t1, t2, t3 above.
1973
1974     callSlowPath(_llint_slow_path_profile_catch)
1975
1976     dispatchOp(size, op_catch)
1977 end)
1978
1979 llintOp(op_end, OpEnd, macro (size, get, dispatch)
1980     checkSwitchToJITForEpilogue()
1981     get(m_value, t0)
1982     assertNotConstant(size, t0)
1983     loadi TagOffset[cfr, t0, 8], t1
1984     loadi PayloadOffset[cfr, t0, 8], t0
1985     doReturn()
1986 end)
1987
1988
1989 op(llint_throw_from_slow_path_trampoline, macro()
1990     loadp Callee[cfr], t1
1991     convertCalleeToVM(t1)
1992     copyCalleeSavesToVMEntryFrameCalleeSavesBuffer(t1, t2)
1993
1994     callSlowPath(_llint_slow_path_handle_exception)
1995
1996     # When throwing from the interpreter (i.e. throwing from LLIntSlowPaths), so
1997     # the throw target is not necessarily interpreted code, we come to here.
1998     # This essentially emulates the JIT's throwing protocol.
1999     loadp Callee[cfr], t1
2000     convertCalleeToVM(t1)
2001     jmp VM::targetMachinePCForThrow[t1]
2002 end)
2003
2004
2005 op(llint_throw_during_call_trampoline, macro()
2006     preserveReturnAddressAfterCall(t2)
2007     jmp _llint_throw_from_slow_path_trampoline
2008 end)
2009
2010
2011 macro nativeCallTrampoline(executableOffsetToFunction)
2012     functionPrologue()
2013     storep 0, CodeBlock[cfr]
2014
2015     if X86 or X86_WIN
2016         subp 8, sp # align stack pointer
2017         storep cfr, [sp]
2018     elsif MIPS
2019         # calling convention says to save stack space for 4 first registers in
2020         # all cases. To match our 16-byte alignment, that means we need to
2021         # take 24 bytes
2022         subp 24, sp
2023     else
2024         subp 8, sp # align stack pointer
2025     end
2026
2027     loadp Callee + PayloadOffset[cfr], a0
2028     loadp JSFunction::m_executable[a0], a2
2029     loadp JSFunction::m_globalObject[a0], a0
2030     loadp JSGlobalObject::m_vm[a0], a1
2031     storep cfr, VM::topCallFrame[a1]
2032     move cfr, a1
2033
2034     checkStackPointerAlignment(t3, 0xdead0001)
2035     if C_LOOP or C_LOOP_WIN
2036         cloopCallNative executableOffsetToFunction[a2]
2037     else
2038         call executableOffsetToFunction[a2]
2039     end
2040
2041     loadp Callee + PayloadOffset[cfr], t3
2042     loadp JSFunction::m_globalObject[t3], t3
2043     loadp JSGlobalObject::m_vm[t3], t3
2044
2045     if MIPS
2046         addp 24, sp
2047     else
2048         addp 8, sp
2049     end
2050
2051     btpnz VM::m_exception[t3], .handleException
2052
2053     functionEpilogue()
2054     ret
2055
2056 .handleException:
2057     if X86 or X86_WIN
2058         subp 8, sp # align stack pointer
2059     end
2060     storep cfr, VM::topCallFrame[t3]
2061     jmp _llint_throw_from_slow_path_trampoline
2062 end
2063
2064
2065 macro internalFunctionCallTrampoline(offsetOfFunction)
2066     functionPrologue()
2067     storep 0, CodeBlock[cfr]
2068
2069     // Callee is still in t1 for code below
2070     if X86 or X86_WIN
2071         subp 8, sp # align stack pointer
2072         storep cfr, [sp]
2073     else
2074         subp 8, sp # align stack pointer
2075     end
2076
2077     loadp Callee + PayloadOffset[cfr], a2
2078     loadp InternalFunction::m_globalObject[a2], a0
2079     loadp JSGlobalObject::m_vm[a0], a1
2080     storep cfr, VM::topCallFrame[a1]
2081     move cfr, a1
2082
2083     checkStackPointerAlignment(t3, 0xdead0001)
2084     if C_LOOP or C_LOOP_WIN
2085         cloopCallNative offsetOfFunction[a2]
2086     else
2087         call offsetOfFunction[a2]
2088     end
2089
2090     loadp Callee + PayloadOffset[cfr], t3
2091     loadp InternalFunction::m_globalObject[t3], t3
2092     loadp JSGlobalObject::m_vm[t3], t3
2093
2094     addp 8, sp
2095
2096     btpnz VM::m_exception[t3], .handleException
2097
2098     functionEpilogue()
2099     ret
2100
2101 .handleException:
2102     if X86 or X86_WIN
2103         subp 8, sp # align stack pointer
2104     end
2105     storep cfr, VM::topCallFrame[t3]
2106     jmp _llint_throw_from_slow_path_trampoline
2107 end
2108
2109
2110 macro varInjectionCheck(slowPath)
2111     loadp CodeBlock[cfr], t0
2112     loadp CodeBlock::m_globalObject[t0], t0
2113     loadp JSGlobalObject::m_varInjectionWatchpoint[t0], t0
2114     bbeq WatchpointSet::m_state[t0], IsInvalidated, slowPath
2115 end
2116
2117
2118 llintOpWithMetadata(op_resolve_scope, OpResolveScope, macro (size, get, dispatch, metadata, return)
2119
2120     macro getConstantScope(dst)
2121         loadp OpResolveScope::Metadata::m_constantScope[t5], dst
2122     end
2123
2124     macro returnConstantScope()
2125         getConstantScope(t0)
2126         return(CellTag, t0)
2127     end
2128
2129     macro globalLexicalBindingEpochCheck(slowPath, globalObject, scratch)
2130         loadi OpResolveScope::Metadata::m_globalLexicalBindingEpoch[t5], scratch
2131         bineq JSGlobalObject::m_globalLexicalBindingEpoch[globalObject], scratch, slowPath
2132     end
2133
2134     macro resolveScope()
2135         loadi OpResolveScope::Metadata::m_localScopeDepth[t5], t2
2136         get(m_scope, t0)
2137         loadp PayloadOffset[cfr, t0, 8], t0
2138         btiz t2, .resolveScopeLoopEnd
2139
2140     .resolveScopeLoop:
2141         loadp JSScope::m_next[t0], t0
2142         subi 1, t2
2143         btinz t2, .resolveScopeLoop
2144
2145     .resolveScopeLoopEnd:
2146         return(CellTag, t0)
2147     end
2148
2149     metadata(t5, t0)
2150     loadi OpResolveScope::Metadata::m_resolveType[t5], t0
2151
2152 #rGlobalProperty:
2153     bineq t0, GlobalProperty, .rGlobalVar
2154     getConstantScope(t0)
2155     globalLexicalBindingEpochCheck(.rDynamic, t0, t2)
2156     return(CellTag, t0)
2157
2158 .rGlobalVar:
2159     bineq t0, GlobalVar, .rGlobalLexicalVar
2160     returnConstantScope()
2161
2162 .rGlobalLexicalVar:
2163     bineq t0, GlobalLexicalVar, .rClosureVar
2164     returnConstantScope()
2165
2166 .rClosureVar:
2167     bineq t0, ClosureVar, .rModuleVar
2168     resolveScope()
2169
2170 .rModuleVar:
2171     bineq t0, ModuleVar, .rGlobalPropertyWithVarInjectionChecks
2172     returnConstantScope()
2173
2174 .rGlobalPropertyWithVarInjectionChecks:
2175     bineq t0, GlobalPropertyWithVarInjectionChecks, .rGlobalVarWithVarInjectionChecks
2176     varInjectionCheck(.rDynamic)
2177     getConstantScope(t0)
2178     globalLexicalBindingEpochCheck(.rDynamic, t0, t2)
2179     return(CellTag, t0)
2180
2181 .rGlobalVarWithVarInjectionChecks:
2182     bineq t0, GlobalVarWithVarInjectionChecks, .rGlobalLexicalVarWithVarInjectionChecks
2183     varInjectionCheck(.rDynamic)
2184     returnConstantScope()
2185
2186 .rGlobalLexicalVarWithVarInjectionChecks:
2187     bineq t0, GlobalLexicalVarWithVarInjectionChecks, .rClosureVarWithVarInjectionChecks
2188     varInjectionCheck(.rDynamic)
2189     returnConstantScope()
2190
2191 .rClosureVarWithVarInjectionChecks:
2192     bineq t0, ClosureVarWithVarInjectionChecks, .rDynamic
2193     varInjectionCheck(.rDynamic)
2194     resolveScope()
2195
2196 .rDynamic:
2197     callSlowPath(_slow_path_resolve_scope)
2198     dispatch()
2199 end)
2200
2201
2202 macro loadWithStructureCheck(opcodeStruct, get, operand, slowPath)
2203     get(m_scope, t0)
2204     loadp PayloadOffset[cfr, t0, 8], t0
2205     loadp %opcodeStruct%::Metadata::m_structure[t5], t1
2206     bineq JSCell::m_structureID[t0], t1, slowPath
2207 end
2208
2209
2210 llintOpWithMetadata(op_get_from_scope, OpGetFromScope, macro (size, get, dispatch, metadata, return)
2211     macro getProperty()
2212         loadp OpGetFromScope::Metadata::m_operand[t5], t3
2213         loadPropertyAtVariableOffset(t3, t0, t1, t2)
2214         valueProfile(OpGetFromScope, t5, t1, t2)
2215         return(t1, t2)
2216     end
2217
2218     macro getGlobalVar(tdzCheckIfNecessary)
2219         loadp OpGetFromScope::Metadata::m_operand[t5], t0
2220         loadp TagOffset[t0], t1
2221         loadp PayloadOffset[t0], t2
2222         tdzCheckIfNecessary(t1)
2223         valueProfile(OpGetFromScope, t5, t1, t2)
2224         return(t1, t2)
2225     end
2226
2227     macro getClosureVar()
2228         loadp OpGetFromScope::Metadata::m_operand[t5], t3
2229         loadp JSLexicalEnvironment_variables + TagOffset[t0, t3, 8], t1
2230         loadp JSLexicalEnvironment_variables + PayloadOffset[t0, t3, 8], t2
2231         valueProfile(OpGetFromScope, t5, t1, t2)
2232         return(t1, t2)
2233     end
2234
2235     metadata(t5, t0)
2236     loadi OpGetFromScope::Metadata::m_getPutInfo + GetPutInfo::m_operand[t5], t0
2237     andi ResolveTypeMask, t0
2238
2239 #gGlobalProperty:
2240     bineq t0, GlobalProperty, .gGlobalVar
2241     loadWithStructureCheck(OpGetFromScope, get, scope, .gDynamic)
2242     getProperty()
2243
2244 .gGlobalVar:
2245     bineq t0, GlobalVar, .gGlobalLexicalVar
2246     getGlobalVar(macro(t) end)
2247
2248 .gGlobalLexicalVar:
2249     bineq t0, GlobalLexicalVar, .gClosureVar
2250     getGlobalVar(
2251         macro(tag)
2252             bieq tag, EmptyValueTag, .gDynamic
2253         end)
2254
2255 .gClosureVar:
2256     bineq t0, ClosureVar, .gGlobalPropertyWithVarInjectionChecks
2257     loadVariable(get, m_scope, t2, t1, t0)
2258     getClosureVar()
2259
2260 .gGlobalPropertyWithVarInjectionChecks:
2261     bineq t0, GlobalPropertyWithVarInjectionChecks, .gGlobalVarWithVarInjectionChecks
2262     loadWithStructureCheck(OpGetFromScope, get, scope, .gDynamic)
2263     getProperty()
2264
2265 .gGlobalVarWithVarInjectionChecks:
2266     bineq t0, GlobalVarWithVarInjectionChecks, .gGlobalLexicalVarWithVarInjectionChecks
2267     varInjectionCheck(.gDynamic)
2268     getGlobalVar(macro(t) end)
2269
2270 .gGlobalLexicalVarWithVarInjectionChecks:
2271     bineq t0, GlobalLexicalVarWithVarInjectionChecks, .gClosureVarWithVarInjectionChecks
2272     varInjectionCheck(.gDynamic)
2273     getGlobalVar(
2274         macro(tag)
2275             bieq tag, EmptyValueTag, .gDynamic
2276         end)
2277
2278 .gClosureVarWithVarInjectionChecks:
2279     bineq t0, ClosureVarWithVarInjectionChecks, .gDynamic
2280     varInjectionCheck(.gDynamic)
2281     loadVariable(get, m_scope, t2, t1, t0)
2282     getClosureVar()
2283
2284 .gDynamic:
2285     callSlowPath(_llint_slow_path_get_from_scope)
2286     dispatch()
2287 end)
2288
2289
2290 llintOpWithMetadata(op_put_to_scope, OpPutToScope, macro (size, get, dispatch, metadata, return)
2291     macro putProperty()
2292         get(m_value, t1)
2293         loadConstantOrVariable(size, t1, t2, t3)
2294         loadp OpPutToScope::Metadata::m_operand[t5], t1
2295         storePropertyAtVariableOffset(t1, t0, t2, t3)
2296     end
2297
2298     macro putGlobalVariable()
2299         get(m_value, t0)
2300         loadConstantOrVariable(size, t0, t1, t2)
2301         loadp OpPutToScope::Metadata::m_watchpointSet[t5], t3
2302         btpz t3, .noVariableWatchpointSet
2303         notifyWrite(t3, .pDynamic)
2304     .noVariableWatchpointSet:
2305         loadp OpPutToScope::Metadata::m_operand[t5], t0
2306         storei t1, TagOffset[t0]
2307         storei t2, PayloadOffset[t0]
2308     end
2309
2310     macro putClosureVar()
2311         get(m_value, t1)
2312         loadConstantOrVariable(size, t1, t2, t3)
2313         loadp OpPutToScope::Metadata::m_operand[t5], t1
2314         storei t2, JSLexicalEnvironment_variables + TagOffset[t0, t1, 8]
2315         storei t3, JSLexicalEnvironment_variables + PayloadOffset[t0, t1, 8]
2316     end
2317
2318     macro putLocalClosureVar()
2319         get(m_value, t1)
2320         loadConstantOrVariable(size, t1, t2, t3)
2321         loadp OpPutToScope::Metadata::m_watchpointSet[t5], t1
2322         btpz t1, .noVariableWatchpointSet
2323         notifyWrite(t1, .pDynamic)
2324     .noVariableWatchpointSet:
2325         loadp OpPutToScope::Metadata::m_operand[t5], t1
2326         storei t2, JSLexicalEnvironment_variables + TagOffset[t0, t1, 8]
2327         storei t3, JSLexicalEnvironment_variables + PayloadOffset[t0, t1, 8]
2328     end
2329
2330     macro checkTDZInGlobalPutToScopeIfNecessary()
2331         loadi OpPutToScope::Metadata::m_getPutInfo + GetPutInfo::m_operand[t5], t0
2332         andi InitializationModeMask, t0
2333         rshifti InitializationModeShift, t0
2334         bineq t0, NotInitialization, .noNeedForTDZCheck
2335         loadp OpPutToScope::Metadata::m_operand[t5], t0
2336         loadi TagOffset[t0], t0
2337         bieq t0, EmptyValueTag, .pDynamic
2338     .noNeedForTDZCheck:
2339     end
2340
2341     metadata(t5, t0)
2342     loadi OpPutToScope::Metadata::m_getPutInfo + GetPutInfo::m_operand[t5], t0
2343     andi ResolveTypeMask, t0
2344
2345 #pLocalClosureVar:
2346     bineq t0, LocalClosureVar, .pGlobalProperty
2347     loadVariable(get, m_scope, t2, t1, t0)
2348     putLocalClosureVar()
2349     writeBarrierOnOperands(size, get, m_scope, m_value)
2350     dispatch()
2351
2352 .pGlobalProperty:
2353     bineq t0, GlobalProperty, .pGlobalVar
2354     loadWithStructureCheck(OpPutToScope, get, scope, .pDynamic)
2355     putProperty()
2356     writeBarrierOnOperands(size, get, m_scope, m_value)
2357     dispatch()
2358
2359 .pGlobalVar:
2360     bineq t0, GlobalVar, .pGlobalLexicalVar
2361     putGlobalVariable()
2362     writeBarrierOnGlobalObject(size, get, m_value)
2363     dispatch()
2364
2365 .pGlobalLexicalVar:
2366     bineq t0, GlobalLexicalVar, .pClosureVar
2367     checkTDZInGlobalPutToScopeIfNecessary()
2368     putGlobalVariable()
2369     writeBarrierOnGlobalLexicalEnvironment(size, get, m_value)
2370     dispatch()
2371
2372 .pClosureVar:
2373     bineq t0, ClosureVar, .pGlobalPropertyWithVarInjectionChecks
2374     loadVariable(get, m_scope, t2, t1, t0)
2375     putClosureVar()
2376     writeBarrierOnOperands(size, get, m_scope, m_value)
2377     dispatch()
2378
2379 .pGlobalPropertyWithVarInjectionChecks:
2380     bineq t0, GlobalPropertyWithVarInjectionChecks, .pGlobalVarWithVarInjectionChecks
2381     loadWithStructureCheck(OpPutToScope, get, scope, .pDynamic)
2382     putProperty()
2383     writeBarrierOnOperands(size, get, m_scope, m_value)
2384     dispatch()
2385
2386 .pGlobalVarWithVarInjectionChecks:
2387     bineq t0, GlobalVarWithVarInjectionChecks, .pGlobalLexicalVarWithVarInjectionChecks
2388     varInjectionCheck(.pDynamic)
2389     putGlobalVariable()
2390     writeBarrierOnGlobalObject(size, get, m_value)
2391     dispatch()
2392
2393 .pGlobalLexicalVarWithVarInjectionChecks:
2394     bineq t0, GlobalLexicalVarWithVarInjectionChecks, .pClosureVarWithVarInjectionChecks
2395     varInjectionCheck(.pDynamic)
2396     checkTDZInGlobalPutToScopeIfNecessary()
2397     putGlobalVariable()
2398     writeBarrierOnGlobalLexicalEnvironment(size, get, m_value)
2399     dispatch()
2400
2401 .pClosureVarWithVarInjectionChecks:
2402     bineq t0, ClosureVarWithVarInjectionChecks, .pModuleVar
2403     varInjectionCheck(.pDynamic)
2404     loadVariable(get, m_scope, t2, t1, t0)
2405     putClosureVar()
2406     writeBarrierOnOperands(size, get, m_scope, m_value)
2407     dispatch()
2408
2409 .pModuleVar:
2410     bineq t0, ModuleVar, .pDynamic
2411     callSlowPath(_slow_path_throw_strict_mode_readonly_property_write_error)
2412     dispatch()
2413
2414 .pDynamic:
2415     callSlowPath(_llint_slow_path_put_to_scope)
2416     dispatch()
2417 end)
2418
2419
2420 llintOpWithProfile(op_get_from_arguments, OpGetFromArguments, macro (size, get, dispatch, return)
2421     get(m_arguments, t0)
2422     loadi PayloadOffset[cfr, t0, 8], t0
2423     getu(size, OpGetFromArguments, m_index, t1)
2424     loadi DirectArguments_storage + TagOffset[t0, t1, 8], t2
2425     loadi DirectArguments_storage + PayloadOffset[t0, t1, 8], t3
2426     return(t2, t3)
2427 end)
2428
2429
2430 llintOp(op_put_to_arguments, OpPutToArguments, macro (size, get, dispatch)
2431     writeBarrierOnOperands(size, get, m_arguments, m_value)
2432     get(m_arguments, t0)
2433     loadi PayloadOffset[cfr, t0, 8], t0
2434     get(m_value, t1)
2435     loadConstantOrVariable(size, t1, t2, t3)
2436     getu(size, OpPutToArguments, m_index, t1)
2437     storei t2, DirectArguments_storage + TagOffset[t0, t1, 8]
2438     storei t3, DirectArguments_storage + PayloadOffset[t0, t1, 8]
2439     dispatch()
2440 end)
2441
2442
2443 llintOpWithReturn(op_get_parent_scope, OpGetParentScope, macro (size, get, dispatch, return)
2444     get(m_scope, t0)
2445     loadp PayloadOffset[cfr, t0, 8], t0
2446     loadp JSScope::m_next[t0], t0
2447     return(CellTag, t0)
2448 end)
2449
2450
2451 llintOpWithMetadata(op_profile_type, OpProfileType, macro (size, get, dispatch, metadata, return)
2452     loadp CodeBlock[cfr], t1
2453     loadp CodeBlock::m_vm[t1], t1
2454     # t1 is holding the pointer to the typeProfilerLog.
2455     loadp VM::m_typeProfilerLog[t1], t1
2456
2457     # t0 is holding the payload, t5 is holding the tag.
2458     get(m_targetVirtualRegister, t2)
2459     loadConstantOrVariable(size, t2, t5, t0)
2460
2461     bieq t5, EmptyValueTag, .opProfileTypeDone
2462
2463     metadata(t3, t2)
2464     # t2 is holding the pointer to the current log entry.
2465     loadp TypeProfilerLog::m_currentLogEntryPtr[t1], t2
2466
2467     # Store the JSValue onto the log entry.
2468     storei t5, TypeProfilerLog::LogEntry::value + TagOffset[t2]
2469     storei t0, TypeProfilerLog::LogEntry::value + PayloadOffset[t2]
2470
2471     # Store the TypeLocation onto the log entry.
2472     loadp OpProfileType::Metadata::m_typeLocation[t3], t3
2473     storep t3, TypeProfilerLog::LogEntry::location[t2]
2474
2475     bieq t5, CellTag, .opProfileTypeIsCell
2476     storei 0, TypeProfilerLog::LogEntry::structureID[t2]
2477     jmp .opProfileTypeSkipIsCell
2478 .opProfileTypeIsCell:
2479     loadi JSCell::m_structureID[t0], t3
2480     storei t3, TypeProfilerLog::LogEntry::structureID[t2]
2481 .opProfileTypeSkipIsCell:
2482     
2483     # Increment the current log entry.
2484     addp sizeof TypeProfilerLog::LogEntry, t2
2485     storep t2, TypeProfilerLog::m_currentLogEntryPtr[t1]
2486
2487     loadp TypeProfilerLog::m_logEndPtr[t1], t1
2488     bpneq t2, t1, .opProfileTypeDone
2489     callSlowPath(_slow_path_profile_type_clear_log)
2490
2491 .opProfileTypeDone:
2492     dispatch()
2493 end)
2494
2495
2496 llintOpWithMetadata(op_profile_control_flow, OpProfileControlFlow, macro (size, get, dispatch, metadata, return)
2497     metadata(t5, t0)
2498     loadp OpProfileControlFlow::Metadata::m_basicBlockLocation[t5], t0
2499     loadi BasicBlockLocation::m_executionCount[t0], t1
2500     baddio 1, t1, .done
2501     storei t1, BasicBlockLocation::m_executionCount[t0]
2502 .done:
2503     dispatch()
2504 end)
2505
2506
2507 llintOpWithReturn(op_get_rest_length, OpGetRestLength, macro (size, get, dispatch, return)
2508     loadi PayloadOffset + ArgumentCount[cfr], t0
2509     subi 1, t0
2510     getu(size, OpGetRestLength, m_numParametersToSkip, t1)
2511     bilteq t0, t1, .storeZero
2512     subi t1, t0
2513     jmp .finish
2514 .storeZero:
2515     move 0, t0
2516 .finish:
2517     return(Int32Tag, t0)
2518 end)
2519
2520
2521 llintOpWithProfile(op_get_internal_field, OpGetInternalField, macro (size, get, dispatch, return)
2522     get(m_base, t0)
2523     loadi PayloadOffset[cfr, t0, 8], t0
2524     getu(size, OpGetInternalField, m_index, t1)
2525     loadi JSInternalFieldObjectImpl_internalFields + TagOffset[t0, t1, SlotSize], t2
2526     loadi JSInternalFieldObjectImpl_internalFields + PayloadOffset[t0, t1, SlotSize], t3
2527     return(t2, t3)
2528 end)
2529
2530 llintOp(op_put_internal_field, OpPutInternalField, macro (size, get, dispatch)
2531     get(m_base, t0)
2532     loadi PayloadOffset[cfr, t0, 8], t0
2533     get(m_value, t1)
2534     loadConstantOrVariable(size, t1, t2, t3)
2535     getu(size, OpPutInternalField, m_index, t1)
2536     storei t2, JSInternalFieldObjectImpl_internalFields + TagOffset[t0, t1, SlotSize]
2537     storei t3, JSInternalFieldObjectImpl_internalFields + PayloadOffset[t0, t1, SlotSize]
2538     writeBarrierOnOperand(size, get, m_base)
2539     dispatch()
2540 end)
2541
2542
2543 llintOp(op_log_shadow_chicken_prologue, OpLogShadowChickenPrologue, macro (size, get, dispatch)
2544     acquireShadowChickenPacket(.opLogShadowChickenPrologueSlow)
2545     storep cfr, ShadowChicken::Packet::frame[t0]
2546     loadp CallerFrame[cfr], t1
2547     storep t1, ShadowChicken::Packet::callerFrame[t0]
2548     loadp Callee + PayloadOffset[cfr], t1
2549     storep t1, ShadowChicken::Packet::callee[t0]
2550     get(m_scope, t1)
2551     loadi PayloadOffset[cfr, t1, 8], t1
2552     storep t1, ShadowChicken::Packet::scope[t0]
2553     dispatch()
2554 .opLogShadowChickenPrologueSlow:
2555     callSlowPath(_llint_slow_path_log_shadow_chicken_prologue)
2556     dispatch()
2557 end)
2558
2559
2560 llintOp(op_log_shadow_chicken_tail, OpLogShadowChickenTail, macro (size, get, dispatch)
2561     acquireShadowChickenPacket(.opLogShadowChickenTailSlow)
2562     storep cfr, ShadowChicken::Packet::frame[t0]
2563     storep ShadowChickenTailMarker, ShadowChicken::Packet::callee[t0]
2564     loadVariable(get, m_thisValue, t3, t2, t1)
2565     storei t2, TagOffset + ShadowChicken::Packet::thisValue[t0]
2566     storei t1, PayloadOffset + ShadowChicken::Packet::thisValue[t0]
2567     get(m_scope, t1)
2568     loadi PayloadOffset[cfr, t1, 8], t1
2569     storep t1, ShadowChicken::Packet::scope[t0]
2570     loadp CodeBlock[cfr], t1
2571     storep t1, ShadowChicken::Packet::codeBlock[t0]
2572     storei PC, ShadowChicken::Packet::callSiteIndex[t0]
2573     dispatch()
2574 .opLogShadowChickenTailSlow:
2575     callSlowPath(_llint_slow_path_log_shadow_chicken_tail)
2576     dispatch()
2577 end)