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