043a00afbf8615682db9141957989fde8b1046a6
[WebKit-https.git] / Source / JavaScriptCore / llint / LowLevelInterpreter.asm
1 # Copyright (C) 2011, 2012, 2013, 2014 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 # First come the common protocols that both interpreters use. Note that each
25 # of these must have an ASSERT() in LLIntData.cpp
26
27 # Work-around for the fact that the toolchain's awareness of armv7s results in
28 # a separate slab in the fat binary, yet the offlineasm doesn't know to expect
29 # it.
30 if ARMv7s
31 end
32
33 # These declarations must match interpreter/JSStack.h.
34
35 if JSVALUE64
36     const PtrSize = 8
37     const CallFrameHeaderSlots = 5
38 else
39     const PtrSize = 4
40     const CallFrameHeaderSlots = 4
41     const CallFrameAlignSlots = 1
42 end
43 const SlotSize = 8
44
45 const StackAlignment = 16
46 const StackAlignmentMask = StackAlignment - 1
47
48 const CallerFrameAndPCSize = 2 * PtrSize
49
50 const CallerFrame = 0
51 const ReturnPC = CallerFrame + PtrSize
52 const CodeBlock = ReturnPC + PtrSize
53 const Callee = CodeBlock + SlotSize
54 const ArgumentCount = Callee + SlotSize
55 const ThisArgumentOffset = ArgumentCount + SlotSize
56 const CallFrameHeaderSize = ThisArgumentOffset
57
58 # Some value representation constants.
59 if JSVALUE64
60     const TagBitTypeOther = 0x2
61     const TagBitBool      = 0x4
62     const TagBitUndefined = 0x8
63     const ValueEmpty      = 0x0
64     const ValueFalse      = TagBitTypeOther | TagBitBool
65     const ValueTrue       = TagBitTypeOther | TagBitBool | 1
66     const ValueUndefined  = TagBitTypeOther | TagBitUndefined
67     const ValueNull       = TagBitTypeOther
68 else
69     const Int32Tag = -1
70     const BooleanTag = -2
71     const NullTag = -3
72     const UndefinedTag = -4
73     const CellTag = -5
74     const EmptyValueTag = -6
75     const DeletedValueTag = -7
76     const LowestTag = DeletedValueTag
77 end
78
79 const CallOpCodeSize = 9
80
81 if X86_64 or ARM64 or C_LOOP
82     const maxFrameExtentForSlowPathCall = 0
83 elsif ARM or ARMv7_TRADITIONAL or ARMv7 or SH4
84     const maxFrameExtentForSlowPathCall = 24
85 elsif X86 or X86_WIN
86     const maxFrameExtentForSlowPathCall = 40
87 elsif MIPS
88     const maxFrameExtentForSlowPathCall = 40
89 elsif X86_64_WIN
90     const maxFrameExtentForSlowPathCall = 64
91 end
92
93 # Watchpoint states
94 const ClearWatchpoint = 0
95 const IsWatched = 1
96 const IsInvalidated = 2
97
98 # Some register conventions.
99 if JSVALUE64
100     # - Use a pair of registers to represent the PC: one register for the
101     #   base of the bytecodes, and one register for the index.
102     # - The PC base (or PB for short) should be stored in the csr. It will
103     #   get clobbered on calls to other JS code, but will get saved on calls
104     #   to C functions.
105     # - C calls are still given the Instruction* rather than the PC index.
106     #   This requires an add before the call, and a sub after.
107     const PC = t5
108     const PB = t6
109     const tagTypeNumber = csr1
110     const tagMask = csr2
111     
112     macro loadisFromInstruction(offset, dest)
113         loadis offset * 8[PB, PC, 8], dest
114     end
115     
116     macro loadpFromInstruction(offset, dest)
117         loadp offset * 8[PB, PC, 8], dest
118     end
119     
120     macro storepToInstruction(value, offset)
121         storep value, offset * 8[PB, PC, 8]
122     end
123
124 else
125     const PC = t5
126     macro loadisFromInstruction(offset, dest)
127         loadis offset * 4[PC], dest
128     end
129     
130     macro loadpFromInstruction(offset, dest)
131         loadp offset * 4[PC], dest
132     end
133 end
134
135 # Constants for reasoning about value representation.
136 if BIG_ENDIAN
137     const TagOffset = 0
138     const PayloadOffset = 4
139 else
140     const TagOffset = 4
141     const PayloadOffset = 0
142 end
143
144 # Constant for reasoning about butterflies.
145 const IsArray                  = 1
146 const IndexingShapeMask        = 30
147 const NoIndexingShape          = 0
148 const Int32Shape               = 20
149 const DoubleShape              = 22
150 const ContiguousShape          = 26
151 const ArrayStorageShape        = 28
152 const SlowPutArrayStorageShape = 30
153
154 # Type constants.
155 const StringType = 6
156 const ObjectType = 18
157 const FinalObjectType = 19
158
159 # Type flags constants.
160 const MasqueradesAsUndefined = 1
161 const ImplementsHasInstance = 2
162 const ImplementsDefaultHasInstance = 8
163
164 # Bytecode operand constants.
165 const FirstConstantRegisterIndex = 0x40000000
166
167 # Code type constants.
168 const GlobalCode = 0
169 const EvalCode = 1
170 const FunctionCode = 2
171
172 # The interpreter steals the tag word of the argument count.
173 const LLIntReturnPC = ArgumentCount + TagOffset
174
175 # String flags.
176 const HashFlags8BitBuffer = 32
177
178 # Copied from PropertyOffset.h
179 const firstOutOfLineOffset = 100
180
181 # ResolveType
182 const GlobalProperty = 0
183 const GlobalVar = 1
184 const ClosureVar = 2
185 const LocalClosureVar = 3
186 const GlobalPropertyWithVarInjectionChecks = 4
187 const GlobalVarWithVarInjectionChecks = 5
188 const ClosureVarWithVarInjectionChecks = 6
189 const Dynamic = 7
190
191 const ResolveModeMask = 0xffff
192
193 const MarkedBlockSize = 64 * 1024
194 const MarkedBlockMask = ~(MarkedBlockSize - 1)
195 # Constants for checking mark bits.
196 const AtomNumberShift = 3
197 const BitMapWordShift = 4
198
199 # Allocation constants
200 if JSVALUE64
201     const JSFinalObjectSizeClassIndex = 1
202 else
203     const JSFinalObjectSizeClassIndex = 3
204 end
205
206 # This must match wtf/Vector.h
207 const VectorBufferOffset = 0
208 if JSVALUE64
209     const VectorSizeOffset = 12
210 else
211     const VectorSizeOffset = 8
212 end
213
214 # Some common utilities.
215 macro crash()
216     if C_LOOP
217         cloopCrash
218     else
219         call _llint_crash
220     end
221 end
222
223 macro assert(assertion)
224     if ASSERT_ENABLED
225         assertion(.ok)
226         crash()
227     .ok:
228     end
229 end
230
231 macro checkStackPointerAlignment(tempReg, location)
232     if ARM64 or C_LOOP or SH4
233         # ARM64 will check for us!
234         # C_LOOP does not need the alignment, and can use a little perf
235         # improvement from avoiding useless work.
236         # SH4 does not need specific alignment (4 bytes).
237     else
238         if ARM or ARMv7 or ARMv7_TRADITIONAL
239             # ARM can't do logical ops with the sp as a source
240             move sp, tempReg
241             andp StackAlignmentMask, tempReg
242         else
243             andp sp, StackAlignmentMask, tempReg
244         end
245         btpz tempReg, .stackPointerOkay
246         move location, tempReg
247         break
248     .stackPointerOkay:
249     end
250 end
251
252 if C_LOOP
253     const CalleeSaveRegisterCount = 0
254 elsif ARM or ARMv7_TRADITIONAL or ARMv7
255     const CalleeSaveRegisterCount = 7
256 elsif ARM64
257     const CalleeSaveRegisterCount = 10
258 elsif SH4 or X86_64 or MIPS
259     const CalleeSaveRegisterCount = 5
260 elsif X86 or X86_WIN
261     const CalleeSaveRegisterCount = 3
262 elsif X86_64_WIN
263     const CalleeSaveRegisterCount = 7
264 end
265
266 const CalleeRegisterSaveSize = CalleeSaveRegisterCount * PtrSize
267
268 # VMEntryTotalFrameSize includes the space for struct VMEntryRecord and the
269 # callee save registers rounded up to keep the stack aligned
270 const VMEntryTotalFrameSize = (CalleeRegisterSaveSize + sizeof VMEntryRecord + StackAlignment - 1) & ~StackAlignmentMask
271
272 macro pushCalleeSaves()
273     if C_LOOP
274     elsif ARM or ARMv7_TRADITIONAL
275         emit "push {r4-r10}"
276     elsif ARMv7
277         emit "push {r4-r6, r8-r11}"
278     elsif ARM64
279         emit "stp x20, x19, [sp, #-16]!"
280         emit "stp x22, x21, [sp, #-16]!"
281         emit "stp x24, x23, [sp, #-16]!"
282         emit "stp x26, x25, [sp, #-16]!"
283         emit "stp x28, x27, [sp, #-16]!"
284     elsif MIPS
285         emit "addiu $sp, $sp, -20"
286         emit "sw $20, 16($sp)"
287         emit "sw $19, 12($sp)"
288         emit "sw $18, 8($sp)"
289         emit "sw $17, 4($sp)"
290         emit "sw $16, 0($sp)"
291     elsif SH4
292         emit "mov.l r13, @-r15"
293         emit "mov.l r11, @-r15"
294         emit "mov.l r10, @-r15"
295         emit "mov.l r9, @-r15"
296         emit "mov.l r8, @-r15"
297     elsif X86
298         emit "push %esi"
299         emit "push %edi"
300         emit "push %ebx"
301     elsif X86_WIN
302         emit "push esi"
303         emit "push edi"
304         emit "push ebx"
305     elsif X86_64
306         emit "push %r12"
307         emit "push %r13"
308         emit "push %r14"
309         emit "push %r15"
310         emit "push %rbx"
311     elsif X86_64_WIN
312         emit "push r12"
313         emit "push r13"
314         emit "push r14"
315         emit "push r15"
316         emit "push rbx"
317         emit "push rdi"
318         emit "push rsi"
319     end
320 end
321
322 macro popCalleeSaves()
323     if C_LOOP
324     elsif ARM or ARMv7_TRADITIONAL
325         emit "pop {r4-r10}"
326     elsif ARMv7
327         emit "pop {r4-r6, r8-r11}"
328     elsif ARM64
329         emit "ldp x28, x27, [sp], #16"
330         emit "ldp x26, x25, [sp], #16"
331         emit "ldp x24, x23, [sp], #16"
332         emit "ldp x22, x21, [sp], #16"
333         emit "ldp x20, x19, [sp], #16"
334     elsif MIPS
335         emit "lw $16, 0($sp)"
336         emit "lw $17, 4($sp)"
337         emit "lw $18, 8($sp)"
338         emit "lw $19, 12($sp)"
339         emit "lw $20, 16($sp)"
340         emit "addiu $sp, $sp, 20"
341     elsif SH4
342         emit "mov.l @r15+, r8"
343         emit "mov.l @r15+, r9"
344         emit "mov.l @r15+, r10"
345         emit "mov.l @r15+, r11"
346         emit "mov.l @r15+, r13"
347     elsif X86
348         emit "pop %ebx"
349         emit "pop %edi"
350         emit "pop %esi"
351     elsif X86_WIN
352         emit "pop ebx"
353         emit "pop edi"
354         emit "pop esi"
355     elsif X86_64
356         emit "pop %rbx"
357         emit "pop %r15"
358         emit "pop %r14"
359         emit "pop %r13"
360         emit "pop %r12"
361     elsif X86_64_WIN
362         emit "pop rsi"
363         emit "pop rdi"
364         emit "pop rbx"
365         emit "pop r15"
366         emit "pop r14"
367         emit "pop r13"
368         emit "pop r12"
369     end
370 end
371
372 macro preserveCallerPCAndCFR()
373     if C_LOOP or ARM or ARMv7 or ARMv7_TRADITIONAL or MIPS or SH4
374         push lr
375         push cfr
376     elsif X86 or X86_WIN or X86_64 or X86_64_WIN
377         push cfr
378     elsif ARM64
379         push cfr, lr
380     else
381         error
382     end
383     move sp, cfr
384 end
385
386 macro restoreCallerPCAndCFR()
387     move cfr, sp
388     if C_LOOP or ARM or ARMv7 or ARMv7_TRADITIONAL or MIPS or SH4
389         pop cfr
390         pop lr
391     elsif X86 or X86_WIN or X86_64 or X86_64_WIN
392         pop cfr
393     elsif ARM64
394         pop lr, cfr
395     end
396 end
397
398 macro preserveReturnAddressAfterCall(destinationRegister)
399     if C_LOOP or ARM or ARMv7 or ARMv7_TRADITIONAL or ARM64 or MIPS or SH4
400         # In C_LOOP case, we're only preserving the bytecode vPC.
401         move lr, destinationRegister
402     elsif X86 or X86_WIN or X86_64 or X86_64_WIN
403         pop destinationRegister
404     else
405         error
406     end
407 end
408
409 macro restoreReturnAddressBeforeReturn(sourceRegister)
410     if C_LOOP or ARM or ARMv7 or ARMv7_TRADITIONAL or ARM64 or MIPS or SH4
411         # In C_LOOP case, we're only restoring the bytecode vPC.
412         move sourceRegister, lr
413     elsif X86 or X86_WIN or X86_64 or X86_64_WIN
414         push sourceRegister
415     else
416         error
417     end
418 end
419
420 macro functionPrologue()
421     if X86 or X86_WIN or X86_64 or X86_64_WIN
422         push cfr
423     elsif ARM64
424         push cfr, lr
425     elsif C_LOOP or ARM or ARMv7 or ARMv7_TRADITIONAL or MIPS or SH4
426         push lr
427         push cfr
428     end
429     move sp, cfr
430 end
431
432 macro functionEpilogue()
433     if X86 or X86_WIN or X86_64 or X86_64_WIN
434         pop cfr
435     elsif ARM64
436         pop lr, cfr
437     elsif C_LOOP or ARM or ARMv7 or ARMv7_TRADITIONAL or MIPS or SH4
438         pop cfr
439         pop lr
440     end
441 end
442
443 macro vmEntryRecord(entryFramePointer, resultReg)
444     subp entryFramePointer, VMEntryTotalFrameSize, resultReg
445 end
446
447 macro moveStackPointerForCodeBlock(codeBlock, scratch)
448     loadi CodeBlock::m_numCalleeRegisters[codeBlock], scratch
449     lshiftp 3, scratch
450     addp maxFrameExtentForSlowPathCall, scratch
451     if ARMv7
452         subp cfr, scratch, scratch
453         move scratch, sp
454     else
455         subp cfr, scratch, sp
456     end
457 end
458
459 macro restoreStackPointerAfterCall()
460     loadp CodeBlock[cfr], t2
461     moveStackPointerForCodeBlock(t2, t4)
462 end
463
464 macro traceExecution()
465     if EXECUTION_TRACING
466         callSlowPath(_llint_trace)
467     end
468 end
469
470 macro callTargetFunction(callLinkInfo, calleeFramePtr)
471     move calleeFramePtr, sp
472     if C_LOOP
473         cloopCallJSFunction LLIntCallLinkInfo::machineCodeTarget[callLinkInfo]
474     else
475         call LLIntCallLinkInfo::machineCodeTarget[callLinkInfo]
476     end
477     restoreStackPointerAfterCall()
478     dispatchAfterCall()
479 end
480
481 macro slowPathForCall(slowPath)
482     callCallSlowPath(
483         slowPath,
484         macro (callee)
485             btpz t1, .dontUpdateSP
486             if ARMv7
487                 addp CallerFrameAndPCSize, t1, t1
488                 move t1, sp
489             else
490                 addp CallerFrameAndPCSize, t1, sp
491             end
492         .dontUpdateSP:
493             if C_LOOP
494                 cloopCallJSFunction callee
495             else
496                 call callee
497             end
498             restoreStackPointerAfterCall()
499             dispatchAfterCall()
500         end)
501 end
502
503 macro arrayProfile(cellAndIndexingType, profile, scratch)
504     const cell = cellAndIndexingType
505     const indexingType = cellAndIndexingType 
506     loadi JSCell::m_structureID[cell], scratch
507     storei scratch, ArrayProfile::m_lastSeenStructureID[profile]
508     loadb JSCell::m_indexingType[cell], indexingType
509 end
510
511 macro skipIfIsRememberedOrInEden(cell, scratch1, scratch2, continuation)
512     loadb JSCell::m_gcData[cell], scratch1
513     continuation(scratch1)
514 end
515
516 macro checkSwitchToJIT(increment, action)
517     loadp CodeBlock[cfr], t0
518     baddis increment, CodeBlock::m_llintExecuteCounter + BaselineExecutionCounter::m_counter[t0], .continue
519     action()
520     .continue:
521 end
522
523 macro checkSwitchToJITForEpilogue()
524     checkSwitchToJIT(
525         10,
526         macro ()
527             callSlowPath(_llint_replace)
528         end)
529 end
530
531 macro assertNotConstant(index)
532     assert(macro (ok) bilt index, FirstConstantRegisterIndex, ok end)
533 end
534
535 macro functionForCallCodeBlockGetter(targetRegister)
536     if JSVALUE64
537         loadp Callee[cfr], targetRegister
538     else
539         loadp Callee + PayloadOffset[cfr], targetRegister
540     end
541     loadp JSFunction::m_executable[targetRegister], targetRegister
542     loadp FunctionExecutable::m_codeBlockForCall[targetRegister], targetRegister
543 end
544
545 macro functionForConstructCodeBlockGetter(targetRegister)
546     if JSVALUE64
547         loadp Callee[cfr], targetRegister
548     else
549         loadp Callee + PayloadOffset[cfr], targetRegister
550     end
551     loadp JSFunction::m_executable[targetRegister], targetRegister
552     loadp FunctionExecutable::m_codeBlockForConstruct[targetRegister], targetRegister
553 end
554
555 macro notFunctionCodeBlockGetter(targetRegister)
556     loadp CodeBlock[cfr], targetRegister
557 end
558
559 macro functionCodeBlockSetter(sourceRegister)
560     storep sourceRegister, CodeBlock[cfr]
561 end
562
563 macro notFunctionCodeBlockSetter(sourceRegister)
564     # Nothing to do!
565 end
566
567 # Do the bare minimum required to execute code. Sets up the PC, leave the CodeBlock*
568 # in t1. May also trigger prologue entry OSR.
569 macro prologue(codeBlockGetter, codeBlockSetter, osrSlowPath, traceSlowPath)
570     # Set up the call frame and check if we should OSR.
571     preserveCallerPCAndCFR()
572
573     if EXECUTION_TRACING
574         subp maxFrameExtentForSlowPathCall, sp
575         callSlowPath(traceSlowPath)
576         addp maxFrameExtentForSlowPathCall, sp
577     end
578     codeBlockGetter(t1)
579     if not C_LOOP
580         baddis 5, CodeBlock::m_llintExecuteCounter + BaselineExecutionCounter::m_counter[t1], .continue
581         if JSVALUE64
582             cCall2(osrSlowPath, cfr, PC)
583         else
584             # We are after the function prologue, but before we have set up sp from the CodeBlock.
585             # Temporarily align stack pointer for this call.
586             subp 8, sp
587             cCall2(osrSlowPath, cfr, PC)
588             addp 8, sp
589         end
590         btpz t0, .recover
591         move cfr, sp # restore the previous sp
592         # pop the callerFrame since we will jump to a function that wants to save it
593         if ARM64
594             pop lr, cfr
595         elsif ARM or ARMv7 or ARMv7_TRADITIONAL or MIPS or SH4
596             pop cfr
597             pop lr
598         else
599             pop cfr
600         end
601         jmp t0
602     .recover:
603         codeBlockGetter(t1)
604     .continue:
605     end
606
607     codeBlockSetter(t1)
608     
609     moveStackPointerForCodeBlock(t1, t2)
610
611     # Set up the PC.
612     if JSVALUE64
613         loadp CodeBlock::m_instructions[t1], PB
614         move 0, PC
615     else
616         loadp CodeBlock::m_instructions[t1], PC
617     end
618 end
619
620 # Expects that CodeBlock is in t1, which is what prologue() leaves behind.
621 # Must call dispatch(0) after calling this.
622 macro functionInitialization(profileArgSkip)
623     # Profile the arguments. Unfortunately, we have no choice but to do this. This
624     # code is pretty horrendous because of the difference in ordering between
625     # arguments and value profiles, the desire to have a simple loop-down-to-zero
626     # loop, and the desire to use only three registers so as to preserve the PC and
627     # the code block. It is likely that this code should be rewritten in a more
628     # optimal way for architectures that have more than five registers available
629     # for arbitrary use in the interpreter.
630     loadi CodeBlock::m_numParameters[t1], t0
631     addp -profileArgSkip, t0 # Use addi because that's what has the peephole
632     assert(macro (ok) bpgteq t0, 0, ok end)
633     btpz t0, .argumentProfileDone
634     loadp CodeBlock::m_argumentValueProfiles + VectorBufferOffset[t1], t3
635     mulp sizeof ValueProfile, t0, t2 # Aaaaahhhh! Need strength reduction!
636     lshiftp 3, t0
637     addp t2, t3
638 .argumentProfileLoop:
639     if JSVALUE64
640         loadq ThisArgumentOffset - 8 + profileArgSkip * 8[cfr, t0], t2
641         subp sizeof ValueProfile, t3
642         storeq t2, profileArgSkip * sizeof ValueProfile + ValueProfile::m_buckets[t3]
643     else
644         loadi ThisArgumentOffset + TagOffset - 8 + profileArgSkip * 8[cfr, t0], t2
645         subp sizeof ValueProfile, t3
646         storei t2, profileArgSkip * sizeof ValueProfile + ValueProfile::m_buckets + TagOffset[t3]
647         loadi ThisArgumentOffset + PayloadOffset - 8 + profileArgSkip * 8[cfr, t0], t2
648         storei t2, profileArgSkip * sizeof ValueProfile + ValueProfile::m_buckets + PayloadOffset[t3]
649     end
650     baddpnz -8, t0, .argumentProfileLoop
651 .argumentProfileDone:
652         
653     # Check stack height.
654     loadi CodeBlock::m_numCalleeRegisters[t1], t0
655     loadp CodeBlock::m_vm[t1], t2
656     lshiftp 3, t0
657     addi maxFrameExtentForSlowPathCall, t0
658     subp cfr, t0, t0
659     bpbeq VM::m_jsStackLimit[t2], t0, .stackHeightOK
660
661     # Stack height check failed - need to call a slow_path.
662     callSlowPath(_llint_stack_check)
663     bpeq t1, 0, .stackHeightOK
664     move t1, cfr
665 .stackHeightOK:
666 end
667
668 macro allocateJSObject(allocator, structure, result, scratch1, slowCase)
669     const offsetOfFirstFreeCell = 
670         MarkedAllocator::m_freeList + 
671         MarkedBlock::FreeList::head
672
673     # Get the object from the free list.   
674     loadp offsetOfFirstFreeCell[allocator], result
675     btpz result, slowCase
676     
677     # Remove the object from the free list.
678     loadp [result], scratch1
679     storep scratch1, offsetOfFirstFreeCell[allocator]
680
681     # Initialize the object.
682     storep 0, JSObject::m_butterfly[result]
683     storeStructureWithTypeInfo(result, structure, scratch1)
684 end
685
686 macro doReturn()
687     restoreCallerPCAndCFR()
688     ret
689 end
690
691 # stub to call into JavaScript or Native functions
692 # EncodedJSValue vmEntryToJavaScript(void* code, VM* vm, ProtoCallFrame* protoFrame)
693 # EncodedJSValue vmEntryToNativeFunction(void* code, VM* vm, ProtoCallFrame* protoFrame)
694
695 if C_LOOP
696     _llint_vm_entry_to_javascript:
697 else
698     global _vmEntryToJavaScript
699     _vmEntryToJavaScript:
700 end
701     doVMEntry(makeJavaScriptCall)
702
703
704 if C_LOOP
705     _llint_vm_entry_to_native:
706 else
707     global _vmEntryToNative
708     _vmEntryToNative:
709 end
710     doVMEntry(makeHostFunctionCall)
711
712
713 if not C_LOOP
714     # void sanitizeStackForVMImpl(VM* vm)
715     global _sanitizeStackForVMImpl
716     _sanitizeStackForVMImpl:
717         if X86_64
718             const vm = t4
719             const address = t1
720             const zeroValue = t0
721         elsif X86_64_WIN
722             const vm = t2
723             const address = t1
724             const zeroValue = t0
725         elsif X86 or X86_WIN
726             const vm = t2
727             const address = t1
728             const zeroValue = t0
729         else
730             const vm = a0
731             const address = t1
732             const zeroValue = t2
733         end
734     
735         if X86 or X86_WIN
736             loadp 4[sp], vm
737         end
738     
739         loadp VM::m_lastStackTop[vm], address
740         bpbeq sp, address, .zeroFillDone
741     
742         move 0, zeroValue
743     .zeroFillLoop:
744         storep zeroValue, [address]
745         addp PtrSize, address
746         bpa sp, address, .zeroFillLoop
747     
748     .zeroFillDone:
749         move sp, address
750         storep address, VM::m_lastStackTop[vm]
751         ret
752     
753     # VMEntryRecord* vmEntryRecord(const VMEntryFrame* entryFrame)
754     global _vmEntryRecord
755     _vmEntryRecord:
756         if X86_64
757             const entryFrame = t4
758             const result = t0
759         elsif X86 or X86_WIN or X86_64_WIN
760             const entryFrame = t2
761             const result = t0
762         else
763             const entryFrame = a0
764             const result = t0
765         end
766     
767         if X86 or X86_WIN
768             loadp 4[sp], entryFrame
769         end
770     
771         vmEntryRecord(entryFrame, result)
772         ret
773 end
774
775 if C_LOOP
776     # Dummy entry point the C Loop uses to initialize.
777     _llint_entry:
778         crash()
779     else
780     macro initPCRelative(pcBase)
781         if X86_64 or X86_64_WIN
782             call _relativePCBase
783         _relativePCBase:
784             pop pcBase
785         elsif X86 or X86_WIN
786             call _relativePCBase
787         _relativePCBase:
788             pop pcBase
789             loadp 20[sp], t4
790         elsif ARM64
791         elsif ARMv7
792         _relativePCBase:
793             move pc, pcBase
794             subp 3, pcBase   # Need to back up the PC and set the Thumb2 bit
795         elsif ARM or ARMv7_TRADITIONAL
796         _relativePCBase:
797             move pc, pcBase
798             subp 8, pcBase
799         elsif MIPS
800             la _relativePCBase, pcBase
801         _relativePCBase:
802         elsif SH4
803             mova _relativePCBase, t0
804             move t0, pcBase
805             alignformova
806         _relativePCBase:
807         end
808 end
809
810 macro setEntryAddress(index, label)
811     if X86_64
812         leap (label - _relativePCBase)[t1], t0
813         move index, t2
814         storep t0, [t4, t2, 8]
815     elsif X86_64_WIN
816         leap (label - _relativePCBase)[t1], t0
817         move index, t4
818         storep t0, [t2, t4, 8]
819     elsif X86 or X86_WIN
820         leap (label - _relativePCBase)[t1], t0
821         move index, t2
822         storep t0, [t4, t2, 4]
823     elsif ARM64
824         pcrtoaddr label, t1
825         move index, t2
826         storep t1, [a0, t2, 8]
827     elsif ARM or ARMv7 or ARMv7_TRADITIONAL
828         mvlbl (label - _relativePCBase), t2
829         addp t2, t1, t2
830         move index, t3
831         storep t2, [a0, t3, 4]
832     elsif SH4
833         move (label - _relativePCBase), t2
834         addp t2, t1, t2
835         move index, t3
836         storep t2, [a0, t3, 4]
837         flushcp # Force constant pool flush to avoid "pcrel too far" link error.
838     elsif MIPS
839         la label, t2
840         la _relativePCBase, t3
841         subp t3, t2
842         addp t2, t1, t2
843         move index, t3
844         storep t2, [a0, t3, 4]
845     end
846 end
847
848 global _llint_entry
849 # Entry point for the llint to initialize.
850 _llint_entry:
851     functionPrologue()
852     pushCalleeSaves()
853     initPCRelative(t1)
854
855     # Include generated bytecode initialization file.
856     include InitBytecodes
857
858     popCalleeSaves()
859     functionEpilogue()
860     ret
861 end
862
863 _llint_program_prologue:
864     prologue(notFunctionCodeBlockGetter, notFunctionCodeBlockSetter, _llint_entry_osr, _llint_trace_prologue)
865     dispatch(0)
866
867
868 _llint_eval_prologue:
869     prologue(notFunctionCodeBlockGetter, notFunctionCodeBlockSetter, _llint_entry_osr, _llint_trace_prologue)
870     dispatch(0)
871
872
873 _llint_function_for_call_prologue:
874     prologue(functionForCallCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_call, _llint_trace_prologue_function_for_call)
875     functionInitialization(0)
876     dispatch(0)
877     
878
879 _llint_function_for_construct_prologue:
880     prologue(functionForConstructCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_construct, _llint_trace_prologue_function_for_construct)
881     functionInitialization(1)
882     dispatch(0)
883     
884
885 _llint_function_for_call_arity_check:
886     prologue(functionForCallCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_call_arityCheck, _llint_trace_arityCheck_for_call)
887     functionArityCheck(.functionForCallBegin, _slow_path_call_arityCheck)
888 .functionForCallBegin:
889     functionInitialization(0)
890     dispatch(0)
891
892
893 _llint_function_for_construct_arity_check:
894     prologue(functionForConstructCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_construct_arityCheck, _llint_trace_arityCheck_for_construct)
895     functionArityCheck(.functionForConstructBegin, _slow_path_construct_arityCheck)
896 .functionForConstructBegin:
897     functionInitialization(1)
898     dispatch(0)
899
900
901 # Value-representation-specific code.
902 if JSVALUE64
903     include LowLevelInterpreter64
904 else
905     include LowLevelInterpreter32_64
906 end
907
908
909 # Value-representation-agnostic code.
910 _llint_op_touch_entry:
911     traceExecution()
912     callSlowPath(_slow_path_touch_entry)
913     dispatch(1)
914
915
916 _llint_op_new_array:
917     traceExecution()
918     callSlowPath(_llint_slow_path_new_array)
919     dispatch(5)
920
921
922 _llint_op_new_array_with_size:
923     traceExecution()
924     callSlowPath(_llint_slow_path_new_array_with_size)
925     dispatch(4)
926
927
928 _llint_op_new_array_buffer:
929     traceExecution()
930     callSlowPath(_llint_slow_path_new_array_buffer)
931     dispatch(5)
932
933
934 _llint_op_new_regexp:
935     traceExecution()
936     callSlowPath(_llint_slow_path_new_regexp)
937     dispatch(3)
938
939
940 _llint_op_less:
941     traceExecution()
942     callSlowPath(_slow_path_less)
943     dispatch(4)
944
945
946 _llint_op_lesseq:
947     traceExecution()
948     callSlowPath(_slow_path_lesseq)
949     dispatch(4)
950
951
952 _llint_op_greater:
953     traceExecution()
954     callSlowPath(_slow_path_greater)
955     dispatch(4)
956
957
958 _llint_op_greatereq:
959     traceExecution()
960     callSlowPath(_slow_path_greatereq)
961     dispatch(4)
962
963
964 _llint_op_mod:
965     traceExecution()
966     callSlowPath(_slow_path_mod)
967     dispatch(4)
968
969
970 _llint_op_typeof:
971     traceExecution()
972     callSlowPath(_slow_path_typeof)
973     dispatch(3)
974
975
976 _llint_op_is_object:
977     traceExecution()
978     callSlowPath(_slow_path_is_object)
979     dispatch(3)
980
981
982 _llint_op_is_function:
983     traceExecution()
984     callSlowPath(_slow_path_is_function)
985     dispatch(3)
986
987
988 _llint_op_in:
989     traceExecution()
990     callSlowPath(_slow_path_in)
991     dispatch(4)
992
993 macro withInlineStorage(object, propertyStorage, continuation)
994     # Indicate that the object is the property storage, and that the
995     # property storage register is unused.
996     continuation(object, propertyStorage)
997 end
998
999 macro withOutOfLineStorage(object, propertyStorage, continuation)
1000     loadp JSObject::m_butterfly[object], propertyStorage
1001     # Indicate that the propertyStorage register now points to the
1002     # property storage, and that the object register may be reused
1003     # if the object pointer is not needed anymore.
1004     continuation(propertyStorage, object)
1005 end
1006
1007
1008 _llint_op_del_by_id:
1009     traceExecution()
1010     callSlowPath(_llint_slow_path_del_by_id)
1011     dispatch(4)
1012
1013
1014 _llint_op_del_by_val:
1015     traceExecution()
1016     callSlowPath(_llint_slow_path_del_by_val)
1017     dispatch(4)
1018
1019
1020 _llint_op_put_by_index:
1021     traceExecution()
1022     callSlowPath(_llint_slow_path_put_by_index)
1023     dispatch(4)
1024
1025
1026 _llint_op_put_getter_setter:
1027     traceExecution()
1028     callSlowPath(_llint_slow_path_put_getter_setter)
1029     dispatch(5)
1030
1031
1032 _llint_op_jtrue:
1033     traceExecution()
1034     jumpTrueOrFalse(
1035         macro (value, target) btinz value, target end,
1036         _llint_slow_path_jtrue)
1037
1038
1039 _llint_op_jfalse:
1040     traceExecution()
1041     jumpTrueOrFalse(
1042         macro (value, target) btiz value, target end,
1043         _llint_slow_path_jfalse)
1044
1045
1046 _llint_op_jless:
1047     traceExecution()
1048     compare(
1049         macro (left, right, target) bilt left, right, target end,
1050         macro (left, right, target) bdlt left, right, target end,
1051         _llint_slow_path_jless)
1052
1053
1054 _llint_op_jnless:
1055     traceExecution()
1056     compare(
1057         macro (left, right, target) bigteq left, right, target end,
1058         macro (left, right, target) bdgtequn left, right, target end,
1059         _llint_slow_path_jnless)
1060
1061
1062 _llint_op_jgreater:
1063     traceExecution()
1064     compare(
1065         macro (left, right, target) bigt left, right, target end,
1066         macro (left, right, target) bdgt left, right, target end,
1067         _llint_slow_path_jgreater)
1068
1069
1070 _llint_op_jngreater:
1071     traceExecution()
1072     compare(
1073         macro (left, right, target) bilteq left, right, target end,
1074         macro (left, right, target) bdltequn left, right, target end,
1075         _llint_slow_path_jngreater)
1076
1077
1078 _llint_op_jlesseq:
1079     traceExecution()
1080     compare(
1081         macro (left, right, target) bilteq left, right, target end,
1082         macro (left, right, target) bdlteq left, right, target end,
1083         _llint_slow_path_jlesseq)
1084
1085
1086 _llint_op_jnlesseq:
1087     traceExecution()
1088     compare(
1089         macro (left, right, target) bigt left, right, target end,
1090         macro (left, right, target) bdgtun left, right, target end,
1091         _llint_slow_path_jnlesseq)
1092
1093
1094 _llint_op_jgreatereq:
1095     traceExecution()
1096     compare(
1097         macro (left, right, target) bigteq left, right, target end,
1098         macro (left, right, target) bdgteq left, right, target end,
1099         _llint_slow_path_jgreatereq)
1100
1101
1102 _llint_op_jngreatereq:
1103     traceExecution()
1104     compare(
1105         macro (left, right, target) bilt left, right, target end,
1106         macro (left, right, target) bdltun left, right, target end,
1107         _llint_slow_path_jngreatereq)
1108
1109
1110 _llint_op_loop_hint:
1111     traceExecution()
1112     loadp CodeBlock[cfr], t1
1113     loadp CodeBlock::m_vm[t1], t1
1114     loadb VM::watchdog+Watchdog::m_timerDidFire[t1], t0
1115     btbnz t0, .handleWatchdogTimer
1116 .afterWatchdogTimerCheck:
1117     checkSwitchToJITForLoop()
1118     dispatch(1)
1119 .handleWatchdogTimer:
1120     callWatchdogTimerHandler(.throwHandler)
1121     jmp .afterWatchdogTimerCheck
1122 .throwHandler:
1123     jmp _llint_throw_from_slow_path_trampoline
1124
1125 _llint_op_switch_string:
1126     traceExecution()
1127     callSlowPath(_llint_slow_path_switch_string)
1128     dispatch(0)
1129
1130
1131 _llint_op_new_func_exp:
1132     traceExecution()
1133     callSlowPath(_llint_slow_path_new_func_exp)
1134     dispatch(4)
1135
1136
1137 _llint_op_call:
1138     traceExecution()
1139     arrayProfileForCall()
1140     doCall(_llint_slow_path_call)
1141
1142
1143 _llint_op_construct:
1144     traceExecution()
1145     doCall(_llint_slow_path_construct)
1146
1147
1148 _llint_op_call_varargs:
1149     traceExecution()
1150     callSlowPath(_llint_slow_path_size_frame_for_varargs)
1151     branchIfException(_llint_throw_from_slow_path_trampoline)
1152     # calleeFrame in t1
1153     if JSVALUE64
1154         move t1, sp
1155     else
1156         # The calleeFrame is not stack aligned, move down by CallerFrameAndPCSize to align
1157         if ARMv7
1158             subp t1, CallerFrameAndPCSize, t2
1159             move t2, sp
1160         else
1161             subp t1, CallerFrameAndPCSize, sp
1162         end
1163     end
1164     slowPathForCall(_llint_slow_path_call_varargs)
1165
1166 _llint_op_construct_varargs:
1167     traceExecution()
1168     callSlowPath(_llint_slow_path_size_frame_for_varargs)
1169     branchIfException(_llint_throw_from_slow_path_trampoline)
1170     # calleeFrame in t1
1171     if JSVALUE64
1172         move t1, sp
1173     else
1174         # The calleeFrame is not stack aligned, move down by CallerFrameAndPCSize to align
1175         if ARMv7
1176             subp t1, CallerFrameAndPCSize, t2
1177             move t2, sp
1178         else
1179             subp t1, CallerFrameAndPCSize, sp
1180         end
1181     end
1182     slowPathForCall(_llint_slow_path_construct_varargs)
1183
1184
1185 _llint_op_call_eval:
1186     traceExecution()
1187     
1188     # Eval is executed in one of two modes:
1189     #
1190     # 1) We find that we're really invoking eval() in which case the
1191     #    execution is perfomed entirely inside the slow_path, and it
1192     #    returns the PC of a function that just returns the return value
1193     #    that the eval returned.
1194     #
1195     # 2) We find that we're invoking something called eval() that is not
1196     #    the real eval. Then the slow_path returns the PC of the thing to
1197     #    call, and we call it.
1198     #
1199     # This allows us to handle two cases, which would require a total of
1200     # up to four pieces of state that cannot be easily packed into two
1201     # registers (C functions can return up to two registers, easily):
1202     #
1203     # - The call frame register. This may or may not have been modified
1204     #   by the slow_path, but the convention is that it returns it. It's not
1205     #   totally clear if that's necessary, since the cfr is callee save.
1206     #   But that's our style in this here interpreter so we stick with it.
1207     #
1208     # - A bit to say if the slow_path successfully executed the eval and has
1209     #   the return value, or did not execute the eval but has a PC for us
1210     #   to call.
1211     #
1212     # - Either:
1213     #   - The JS return value (two registers), or
1214     #
1215     #   - The PC to call.
1216     #
1217     # It turns out to be easier to just always have this return the cfr
1218     # and a PC to call, and that PC may be a dummy thunk that just
1219     # returns the JS value that the eval returned.
1220     
1221     slowPathForCall(_llint_slow_path_call_eval)
1222
1223
1224 _llint_generic_return_point:
1225     dispatchAfterCall()
1226
1227
1228 _llint_op_strcat:
1229     traceExecution()
1230     callSlowPath(_slow_path_strcat)
1231     dispatch(4)
1232
1233
1234 _llint_op_push_with_scope:
1235     traceExecution()
1236     callSlowPath(_llint_slow_path_push_with_scope)
1237     dispatch(3)
1238
1239
1240 _llint_op_pop_scope:
1241     traceExecution()
1242     callSlowPath(_llint_slow_path_pop_scope)
1243     dispatch(2)
1244
1245
1246 _llint_op_push_name_scope:
1247     traceExecution()
1248     callSlowPath(_llint_slow_path_push_name_scope)
1249     dispatch(6)
1250
1251
1252 _llint_op_throw:
1253     traceExecution()
1254     callSlowPath(_llint_slow_path_throw)
1255     dispatch(2)
1256
1257
1258 _llint_op_throw_static_error:
1259     traceExecution()
1260     callSlowPath(_llint_slow_path_throw_static_error)
1261     dispatch(3)
1262
1263
1264 _llint_op_profile_will_call:
1265     traceExecution()
1266     loadp CodeBlock[cfr], t0
1267     loadp CodeBlock::m_vm[t0], t0
1268     loadi VM::m_enabledProfiler[t0], t0
1269     btpz t0, .opProfilerWillCallDone
1270     callSlowPath(_llint_slow_path_profile_will_call)
1271 .opProfilerWillCallDone:
1272     dispatch(2)
1273
1274
1275 _llint_op_profile_did_call:
1276     traceExecution()
1277     loadp CodeBlock[cfr], t0
1278     loadp CodeBlock::m_vm[t0], t0
1279     loadi VM::m_enabledProfiler[t0], t0
1280     btpz t0, .opProfilerDidCallDone
1281     callSlowPath(_llint_slow_path_profile_did_call)
1282 .opProfilerDidCallDone:
1283     dispatch(2)
1284
1285
1286 _llint_op_debug:
1287     traceExecution()
1288     loadp CodeBlock[cfr], t0
1289     loadi CodeBlock::m_debuggerRequests[t0], t0
1290     btiz t0, .opDebugDone
1291     callSlowPath(_llint_slow_path_debug)
1292 .opDebugDone:                    
1293     dispatch(3)
1294
1295
1296 _llint_native_call_trampoline:
1297     nativeCallTrampoline(NativeExecutable::m_function)
1298
1299
1300 _llint_native_construct_trampoline:
1301     nativeCallTrampoline(NativeExecutable::m_constructor)
1302
1303 _llint_op_get_enumerable_length:
1304     traceExecution()
1305     callSlowPath(_slow_path_get_enumerable_length)
1306     dispatch(3)
1307
1308 _llint_op_has_indexed_property:
1309     traceExecution()
1310     callSlowPath(_slow_path_has_indexed_property)
1311     dispatch(5)
1312
1313 _llint_op_has_structure_property:
1314     traceExecution()
1315     callSlowPath(_slow_path_has_structure_property)
1316     dispatch(5)
1317
1318 _llint_op_has_generic_property:
1319     traceExecution()
1320     callSlowPath(_slow_path_has_generic_property)
1321     dispatch(4)
1322
1323 _llint_op_get_direct_pname:
1324     traceExecution()
1325     callSlowPath(_slow_path_get_direct_pname)
1326     dispatch(7)
1327
1328 _llint_op_get_structure_property_enumerator:
1329     traceExecution()
1330     callSlowPath(_slow_path_get_structure_property_enumerator)
1331     dispatch(4)
1332
1333 _llint_op_get_generic_property_enumerator:
1334     traceExecution()
1335     callSlowPath(_slow_path_get_generic_property_enumerator)
1336     dispatch(5)
1337
1338 _llint_op_next_enumerator_pname:
1339     traceExecution()
1340     callSlowPath(_slow_path_next_enumerator_pname)
1341     dispatch(4)
1342
1343 _llint_op_to_index_string:
1344     traceExecution()
1345     callSlowPath(_slow_path_to_index_string)
1346     dispatch(3)
1347
1348 _llint_op_profile_control_flow:
1349     traceExecution()
1350     loadpFromInstruction(1, t0)
1351     storeb 1, BasicBlockLocation::m_hasExecuted[t0]
1352     dispatch(2)
1353
1354 # Lastly, make sure that we can link even though we don't support all opcodes.
1355 # These opcodes should never arise when using LLInt or either JIT. We assert
1356 # as much.
1357
1358 macro notSupported()
1359     if ASSERT_ENABLED
1360         crash()
1361     else
1362         # We should use whatever the smallest possible instruction is, just to
1363         # ensure that there is a gap between instruction labels. If multiple
1364         # smallest instructions exist, we should pick the one that is most
1365         # likely result in execution being halted. Currently that is the break
1366         # instruction on all architectures we're interested in. (Break is int3
1367         # on Intel, which is 1 byte, and bkpt on ARMv7, which is 2 bytes.)
1368         break
1369     end
1370 end
1371
1372 _llint_op_init_global_const_nop:
1373     dispatch(5)