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