Get rid of method_check
[WebKit-https.git] / Source / JavaScriptCore / llint / LowLevelInterpreter.asm
1 # Copyright (C) 2011, 2012 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 const CallFrameHeaderSize = 48
35 const ArgumentCount = -48
36 const CallerFrame = -40
37 const Callee = -32
38 const ScopeChain = -24
39 const ReturnPC = -16
40 const CodeBlock = -8
41
42 const ThisArgumentOffset = -CallFrameHeaderSize - 8
43
44 # Some register conventions.
45 if JSVALUE64
46     # - Use a pair of registers to represent the PC: one register for the
47     #   base of the stack, and one register for the index.
48     # - The PC base (or PB for short) should be stored in the csr. It will
49     #   get clobbered on calls to other JS code, but will get saved on calls
50     #   to C functions.
51     # - C calls are still given the Instruction* rather than the PC index.
52     #   This requires an add before the call, and a sub after.
53     const PC = t4
54     const PB = t6
55     const tagTypeNumber = csr1
56     const tagMask = csr2
57     
58     macro loadisFromInstruction(offset, dest)
59         loadis offset * 8[PB, PC, 8], dest
60     end
61     
62     macro loadpFromInstruction(offset, dest)
63         loadp offset * 8[PB, PC, 8], dest
64     end
65     
66     macro storepToInstruction(value, offset)
67         storep value, offset * 8[PB, PC, 8]
68     end
69
70 else
71     const PC = t4
72     macro loadisFromInstruction(offset, dest)
73         loadis offset * 4[PC], dest
74     end
75     
76     macro loadpFromInstruction(offset, dest)
77         loadp offset * 4[PC], dest
78     end
79 end
80
81 # Constants for reasoning about value representation.
82 if BIG_ENDIAN
83     const TagOffset = 0
84     const PayloadOffset = 4
85 else
86     const TagOffset = 4
87     const PayloadOffset = 0
88 end
89
90 # Constant for reasoning about butterflies.
91 const IsArray = 1
92 const IndexingShapeMask = 30
93 const ContiguousShape = 26
94 const ArrayStorageShape = 28
95 const SlowPutArrayStorageShape = 30
96
97 # Type constants.
98 const StringType = 5
99 const ObjectType = 13
100
101 # Type flags constants.
102 const MasqueradesAsUndefined = 1
103 const ImplementsHasInstance = 2
104 const ImplementsDefaultHasInstance = 8
105
106 # Bytecode operand constants.
107 const FirstConstantRegisterIndex = 0x40000000
108
109 # Code type constants.
110 const GlobalCode = 0
111 const EvalCode = 1
112 const FunctionCode = 2
113
114 # The interpreter steals the tag word of the argument count.
115 const LLIntReturnPC = ArgumentCount + TagOffset
116
117 # String flags.
118 const HashFlags8BitBuffer = 64
119
120 # Copied from PropertyOffset.h
121 const firstOutOfLineOffset = 100
122
123 # From ResolveOperations.h
124 const ResolveOperationFail = 0
125 const ResolveOperationSetBaseToUndefined = 1
126 const ResolveOperationReturnScopeAsBase = 2
127 const ResolveOperationSetBaseToScope = 3
128 const ResolveOperationSetBaseToGlobal = 4
129 const ResolveOperationGetAndReturnScopedVar = 5
130 const ResolveOperationGetAndReturnGlobalVar = 6
131 const ResolveOperationGetAndReturnGlobalVarWatchable = 7
132 const ResolveOperationSkipTopScopeNode = 8
133 const ResolveOperationSkipScopes = 9
134 const ResolveOperationReturnGlobalObjectAsBase = 10
135 const ResolveOperationGetAndReturnGlobalProperty = 11
136 const ResolveOperationCheckForDynamicEntriesBeforeGlobalScope = 12
137
138 const PutToBaseOperationKindUninitialised = 0
139 const PutToBaseOperationKindGeneric = 1
140 const PutToBaseOperationKindReadonly = 2
141 const PutToBaseOperationKindGlobalVariablePut = 3
142 const PutToBaseOperationKindGlobalVariablePutChecked = 4
143 const PutToBaseOperationKindGlobalPropertyPut = 5
144 const PutToBaseOperationKindVariablePut = 6
145
146 # Allocation constants
147 if JSVALUE64
148     const JSFinalObjectSizeClassIndex = 1
149 else
150     const JSFinalObjectSizeClassIndex = 3
151 end
152
153 # This must match wtf/Vector.h
154 const VectorSizeOffset = 0
155 if JSVALUE64
156     const VectorBufferOffset = 8
157 else
158     const VectorBufferOffset = 4
159 end
160
161
162 # Some common utilities.
163 macro crash()
164     if C_LOOP
165         cloopCrash
166     else
167         storei t0, 0xbbadbeef[]
168         move 0, t0
169         call t0
170     end
171 end
172
173 macro assert(assertion)
174     if ASSERT_ENABLED
175         assertion(.ok)
176         crash()
177     .ok:
178     end
179 end
180
181 macro preserveReturnAddressAfterCall(destinationRegister)
182     if C_LOOP
183         # In our case, we're only preserving the bytecode vPC. 
184         move lr, destinationRegister
185     elsif ARMv7
186         move lr, destinationRegister
187     elsif X86 or X86_64
188         pop destinationRegister
189     else
190         error
191     end
192 end
193
194 macro restoreReturnAddressBeforeReturn(sourceRegister)
195     if C_LOOP
196         # In our case, we're only restoring the bytecode vPC. 
197         move sourceRegister, lr
198     elsif ARMv7
199         move sourceRegister, lr
200     elsif X86 or X86_64
201         push sourceRegister
202     else
203         error
204     end
205 end
206
207 macro traceExecution()
208     if EXECUTION_TRACING
209         callSlowPath(_llint_trace)
210     end
211 end
212
213 macro callTargetFunction(callLinkInfo)
214     if C_LOOP
215         cloopCallJSFunction LLIntCallLinkInfo::machineCodeTarget[callLinkInfo]
216     else
217         call LLIntCallLinkInfo::machineCodeTarget[callLinkInfo]
218         dispatchAfterCall()
219     end
220 end
221
222 macro slowPathForCall(advance, slowPath)
223     callCallSlowPath(
224         advance,
225         slowPath,
226         macro (callee)
227             if C_LOOP
228                 cloopCallJSFunction callee
229             else
230                 call callee
231                 dispatchAfterCall()
232             end
233         end)
234 end
235
236 macro arrayProfile(structureAndIndexingType, profile, scratch)
237     const structure = structureAndIndexingType
238     const indexingType = structureAndIndexingType
239     if VALUE_PROFILER
240         storep structure, ArrayProfile::m_lastSeenStructure[profile]
241     end
242     loadb Structure::m_indexingType[structure], indexingType
243 end
244
245 macro checkSwitchToJIT(increment, action)
246     if JIT_ENABLED
247         loadp CodeBlock[cfr], t0
248         baddis increment, CodeBlock::m_llintExecuteCounter + ExecutionCounter::m_counter[t0], .continue
249         action()
250     .continue:
251     end
252 end
253
254 macro checkSwitchToJITForEpilogue()
255     checkSwitchToJIT(
256         10,
257         macro ()
258             callSlowPath(_llint_replace)
259         end)
260 end
261
262 macro assertNotConstant(index)
263     assert(macro (ok) bilt index, FirstConstantRegisterIndex, ok end)
264 end
265
266 macro functionForCallCodeBlockGetter(targetRegister)
267     loadp Callee[cfr], targetRegister
268     loadp JSFunction::m_executable[targetRegister], targetRegister
269     loadp FunctionExecutable::m_codeBlockForCall[targetRegister], targetRegister
270 end
271
272 macro functionForConstructCodeBlockGetter(targetRegister)
273     loadp Callee[cfr], targetRegister
274     loadp JSFunction::m_executable[targetRegister], targetRegister
275     loadp FunctionExecutable::m_codeBlockForConstruct[targetRegister], targetRegister
276 end
277
278 macro notFunctionCodeBlockGetter(targetRegister)
279     loadp CodeBlock[cfr], targetRegister
280 end
281
282 macro functionCodeBlockSetter(sourceRegister)
283     storep sourceRegister, CodeBlock[cfr]
284 end
285
286 macro notFunctionCodeBlockSetter(sourceRegister)
287     # Nothing to do!
288 end
289
290 # Do the bare minimum required to execute code. Sets up the PC, leave the CodeBlock*
291 # in t1. May also trigger prologue entry OSR.
292 macro prologue(codeBlockGetter, codeBlockSetter, osrSlowPath, traceSlowPath)
293     preserveReturnAddressAfterCall(t2)
294     
295     # Set up the call frame and check if we should OSR.
296     storep t2, ReturnPC[cfr]
297     if EXECUTION_TRACING
298         callSlowPath(traceSlowPath)
299     end
300     codeBlockGetter(t1)
301     if JIT_ENABLED
302         baddis 5, CodeBlock::m_llintExecuteCounter + ExecutionCounter::m_counter[t1], .continue
303         cCall2(osrSlowPath, cfr, PC)
304         move t1, cfr
305         btpz t0, .recover
306         loadp ReturnPC[cfr], t2
307         restoreReturnAddressBeforeReturn(t2)
308         jmp t0
309     .recover:
310         codeBlockGetter(t1)
311     .continue:
312     end
313     codeBlockSetter(t1)
314     
315     # Set up the PC.
316     if JSVALUE64
317         loadp CodeBlock::m_instructions[t1], PB
318         move 0, PC
319     else
320         loadp CodeBlock::m_instructions[t1], PC
321     end
322 end
323
324 # Expects that CodeBlock is in t1, which is what prologue() leaves behind.
325 # Must call dispatch(0) after calling this.
326 macro functionInitialization(profileArgSkip)
327     if VALUE_PROFILER
328         # Profile the arguments. Unfortunately, we have no choice but to do this. This
329         # code is pretty horrendous because of the difference in ordering between
330         # arguments and value profiles, the desire to have a simple loop-down-to-zero
331         # loop, and the desire to use only three registers so as to preserve the PC and
332         # the code block. It is likely that this code should be rewritten in a more
333         # optimal way for architectures that have more than five registers available
334         # for arbitrary use in the interpreter.
335         loadi CodeBlock::m_numParameters[t1], t0
336         addp -profileArgSkip, t0 # Use addi because that's what has the peephole
337         assert(macro (ok) bpgteq t0, 0, ok end)
338         btpz t0, .argumentProfileDone
339         loadp CodeBlock::m_argumentValueProfiles + VectorBufferOffset[t1], t3
340         mulp sizeof ValueProfile, t0, t2 # Aaaaahhhh! Need strength reduction!
341         negp t0
342         lshiftp 3, t0
343         addp t2, t3
344     .argumentProfileLoop:
345         if JSVALUE64
346             loadq ThisArgumentOffset + 8 - profileArgSkip * 8[cfr, t0], t2
347             subp sizeof ValueProfile, t3
348             storeq t2, profileArgSkip * sizeof ValueProfile + ValueProfile::m_buckets[t3]
349         else
350             loadi ThisArgumentOffset + TagOffset + 8 - profileArgSkip * 8[cfr, t0], t2
351             subp sizeof ValueProfile, t3
352             storei t2, profileArgSkip * sizeof ValueProfile + ValueProfile::m_buckets + TagOffset[t3]
353             loadi ThisArgumentOffset + PayloadOffset + 8 - profileArgSkip * 8[cfr, t0], t2
354             storei t2, profileArgSkip * sizeof ValueProfile + ValueProfile::m_buckets + PayloadOffset[t3]
355         end
356         baddpnz 8, t0, .argumentProfileLoop
357     .argumentProfileDone:
358     end
359         
360     # Check stack height.
361     loadi CodeBlock::m_numCalleeRegisters[t1], t0
362     loadp CodeBlock::m_globalData[t1], t2
363     loadp JSGlobalData::interpreter[t2], t2   # FIXME: Can get to the JSStack from the JITStackFrame
364     lshifti 3, t0
365     addp t0, cfr, t0
366     bpaeq Interpreter::m_stack + JSStack::m_end[t2], t0, .stackHeightOK
367
368     # Stack height check failed - need to call a slow_path.
369     callSlowPath(_llint_stack_check)
370 .stackHeightOK:
371 end
372
373 macro allocateBasicJSObject(sizeClassIndex, structure, result, scratch1, scratch2, slowCase)
374     if ALWAYS_ALLOCATE_SLOW
375         jmp slowCase
376     else
377         const offsetOfMySizeClass =
378             JSGlobalData::heap +
379             Heap::m_objectSpace +
380             MarkedSpace::m_normalSpace +
381             MarkedSpace::Subspace::preciseAllocators +
382             sizeClassIndex * sizeof MarkedAllocator
383         
384         const offsetOfFirstFreeCell = 
385             MarkedAllocator::m_freeList + 
386             MarkedBlock::FreeList::head
387
388         # FIXME: we can get the global data in one load from the stack.
389         loadp CodeBlock[cfr], scratch1
390         loadp CodeBlock::m_globalData[scratch1], scratch1
391         
392         # Get the object from the free list.   
393         loadp offsetOfMySizeClass + offsetOfFirstFreeCell[scratch1], result
394         btpz result, slowCase
395         
396         # Remove the object from the free list.
397         loadp [result], scratch2
398         storep scratch2, offsetOfMySizeClass + offsetOfFirstFreeCell[scratch1]
399     
400         # Initialize the object.
401         storep structure, JSCell::m_structure[result]
402         storep 0, JSObject::m_butterfly[result]
403     end
404 end
405
406 macro doReturn()
407     loadp ReturnPC[cfr], t2
408     loadp CallerFrame[cfr], cfr
409     restoreReturnAddressBeforeReturn(t2)
410     ret
411 end
412
413
414 # Indicate the beginning of LLInt.
415 _llint_begin:
416     crash()
417
418
419 _llint_program_prologue:
420     prologue(notFunctionCodeBlockGetter, notFunctionCodeBlockSetter, _llint_entry_osr, _llint_trace_prologue)
421     dispatch(0)
422
423
424 _llint_eval_prologue:
425     prologue(notFunctionCodeBlockGetter, notFunctionCodeBlockSetter, _llint_entry_osr, _llint_trace_prologue)
426     dispatch(0)
427
428
429 _llint_function_for_call_prologue:
430     prologue(functionForCallCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_call, _llint_trace_prologue_function_for_call)
431 .functionForCallBegin:
432     functionInitialization(0)
433     dispatch(0)
434     
435
436 _llint_function_for_construct_prologue:
437     prologue(functionForConstructCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_construct, _llint_trace_prologue_function_for_construct)
438 .functionForConstructBegin:
439     functionInitialization(1)
440     dispatch(0)
441     
442
443 _llint_function_for_call_arity_check:
444     prologue(functionForCallCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_call_arityCheck, _llint_trace_arityCheck_for_call)
445     functionArityCheck(.functionForCallBegin, _llint_slow_path_call_arityCheck)
446
447
448 _llint_function_for_construct_arity_check:
449     prologue(functionForConstructCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_construct_arityCheck, _llint_trace_arityCheck_for_construct)
450     functionArityCheck(.functionForConstructBegin, _llint_slow_path_construct_arityCheck)
451
452
453 # Value-representation-specific code.
454 if JSVALUE64
455     include LowLevelInterpreter64
456 else
457     include LowLevelInterpreter32_64
458 end
459
460
461 # Value-representation-agnostic code.
462 _llint_op_new_array:
463     traceExecution()
464     callSlowPath(_llint_slow_path_new_array)
465     dispatch(4)
466
467
468 _llint_op_new_array_with_size:
469     traceExecution()
470     callSlowPath(_llint_slow_path_new_array_with_size)
471     dispatch(3)
472
473
474 _llint_op_new_array_buffer:
475     traceExecution()
476     callSlowPath(_llint_slow_path_new_array_buffer)
477     dispatch(4)
478
479
480 _llint_op_new_regexp:
481     traceExecution()
482     callSlowPath(_llint_slow_path_new_regexp)
483     dispatch(3)
484
485
486 _llint_op_less:
487     traceExecution()
488     callSlowPath(_llint_slow_path_less)
489     dispatch(4)
490
491
492 _llint_op_lesseq:
493     traceExecution()
494     callSlowPath(_llint_slow_path_lesseq)
495     dispatch(4)
496
497
498 _llint_op_greater:
499     traceExecution()
500     callSlowPath(_llint_slow_path_greater)
501     dispatch(4)
502
503
504 _llint_op_greatereq:
505     traceExecution()
506     callSlowPath(_llint_slow_path_greatereq)
507     dispatch(4)
508
509
510 _llint_op_mod:
511     traceExecution()
512     callSlowPath(_llint_slow_path_mod)
513     dispatch(4)
514
515
516 _llint_op_typeof:
517     traceExecution()
518     callSlowPath(_llint_slow_path_typeof)
519     dispatch(3)
520
521
522 _llint_op_is_object:
523     traceExecution()
524     callSlowPath(_llint_slow_path_is_object)
525     dispatch(3)
526
527
528 _llint_op_is_function:
529     traceExecution()
530     callSlowPath(_llint_slow_path_is_function)
531     dispatch(3)
532
533
534 _llint_op_in:
535     traceExecution()
536     callSlowPath(_llint_slow_path_in)
537     dispatch(4)
538
539 macro getPutToBaseOperationField(scratch, scratch1, fieldOffset, fieldGetter)
540     loadisFromInstruction(4, scratch)
541     mulp sizeof PutToBaseOperation, scratch, scratch
542     loadp CodeBlock[cfr], scratch1
543     loadp VectorBufferOffset + CodeBlock::m_putToBaseOperations[scratch1], scratch1
544     fieldGetter(fieldOffset[scratch1, scratch, 1])
545 end
546
547 macro moveJSValueFromRegisterWithoutProfiling(value, destBuffer, destOffsetReg)
548     storeq value, [destBuffer, destOffsetReg, 8]
549 end
550
551
552 macro moveJSValueFromRegistersWithoutProfiling(tag, payload, destBuffer, destOffsetReg)
553     storei tag, TagOffset[destBuffer, destOffsetReg, 8]
554     storei payload, PayloadOffset[destBuffer, destOffsetReg, 8]
555 end
556
557 macro putToBaseVariableBody(variableOffset, scratch1, scratch2, scratch3)
558     loadisFromInstruction(1, scratch1)
559     loadp PayloadOffset[cfr, scratch1, 8], scratch1
560     loadp JSVariableObject::m_registers[scratch1], scratch1
561     loadisFromInstruction(3, scratch2)
562     if JSVALUE64
563         loadConstantOrVariable(scratch2, scratch3)
564         moveJSValueFromRegisterWithoutProfiling(scratch3, scratch1, variableOffset)
565     else
566         loadConstantOrVariable2Reg(scratch2, scratch3, scratch2) # scratch3=tag, scratch2=payload
567         moveJSValueFromRegistersWithoutProfiling(scratch3, scratch2, scratch1, variableOffset)
568     end
569 end
570
571 _llint_op_put_to_base_variable:
572     traceExecution()
573     getPutToBaseOperationField(t0, t1, PutToBaseOperation::m_offset, macro(addr)
574                                               loadis  addr, t0
575                                           end)
576     putToBaseVariableBody(t0, t1, t2, t3)
577     dispatch(5)
578
579 _llint_op_put_to_base:
580     traceExecution()
581     getPutToBaseOperationField(t0, t1, 0, macro(addr)
582                                               leap addr, t0
583                                               bbneq PutToBaseOperation::m_kindAsUint8[t0], PutToBaseOperationKindVariablePut, .notPutToBaseVariable
584                                               loadis PutToBaseOperation::m_offset[t0], t0
585                                               putToBaseVariableBody(t0, t1, t2, t3)
586                                               dispatch(5)
587                                               .notPutToBaseVariable:
588                                           end)
589     callSlowPath(_llint_slow_path_put_to_base)
590     dispatch(5)
591
592 macro getResolveOperation(resolveOperationIndex, dest, scratch)
593     loadisFromInstruction(resolveOperationIndex, dest)
594     mulp sizeof ResolveOperations, dest, dest
595     loadp CodeBlock[cfr], scratch
596     loadp VectorBufferOffset + CodeBlock::m_resolveOperations[scratch], scratch
597     loadp VectorBufferOffset[scratch, dest, 1], dest
598 end
599
600 macro getScope(loadInitialScope, scopeCount, dest, scratch)
601     loadInitialScope(dest)
602     loadi scopeCount, scratch
603
604     btiz scratch, .done
605 .loop:
606     loadp JSScope::m_next[dest], dest
607     subi 1, scratch
608     btinz scratch, .loop
609
610 .done:
611 end
612
613 macro moveJSValue(sourceBuffer, sourceOffsetReg, destBuffer, destOffsetReg, profileOffset, scratchRegister)
614     if JSVALUE64
615         loadq [sourceBuffer, sourceOffsetReg, 8], scratchRegister
616         storeq scratchRegister, [destBuffer, destOffsetReg, 8]
617         loadpFromInstruction(profileOffset, destOffsetReg)
618         valueProfile(scratchRegister, destOffsetReg)
619     else
620         loadi PayloadOffset[sourceBuffer, sourceOffsetReg, 8], scratchRegister
621         storei scratchRegister, PayloadOffset[destBuffer, destOffsetReg, 8]
622         loadi TagOffset[sourceBuffer, sourceOffsetReg, 8], sourceOffsetReg
623         storei sourceOffsetReg, TagOffset[destBuffer, destOffsetReg, 8]
624         loadpFromInstruction(profileOffset, destOffsetReg)
625         valueProfile(sourceOffsetReg, scratchRegister, destOffsetReg)
626     end
627 end
628
629 macro moveJSValueFromSlot(slot, destBuffer, destOffsetReg, profileOffset, scratchRegister)
630     if JSVALUE64
631         loadq [slot], scratchRegister
632         storeq scratchRegister, [destBuffer, destOffsetReg, 8]
633         loadpFromInstruction(profileOffset, destOffsetReg)
634         valueProfile(scratchRegister, destOffsetReg)
635     else
636         loadi PayloadOffset[slot], scratchRegister
637         storei scratchRegister, PayloadOffset[destBuffer, destOffsetReg, 8]
638         loadi TagOffset[slot], slot
639         storei slot, TagOffset[destBuffer, destOffsetReg, 8]
640         loadpFromInstruction(profileOffset, destOffsetReg)
641         valueProfile(slot, scratchRegister, destOffsetReg)
642     end
643 end
644
645 macro moveJSValueFromRegister(value, destBuffer, destOffsetReg, profileOffset)
646     storeq value, [destBuffer, destOffsetReg, 8]
647     loadpFromInstruction(profileOffset, destOffsetReg)
648     valueProfile(value, destOffsetReg)
649 end
650
651 macro moveJSValueFromRegisters(tag, payload, destBuffer, destOffsetReg, profileOffset)
652     storei tag, TagOffset[destBuffer, destOffsetReg, 8]
653     storei payload, PayloadOffset[destBuffer, destOffsetReg, 8]
654     loadpFromInstruction(profileOffset, destOffsetReg)
655     valueProfile(tag, payload, destOffsetReg)
656 end
657
658 _llint_op_resolve_global_property:
659     traceExecution()
660     getResolveOperation(3, t0, t1)
661     loadp CodeBlock[cfr], t1
662     loadp CodeBlock::m_globalObject[t1], t1
663     loadp ResolveOperation::m_structure[t0], t2
664     bpneq JSCell::m_structure[t1], t2, .llint_op_resolve_local
665     loadis ResolveOperation::m_offset[t0], t0
666     if JSVALUE64
667         loadPropertyAtVariableOffsetKnownNotInline(t0, t1, t2)
668         loadisFromInstruction(1, t0)
669         moveJSValueFromRegister(t2, cfr, t0, 4)
670     else
671         loadPropertyAtVariableOffsetKnownNotInline(t0, t1, t2, t3)
672         loadisFromInstruction(1, t0)
673         moveJSValueFromRegisters(t2, t3, cfr, t0, 4)
674     end
675     dispatch(5)
676
677 _llint_op_resolve_global_var:
678     traceExecution()
679     getResolveOperation(3, t0, t1)
680     loadp ResolveOperation::m_registerAddress[t0], t0
681     loadisFromInstruction(1, t1)
682     moveJSValueFromSlot(t0, cfr, t1, 4, t3)
683     dispatch(5)
684
685 macro resolveScopedVarBody(resolveOperations)
686     # First ResolveOperation is to skip scope chain nodes
687     getScope(macro(dest)
688                  loadp ScopeChain + PayloadOffset[cfr], dest
689              end,
690              ResolveOperation::m_scopesToSkip[resolveOperations], t1, t2)
691     loadp JSVariableObject::m_registers[t1], t1 # t1 now contains the activation registers
692     
693     # Second ResolveOperation tells us what offset to use
694     loadis ResolveOperation::m_offset + sizeof ResolveOperation[resolveOperations], t2
695     loadisFromInstruction(1, t3)
696     moveJSValue(t1, t2, cfr, t3, 4, t0)
697 end
698
699 _llint_op_resolve_scoped_var:
700     traceExecution()
701     getResolveOperation(3, t0, t1)
702     resolveScopedVarBody(t0)
703     dispatch(5)
704     
705 _llint_op_resolve_scoped_var_on_top_scope:
706     traceExecution()
707     getResolveOperation(3, t0, t1)
708
709     # Load destination index
710     loadisFromInstruction(1, t3)
711
712     # We know we want the top scope chain entry
713     loadp ScopeChain + PayloadOffset[cfr], t1
714     loadp JSVariableObject::m_registers[t1], t1 # t1 now contains the activation registers
715     
716     # Second ResolveOperation tells us what offset to use
717     loadis ResolveOperation::m_offset + sizeof ResolveOperation[t0], t2
718
719     moveJSValue(t1, t2, cfr, t3, 4, t0)
720     dispatch(5)
721
722 _llint_op_resolve_scoped_var_with_top_scope_check:
723     traceExecution()
724     getResolveOperation(3, t0, t1)
725     # First ResolveOperation tells us what register to check
726     loadis ResolveOperation::m_activationRegister[t0], t1
727
728     loadp PayloadOffset[cfr, t1, 8], t1
729
730     getScope(macro(dest)
731                  btpz t1, .scopeChainNotCreated
732                      loadp JSScope::m_next[t1], dest
733                  jmp .done
734                  .scopeChainNotCreated:
735                      loadp ScopeChain + PayloadOffset[cfr], dest
736                  .done:
737              end, 
738              # Second ResolveOperation tells us how many more nodes to skip
739              ResolveOperation::m_scopesToSkip + sizeof ResolveOperation[t0], t1, t2)
740     loadp JSVariableObject::m_registers[t1], t1 # t1 now contains the activation registers
741     
742     # Third operation tells us what offset to use
743     loadis ResolveOperation::m_offset + 2 * sizeof ResolveOperation[t0], t2
744     loadisFromInstruction(1, t3)
745     moveJSValue(t1, t2, cfr, t3, 4, t0)
746     dispatch(5)
747
748 _llint_op_resolve:
749 .llint_op_resolve_local:
750     traceExecution()
751     getResolveOperation(3, t0, t1)
752     btpz t0, .noInstructions
753     loadis ResolveOperation::m_operation[t0], t1
754     bineq t1, ResolveOperationSkipScopes, .notSkipScopes
755         resolveScopedVarBody(t0)
756         dispatch(5)
757 .notSkipScopes:
758     bineq t1, ResolveOperationGetAndReturnGlobalVar, .notGetAndReturnGlobalVar
759         loadp ResolveOperation::m_registerAddress[t0], t0
760         loadisFromInstruction(1, t1)
761         moveJSValueFromSlot(t0, cfr, t1, 4, t3)
762         dispatch(5)
763 .notGetAndReturnGlobalVar:
764
765 .noInstructions:
766     callSlowPath(_llint_slow_path_resolve)
767     dispatch(5)
768
769 _llint_op_resolve_base_to_global:
770     traceExecution()
771     loadp CodeBlock[cfr], t1
772     loadp CodeBlock::m_globalObject[t1], t1
773     loadisFromInstruction(1, t3)
774     if JSVALUE64
775         moveJSValueFromRegister(t1, cfr, t3, 6)
776     else
777         move CellTag, t2
778         moveJSValueFromRegisters(t2, t1, cfr, t3, 6)
779     end
780     dispatch(7)
781
782 _llint_op_resolve_base_to_global_dynamic:
783     jmp _llint_op_resolve_base
784
785 _llint_op_resolve_base_to_scope:
786     traceExecution()
787     getResolveOperation(4, t0, t1)
788     # First ResolveOperation is to skip scope chain nodes
789     getScope(macro(dest)
790                  loadp ScopeChain + PayloadOffset[cfr], dest
791              end,
792              ResolveOperation::m_scopesToSkip[t0], t1, t2)
793     loadisFromInstruction(1, t3)
794     if JSVALUE64
795         moveJSValueFromRegister(t1, cfr, t3, 6)
796     else
797         move CellTag, t2
798         moveJSValueFromRegisters(t2, t1, cfr, t3, 6)
799     end
800     dispatch(7)
801
802 _llint_op_resolve_base_to_scope_with_top_scope_check:
803     traceExecution()
804     getResolveOperation(4, t0, t1)
805     # First ResolveOperation tells us what register to check
806     loadis ResolveOperation::m_activationRegister[t0], t1
807
808     loadp PayloadOffset[cfr, t1, 8], t1
809
810     getScope(macro(dest)
811                  btpz t1, .scopeChainNotCreated
812                      loadp JSScope::m_next[t1], dest
813                  jmp .done
814                  .scopeChainNotCreated:
815                      loadp ScopeChain + PayloadOffset[cfr], dest
816                  .done:
817              end, 
818              # Second ResolveOperation tells us how many more nodes to skip
819              ResolveOperation::m_scopesToSkip + sizeof ResolveOperation[t0], t1, t2)
820
821     loadisFromInstruction(1, t3)
822     if JSVALUE64
823         moveJSValueFromRegister(t1, cfr, t3, 6)
824     else
825         move CellTag, t2
826         moveJSValueFromRegisters(t2, t1, cfr, t3, 6)
827     end
828     dispatch(7)
829
830 _llint_op_resolve_base:
831     traceExecution()
832     callSlowPath(_llint_slow_path_resolve_base)
833     dispatch(7)
834
835 _llint_op_ensure_property_exists:
836     traceExecution()
837     callSlowPath(_llint_slow_path_ensure_property_exists)
838     dispatch(3)
839
840 macro interpretResolveWithBase(opcodeLength, slowPath)
841     traceExecution()
842     getResolveOperation(4, t0, t1)
843     btpz t0, .slowPath
844
845     loadp ScopeChain[cfr], t3
846     # Get the base
847     loadis ResolveOperation::m_operation[t0], t2
848
849     bineq t2, ResolveOperationSkipScopes, .notSkipScopes
850         getScope(macro(dest) move t3, dest end,
851                  ResolveOperation::m_scopesToSkip[t0], t1, t2)
852         move t1, t3
853         addp sizeof ResolveOperation, t0, t0
854         jmp .haveCorrectScope
855
856     .notSkipScopes:
857
858     bineq t2, ResolveOperationSkipTopScopeNode, .notSkipTopScopeNode
859         loadis ResolveOperation::m_activationRegister[t0], t1
860         loadp PayloadOffset[cfr, t1, 8], t1
861
862         getScope(macro(dest)
863                      btpz t1, .scopeChainNotCreated
864                          loadp JSScope::m_next[t1], dest
865                      jmp .done
866                      .scopeChainNotCreated:
867                          loadp ScopeChain + PayloadOffset[cfr], dest
868                      .done:
869                  end,
870                  sizeof ResolveOperation + ResolveOperation::m_scopesToSkip[t0], t1, t2)
871         move t1, t3
872         # We've handled two opcodes here
873         addp 2 * sizeof ResolveOperation, t0, t0
874
875     .notSkipTopScopeNode:
876
877     .haveCorrectScope:
878
879     # t3 now contains the correct Scope
880     # t0 contains a pointer to the current ResolveOperation
881
882     loadis ResolveOperation::m_operation[t0], t2
883     # t2 contains the next instruction
884
885     loadisFromInstruction(1, t1)
886     # t1 now contains the index for the base register
887
888     bineq t2, ResolveOperationSetBaseToScope, .notSetBaseToScope
889         if JSVALUE64
890             storeq t3, [cfr, t1, 8]
891         else
892             storei t3, PayloadOffset[cfr, t1, 8]
893             storei CellTag, TagOffset[cfr, t1, 8]
894         end
895         jmp .haveSetBase
896
897     .notSetBaseToScope:
898
899     bineq t2, ResolveOperationSetBaseToUndefined, .notSetBaseToUndefined
900         if JSVALUE64
901             storeq ValueUndefined, [cfr, t1, 8]
902         else
903             storei 0, PayloadOffset[cfr, t1, 8]
904             storei UndefinedTag, TagOffset[cfr, t1, 8]
905         end
906         jmp .haveSetBase
907
908     .notSetBaseToUndefined:
909     bineq t2, ResolveOperationSetBaseToGlobal, .slowPath
910         loadp JSCell::m_structure[t3], t2
911         loadp Structure::m_globalObject[t2], t2
912         if JSVALUE64
913             storeq t2, [cfr, t1, 8]
914         else
915             storei t2, PayloadOffset[cfr, t1, 8]
916             storei CellTag, TagOffset[cfr, t1, 8]
917         end
918
919     .haveSetBase:
920
921     # Get the value
922
923     # Load the operation into t2
924     loadis ResolveOperation::m_operation + sizeof ResolveOperation[t0], t2
925
926     # Load the index for the value register into t1
927     loadisFromInstruction(2, t1)
928
929     bineq t2, ResolveOperationGetAndReturnScopedVar, .notGetAndReturnScopedVar
930         loadp JSVariableObject::m_registers[t3], t3 # t3 now contains the activation registers
931
932         # Second ResolveOperation tells us what offset to use
933         loadis ResolveOperation::m_offset + sizeof ResolveOperation[t0], t2
934         moveJSValue(t3, t2, cfr, t1, opcodeLength - 1, t0)
935         dispatch(opcodeLength)
936
937     .notGetAndReturnScopedVar:
938     bineq t2, ResolveOperationGetAndReturnGlobalProperty, .slowPath
939         callSlowPath(slowPath)
940         dispatch(opcodeLength)
941
942 .slowPath:
943     callSlowPath(slowPath)
944     dispatch(opcodeLength)
945 end
946
947 _llint_op_resolve_with_base:
948     interpretResolveWithBase(7, _llint_slow_path_resolve_with_base)
949
950
951 _llint_op_resolve_with_this:
952     interpretResolveWithBase(6, _llint_slow_path_resolve_with_this)
953
954
955 macro withInlineStorage(object, propertyStorage, continuation)
956     # Indicate that the object is the property storage, and that the
957     # property storage register is unused.
958     continuation(object, propertyStorage)
959 end
960
961 macro withOutOfLineStorage(object, propertyStorage, continuation)
962     loadp JSObject::m_butterfly[object], propertyStorage
963     # Indicate that the propertyStorage register now points to the
964     # property storage, and that the object register may be reused
965     # if the object pointer is not needed anymore.
966     continuation(propertyStorage, object)
967 end
968
969
970 _llint_op_del_by_id:
971     traceExecution()
972     callSlowPath(_llint_slow_path_del_by_id)
973     dispatch(4)
974
975
976 _llint_op_del_by_val:
977     traceExecution()
978     callSlowPath(_llint_slow_path_del_by_val)
979     dispatch(4)
980
981
982 _llint_op_put_by_index:
983     traceExecution()
984     callSlowPath(_llint_slow_path_put_by_index)
985     dispatch(4)
986
987
988 _llint_op_put_getter_setter:
989     traceExecution()
990     callSlowPath(_llint_slow_path_put_getter_setter)
991     dispatch(5)
992
993
994 _llint_op_jmp_scopes:
995     traceExecution()
996     callSlowPath(_llint_slow_path_jmp_scopes)
997     dispatch(0)
998
999
1000 _llint_op_loop_if_true:
1001     traceExecution()
1002     jumpTrueOrFalse(
1003         macro (value, target) btinz value, target end,
1004         _llint_slow_path_jtrue)
1005
1006
1007 _llint_op_jtrue:
1008     traceExecution()
1009     jumpTrueOrFalse(
1010         macro (value, target) btinz value, target end,
1011         _llint_slow_path_jtrue)
1012
1013
1014 _llint_op_loop_if_false:
1015     traceExecution()
1016     jumpTrueOrFalse(
1017         macro (value, target) btiz value, target end,
1018         _llint_slow_path_jfalse)
1019
1020
1021 _llint_op_jfalse:
1022     traceExecution()
1023     jumpTrueOrFalse(
1024         macro (value, target) btiz value, target end,
1025         _llint_slow_path_jfalse)
1026
1027
1028 _llint_op_loop_if_less:
1029     traceExecution()
1030     compare(
1031         macro (left, right, target) bilt left, right, target end,
1032         macro (left, right, target) bdlt left, right, target end,
1033         _llint_slow_path_jless)
1034
1035
1036 _llint_op_jless:
1037     traceExecution()
1038     compare(
1039         macro (left, right, target) bilt left, right, target end,
1040         macro (left, right, target) bdlt left, right, target end,
1041         _llint_slow_path_jless)
1042
1043
1044 _llint_op_jnless:
1045     traceExecution()
1046     compare(
1047         macro (left, right, target) bigteq left, right, target end,
1048         macro (left, right, target) bdgtequn left, right, target end,
1049         _llint_slow_path_jnless)
1050
1051
1052 _llint_op_loop_if_greater:
1053     traceExecution()
1054     compare(
1055         macro (left, right, target) bigt left, right, target end,
1056         macro (left, right, target) bdgt left, right, target end,
1057         _llint_slow_path_jgreater)
1058
1059
1060 _llint_op_jgreater:
1061     traceExecution()
1062     compare(
1063         macro (left, right, target) bigt left, right, target end,
1064         macro (left, right, target) bdgt left, right, target end,
1065         _llint_slow_path_jgreater)
1066
1067
1068 _llint_op_jngreater:
1069     traceExecution()
1070     compare(
1071         macro (left, right, target) bilteq left, right, target end,
1072         macro (left, right, target) bdltequn left, right, target end,
1073         _llint_slow_path_jngreater)
1074
1075
1076 _llint_op_loop_if_lesseq:
1077     traceExecution()
1078     compare(
1079         macro (left, right, target) bilteq left, right, target end,
1080         macro (left, right, target) bdlteq left, right, target end,
1081         _llint_slow_path_jlesseq)
1082
1083
1084 _llint_op_jlesseq:
1085     traceExecution()
1086     compare(
1087         macro (left, right, target) bilteq left, right, target end,
1088         macro (left, right, target) bdlteq left, right, target end,
1089         _llint_slow_path_jlesseq)
1090
1091
1092 _llint_op_jnlesseq:
1093     traceExecution()
1094     compare(
1095         macro (left, right, target) bigt left, right, target end,
1096         macro (left, right, target) bdgtun left, right, target end,
1097         _llint_slow_path_jnlesseq)
1098
1099
1100 _llint_op_loop_if_greatereq:
1101     traceExecution()
1102     compare(
1103         macro (left, right, target) bigteq left, right, target end,
1104         macro (left, right, target) bdgteq left, right, target end,
1105         _llint_slow_path_jgreatereq)
1106
1107
1108 _llint_op_jgreatereq:
1109     traceExecution()
1110     compare(
1111         macro (left, right, target) bigteq left, right, target end,
1112         macro (left, right, target) bdgteq left, right, target end,
1113         _llint_slow_path_jgreatereq)
1114
1115
1116 _llint_op_jngreatereq:
1117     traceExecution()
1118     compare(
1119         macro (left, right, target) bilt left, right, target end,
1120         macro (left, right, target) bdltun left, right, target end,
1121         _llint_slow_path_jngreatereq)
1122
1123
1124 _llint_op_loop_hint:
1125     traceExecution()
1126     checkSwitchToJITForLoop()
1127     dispatch(1)
1128
1129
1130 _llint_op_switch_string:
1131     traceExecution()
1132     callSlowPath(_llint_slow_path_switch_string)
1133     dispatch(0)
1134
1135
1136 _llint_op_new_func_exp:
1137     traceExecution()
1138     callSlowPath(_llint_slow_path_new_func_exp)
1139     dispatch(3)
1140
1141
1142 _llint_op_call:
1143     traceExecution()
1144     arrayProfileForCall()
1145     doCall(_llint_slow_path_call)
1146
1147
1148 _llint_op_construct:
1149     traceExecution()
1150     doCall(_llint_slow_path_construct)
1151
1152
1153 _llint_op_call_varargs:
1154     traceExecution()
1155     slowPathForCall(6, _llint_slow_path_call_varargs)
1156
1157
1158 _llint_op_call_eval:
1159     traceExecution()
1160     
1161     # Eval is executed in one of two modes:
1162     #
1163     # 1) We find that we're really invoking eval() in which case the
1164     #    execution is perfomed entirely inside the slow_path, and it
1165     #    returns the PC of a function that just returns the return value
1166     #    that the eval returned.
1167     #
1168     # 2) We find that we're invoking something called eval() that is not
1169     #    the real eval. Then the slow_path returns the PC of the thing to
1170     #    call, and we call it.
1171     #
1172     # This allows us to handle two cases, which would require a total of
1173     # up to four pieces of state that cannot be easily packed into two
1174     # registers (C functions can return up to two registers, easily):
1175     #
1176     # - The call frame register. This may or may not have been modified
1177     #   by the slow_path, but the convention is that it returns it. It's not
1178     #   totally clear if that's necessary, since the cfr is callee save.
1179     #   But that's our style in this here interpreter so we stick with it.
1180     #
1181     # - A bit to say if the slow_path successfully executed the eval and has
1182     #   the return value, or did not execute the eval but has a PC for us
1183     #   to call.
1184     #
1185     # - Either:
1186     #   - The JS return value (two registers), or
1187     #
1188     #   - The PC to call.
1189     #
1190     # It turns out to be easier to just always have this return the cfr
1191     # and a PC to call, and that PC may be a dummy thunk that just
1192     # returns the JS value that the eval returned.
1193     
1194     slowPathForCall(4, _llint_slow_path_call_eval)
1195
1196
1197 _llint_generic_return_point:
1198     dispatchAfterCall()
1199
1200
1201 _llint_op_strcat:
1202     traceExecution()
1203     callSlowPath(_llint_slow_path_strcat)
1204     dispatch(4)
1205
1206
1207 _llint_op_get_pnames:
1208     traceExecution()
1209     callSlowPath(_llint_slow_path_get_pnames)
1210     dispatch(0) # The slow_path either advances the PC or jumps us to somewhere else.
1211
1212
1213 _llint_op_push_with_scope:
1214     traceExecution()
1215     callSlowPath(_llint_slow_path_push_with_scope)
1216     dispatch(2)
1217
1218
1219 _llint_op_pop_scope:
1220     traceExecution()
1221     callSlowPath(_llint_slow_path_pop_scope)
1222     dispatch(1)
1223
1224
1225 _llint_op_push_name_scope:
1226     traceExecution()
1227     callSlowPath(_llint_slow_path_push_name_scope)
1228     dispatch(4)
1229
1230
1231 _llint_op_throw:
1232     traceExecution()
1233     callSlowPath(_llint_slow_path_throw)
1234     dispatch(2)
1235
1236
1237 _llint_op_throw_reference_error:
1238     traceExecution()
1239     callSlowPath(_llint_slow_path_throw_reference_error)
1240     dispatch(2)
1241
1242
1243 _llint_op_profile_will_call:
1244     traceExecution()
1245     callSlowPath(_llint_slow_path_profile_will_call)
1246     dispatch(2)
1247
1248
1249 _llint_op_profile_did_call:
1250     traceExecution()
1251     callSlowPath(_llint_slow_path_profile_did_call)
1252     dispatch(2)
1253
1254
1255 _llint_op_debug:
1256     traceExecution()
1257     callSlowPath(_llint_slow_path_debug)
1258     dispatch(5)
1259
1260
1261 _llint_native_call_trampoline:
1262     nativeCallTrampoline(NativeExecutable::m_function)
1263
1264
1265 _llint_native_construct_trampoline:
1266     nativeCallTrampoline(NativeExecutable::m_constructor)
1267
1268
1269 # Lastly, make sure that we can link even though we don't support all opcodes.
1270 # These opcodes should never arise when using LLInt or either JIT. We assert
1271 # as much.
1272
1273 macro notSupported()
1274     if ASSERT_ENABLED
1275         crash()
1276     else
1277         # We should use whatever the smallest possible instruction is, just to
1278         # ensure that there is a gap between instruction labels. If multiple
1279         # smallest instructions exist, we should pick the one that is most
1280         # likely result in execution being halted. Currently that is the break
1281         # instruction on all architectures we're interested in. (Break is int3
1282         # on Intel, which is 1 byte, and bkpt on ARMv7, which is 2 bytes.)
1283         break
1284     end
1285 end
1286
1287 _llint_op_get_by_id_chain:
1288     notSupported()
1289
1290 _llint_op_get_by_id_custom_chain:
1291     notSupported()
1292
1293 _llint_op_get_by_id_custom_proto:
1294     notSupported()
1295
1296 _llint_op_get_by_id_custom_self:
1297     notSupported()
1298
1299 _llint_op_get_by_id_generic:
1300     notSupported()
1301
1302 _llint_op_get_by_id_getter_chain:
1303     notSupported()
1304
1305 _llint_op_get_by_id_getter_proto:
1306     notSupported()
1307
1308 _llint_op_get_by_id_getter_self:
1309     notSupported()
1310
1311 _llint_op_get_by_id_proto:
1312     notSupported()
1313
1314 _llint_op_get_by_id_self:
1315     notSupported()
1316
1317 _llint_op_get_string_length:
1318     notSupported()
1319
1320 _llint_op_put_by_id_generic:
1321     notSupported()
1322
1323 _llint_op_put_by_id_replace:
1324     notSupported()
1325
1326 _llint_op_put_by_id_transition:
1327     notSupported()
1328
1329
1330 # Indicate the end of LLInt.
1331 _llint_end:
1332     crash()
1333