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