1 # Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
 
   3 # Redistribution and use in source and binary forms, with or without
 
   4 # modification, are permitted provided that the following conditions
 
   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.
 
  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.
 
  24 # First come the common protocols that both interpreters use. Note that each
 
  25 # of these must have an ASSERT() in LLIntData.cpp
 
  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
 
  33 # These declarations must match interpreter/JSStack.h.
 
  34 const CallFrameHeaderSize = 48
 
  35 const ArgumentCount = -48
 
  36 const CallerFrame = -40
 
  38 const ScopeChain = -24
 
  42 const ThisArgumentOffset = -CallFrameHeaderSize - 8
 
  44 # Some register conventions.
 
  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
 
  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.
 
  55     const tagTypeNumber = csr1
 
  58     macro loadisFromInstruction(offset, dest)
 
  59         loadis offset * 8[PB, PC, 8], dest
 
  62     macro loadpFromInstruction(offset, dest)
 
  63         loadp offset * 8[PB, PC, 8], dest
 
  66     macro storepToInstruction(value, offset)
 
  67         storep value, offset * 8[PB, PC, 8]
 
  72     macro loadisFromInstruction(offset, dest)
 
  73         loadis offset * 4[PC], dest
 
  76     macro loadpFromInstruction(offset, dest)
 
  77         loadp offset * 4[PC], dest
 
  81 # Constants for reasoning about value representation.
 
  84     const PayloadOffset = 4
 
  87     const PayloadOffset = 0
 
  90 # Constant for reasoning about butterflies.
 
  92 const IndexingShapeMask        = 30
 
  93 const NoIndexingShape          = 0
 
  95 const DoubleShape              = 22
 
  96 const ContiguousShape          = 26
 
  97 const ArrayStorageShape        = 28
 
  98 const SlowPutArrayStorageShape = 30
 
 102 const ObjectType = 17
 
 104 # Type flags constants.
 
 105 const MasqueradesAsUndefined = 1
 
 106 const ImplementsHasInstance = 2
 
 107 const ImplementsDefaultHasInstance = 8
 
 109 # Bytecode operand constants.
 
 110 const FirstConstantRegisterIndex = 0x40000000
 
 112 # Code type constants.
 
 115 const FunctionCode = 2
 
 117 # The interpreter steals the tag word of the argument count.
 
 118 const LLIntReturnPC = ArgumentCount + TagOffset
 
 121 const HashFlags8BitBuffer = 64
 
 123 # Copied from PropertyOffset.h
 
 124 const firstOutOfLineOffset = 100
 
 126 # From ResolveOperations.h
 
 127 const ResolveOperationFail = 0
 
 128 const ResolveOperationSetBaseToUndefined = 1
 
 129 const ResolveOperationReturnScopeAsBase = 2
 
 130 const ResolveOperationSetBaseToScope = 3
 
 131 const ResolveOperationSetBaseToGlobal = 4
 
 132 const ResolveOperationGetAndReturnScopedVar = 5
 
 133 const ResolveOperationGetAndReturnGlobalVar = 6
 
 134 const ResolveOperationGetAndReturnGlobalVarWatchable = 7
 
 135 const ResolveOperationSkipTopScopeNode = 8
 
 136 const ResolveOperationSkipScopes = 9
 
 137 const ResolveOperationReturnGlobalObjectAsBase = 10
 
 138 const ResolveOperationGetAndReturnGlobalProperty = 11
 
 139 const ResolveOperationCheckForDynamicEntriesBeforeGlobalScope = 12
 
 141 const PutToBaseOperationKindUninitialised = 0
 
 142 const PutToBaseOperationKindGeneric = 1
 
 143 const PutToBaseOperationKindReadonly = 2
 
 144 const PutToBaseOperationKindGlobalVariablePut = 3
 
 145 const PutToBaseOperationKindGlobalVariablePutChecked = 4
 
 146 const PutToBaseOperationKindGlobalPropertyPut = 5
 
 147 const PutToBaseOperationKindVariablePut = 6
 
 149 # Allocation constants
 
 151     const JSFinalObjectSizeClassIndex = 1
 
 153     const JSFinalObjectSizeClassIndex = 3
 
 156 # This must match wtf/Vector.h
 
 157 const VectorBufferOffset = 0
 
 159     const VectorSizeOffset = 12
 
 161     const VectorSizeOffset = 8
 
 165 # Some common utilities.
 
 170         storei t0, 0xbbadbeef[]
 
 176 macro assert(assertion)
 
 184 macro preserveReturnAddressAfterCall(destinationRegister)
 
 185     if C_LOOP or ARM or ARMv7 or ARMv7_TRADITIONAL or ARM64 or MIPS
 
 186         # In C_LOOP case, we're only preserving the bytecode vPC.
 
 187         move lr, destinationRegister
 
 189         stspr destinationRegister
 
 191         pop destinationRegister
 
 197 macro restoreReturnAddressBeforeReturn(sourceRegister)
 
 198     if C_LOOP or ARM or ARMv7 or ARMv7_TRADITIONAL or ARM64 or MIPS
 
 199         # In C_LOOP case, we're only restoring the bytecode vPC.
 
 200         move sourceRegister, lr
 
 210 macro traceExecution()
 
 212         callSlowPath(_llint_trace)
 
 216 macro callTargetFunction(callLinkInfo)
 
 218         cloopCallJSFunction LLIntCallLinkInfo::machineCodeTarget[callLinkInfo]
 
 220         call LLIntCallLinkInfo::machineCodeTarget[callLinkInfo]
 
 225 macro slowPathForCall(advance, slowPath)
 
 231                 cloopCallJSFunction callee
 
 239 macro arrayProfile(structureAndIndexingType, profile, scratch)
 
 240     const structure = structureAndIndexingType
 
 241     const indexingType = structureAndIndexingType
 
 243         storep structure, ArrayProfile::m_lastSeenStructure[profile]
 
 245     loadb Structure::m_indexingType[structure], indexingType
 
 248 macro checkSwitchToJIT(increment, action)
 
 250         loadp CodeBlock[cfr], t0
 
 251         baddis increment, CodeBlock::m_llintExecuteCounter + ExecutionCounter::m_counter[t0], .continue
 
 257 macro checkSwitchToJITForEpilogue()
 
 261             callSlowPath(_llint_replace)
 
 265 macro assertNotConstant(index)
 
 266     assert(macro (ok) bilt index, FirstConstantRegisterIndex, ok end)
 
 269 macro functionForCallCodeBlockGetter(targetRegister)
 
 270     loadp Callee[cfr], targetRegister
 
 271     loadp JSFunction::m_executable[targetRegister], targetRegister
 
 272     loadp FunctionExecutable::m_codeBlockForCall[targetRegister], targetRegister
 
 275 macro functionForConstructCodeBlockGetter(targetRegister)
 
 276     loadp Callee[cfr], targetRegister
 
 277     loadp JSFunction::m_executable[targetRegister], targetRegister
 
 278     loadp FunctionExecutable::m_codeBlockForConstruct[targetRegister], targetRegister
 
 281 macro notFunctionCodeBlockGetter(targetRegister)
 
 282     loadp CodeBlock[cfr], targetRegister
 
 285 macro functionCodeBlockSetter(sourceRegister)
 
 286     storep sourceRegister, CodeBlock[cfr]
 
 289 macro notFunctionCodeBlockSetter(sourceRegister)
 
 293 # Do the bare minimum required to execute code. Sets up the PC, leave the CodeBlock*
 
 294 # in t1. May also trigger prologue entry OSR.
 
 295 macro prologue(codeBlockGetter, codeBlockSetter, osrSlowPath, traceSlowPath)
 
 296     preserveReturnAddressAfterCall(t2)
 
 298     # Set up the call frame and check if we should OSR.
 
 299     storep t2, ReturnPC[cfr]
 
 301         callSlowPath(traceSlowPath)
 
 305         baddis 5, CodeBlock::m_llintExecuteCounter + ExecutionCounter::m_counter[t1], .continue
 
 306         cCall2(osrSlowPath, cfr, PC)
 
 309         loadp ReturnPC[cfr], t2
 
 310         restoreReturnAddressBeforeReturn(t2)
 
 320         loadp CodeBlock::m_instructions[t1], PB
 
 323         loadp CodeBlock::m_instructions[t1], PC
 
 327 # Expects that CodeBlock is in t1, which is what prologue() leaves behind.
 
 328 # Must call dispatch(0) after calling this.
 
 329 macro functionInitialization(profileArgSkip)
 
 331         # Profile the arguments. Unfortunately, we have no choice but to do this. This
 
 332         # code is pretty horrendous because of the difference in ordering between
 
 333         # arguments and value profiles, the desire to have a simple loop-down-to-zero
 
 334         # loop, and the desire to use only three registers so as to preserve the PC and
 
 335         # the code block. It is likely that this code should be rewritten in a more
 
 336         # optimal way for architectures that have more than five registers available
 
 337         # for arbitrary use in the interpreter.
 
 338         loadi CodeBlock::m_numParameters[t1], t0
 
 339         addp -profileArgSkip, t0 # Use addi because that's what has the peephole
 
 340         assert(macro (ok) bpgteq t0, 0, ok end)
 
 341         btpz t0, .argumentProfileDone
 
 342         loadp CodeBlock::m_argumentValueProfiles + VectorBufferOffset[t1], t3
 
 343         mulp sizeof ValueProfile, t0, t2 # Aaaaahhhh! Need strength reduction!
 
 347     .argumentProfileLoop:
 
 349             loadq ThisArgumentOffset + 8 - profileArgSkip * 8[cfr, t0], t2
 
 350             subp sizeof ValueProfile, t3
 
 351             storeq t2, profileArgSkip * sizeof ValueProfile + ValueProfile::m_buckets[t3]
 
 353             loadi ThisArgumentOffset + TagOffset + 8 - profileArgSkip * 8[cfr, t0], t2
 
 354             subp sizeof ValueProfile, t3
 
 355             storei t2, profileArgSkip * sizeof ValueProfile + ValueProfile::m_buckets + TagOffset[t3]
 
 356             loadi ThisArgumentOffset + PayloadOffset + 8 - profileArgSkip * 8[cfr, t0], t2
 
 357             storei t2, profileArgSkip * sizeof ValueProfile + ValueProfile::m_buckets + PayloadOffset[t3]
 
 359         baddpnz 8, t0, .argumentProfileLoop
 
 360     .argumentProfileDone:
 
 363     # Check stack height.
 
 364     loadi CodeBlock::m_numCalleeRegisters[t1], t0
 
 365     loadp CodeBlock::m_vm[t1], t2
 
 366     loadp VM::interpreter[t2], t2   # FIXME: Can get to the JSStack from the JITStackFrame
 
 369     bpaeq Interpreter::m_stack + JSStack::m_end[t2], t0, .stackHeightOK
 
 371     # Stack height check failed - need to call a slow_path.
 
 372     callSlowPath(_llint_stack_check)
 
 376 macro allocateJSObject(allocator, structure, result, scratch1, slowCase)
 
 377     if ALWAYS_ALLOCATE_SLOW
 
 380         const offsetOfFirstFreeCell = 
 
 381             MarkedAllocator::m_freeList + 
 
 382             MarkedBlock::FreeList::head
 
 384         # Get the object from the free list.   
 
 385         loadp offsetOfFirstFreeCell[allocator], result
 
 386         btpz result, slowCase
 
 388         # Remove the object from the free list.
 
 389         loadp [result], scratch1
 
 390         storep scratch1, offsetOfFirstFreeCell[allocator]
 
 392         # Initialize the object.
 
 393         storep structure, JSCell::m_structure[result]
 
 394         storep 0, JSObject::m_butterfly[result]
 
 399     loadp ReturnPC[cfr], t2
 
 400     loadp CallerFrame[cfr], cfr
 
 401     restoreReturnAddressBeforeReturn(t2)
 
 406 # Indicate the beginning of LLInt.
 
 411 _llint_program_prologue:
 
 412     prologue(notFunctionCodeBlockGetter, notFunctionCodeBlockSetter, _llint_entry_osr, _llint_trace_prologue)
 
 416 _llint_eval_prologue:
 
 417     prologue(notFunctionCodeBlockGetter, notFunctionCodeBlockSetter, _llint_entry_osr, _llint_trace_prologue)
 
 421 _llint_function_for_call_prologue:
 
 422     prologue(functionForCallCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_call, _llint_trace_prologue_function_for_call)
 
 423 .functionForCallBegin:
 
 424     functionInitialization(0)
 
 428 _llint_function_for_construct_prologue:
 
 429     prologue(functionForConstructCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_construct, _llint_trace_prologue_function_for_construct)
 
 430 .functionForConstructBegin:
 
 431     functionInitialization(1)
 
 435 _llint_function_for_call_arity_check:
 
 436     prologue(functionForCallCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_call_arityCheck, _llint_trace_arityCheck_for_call)
 
 437     functionArityCheck(.functionForCallBegin, _llint_slow_path_call_arityCheck)
 
 440 _llint_function_for_construct_arity_check:
 
 441     prologue(functionForConstructCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_construct_arityCheck, _llint_trace_arityCheck_for_construct)
 
 442     functionArityCheck(.functionForConstructBegin, _llint_slow_path_construct_arityCheck)
 
 445 # Value-representation-specific code.
 
 447     include LowLevelInterpreter64
 
 449     include LowLevelInterpreter32_64
 
 453 # Value-representation-agnostic code.
 
 456     callSlowPath(_llint_slow_path_new_array)
 
 460 _llint_op_new_array_with_size:
 
 462     callSlowPath(_llint_slow_path_new_array_with_size)
 
 466 _llint_op_new_array_buffer:
 
 468     callSlowPath(_llint_slow_path_new_array_buffer)
 
 472 _llint_op_new_regexp:
 
 474     callSlowPath(_llint_slow_path_new_regexp)
 
 480     callSlowPath(_llint_slow_path_less)
 
 486     callSlowPath(_llint_slow_path_lesseq)
 
 492     callSlowPath(_llint_slow_path_greater)
 
 498     callSlowPath(_llint_slow_path_greatereq)
 
 504     callSlowPath(_llint_slow_path_mod)
 
 510     callSlowPath(_llint_slow_path_typeof)
 
 516     callSlowPath(_llint_slow_path_is_object)
 
 520 _llint_op_is_function:
 
 522     callSlowPath(_llint_slow_path_is_function)
 
 528     callSlowPath(_llint_slow_path_in)
 
 531 macro getPutToBaseOperationField(scratch, scratch1, fieldOffset, fieldGetter)
 
 532     loadpFromInstruction(4, scratch)
 
 533     fieldGetter(fieldOffset[scratch])
 
 536 macro moveJSValueFromRegisterWithoutProfiling(value, destBuffer, destOffsetReg)
 
 537     storeq value, [destBuffer, destOffsetReg, 8]
 
 541 macro moveJSValueFromRegistersWithoutProfiling(tag, payload, destBuffer, destOffsetReg)
 
 542     storei tag, TagOffset[destBuffer, destOffsetReg, 8]
 
 543     storei payload, PayloadOffset[destBuffer, destOffsetReg, 8]
 
 546 macro putToBaseVariableBody(variableOffset, scratch1, scratch2, scratch3)
 
 547     loadisFromInstruction(1, scratch1)
 
 548     loadp PayloadOffset[cfr, scratch1, 8], scratch1
 
 549     loadp JSVariableObject::m_registers[scratch1], scratch1
 
 550     loadisFromInstruction(3, scratch2)
 
 552         loadConstantOrVariable(scratch2, scratch3)
 
 553         moveJSValueFromRegisterWithoutProfiling(scratch3, scratch1, variableOffset)
 
 555         loadConstantOrVariable2Reg(scratch2, scratch3, scratch2) # scratch3=tag, scratch2=payload
 
 556         moveJSValueFromRegistersWithoutProfiling(scratch3, scratch2, scratch1, variableOffset)
 
 560 _llint_op_put_to_base_variable:
 
 562     getPutToBaseOperationField(t0, t1, PutToBaseOperation::m_offset, macro(addr)
 
 565     putToBaseVariableBody(t0, t1, t2, t3)
 
 568 _llint_op_put_to_base:
 
 570     getPutToBaseOperationField(t0, t1, 0, macro(addr)
 
 572                                               bbneq PutToBaseOperation::m_kindAsUint8[t0], PutToBaseOperationKindVariablePut, .notPutToBaseVariable
 
 573                                               loadis PutToBaseOperation::m_offset[t0], t0
 
 574                                               putToBaseVariableBody(t0, t1, t2, t3)
 
 576                                               .notPutToBaseVariable:
 
 578     callSlowPath(_llint_slow_path_put_to_base)
 
 581 macro getResolveOperation(resolveOperationIndex, dest)
 
 582     loadpFromInstruction(resolveOperationIndex, dest)
 
 583     loadp VectorBufferOffset[dest], dest
 
 586 macro getScope(loadInitialScope, scopeCount, dest, scratch)
 
 587     loadInitialScope(dest)
 
 588     loadi scopeCount, scratch
 
 592     loadp JSScope::m_next[dest], dest
 
 599 macro moveJSValue(sourceBuffer, sourceOffsetReg, destBuffer, destOffsetReg, profileOffset, scratchRegister)
 
 601         loadq [sourceBuffer, sourceOffsetReg, 8], scratchRegister
 
 602         storeq scratchRegister, [destBuffer, destOffsetReg, 8]
 
 603         loadpFromInstruction(profileOffset, destOffsetReg)
 
 604         valueProfile(scratchRegister, destOffsetReg)
 
 606         loadi PayloadOffset[sourceBuffer, sourceOffsetReg, 8], scratchRegister
 
 607         storei scratchRegister, PayloadOffset[destBuffer, destOffsetReg, 8]
 
 608         loadi TagOffset[sourceBuffer, sourceOffsetReg, 8], sourceOffsetReg
 
 609         storei sourceOffsetReg, TagOffset[destBuffer, destOffsetReg, 8]
 
 610         loadpFromInstruction(profileOffset, destOffsetReg)
 
 611         valueProfile(sourceOffsetReg, scratchRegister, destOffsetReg)
 
 615 macro moveJSValueFromSlot(slot, destBuffer, destOffsetReg, profileOffset, scratchRegister)
 
 617         loadq [slot], scratchRegister
 
 618         storeq scratchRegister, [destBuffer, destOffsetReg, 8]
 
 619         loadpFromInstruction(profileOffset, destOffsetReg)
 
 620         valueProfile(scratchRegister, destOffsetReg)
 
 622         loadi PayloadOffset[slot], scratchRegister
 
 623         storei scratchRegister, PayloadOffset[destBuffer, destOffsetReg, 8]
 
 624         loadi TagOffset[slot], slot
 
 625         storei slot, TagOffset[destBuffer, destOffsetReg, 8]
 
 626         loadpFromInstruction(profileOffset, destOffsetReg)
 
 627         valueProfile(slot, scratchRegister, destOffsetReg)
 
 631 macro moveJSValueFromRegister(value, destBuffer, destOffsetReg, profileOffset)
 
 632     storeq value, [destBuffer, destOffsetReg, 8]
 
 633     loadpFromInstruction(profileOffset, destOffsetReg)
 
 634     valueProfile(value, destOffsetReg)
 
 637 macro moveJSValueFromRegisters(tag, payload, destBuffer, destOffsetReg, profileOffset)
 
 638     storei tag, TagOffset[destBuffer, destOffsetReg, 8]
 
 639     storei payload, PayloadOffset[destBuffer, destOffsetReg, 8]
 
 640     loadpFromInstruction(profileOffset, destOffsetReg)
 
 641     valueProfile(tag, payload, destOffsetReg)
 
 644 _llint_op_resolve_global_property:
 
 646     getResolveOperation(3, t0)
 
 647     loadp CodeBlock[cfr], t1
 
 648     loadp CodeBlock::m_globalObject[t1], t1
 
 649     loadp ResolveOperation::m_structure[t0], t2
 
 650     bpneq JSCell::m_structure[t1], t2, .llint_op_resolve_local
 
 651     loadis ResolveOperation::m_offset[t0], t0
 
 653         loadPropertyAtVariableOffsetKnownNotInline(t0, t1, t2)
 
 654         loadisFromInstruction(1, t0)
 
 655         moveJSValueFromRegister(t2, cfr, t0, 4)
 
 657         loadPropertyAtVariableOffsetKnownNotInline(t0, t1, t2, t3)
 
 658         loadisFromInstruction(1, t0)
 
 659         moveJSValueFromRegisters(t2, t3, cfr, t0, 4)
 
 663 _llint_op_resolve_global_var:
 
 665     getResolveOperation(3, t0)
 
 666     loadp ResolveOperation::m_registerAddress[t0], t0
 
 667     loadisFromInstruction(1, t1)
 
 668     moveJSValueFromSlot(t0, cfr, t1, 4, t3)
 
 671 macro resolveScopedVarBody(resolveOperations)
 
 672     # First ResolveOperation is to skip scope chain nodes
 
 674                  loadp ScopeChain + PayloadOffset[cfr], dest
 
 676              ResolveOperation::m_scopesToSkip[resolveOperations], t1, t2)
 
 677     loadp JSVariableObject::m_registers[t1], t1 # t1 now contains the activation registers
 
 679     # Second ResolveOperation tells us what offset to use
 
 680     loadis ResolveOperation::m_offset + sizeof ResolveOperation[resolveOperations], t2
 
 681     loadisFromInstruction(1, t3)
 
 682     moveJSValue(t1, t2, cfr, t3, 4, t0)
 
 685 _llint_op_resolve_scoped_var:
 
 687     getResolveOperation(3, t0)
 
 688     resolveScopedVarBody(t0)
 
 691 _llint_op_resolve_scoped_var_on_top_scope:
 
 693     getResolveOperation(3, t0)
 
 695     # Load destination index
 
 696     loadisFromInstruction(1, t3)
 
 698     # We know we want the top scope chain entry
 
 699     loadp ScopeChain + PayloadOffset[cfr], t1
 
 700     loadp JSVariableObject::m_registers[t1], t1 # t1 now contains the activation registers
 
 702     # Second ResolveOperation tells us what offset to use
 
 703     loadis ResolveOperation::m_offset + sizeof ResolveOperation[t0], t2
 
 705     moveJSValue(t1, t2, cfr, t3, 4, t0)
 
 708 _llint_op_resolve_scoped_var_with_top_scope_check:
 
 710     getResolveOperation(3, t0)
 
 711     # First ResolveOperation tells us what register to check
 
 712     loadis ResolveOperation::m_activationRegister[t0], t1
 
 714     loadp PayloadOffset[cfr, t1, 8], t1
 
 717                  btpz t1, .scopeChainNotCreated
 
 718                      loadp JSScope::m_next[t1], dest
 
 720                  .scopeChainNotCreated:
 
 721                      loadp ScopeChain + PayloadOffset[cfr], dest
 
 724              # Second ResolveOperation tells us how many more nodes to skip
 
 725              ResolveOperation::m_scopesToSkip + sizeof ResolveOperation[t0], t1, t2)
 
 726     loadp JSVariableObject::m_registers[t1], t1 # t1 now contains the activation registers
 
 728     # Third operation tells us what offset to use
 
 729     loadis ResolveOperation::m_offset + 2 * sizeof ResolveOperation[t0], t2
 
 730     loadisFromInstruction(1, t3)
 
 731     moveJSValue(t1, t2, cfr, t3, 4, t0)
 
 735 .llint_op_resolve_local:
 
 737     getResolveOperation(3, t0)
 
 738     btpz t0, .noInstructions
 
 739     loadis ResolveOperation::m_operation[t0], t1
 
 740     bineq t1, ResolveOperationSkipScopes, .notSkipScopes
 
 741         resolveScopedVarBody(t0)
 
 744     bineq t1, ResolveOperationGetAndReturnGlobalVar, .notGetAndReturnGlobalVar
 
 745         loadp ResolveOperation::m_registerAddress[t0], t0
 
 746         loadisFromInstruction(1, t1)
 
 747         moveJSValueFromSlot(t0, cfr, t1, 4, t3)
 
 749 .notGetAndReturnGlobalVar:
 
 752     callSlowPath(_llint_slow_path_resolve)
 
 755 _llint_op_resolve_base_to_global:
 
 757     loadp CodeBlock[cfr], t1
 
 758     loadp CodeBlock::m_globalObject[t1], t1
 
 759     loadisFromInstruction(1, t3)
 
 761         moveJSValueFromRegister(t1, cfr, t3, 6)
 
 764         moveJSValueFromRegisters(t2, t1, cfr, t3, 6)
 
 768 _llint_op_resolve_base_to_global_dynamic:
 
 769     jmp _llint_op_resolve_base
 
 771 _llint_op_resolve_base_to_scope:
 
 773     getResolveOperation(4, t0)
 
 774     # First ResolveOperation is to skip scope chain nodes
 
 776                  loadp ScopeChain + PayloadOffset[cfr], dest
 
 778              ResolveOperation::m_scopesToSkip[t0], t1, t2)
 
 779     loadisFromInstruction(1, t3)
 
 781         moveJSValueFromRegister(t1, cfr, t3, 6)
 
 784         moveJSValueFromRegisters(t2, t1, cfr, t3, 6)
 
 788 _llint_op_resolve_base_to_scope_with_top_scope_check:
 
 790     getResolveOperation(4, t0)
 
 791     # First ResolveOperation tells us what register to check
 
 792     loadis ResolveOperation::m_activationRegister[t0], t1
 
 794     loadp PayloadOffset[cfr, t1, 8], t1
 
 797                  btpz t1, .scopeChainNotCreated
 
 798                      loadp JSScope::m_next[t1], dest
 
 800                  .scopeChainNotCreated:
 
 801                      loadp ScopeChain + PayloadOffset[cfr], dest
 
 804              # Second ResolveOperation tells us how many more nodes to skip
 
 805              ResolveOperation::m_scopesToSkip + sizeof ResolveOperation[t0], t1, t2)
 
 807     loadisFromInstruction(1, t3)
 
 809         moveJSValueFromRegister(t1, cfr, t3, 6)
 
 812         moveJSValueFromRegisters(t2, t1, cfr, t3, 6)
 
 816 _llint_op_resolve_base:
 
 818     callSlowPath(_llint_slow_path_resolve_base)
 
 821 macro interpretResolveWithBase(opcodeLength, slowPath)
 
 823     getResolveOperation(4, t0)
 
 826     loadp ScopeChain[cfr], t3
 
 828     loadis ResolveOperation::m_operation[t0], t2
 
 830     bineq t2, ResolveOperationSkipScopes, .notSkipScopes
 
 831         getScope(macro(dest) move t3, dest end,
 
 832                  ResolveOperation::m_scopesToSkip[t0], t1, t2)
 
 834         addp sizeof ResolveOperation, t0, t0
 
 835         jmp .haveCorrectScope
 
 839     bineq t2, ResolveOperationSkipTopScopeNode, .notSkipTopScopeNode
 
 840         loadis ResolveOperation::m_activationRegister[t0], t1
 
 841         loadp PayloadOffset[cfr, t1, 8], t1
 
 844                      btpz t1, .scopeChainNotCreated
 
 845                          loadp JSScope::m_next[t1], dest
 
 847                      .scopeChainNotCreated:
 
 848                          loadp ScopeChain + PayloadOffset[cfr], dest
 
 851                  sizeof ResolveOperation + ResolveOperation::m_scopesToSkip[t0], t1, t2)
 
 853         # We've handled two opcodes here
 
 854         addp 2 * sizeof ResolveOperation, t0, t0
 
 856     .notSkipTopScopeNode:
 
 860     # t3 now contains the correct Scope
 
 861     # t0 contains a pointer to the current ResolveOperation
 
 863     loadis ResolveOperation::m_operation[t0], t2
 
 864     # t2 contains the next instruction
 
 866     loadisFromInstruction(1, t1)
 
 867     # t1 now contains the index for the base register
 
 869     bineq t2, ResolveOperationSetBaseToScope, .notSetBaseToScope
 
 871             storeq t3, [cfr, t1, 8]
 
 873             storei t3, PayloadOffset[cfr, t1, 8]
 
 874             storei CellTag, TagOffset[cfr, t1, 8]
 
 880     bineq t2, ResolveOperationSetBaseToUndefined, .notSetBaseToUndefined
 
 882             storeq ValueUndefined, [cfr, t1, 8]
 
 884             storei 0, PayloadOffset[cfr, t1, 8]
 
 885             storei UndefinedTag, TagOffset[cfr, t1, 8]
 
 889     .notSetBaseToUndefined:
 
 890     bineq t2, ResolveOperationSetBaseToGlobal, .slowPath
 
 891         loadp JSCell::m_structure[t3], t2
 
 892         loadp Structure::m_globalObject[t2], t2
 
 894             storeq t2, [cfr, t1, 8]
 
 896             storei t2, PayloadOffset[cfr, t1, 8]
 
 897             storei CellTag, TagOffset[cfr, t1, 8]
 
 904     # Load the operation into t2
 
 905     loadis ResolveOperation::m_operation + sizeof ResolveOperation[t0], t2
 
 907     # Load the index for the value register into t1
 
 908     loadisFromInstruction(2, t1)
 
 910     bineq t2, ResolveOperationGetAndReturnScopedVar, .notGetAndReturnScopedVar
 
 911         loadp JSVariableObject::m_registers[t3], t3 # t3 now contains the activation registers
 
 913         # Second ResolveOperation tells us what offset to use
 
 914         loadis ResolveOperation::m_offset + sizeof ResolveOperation[t0], t2
 
 915         moveJSValue(t3, t2, cfr, t1, opcodeLength - 1, t0)
 
 916         dispatch(opcodeLength)
 
 918     .notGetAndReturnScopedVar:
 
 919     bineq t2, ResolveOperationGetAndReturnGlobalProperty, .slowPath
 
 920         callSlowPath(slowPath)
 
 921         dispatch(opcodeLength)
 
 924     callSlowPath(slowPath)
 
 925     dispatch(opcodeLength)
 
 928 _llint_op_resolve_with_base:
 
 929     interpretResolveWithBase(7, _llint_slow_path_resolve_with_base)
 
 932 _llint_op_resolve_with_this:
 
 933     interpretResolveWithBase(6, _llint_slow_path_resolve_with_this)
 
 936 macro withInlineStorage(object, propertyStorage, continuation)
 
 937     # Indicate that the object is the property storage, and that the
 
 938     # property storage register is unused.
 
 939     continuation(object, propertyStorage)
 
 942 macro withOutOfLineStorage(object, propertyStorage, continuation)
 
 943     loadp JSObject::m_butterfly[object], propertyStorage
 
 944     # Indicate that the propertyStorage register now points to the
 
 945     # property storage, and that the object register may be reused
 
 946     # if the object pointer is not needed anymore.
 
 947     continuation(propertyStorage, object)
 
 953     callSlowPath(_llint_slow_path_del_by_id)
 
 957 _llint_op_del_by_val:
 
 959     callSlowPath(_llint_slow_path_del_by_val)
 
 963 _llint_op_put_by_index:
 
 965     callSlowPath(_llint_slow_path_put_by_index)
 
 969 _llint_op_put_getter_setter:
 
 971     callSlowPath(_llint_slow_path_put_getter_setter)
 
 978         macro (value, target) btinz value, target end,
 
 979         _llint_slow_path_jtrue)
 
 985         macro (value, target) btiz value, target end,
 
 986         _llint_slow_path_jfalse)
 
 992         macro (left, right, target) bilt left, right, target end,
 
 993         macro (left, right, target) bdlt left, right, target end,
 
 994         _llint_slow_path_jless)
 
1000         macro (left, right, target) bigteq left, right, target end,
 
1001         macro (left, right, target) bdgtequn left, right, target end,
 
1002         _llint_slow_path_jnless)
 
1008         macro (left, right, target) bigt left, right, target end,
 
1009         macro (left, right, target) bdgt left, right, target end,
 
1010         _llint_slow_path_jgreater)
 
1013 _llint_op_jngreater:
 
1016         macro (left, right, target) bilteq left, right, target end,
 
1017         macro (left, right, target) bdltequn left, right, target end,
 
1018         _llint_slow_path_jngreater)
 
1024         macro (left, right, target) bilteq left, right, target end,
 
1025         macro (left, right, target) bdlteq left, right, target end,
 
1026         _llint_slow_path_jlesseq)
 
1032         macro (left, right, target) bigt left, right, target end,
 
1033         macro (left, right, target) bdgtun left, right, target end,
 
1034         _llint_slow_path_jnlesseq)
 
1037 _llint_op_jgreatereq:
 
1040         macro (left, right, target) bigteq left, right, target end,
 
1041         macro (left, right, target) bdgteq left, right, target end,
 
1042         _llint_slow_path_jgreatereq)
 
1045 _llint_op_jngreatereq:
 
1048         macro (left, right, target) bilt left, right, target end,
 
1049         macro (left, right, target) bdltun left, right, target end,
 
1050         _llint_slow_path_jngreatereq)
 
1053 _llint_op_loop_hint:
 
1055     loadp JITStackFrame::vm[sp], t1
 
1056     loadb VM::watchdog+Watchdog::m_timerDidFire[t1], t0
 
1057     btbnz t0, .handleWatchdogTimer
 
1058 .afterWatchdogTimerCheck:
 
1059     checkSwitchToJITForLoop()
 
1061 .handleWatchdogTimer:
 
1062     callWatchdogTimerHandler(.throwHandler)
 
1063     jmp .afterWatchdogTimerCheck
 
1065     jmp _llint_throw_from_slow_path_trampoline
 
1067 _llint_op_switch_string:
 
1069     callSlowPath(_llint_slow_path_switch_string)
 
1073 _llint_op_new_func_exp:
 
1075     callSlowPath(_llint_slow_path_new_func_exp)
 
1081     arrayProfileForCall()
 
1082     doCall(_llint_slow_path_call)
 
1085 _llint_op_construct:
 
1087     doCall(_llint_slow_path_construct)
 
1090 _llint_op_call_varargs:
 
1092     slowPathForCall(6, _llint_slow_path_call_varargs)
 
1095 _llint_op_call_eval:
 
1098     # Eval is executed in one of two modes:
 
1100     # 1) We find that we're really invoking eval() in which case the
 
1101     #    execution is perfomed entirely inside the slow_path, and it
 
1102     #    returns the PC of a function that just returns the return value
 
1103     #    that the eval returned.
 
1105     # 2) We find that we're invoking something called eval() that is not
 
1106     #    the real eval. Then the slow_path returns the PC of the thing to
 
1107     #    call, and we call it.
 
1109     # This allows us to handle two cases, which would require a total of
 
1110     # up to four pieces of state that cannot be easily packed into two
 
1111     # registers (C functions can return up to two registers, easily):
 
1113     # - The call frame register. This may or may not have been modified
 
1114     #   by the slow_path, but the convention is that it returns it. It's not
 
1115     #   totally clear if that's necessary, since the cfr is callee save.
 
1116     #   But that's our style in this here interpreter so we stick with it.
 
1118     # - A bit to say if the slow_path successfully executed the eval and has
 
1119     #   the return value, or did not execute the eval but has a PC for us
 
1123     #   - The JS return value (two registers), or
 
1127     # It turns out to be easier to just always have this return the cfr
 
1128     # and a PC to call, and that PC may be a dummy thunk that just
 
1129     # returns the JS value that the eval returned.
 
1131     slowPathForCall(4, _llint_slow_path_call_eval)
 
1134 _llint_generic_return_point:
 
1140     callSlowPath(_llint_slow_path_strcat)
 
1144 _llint_op_get_pnames:
 
1146     callSlowPath(_llint_slow_path_get_pnames)
 
1147     dispatch(0) # The slow_path either advances the PC or jumps us to somewhere else.
 
1150 _llint_op_push_with_scope:
 
1152     callSlowPath(_llint_slow_path_push_with_scope)
 
1156 _llint_op_pop_scope:
 
1158     callSlowPath(_llint_slow_path_pop_scope)
 
1162 _llint_op_push_name_scope:
 
1164     callSlowPath(_llint_slow_path_push_name_scope)
 
1170     callSlowPath(_llint_slow_path_throw)
 
1174 _llint_op_throw_static_error:
 
1176     callSlowPath(_llint_slow_path_throw_static_error)
 
1180 _llint_op_profile_will_call:
 
1182     callSlowPath(_llint_slow_path_profile_will_call)
 
1186 _llint_op_profile_did_call:
 
1188     callSlowPath(_llint_slow_path_profile_did_call)
 
1194     callSlowPath(_llint_slow_path_debug)
 
1198 _llint_native_call_trampoline:
 
1199     nativeCallTrampoline(NativeExecutable::m_function)
 
1202 _llint_native_construct_trampoline:
 
1203     nativeCallTrampoline(NativeExecutable::m_constructor)
 
1206 # Lastly, make sure that we can link even though we don't support all opcodes.
 
1207 # These opcodes should never arise when using LLInt or either JIT. We assert
 
1210 macro notSupported()
 
1214         # We should use whatever the smallest possible instruction is, just to
 
1215         # ensure that there is a gap between instruction labels. If multiple
 
1216         # smallest instructions exist, we should pick the one that is most
 
1217         # likely result in execution being halted. Currently that is the break
 
1218         # instruction on all architectures we're interested in. (Break is int3
 
1219         # on Intel, which is 1 byte, and bkpt on ARMv7, which is 2 bytes.)
 
1224 _llint_op_get_by_id_chain:
 
1227 _llint_op_get_by_id_custom_chain:
 
1230 _llint_op_get_by_id_custom_proto:
 
1233 _llint_op_get_by_id_custom_self:
 
1236 _llint_op_get_by_id_generic:
 
1239 _llint_op_get_by_id_getter_chain:
 
1242 _llint_op_get_by_id_getter_proto:
 
1245 _llint_op_get_by_id_getter_self:
 
1248 _llint_op_get_by_id_proto:
 
1251 _llint_op_get_by_id_self:
 
1254 _llint_op_get_string_length:
 
1257 _llint_op_put_by_id_generic:
 
1260 _llint_op_put_by_id_replace:
 
1263 _llint_op_put_by_id_transition:
 
1266 _llint_op_init_global_const_nop:
 
1269 # Indicate the end of LLInt.