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
35namespace v8 {
36namespace internal {
37
38// ----------------------------------------------------------------------------
39// Static helper functions
40
41// Generate a MemOperand for loading a field from an object.
42inline MemOperand FieldMemOperand(Register object, int offset) {
43  return MemOperand(object, offset - kHeapObjectTag);
44}
45
46
47inline Operand SmiUntagOperand(Register object) {
48  return Operand(object, ASR, kSmiTagSize);
49}
50
51
52
53// Give alias names to registers
54const Register cp = { 8 };  // JavaScript context pointer
55const Register kRootRegister = { 10 };  // Roots array pointer.
56
57// Flags used for the AllocateInNewSpace functions.
58enum 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.
73enum 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
83enum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET };
84enum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK };
85enum LinkRegisterStatus { kLRHasNotBeenSaved, kLRHasBeenSaved };
86
87
88bool AreAliased(Register r1, Register r2, Register r3, Register r4);
89
90
91// MacroAssembler implements a collection of frequently used macros.
92class 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.
1330class 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
1360inline MemOperand ContextOperand(Register context, int index) {
1361  return MemOperand(context, Context::SlotOffset(index));
1362}
1363
1364
1365inline 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