Home | History | Annotate | Download | only in arm
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #ifndef V8_ARM_MACRO_ASSEMBLER_ARM_H_
     29 #define V8_ARM_MACRO_ASSEMBLER_ARM_H_
     30 
     31 #include "assembler.h"
     32 #include "frames.h"
     33 #include "v8globals.h"
     34 
     35 namespace v8 {
     36 namespace internal {
     37 
     38 // ----------------------------------------------------------------------------
     39 // Static helper functions
     40 
     41 // Generate a MemOperand for loading a field from an object.
     42 inline MemOperand FieldMemOperand(Register object, int offset) {
     43   return MemOperand(object, offset - kHeapObjectTag);
     44 }
     45 
     46 
     47 inline Operand SmiUntagOperand(Register object) {
     48   return Operand(object, ASR, kSmiTagSize);
     49 }
     50 
     51 
     52 
     53 // Give alias names to registers
     54 const Register cp = { 8 };  // JavaScript context pointer
     55 const Register kRootRegister = { 10 };  // Roots array pointer.
     56 
     57 // Flags used for the AllocateInNewSpace functions.
     58 enum AllocationFlags {
     59   // No special flags.
     60   NO_ALLOCATION_FLAGS = 0,
     61   // Return the pointer to the allocated already tagged as a heap object.
     62   TAG_OBJECT = 1 << 0,
     63   // The content of the result register already contains the allocation top in
     64   // new space.
     65   RESULT_CONTAINS_TOP = 1 << 1,
     66   // Specify that the requested size of the space to allocate is specified in
     67   // words instead of bytes.
     68   SIZE_IN_WORDS = 1 << 2
     69 };
     70 
     71 
     72 // Flags used for the ObjectToDoubleVFPRegister function.
     73 enum ObjectToDoubleFlags {
     74   // No special flags.
     75   NO_OBJECT_TO_DOUBLE_FLAGS = 0,
     76   // Object is known to be a non smi.
     77   OBJECT_NOT_SMI = 1 << 0,
     78   // Don't load NaNs or infinities, branch to the non number case instead.
     79   AVOID_NANS_AND_INFINITIES = 1 << 1
     80 };
     81 
     82 
     83 enum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET };
     84 enum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK };
     85 enum LinkRegisterStatus { kLRHasNotBeenSaved, kLRHasBeenSaved };
     86 
     87 
     88 bool AreAliased(Register r1, Register r2, Register r3, Register r4);
     89 
     90 
     91 // MacroAssembler implements a collection of frequently used macros.
     92 class MacroAssembler: public Assembler {
     93  public:
     94   // The isolate parameter can be NULL if the macro assembler should
     95   // not use isolate-dependent functionality. In this case, it's the
     96   // responsibility of the caller to never invoke such function on the
     97   // macro assembler.
     98   MacroAssembler(Isolate* isolate, void* buffer, int size);
     99 
    100   // Jump, Call, and Ret pseudo instructions implementing inter-working.
    101   void Jump(Register target, Condition cond = al);
    102   void Jump(Address target, RelocInfo::Mode rmode, Condition cond = al);
    103   void Jump(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al);
    104   static int CallSize(Register target, Condition cond = al);
    105   void Call(Register target, Condition cond = al);
    106   static int CallSize(Address target,
    107                       RelocInfo::Mode rmode,
    108                       Condition cond = al);
    109   void Call(Address target, RelocInfo::Mode rmode, Condition cond = al);
    110   static int CallSize(Handle<Code> code,
    111                       RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
    112                       unsigned ast_id = kNoASTId,
    113                       Condition cond = al);
    114   void Call(Handle<Code> code,
    115             RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
    116             unsigned ast_id = kNoASTId,
    117             Condition cond = al);
    118   void Ret(Condition cond = al);
    119 
    120   // Emit code to discard a non-negative number of pointer-sized elements
    121   // from the stack, clobbering only the sp register.
    122   void Drop(int count, Condition cond = al);
    123 
    124   void Ret(int drop, Condition cond = al);
    125 
    126   // Swap two registers.  If the scratch register is omitted then a slightly
    127   // less efficient form using xor instead of mov is emitted.
    128   void Swap(Register reg1,
    129             Register reg2,
    130             Register scratch = no_reg,
    131             Condition cond = al);
    132 
    133 
    134   void And(Register dst, Register src1, const Operand& src2,
    135            Condition cond = al);
    136   void Ubfx(Register dst, Register src, int lsb, int width,
    137             Condition cond = al);
    138   void Sbfx(Register dst, Register src, int lsb, int width,
    139             Condition cond = al);
    140   // The scratch register is not used for ARMv7.
    141   // scratch can be the same register as src (in which case it is trashed), but
    142   // not the same as dst.
    143   void Bfi(Register dst,
    144            Register src,
    145            Register scratch,
    146            int lsb,
    147            int width,
    148            Condition cond = al);
    149   void Bfc(Register dst, int lsb, int width, Condition cond = al);
    150   void Usat(Register dst, int satpos, const Operand& src,
    151             Condition cond = al);
    152 
    153   void Call(Label* target);
    154 
    155   // Register move. May do nothing if the registers are identical.
    156   void Move(Register dst, Handle<Object> value);
    157   void Move(Register dst, Register src, Condition cond = al);
    158   void Move(DoubleRegister dst, DoubleRegister src);
    159 
    160   // Load an object from the root table.
    161   void LoadRoot(Register destination,
    162                 Heap::RootListIndex index,
    163                 Condition cond = al);
    164   // Store an object to the root table.
    165   void StoreRoot(Register source,
    166                  Heap::RootListIndex index,
    167                  Condition cond = al);
    168 
    169   void LoadHeapObject(Register dst, Handle<HeapObject> object);
    170 
    171   void LoadObject(Register result, Handle<Object> object) {
    172     if (object->IsHeapObject()) {
    173       LoadHeapObject(result, Handle<HeapObject>::cast(object));
    174     } else {
    175       Move(result, object);
    176     }
    177   }
    178 
    179   // ---------------------------------------------------------------------------
    180   // GC Support
    181 
    182   void IncrementalMarkingRecordWriteHelper(Register object,
    183                                            Register value,
    184                                            Register address);
    185 
    186   enum RememberedSetFinalAction {
    187     kReturnAtEnd,
    188     kFallThroughAtEnd
    189   };
    190 
    191   // Record in the remembered set the fact that we have a pointer to new space
    192   // at the address pointed to by the addr register.  Only works if addr is not
    193   // in new space.
    194   void RememberedSetHelper(Register object,  // Used for debug code.
    195                            Register addr,
    196                            Register scratch,
    197                            SaveFPRegsMode save_fp,
    198                            RememberedSetFinalAction and_then);
    199 
    200   void CheckPageFlag(Register object,
    201                      Register scratch,
    202                      int mask,
    203                      Condition cc,
    204                      Label* condition_met);
    205 
    206   // Check if object is in new space.  Jumps if the object is not in new space.
    207   // The register scratch can be object itself, but scratch will be clobbered.
    208   void JumpIfNotInNewSpace(Register object,
    209                            Register scratch,
    210                            Label* branch) {
    211     InNewSpace(object, scratch, ne, branch);
    212   }
    213 
    214   // Check if object is in new space.  Jumps if the object is in new space.
    215   // The register scratch can be object itself, but it will be clobbered.
    216   void JumpIfInNewSpace(Register object,
    217                         Register scratch,
    218                         Label* branch) {
    219     InNewSpace(object, scratch, eq, branch);
    220   }
    221 
    222   // Check if an object has a given incremental marking color.
    223   void HasColor(Register object,
    224                 Register scratch0,
    225                 Register scratch1,
    226                 Label* has_color,
    227                 int first_bit,
    228                 int second_bit);
    229 
    230   void JumpIfBlack(Register object,
    231                    Register scratch0,
    232                    Register scratch1,
    233                    Label* on_black);
    234 
    235   // Checks the color of an object.  If the object is already grey or black
    236   // then we just fall through, since it is already live.  If it is white and
    237   // we can determine that it doesn't need to be scanned, then we just mark it
    238   // black and fall through.  For the rest we jump to the label so the
    239   // incremental marker can fix its assumptions.
    240   void EnsureNotWhite(Register object,
    241                       Register scratch1,
    242                       Register scratch2,
    243                       Register scratch3,
    244                       Label* object_is_white_and_not_data);
    245 
    246   // Detects conservatively whether an object is data-only, i.e. it does need to
    247   // be scanned by the garbage collector.
    248   void JumpIfDataObject(Register value,
    249                         Register scratch,
    250                         Label* not_data_object);
    251 
    252   // Notify the garbage collector that we wrote a pointer into an object.
    253   // |object| is the object being stored into, |value| is the object being
    254   // stored.  value and scratch registers are clobbered by the operation.
    255   // The offset is the offset from the start of the object, not the offset from
    256   // the tagged HeapObject pointer.  For use with FieldOperand(reg, off).
    257   void RecordWriteField(
    258       Register object,
    259       int offset,
    260       Register value,
    261       Register scratch,
    262       LinkRegisterStatus lr_status,
    263       SaveFPRegsMode save_fp,
    264       RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
    265       SmiCheck smi_check = INLINE_SMI_CHECK);
    266 
    267   // As above, but the offset has the tag presubtracted.  For use with
    268   // MemOperand(reg, off).
    269   inline void RecordWriteContextSlot(
    270       Register context,
    271       int offset,
    272       Register value,
    273       Register scratch,
    274       LinkRegisterStatus lr_status,
    275       SaveFPRegsMode save_fp,
    276       RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
    277       SmiCheck smi_check = INLINE_SMI_CHECK) {
    278     RecordWriteField(context,
    279                      offset + kHeapObjectTag,
    280                      value,
    281                      scratch,
    282                      lr_status,
    283                      save_fp,
    284                      remembered_set_action,
    285                      smi_check);
    286   }
    287 
    288   // For a given |object| notify the garbage collector that the slot |address|
    289   // has been written.  |value| is the object being stored. The value and
    290   // address registers are clobbered by the operation.
    291   void RecordWrite(
    292       Register object,
    293       Register address,
    294       Register value,
    295       LinkRegisterStatus lr_status,
    296       SaveFPRegsMode save_fp,
    297       RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
    298       SmiCheck smi_check = INLINE_SMI_CHECK);
    299 
    300   // Push a handle.
    301   void Push(Handle<Object> handle);
    302 
    303   // Push two registers.  Pushes leftmost register first (to highest address).
    304   void Push(Register src1, Register src2, Condition cond = al) {
    305     ASSERT(!src1.is(src2));
    306     if (src1.code() > src2.code()) {
    307       stm(db_w, sp, src1.bit() | src2.bit(), cond);
    308     } else {
    309       str(src1, MemOperand(sp, 4, NegPreIndex), cond);
    310       str(src2, MemOperand(sp, 4, NegPreIndex), cond);
    311     }
    312   }
    313 
    314   // Push three registers.  Pushes leftmost register first (to highest address).
    315   void Push(Register src1, Register src2, Register src3, Condition cond = al) {
    316     ASSERT(!src1.is(src2));
    317     ASSERT(!src2.is(src3));
    318     ASSERT(!src1.is(src3));
    319     if (src1.code() > src2.code()) {
    320       if (src2.code() > src3.code()) {
    321         stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
    322       } else {
    323         stm(db_w, sp, src1.bit() | src2.bit(), cond);
    324         str(src3, MemOperand(sp, 4, NegPreIndex), cond);
    325       }
    326     } else {
    327       str(src1, MemOperand(sp, 4, NegPreIndex), cond);
    328       Push(src2, src3, cond);
    329     }
    330   }
    331 
    332   // Push four registers.  Pushes leftmost register first (to highest address).
    333   void Push(Register src1,
    334             Register src2,
    335             Register src3,
    336             Register src4,
    337             Condition cond = al) {
    338     ASSERT(!src1.is(src2));
    339     ASSERT(!src2.is(src3));
    340     ASSERT(!src1.is(src3));
    341     ASSERT(!src1.is(src4));
    342     ASSERT(!src2.is(src4));
    343     ASSERT(!src3.is(src4));
    344     if (src1.code() > src2.code()) {
    345       if (src2.code() > src3.code()) {
    346         if (src3.code() > src4.code()) {
    347           stm(db_w,
    348               sp,
    349               src1.bit() | src2.bit() | src3.bit() | src4.bit(),
    350               cond);
    351         } else {
    352           stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
    353           str(src4, MemOperand(sp, 4, NegPreIndex), cond);
    354         }
    355       } else {
    356         stm(db_w, sp, src1.bit() | src2.bit(), cond);
    357         Push(src3, src4, cond);
    358       }
    359     } else {
    360       str(src1, MemOperand(sp, 4, NegPreIndex), cond);
    361       Push(src2, src3, src4, cond);
    362     }
    363   }
    364 
    365   // Pop two registers. Pops rightmost register first (from lower address).
    366   void Pop(Register src1, Register src2, Condition cond = al) {
    367     ASSERT(!src1.is(src2));
    368     if (src1.code() > src2.code()) {
    369       ldm(ia_w, sp, src1.bit() | src2.bit(), cond);
    370     } else {
    371       ldr(src2, MemOperand(sp, 4, PostIndex), cond);
    372       ldr(src1, MemOperand(sp, 4, PostIndex), cond);
    373     }
    374   }
    375 
    376   // Pop three registers.  Pops rightmost register first (from lower address).
    377   void Pop(Register src1, Register src2, Register src3, Condition cond = al) {
    378     ASSERT(!src1.is(src2));
    379     ASSERT(!src2.is(src3));
    380     ASSERT(!src1.is(src3));
    381     if (src1.code() > src2.code()) {
    382       if (src2.code() > src3.code()) {
    383         ldm(ia_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
    384       } else {
    385         ldr(src3, MemOperand(sp, 4, PostIndex), cond);
    386         ldm(ia_w, sp, src1.bit() | src2.bit(), cond);
    387       }
    388     } else {
    389       Pop(src2, src3, cond);
    390       str(src1, MemOperand(sp, 4, PostIndex), cond);
    391     }
    392   }
    393 
    394   // Pop four registers.  Pops rightmost register first (from lower address).
    395   void Pop(Register src1,
    396            Register src2,
    397            Register src3,
    398            Register src4,
    399            Condition cond = al) {
    400     ASSERT(!src1.is(src2));
    401     ASSERT(!src2.is(src3));
    402     ASSERT(!src1.is(src3));
    403     ASSERT(!src1.is(src4));
    404     ASSERT(!src2.is(src4));
    405     ASSERT(!src3.is(src4));
    406     if (src1.code() > src2.code()) {
    407       if (src2.code() > src3.code()) {
    408         if (src3.code() > src4.code()) {
    409           ldm(ia_w,
    410               sp,
    411               src1.bit() | src2.bit() | src3.bit() | src4.bit(),
    412               cond);
    413         } else {
    414           ldr(src4, MemOperand(sp, 4, PostIndex), cond);
    415           ldm(ia_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
    416         }
    417       } else {
    418         Pop(src3, src4, cond);
    419         ldm(ia_w, sp, src1.bit() | src2.bit(), cond);
    420       }
    421     } else {
    422       Pop(src2, src3, src4, cond);
    423       ldr(src1, MemOperand(sp, 4, PostIndex), cond);
    424     }
    425   }
    426 
    427   // Push and pop the registers that can hold pointers, as defined by the
    428   // RegList constant kSafepointSavedRegisters.
    429   void PushSafepointRegisters();
    430   void PopSafepointRegisters();
    431   void PushSafepointRegistersAndDoubles();
    432   void PopSafepointRegistersAndDoubles();
    433   // Store value in register src in the safepoint stack slot for
    434   // register dst.
    435   void StoreToSafepointRegisterSlot(Register src, Register dst);
    436   void StoreToSafepointRegistersAndDoublesSlot(Register src, Register dst);
    437   // Load the value of the src register from its safepoint stack slot
    438   // into register dst.
    439   void LoadFromSafepointRegisterSlot(Register dst, Register src);
    440 
    441   // Load two consecutive registers with two consecutive memory locations.
    442   void Ldrd(Register dst1,
    443             Register dst2,
    444             const MemOperand& src,
    445             Condition cond = al);
    446 
    447   // Store two consecutive registers to two consecutive memory locations.
    448   void Strd(Register src1,
    449             Register src2,
    450             const MemOperand& dst,
    451             Condition cond = al);
    452 
    453   // Clear specified FPSCR bits.
    454   void ClearFPSCRBits(const uint32_t bits_to_clear,
    455                       const Register scratch,
    456                       const Condition cond = al);
    457 
    458   // Compare double values and move the result to the normal condition flags.
    459   void VFPCompareAndSetFlags(const DwVfpRegister src1,
    460                              const DwVfpRegister src2,
    461                              const Condition cond = al);
    462   void VFPCompareAndSetFlags(const DwVfpRegister src1,
    463                              const double src2,
    464                              const Condition cond = al);
    465 
    466   // Compare double values and then load the fpscr flags to a register.
    467   void VFPCompareAndLoadFlags(const DwVfpRegister src1,
    468                               const DwVfpRegister src2,
    469                               const Register fpscr_flags,
    470                               const Condition cond = al);
    471   void VFPCompareAndLoadFlags(const DwVfpRegister src1,
    472                               const double src2,
    473                               const Register fpscr_flags,
    474                               const Condition cond = al);
    475 
    476   void Vmov(const DwVfpRegister dst,
    477             const double imm,
    478             const Condition cond = al);
    479 
    480   // Enter exit frame.
    481   // stack_space - extra stack space, used for alignment before call to C.
    482   void EnterExitFrame(bool save_doubles, int stack_space = 0);
    483 
    484   // Leave the current exit frame. Expects the return value in r0.
    485   // Expect the number of values, pushed prior to the exit frame, to
    486   // remove in a register (or no_reg, if there is nothing to remove).
    487   void LeaveExitFrame(bool save_doubles, Register argument_count);
    488 
    489   // Get the actual activation frame alignment for target environment.
    490   static int ActivationFrameAlignment();
    491 
    492   void LoadContext(Register dst, int context_chain_length);
    493 
    494   // Conditionally load the cached Array transitioned map of type
    495   // transitioned_kind from the global context if the map in register
    496   // map_in_out is the cached Array map in the global context of
    497   // expected_kind.
    498   void LoadTransitionedArrayMapConditional(
    499       ElementsKind expected_kind,
    500       ElementsKind transitioned_kind,
    501       Register map_in_out,
    502       Register scratch,
    503       Label* no_map_match);
    504 
    505   // Load the initial map for new Arrays from a JSFunction.
    506   void LoadInitialArrayMap(Register function_in,
    507                            Register scratch,
    508                            Register map_out);
    509 
    510   void LoadGlobalFunction(int index, Register function);
    511 
    512   // Load the initial map from the global function. The registers
    513   // function and map can be the same, function is then overwritten.
    514   void LoadGlobalFunctionInitialMap(Register function,
    515                                     Register map,
    516                                     Register scratch);
    517 
    518   void InitializeRootRegister() {
    519     ExternalReference roots_array_start =
    520         ExternalReference::roots_array_start(isolate());
    521     mov(kRootRegister, Operand(roots_array_start));
    522   }
    523 
    524   // ---------------------------------------------------------------------------
    525   // JavaScript invokes
    526 
    527   // Set up call kind marking in ecx. The method takes ecx as an
    528   // explicit first parameter to make the code more readable at the
    529   // call sites.
    530   void SetCallKind(Register dst, CallKind kind);
    531 
    532   // Invoke the JavaScript function code by either calling or jumping.
    533   void InvokeCode(Register code,
    534                   const ParameterCount& expected,
    535                   const ParameterCount& actual,
    536                   InvokeFlag flag,
    537                   const CallWrapper& call_wrapper,
    538                   CallKind call_kind);
    539 
    540   void InvokeCode(Handle<Code> code,
    541                   const ParameterCount& expected,
    542                   const ParameterCount& actual,
    543                   RelocInfo::Mode rmode,
    544                   InvokeFlag flag,
    545                   CallKind call_kind);
    546 
    547   // Invoke the JavaScript function in the given register. Changes the
    548   // current context to the context in the function before invoking.
    549   void InvokeFunction(Register function,
    550                       const ParameterCount& actual,
    551                       InvokeFlag flag,
    552                       const CallWrapper& call_wrapper,
    553                       CallKind call_kind);
    554 
    555   void InvokeFunction(Handle<JSFunction> function,
    556                       const ParameterCount& actual,
    557                       InvokeFlag flag,
    558                       const CallWrapper& call_wrapper,
    559                       CallKind call_kind);
    560 
    561   void IsObjectJSObjectType(Register heap_object,
    562                             Register map,
    563                             Register scratch,
    564                             Label* fail);
    565 
    566   void IsInstanceJSObjectType(Register map,
    567                               Register scratch,
    568                               Label* fail);
    569 
    570   void IsObjectJSStringType(Register object,
    571                             Register scratch,
    572                             Label* fail);
    573 
    574 #ifdef ENABLE_DEBUGGER_SUPPORT
    575   // ---------------------------------------------------------------------------
    576   // Debugger Support
    577 
    578   void DebugBreak();
    579 #endif
    580 
    581   // ---------------------------------------------------------------------------
    582   // Exception handling
    583 
    584   // Push a new try handler and link into try handler chain.
    585   void PushTryHandler(StackHandler::Kind kind, int handler_index);
    586 
    587   // Unlink the stack handler on top of the stack from the try handler chain.
    588   // Must preserve the result register.
    589   void PopTryHandler();
    590 
    591   // Passes thrown value to the handler of top of the try handler chain.
    592   void Throw(Register value);
    593 
    594   // Propagates an uncatchable exception to the top of the current JS stack's
    595   // handler chain.
    596   void ThrowUncatchable(Register value);
    597 
    598   // ---------------------------------------------------------------------------
    599   // Inline caching support
    600 
    601   // Generate code for checking access rights - used for security checks
    602   // on access to global objects across environments. The holder register
    603   // is left untouched, whereas both scratch registers are clobbered.
    604   void CheckAccessGlobalProxy(Register holder_reg,
    605                               Register scratch,
    606                               Label* miss);
    607 
    608   void GetNumberHash(Register t0, Register scratch);
    609 
    610   void LoadFromNumberDictionary(Label* miss,
    611                                 Register elements,
    612                                 Register key,
    613                                 Register result,
    614                                 Register t0,
    615                                 Register t1,
    616                                 Register t2);
    617 
    618 
    619   inline void MarkCode(NopMarkerTypes type) {
    620     nop(type);
    621   }
    622 
    623   // Check if the given instruction is a 'type' marker.
    624   // i.e. check if is is a mov r<type>, r<type> (referenced as nop(type))
    625   // These instructions are generated to mark special location in the code,
    626   // like some special IC code.
    627   static inline bool IsMarkedCode(Instr instr, int type) {
    628     ASSERT((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER));
    629     return IsNop(instr, type);
    630   }
    631 
    632 
    633   static inline int GetCodeMarker(Instr instr) {
    634     int dst_reg_offset = 12;
    635     int dst_mask = 0xf << dst_reg_offset;
    636     int src_mask = 0xf;
    637     int dst_reg = (instr & dst_mask) >> dst_reg_offset;
    638     int src_reg = instr & src_mask;
    639     uint32_t non_register_mask = ~(dst_mask | src_mask);
    640     uint32_t mov_mask = al | 13 << 21;
    641 
    642     // Return <n> if we have a mov rn rn, else return -1.
    643     int type = ((instr & non_register_mask) == mov_mask) &&
    644                (dst_reg == src_reg) &&
    645                (FIRST_IC_MARKER <= dst_reg) && (dst_reg < LAST_CODE_MARKER)
    646                    ? src_reg
    647                    : -1;
    648     ASSERT((type == -1) ||
    649            ((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER)));
    650     return type;
    651   }
    652 
    653 
    654   // ---------------------------------------------------------------------------
    655   // Allocation support
    656 
    657   // Allocate an object in new space. The object_size is specified
    658   // either in bytes or in words if the allocation flag SIZE_IN_WORDS
    659   // is passed. If the new space is exhausted control continues at the
    660   // gc_required label. The allocated object is returned in result. If
    661   // the flag tag_allocated_object is true the result is tagged as as
    662   // a heap object. All registers are clobbered also when control
    663   // continues at the gc_required label.
    664   void AllocateInNewSpace(int object_size,
    665                           Register result,
    666                           Register scratch1,
    667                           Register scratch2,
    668                           Label* gc_required,
    669                           AllocationFlags flags);
    670   void AllocateInNewSpace(Register object_size,
    671                           Register result,
    672                           Register scratch1,
    673                           Register scratch2,
    674                           Label* gc_required,
    675                           AllocationFlags flags);
    676 
    677   // Undo allocation in new space. The object passed and objects allocated after
    678   // it will no longer be allocated. The caller must make sure that no pointers
    679   // are left to the object(s) no longer allocated as they would be invalid when
    680   // allocation is undone.
    681   void UndoAllocationInNewSpace(Register object, Register scratch);
    682 
    683 
    684   void AllocateTwoByteString(Register result,
    685                              Register length,
    686                              Register scratch1,
    687                              Register scratch2,
    688                              Register scratch3,
    689                              Label* gc_required);
    690   void AllocateAsciiString(Register result,
    691                            Register length,
    692                            Register scratch1,
    693                            Register scratch2,
    694                            Register scratch3,
    695                            Label* gc_required);
    696   void AllocateTwoByteConsString(Register result,
    697                                  Register length,
    698                                  Register scratch1,
    699                                  Register scratch2,
    700                                  Label* gc_required);
    701   void AllocateAsciiConsString(Register result,
    702                                Register length,
    703                                Register scratch1,
    704                                Register scratch2,
    705                                Label* gc_required);
    706   void AllocateTwoByteSlicedString(Register result,
    707                                    Register length,
    708                                    Register scratch1,
    709                                    Register scratch2,
    710                                    Label* gc_required);
    711   void AllocateAsciiSlicedString(Register result,
    712                                  Register length,
    713                                  Register scratch1,
    714                                  Register scratch2,
    715                                  Label* gc_required);
    716 
    717   // Allocates a heap number or jumps to the gc_required label if the young
    718   // space is full and a scavenge is needed. All registers are clobbered also
    719   // when control continues at the gc_required label.
    720   void AllocateHeapNumber(Register result,
    721                           Register scratch1,
    722                           Register scratch2,
    723                           Register heap_number_map,
    724                           Label* gc_required);
    725   void AllocateHeapNumberWithValue(Register result,
    726                                    DwVfpRegister value,
    727                                    Register scratch1,
    728                                    Register scratch2,
    729                                    Register heap_number_map,
    730                                    Label* gc_required);
    731 
    732   // Copies a fixed number of fields of heap objects from src to dst.
    733   void CopyFields(Register dst, Register src, RegList temps, int field_count);
    734 
    735   // Copies a number of bytes from src to dst. All registers are clobbered. On
    736   // exit src and dst will point to the place just after where the last byte was
    737   // read or written and length will be zero.
    738   void CopyBytes(Register src,
    739                  Register dst,
    740                  Register length,
    741                  Register scratch);
    742 
    743   // Initialize fields with filler values.  Fields starting at |start_offset|
    744   // not including end_offset are overwritten with the value in |filler|.  At
    745   // the end the loop, |start_offset| takes the value of |end_offset|.
    746   void InitializeFieldsWithFiller(Register start_offset,
    747                                   Register end_offset,
    748                                   Register filler);
    749 
    750   // ---------------------------------------------------------------------------
    751   // Support functions.
    752 
    753   // Try to get function prototype of a function and puts the value in
    754   // the result register. Checks that the function really is a
    755   // function and jumps to the miss label if the fast checks fail. The
    756   // function register will be untouched; the other registers may be
    757   // clobbered.
    758   void TryGetFunctionPrototype(Register function,
    759                                Register result,
    760                                Register scratch,
    761                                Label* miss,
    762                                bool miss_on_bound_function = false);
    763 
    764   // Compare object type for heap object.  heap_object contains a non-Smi
    765   // whose object type should be compared with the given type.  This both
    766   // sets the flags and leaves the object type in the type_reg register.
    767   // It leaves the map in the map register (unless the type_reg and map register
    768   // are the same register).  It leaves the heap object in the heap_object
    769   // register unless the heap_object register is the same register as one of the
    770   // other registers.
    771   void CompareObjectType(Register heap_object,
    772                          Register map,
    773                          Register type_reg,
    774                          InstanceType type);
    775 
    776   // Compare instance type in a map.  map contains a valid map object whose
    777   // object type should be compared with the given type.  This both
    778   // sets the flags and leaves the object type in the type_reg register.
    779   void CompareInstanceType(Register map,
    780                            Register type_reg,
    781                            InstanceType type);
    782 
    783 
    784   // Check if a map for a JSObject indicates that the object has fast elements.
    785   // Jump to the specified label if it does not.
    786   void CheckFastElements(Register map,
    787                          Register scratch,
    788                          Label* fail);
    789 
    790   // Check if a map for a JSObject indicates that the object can have both smi
    791   // and HeapObject elements.  Jump to the specified label if it does not.
    792   void CheckFastObjectElements(Register map,
    793                                Register scratch,
    794                                Label* fail);
    795 
    796   // Check if a map for a JSObject indicates that the object has fast smi only
    797   // elements.  Jump to the specified label if it does not.
    798   void CheckFastSmiOnlyElements(Register map,
    799                                 Register scratch,
    800                                 Label* fail);
    801 
    802   // Check to see if maybe_number can be stored as a double in
    803   // FastDoubleElements. If it can, store it at the index specified by key in
    804   // the FastDoubleElements array elements. Otherwise jump to fail, in which
    805   // case scratch2, scratch3 and scratch4 are unmodified.
    806   void StoreNumberToDoubleElements(Register value_reg,
    807                                    Register key_reg,
    808                                    Register receiver_reg,
    809                                    Register elements_reg,
    810                                    Register scratch1,
    811                                    Register scratch2,
    812                                    Register scratch3,
    813                                    Register scratch4,
    814                                    Label* fail);
    815 
    816   // Compare an object's map with the specified map and its transitioned
    817   // elements maps if mode is ALLOW_ELEMENT_TRANSITION_MAPS. Condition flags are
    818   // set with result of map compare. If multiple map compares are required, the
    819   // compare sequences branches to early_success.
    820   void CompareMap(Register obj,
    821                   Register scratch,
    822                   Handle<Map> map,
    823                   Label* early_success,
    824                   CompareMapMode mode = REQUIRE_EXACT_MAP);
    825 
    826   // Check if the map of an object is equal to a specified map and branch to
    827   // label if not. Skip the smi check if not required (object is known to be a
    828   // heap object). If mode is ALLOW_ELEMENT_TRANSITION_MAPS, then also match
    829   // against maps that are ElementsKind transition maps of the specified map.
    830   void CheckMap(Register obj,
    831                 Register scratch,
    832                 Handle<Map> map,
    833                 Label* fail,
    834                 SmiCheckType smi_check_type,
    835                 CompareMapMode mode = REQUIRE_EXACT_MAP);
    836 
    837 
    838   void CheckMap(Register obj,
    839                 Register scratch,
    840                 Heap::RootListIndex index,
    841                 Label* fail,
    842                 SmiCheckType smi_check_type);
    843 
    844 
    845   // Check if the map of an object is equal to a specified map and branch to a
    846   // specified target if equal. Skip the smi check if not required (object is
    847   // known to be a heap object)
    848   void DispatchMap(Register obj,
    849                    Register scratch,
    850                    Handle<Map> map,
    851                    Handle<Code> success,
    852                    SmiCheckType smi_check_type);
    853 
    854 
    855   // Compare the object in a register to a value from the root list.
    856   // Uses the ip register as scratch.
    857   void CompareRoot(Register obj, Heap::RootListIndex index);
    858 
    859 
    860   // Load and check the instance type of an object for being a string.
    861   // Loads the type into the second argument register.
    862   // Returns a condition that will be enabled if the object was a string.
    863   Condition IsObjectStringType(Register obj,
    864                                Register type) {
    865     ldr(type, FieldMemOperand(obj, HeapObject::kMapOffset));
    866     ldrb(type, FieldMemOperand(type, Map::kInstanceTypeOffset));
    867     tst(type, Operand(kIsNotStringMask));
    868     ASSERT_EQ(0, kStringTag);
    869     return eq;
    870   }
    871 
    872 
    873   // Generates code for reporting that an illegal operation has
    874   // occurred.
    875   void IllegalOperation(int num_arguments);
    876 
    877   // Picks out an array index from the hash field.
    878   // Register use:
    879   //   hash - holds the index's hash. Clobbered.
    880   //   index - holds the overwritten index on exit.
    881   void IndexFromHash(Register hash, Register index);
    882 
    883   // Get the number of least significant bits from a register
    884   void GetLeastBitsFromSmi(Register dst, Register src, int num_least_bits);
    885   void GetLeastBitsFromInt32(Register dst, Register src, int mun_least_bits);
    886 
    887   // Uses VFP instructions to Convert a Smi to a double.
    888   void IntegerToDoubleConversionWithVFP3(Register inReg,
    889                                          Register outHighReg,
    890                                          Register outLowReg);
    891 
    892   // Load the value of a number object into a VFP double register. If the object
    893   // is not a number a jump to the label not_number is performed and the VFP
    894   // double register is unchanged.
    895   void ObjectToDoubleVFPRegister(
    896       Register object,
    897       DwVfpRegister value,
    898       Register scratch1,
    899       Register scratch2,
    900       Register heap_number_map,
    901       SwVfpRegister scratch3,
    902       Label* not_number,
    903       ObjectToDoubleFlags flags = NO_OBJECT_TO_DOUBLE_FLAGS);
    904 
    905   // Load the value of a smi object into a VFP double register. The register
    906   // scratch1 can be the same register as smi in which case smi will hold the
    907   // untagged value afterwards.
    908   void SmiToDoubleVFPRegister(Register smi,
    909                               DwVfpRegister value,
    910                               Register scratch1,
    911                               SwVfpRegister scratch2);
    912 
    913   // Convert the HeapNumber pointed to by source to a 32bits signed integer
    914   // dest. If the HeapNumber does not fit into a 32bits signed integer branch
    915   // to not_int32 label. If VFP3 is available double_scratch is used but not
    916   // scratch2.
    917   void ConvertToInt32(Register source,
    918                       Register dest,
    919                       Register scratch,
    920                       Register scratch2,
    921                       DwVfpRegister double_scratch,
    922                       Label *not_int32);
    923 
    924   // Truncates a double using a specific rounding mode.
    925   // Clears the z flag (ne condition) if an overflow occurs.
    926   // If exact_conversion is true, the z flag is also cleared if the conversion
    927   // was inexact, i.e. if the double value could not be converted exactly
    928   // to a 32bit integer.
    929   void EmitVFPTruncate(VFPRoundingMode rounding_mode,
    930                        SwVfpRegister result,
    931                        DwVfpRegister double_input,
    932                        Register scratch1,
    933                        Register scratch2,
    934                        CheckForInexactConversion check
    935                            = kDontCheckForInexactConversion);
    936 
    937   // Helper for EmitECMATruncate.
    938   // This will truncate a floating-point value outside of the singed 32bit
    939   // integer range to a 32bit signed integer.
    940   // Expects the double value loaded in input_high and input_low.
    941   // Exits with the answer in 'result'.
    942   // Note that this code does not work for values in the 32bit range!
    943   void EmitOutOfInt32RangeTruncate(Register result,
    944                                    Register input_high,
    945                                    Register input_low,
    946                                    Register scratch);
    947 
    948   // Performs a truncating conversion of a floating point number as used by
    949   // the JS bitwise operations. See ECMA-262 9.5: ToInt32.
    950   // Exits with 'result' holding the answer and all other registers clobbered.
    951   void EmitECMATruncate(Register result,
    952                         DwVfpRegister double_input,
    953                         SwVfpRegister single_scratch,
    954                         Register scratch,
    955                         Register scratch2,
    956                         Register scratch3);
    957 
    958   // Count leading zeros in a 32 bit word.  On ARM5 and later it uses the clz
    959   // instruction.  On pre-ARM5 hardware this routine gives the wrong answer
    960   // for 0 (31 instead of 32).  Source and scratch can be the same in which case
    961   // the source is clobbered.  Source and zeros can also be the same in which
    962   // case scratch should be a different register.
    963   void CountLeadingZeros(Register zeros,
    964                          Register source,
    965                          Register scratch);
    966 
    967   // ---------------------------------------------------------------------------
    968   // Runtime calls
    969 
    970   // Call a code stub.
    971   void CallStub(CodeStub* stub, Condition cond = al);
    972 
    973   // Call a code stub.
    974   void TailCallStub(CodeStub* stub, Condition cond = al);
    975 
    976   // Call a runtime routine.
    977   void CallRuntime(const Runtime::Function* f, int num_arguments);
    978   void CallRuntimeSaveDoubles(Runtime::FunctionId id);
    979 
    980   // Convenience function: Same as above, but takes the fid instead.
    981   void CallRuntime(Runtime::FunctionId fid, int num_arguments);
    982 
    983   // Convenience function: call an external reference.
    984   void CallExternalReference(const ExternalReference& ext,
    985                              int num_arguments);
    986 
    987   // Tail call of a runtime routine (jump).
    988   // Like JumpToExternalReference, but also takes care of passing the number
    989   // of parameters.
    990   void TailCallExternalReference(const ExternalReference& ext,
    991                                  int num_arguments,
    992                                  int result_size);
    993 
    994   // Convenience function: tail call a runtime routine (jump).
    995   void TailCallRuntime(Runtime::FunctionId fid,
    996                        int num_arguments,
    997                        int result_size);
    998 
    999   int CalculateStackPassedWords(int num_reg_arguments,
   1000                                 int num_double_arguments);
   1001 
   1002   // Before calling a C-function from generated code, align arguments on stack.
   1003   // After aligning the frame, non-register arguments must be stored in
   1004   // sp[0], sp[4], etc., not pushed. The argument count assumes all arguments
   1005   // are word sized. If double arguments are used, this function assumes that
   1006   // all double arguments are stored before core registers; otherwise the
   1007   // correct alignment of the double values is not guaranteed.
   1008   // Some compilers/platforms require the stack to be aligned when calling
   1009   // C++ code.
   1010   // Needs a scratch register to do some arithmetic. This register will be
   1011   // trashed.
   1012   void PrepareCallCFunction(int num_reg_arguments,
   1013                             int num_double_registers,
   1014                             Register scratch);
   1015   void PrepareCallCFunction(int num_reg_arguments,
   1016                             Register scratch);
   1017 
   1018   // There are two ways of passing double arguments on ARM, depending on
   1019   // whether soft or hard floating point ABI is used. These functions
   1020   // abstract parameter passing for the three different ways we call
   1021   // C functions from generated code.
   1022   void SetCallCDoubleArguments(DoubleRegister dreg);
   1023   void SetCallCDoubleArguments(DoubleRegister dreg1, DoubleRegister dreg2);
   1024   void SetCallCDoubleArguments(DoubleRegister dreg, Register reg);
   1025 
   1026   // Calls a C function and cleans up the space for arguments allocated
   1027   // by PrepareCallCFunction. The called function is not allowed to trigger a
   1028   // garbage collection, since that might move the code and invalidate the
   1029   // return address (unless this is somehow accounted for by the called
   1030   // function).
   1031   void CallCFunction(ExternalReference function, int num_arguments);
   1032   void CallCFunction(Register function, int num_arguments);
   1033   void CallCFunction(ExternalReference function,
   1034                      int num_reg_arguments,
   1035                      int num_double_arguments);
   1036   void CallCFunction(Register function,
   1037                      int num_reg_arguments,
   1038                      int num_double_arguments);
   1039 
   1040   void GetCFunctionDoubleResult(const DoubleRegister dst);
   1041 
   1042   // Calls an API function.  Allocates HandleScope, extracts returned value
   1043   // from handle and propagates exceptions.  Restores context.  stack_space
   1044   // - space to be unwound on exit (includes the call JS arguments space and
   1045   // the additional space allocated for the fast call).
   1046   void CallApiFunctionAndReturn(ExternalReference function, int stack_space);
   1047 
   1048   // Jump to a runtime routine.
   1049   void JumpToExternalReference(const ExternalReference& builtin);
   1050 
   1051   // Invoke specified builtin JavaScript function. Adds an entry to
   1052   // the unresolved list if the name does not resolve.
   1053   void InvokeBuiltin(Builtins::JavaScript id,
   1054                      InvokeFlag flag,
   1055                      const CallWrapper& call_wrapper = NullCallWrapper());
   1056 
   1057   // Store the code object for the given builtin in the target register and
   1058   // setup the function in r1.
   1059   void GetBuiltinEntry(Register target, Builtins::JavaScript id);
   1060 
   1061   // Store the function for the given builtin in the target register.
   1062   void GetBuiltinFunction(Register target, Builtins::JavaScript id);
   1063 
   1064   Handle<Object> CodeObject() {
   1065     ASSERT(!code_object_.is_null());
   1066     return code_object_;
   1067   }
   1068 
   1069 
   1070   // ---------------------------------------------------------------------------
   1071   // StatsCounter support
   1072 
   1073   void SetCounter(StatsCounter* counter, int value,
   1074                   Register scratch1, Register scratch2);
   1075   void IncrementCounter(StatsCounter* counter, int value,
   1076                         Register scratch1, Register scratch2);
   1077   void DecrementCounter(StatsCounter* counter, int value,
   1078                         Register scratch1, Register scratch2);
   1079 
   1080 
   1081   // ---------------------------------------------------------------------------
   1082   // Debugging
   1083 
   1084   // Calls Abort(msg) if the condition cond is not satisfied.
   1085   // Use --debug_code to enable.
   1086   void Assert(Condition cond, const char* msg);
   1087   void AssertRegisterIsRoot(Register reg, Heap::RootListIndex index);
   1088   void AssertFastElements(Register elements);
   1089 
   1090   // Like Assert(), but always enabled.
   1091   void Check(Condition cond, const char* msg);
   1092 
   1093   // Print a message to stdout and abort execution.
   1094   void Abort(const char* msg);
   1095 
   1096   // Verify restrictions about code generated in stubs.
   1097   void set_generating_stub(bool value) { generating_stub_ = value; }
   1098   bool generating_stub() { return generating_stub_; }
   1099   void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; }
   1100   bool allow_stub_calls() { return allow_stub_calls_; }
   1101   void set_has_frame(bool value) { has_frame_ = value; }
   1102   bool has_frame() { return has_frame_; }
   1103   inline bool AllowThisStubCall(CodeStub* stub);
   1104 
   1105   // EABI variant for double arguments in use.
   1106   bool use_eabi_hardfloat() {
   1107 #if USE_EABI_HARDFLOAT
   1108     return true;
   1109 #else
   1110     return false;
   1111 #endif
   1112   }
   1113 
   1114   // ---------------------------------------------------------------------------
   1115   // Number utilities
   1116 
   1117   // Check whether the value of reg is a power of two and not zero. If not
   1118   // control continues at the label not_power_of_two. If reg is a power of two
   1119   // the register scratch contains the value of (reg - 1) when control falls
   1120   // through.
   1121   void JumpIfNotPowerOfTwoOrZero(Register reg,
   1122                                  Register scratch,
   1123                                  Label* not_power_of_two_or_zero);
   1124   // Check whether the value of reg is a power of two and not zero.
   1125   // Control falls through if it is, with scratch containing the mask
   1126   // value (reg - 1).
   1127   // Otherwise control jumps to the 'zero_and_neg' label if the value of reg is
   1128   // zero or negative, or jumps to the 'not_power_of_two' label if the value is
   1129   // strictly positive but not a power of two.
   1130   void JumpIfNotPowerOfTwoOrZeroAndNeg(Register reg,
   1131                                        Register scratch,
   1132                                        Label* zero_and_neg,
   1133                                        Label* not_power_of_two);
   1134 
   1135   // ---------------------------------------------------------------------------
   1136   // Smi utilities
   1137 
   1138   void SmiTag(Register reg, SBit s = LeaveCC) {
   1139     add(reg, reg, Operand(reg), s);
   1140   }
   1141   void SmiTag(Register dst, Register src, SBit s = LeaveCC) {
   1142     add(dst, src, Operand(src), s);
   1143   }
   1144 
   1145   // Try to convert int32 to smi. If the value is to large, preserve
   1146   // the original value and jump to not_a_smi. Destroys scratch and
   1147   // sets flags.
   1148   void TrySmiTag(Register reg, Label* not_a_smi, Register scratch) {
   1149     mov(scratch, reg);
   1150     SmiTag(scratch, SetCC);
   1151     b(vs, not_a_smi);
   1152     mov(reg, scratch);
   1153   }
   1154 
   1155   void SmiUntag(Register reg, SBit s = LeaveCC) {
   1156     mov(reg, Operand(reg, ASR, kSmiTagSize), s);
   1157   }
   1158   void SmiUntag(Register dst, Register src, SBit s = LeaveCC) {
   1159     mov(dst, Operand(src, ASR, kSmiTagSize), s);
   1160   }
   1161 
   1162   // Untag the source value into destination and jump if source is a smi.
   1163   // Souce and destination can be the same register.
   1164   void UntagAndJumpIfSmi(Register dst, Register src, Label* smi_case);
   1165 
   1166   // Untag the source value into destination and jump if source is not a smi.
   1167   // Souce and destination can be the same register.
   1168   void UntagAndJumpIfNotSmi(Register dst, Register src, Label* non_smi_case);
   1169 
   1170   // Jump the register contains a smi.
   1171   inline void JumpIfSmi(Register value, Label* smi_label) {
   1172     tst(value, Operand(kSmiTagMask));
   1173     b(eq, smi_label);
   1174   }
   1175   // Jump if either of the registers contain a non-smi.
   1176   inline void JumpIfNotSmi(Register value, Label* not_smi_label) {
   1177     tst(value, Operand(kSmiTagMask));
   1178     b(ne, not_smi_label);
   1179   }
   1180   // Jump if either of the registers contain a non-smi.
   1181   void JumpIfNotBothSmi(Register reg1, Register reg2, Label* on_not_both_smi);
   1182   // Jump if either of the registers contain a smi.
   1183   void JumpIfEitherSmi(Register reg1, Register reg2, Label* on_either_smi);
   1184 
   1185   // Abort execution if argument is a smi. Used in debug code.
   1186   void AbortIfSmi(Register object);
   1187   void AbortIfNotSmi(Register object);
   1188 
   1189   // Abort execution if argument is a string. Used in debug code.
   1190   void AbortIfNotString(Register object);
   1191 
   1192   // Abort execution if argument is not the root value with the given index.
   1193   void AbortIfNotRootValue(Register src,
   1194                            Heap::RootListIndex root_value_index,
   1195                            const char* message);
   1196 
   1197   // ---------------------------------------------------------------------------
   1198   // HeapNumber utilities
   1199 
   1200   void JumpIfNotHeapNumber(Register object,
   1201                            Register heap_number_map,
   1202                            Register scratch,
   1203                            Label* on_not_heap_number);
   1204 
   1205   // ---------------------------------------------------------------------------
   1206   // String utilities
   1207 
   1208   // Checks if both objects are sequential ASCII strings and jumps to label
   1209   // if either is not. Assumes that neither object is a smi.
   1210   void JumpIfNonSmisNotBothSequentialAsciiStrings(Register object1,
   1211                                                   Register object2,
   1212                                                   Register scratch1,
   1213                                                   Register scratch2,
   1214                                                   Label* failure);
   1215 
   1216   // Checks if both objects are sequential ASCII strings and jumps to label
   1217   // if either is not.
   1218   void JumpIfNotBothSequentialAsciiStrings(Register first,
   1219                                            Register second,
   1220                                            Register scratch1,
   1221                                            Register scratch2,
   1222                                            Label* not_flat_ascii_strings);
   1223 
   1224   // Checks if both instance types are sequential ASCII strings and jumps to
   1225   // label if either is not.
   1226   void JumpIfBothInstanceTypesAreNotSequentialAscii(
   1227       Register first_object_instance_type,
   1228       Register second_object_instance_type,
   1229       Register scratch1,
   1230       Register scratch2,
   1231       Label* failure);
   1232 
   1233   // Check if instance type is sequential ASCII string and jump to label if
   1234   // it is not.
   1235   void JumpIfInstanceTypeIsNotSequentialAscii(Register type,
   1236                                               Register scratch,
   1237                                               Label* failure);
   1238 
   1239 
   1240   // ---------------------------------------------------------------------------
   1241   // Patching helpers.
   1242 
   1243   // Get the location of a relocated constant (its address in the constant pool)
   1244   // from its load site.
   1245   void GetRelocatedValueLocation(Register ldr_location,
   1246                                  Register result);
   1247 
   1248 
   1249   void ClampUint8(Register output_reg, Register input_reg);
   1250 
   1251   void ClampDoubleToUint8(Register result_reg,
   1252                           DoubleRegister input_reg,
   1253                           DoubleRegister temp_double_reg);
   1254 
   1255 
   1256   void LoadInstanceDescriptors(Register map, Register descriptors);
   1257 
   1258   // Activation support.
   1259   void EnterFrame(StackFrame::Type type);
   1260   void LeaveFrame(StackFrame::Type type);
   1261 
   1262   // Expects object in r0 and returns map with validated enum cache
   1263   // in r0.  Assumes that any other register can be used as a scratch.
   1264   void CheckEnumCache(Register null_value, Label* call_runtime);
   1265 
   1266  private:
   1267   void CallCFunctionHelper(Register function,
   1268                            int num_reg_arguments,
   1269                            int num_double_arguments);
   1270 
   1271   void Jump(intptr_t target, RelocInfo::Mode rmode, Condition cond = al);
   1272 
   1273   // Helper functions for generating invokes.
   1274   void InvokePrologue(const ParameterCount& expected,
   1275                       const ParameterCount& actual,
   1276                       Handle<Code> code_constant,
   1277                       Register code_reg,
   1278                       Label* done,
   1279                       bool* definitely_mismatches,
   1280                       InvokeFlag flag,
   1281                       const CallWrapper& call_wrapper,
   1282                       CallKind call_kind);
   1283 
   1284   void InitializeNewString(Register string,
   1285                            Register length,
   1286                            Heap::RootListIndex map_index,
   1287                            Register scratch1,
   1288                            Register scratch2);
   1289 
   1290   // Helper for implementing JumpIfNotInNewSpace and JumpIfInNewSpace.
   1291   void InNewSpace(Register object,
   1292                   Register scratch,
   1293                   Condition cond,  // eq for new space, ne otherwise.
   1294                   Label* branch);
   1295 
   1296   // Helper for finding the mark bits for an address.  Afterwards, the
   1297   // bitmap register points at the word with the mark bits and the mask
   1298   // the position of the first bit.  Leaves addr_reg unchanged.
   1299   inline void GetMarkBits(Register addr_reg,
   1300                           Register bitmap_reg,
   1301                           Register mask_reg);
   1302 
   1303   // Helper for throwing exceptions.  Compute a handler address and jump to
   1304   // it.  See the implementation for register usage.
   1305   void JumpToHandlerEntry();
   1306 
   1307   // Compute memory operands for safepoint stack slots.
   1308   static int SafepointRegisterStackIndex(int reg_code);
   1309   MemOperand SafepointRegisterSlot(Register reg);
   1310   MemOperand SafepointRegistersAndDoublesSlot(Register reg);
   1311 
   1312   bool generating_stub_;
   1313   bool allow_stub_calls_;
   1314   bool has_frame_;
   1315   // This handle will be patched with the code object on installation.
   1316   Handle<Object> code_object_;
   1317 
   1318   // Needs access to SafepointRegisterStackIndex for optimized frame
   1319   // traversal.
   1320   friend class OptimizedFrame;
   1321 };
   1322 
   1323 
   1324 #ifdef ENABLE_DEBUGGER_SUPPORT
   1325 // The code patcher is used to patch (typically) small parts of code e.g. for
   1326 // debugging and other types of instrumentation. When using the code patcher
   1327 // the exact number of bytes specified must be emitted. It is not legal to emit
   1328 // relocation information. If any of these constraints are violated it causes
   1329 // an assertion to fail.
   1330 class CodePatcher {
   1331  public:
   1332   CodePatcher(byte* address, int instructions);
   1333   virtual ~CodePatcher();
   1334 
   1335   // Macro assembler to emit code.
   1336   MacroAssembler* masm() { return &masm_; }
   1337 
   1338   // Emit an instruction directly.
   1339   void Emit(Instr instr);
   1340 
   1341   // Emit an address directly.
   1342   void Emit(Address addr);
   1343 
   1344   // Emit the condition part of an instruction leaving the rest of the current
   1345   // instruction unchanged.
   1346   void EmitCondition(Condition cond);
   1347 
   1348  private:
   1349   byte* address_;  // The address of the code being patched.
   1350   int instructions_;  // Number of instructions of the expected patch size.
   1351   int size_;  // Number of bytes of the expected patch size.
   1352   MacroAssembler masm_;  // Macro assembler used to generate the code.
   1353 };
   1354 #endif  // ENABLE_DEBUGGER_SUPPORT
   1355 
   1356 
   1357 // -----------------------------------------------------------------------------
   1358 // Static helper functions.
   1359 
   1360 inline MemOperand ContextOperand(Register context, int index) {
   1361   return MemOperand(context, Context::SlotOffset(index));
   1362 }
   1363 
   1364 
   1365 inline MemOperand GlobalObjectOperand()  {
   1366   return ContextOperand(cp, Context::GLOBAL_INDEX);
   1367 }
   1368 
   1369 
   1370 #ifdef GENERATED_CODE_COVERAGE
   1371 #define CODE_COVERAGE_STRINGIFY(x) #x
   1372 #define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x)
   1373 #define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__)
   1374 #define ACCESS_MASM(masm) masm->stop(__FILE_LINE__); masm->
   1375 #else
   1376 #define ACCESS_MASM(masm) masm->
   1377 #endif
   1378 
   1379 
   1380 } }  // namespace v8::internal
   1381 
   1382 #endif  // V8_ARM_MACRO_ASSEMBLER_ARM_H_
   1383