V8 Project
macro-assembler-mips64.h
Go to the documentation of this file.
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_MIPS_MACRO_ASSEMBLER_MIPS_H_
6 #define V8_MIPS_MACRO_ASSEMBLER_MIPS_H_
7 
8 #include "src/assembler.h"
9 #include "src/globals.h"
11 
12 namespace v8 {
13 namespace internal {
14 
15 // Forward declaration.
16 class JumpTarget;
17 
18 // Reserved Register Usage Summary.
19 //
20 // Registers t8, t9, and at are reserved for use by the MacroAssembler.
21 //
22 // The programmer should know that the MacroAssembler may clobber these three,
23 // but won't touch other registers except in special cases.
24 //
25 // Per the MIPS ABI, register t9 must be used for indirect function call
26 // via 'jalr t9' or 'jr t9' instructions. This is relied upon by gcc when
27 // trying to update gp register for position-independent-code. Whenever
28 // MIPS generated code calls C code, it must be via t9 register.
29 
30 
31 // Flags used for LeaveExitFrame function.
33  EMIT_RETURN = true,
34  NO_EMIT_RETURN = false
35 };
36 
37 // Flags used for AllocateHeapNumber
39  // Tag the result.
40  TAG_RESULT,
41  // Don't tag
43 };
44 
45 // Flags used for the ObjectToDoubleFPURegister function.
47  // No special flags.
49  // Object is known to be a non smi.
50  OBJECT_NOT_SMI = 1 << 0,
51  // Don't load NaNs or infinities, branch to the non number case instead.
53 };
54 
55 // Allow programmer to use Branch Delay Slot of Branches, Jumps, Calls.
58  PROTECT
59 };
60 
61 // Flags used for the li macro-assembler function.
62 enum LiFlags {
63  // If the constant value can be represented in just 16 bits, then
64  // optimize the li to use a single instruction, rather than lui/ori/dsll
65  // sequence.
66  OPTIMIZE_SIZE = 0,
67  // Always use 6 instructions (lui/ori/dsll sequence), even if the constant
68  // could be loaded with just one, so that this value is patchable later.
69  CONSTANT_SIZE = 1,
70  // For address loads only 4 instruction are required. Used to mark
71  // constant load that will be used as address without relocation
72  // information. It ensures predictable code size, so specific sites
73  // in code are patchable.
74  ADDRESS_LOAD = 2
75 };
76 
77 
83 };
85 
86 Register GetRegisterThatIsNotOneOf(Register reg1,
87  Register reg2 = no_reg,
88  Register reg3 = no_reg,
89  Register reg4 = no_reg,
90  Register reg5 = no_reg,
91  Register reg6 = no_reg);
92 
93 bool AreAliased(Register reg1,
94  Register reg2,
95  Register reg3 = no_reg,
96  Register reg4 = no_reg,
97  Register reg5 = no_reg,
98  Register reg6 = no_reg,
99  Register reg7 = no_reg,
100  Register reg8 = no_reg);
101 
102 
103 // -----------------------------------------------------------------------------
104 // Static helper functions.
105 
106 inline MemOperand ContextOperand(Register context, int index) {
107  return MemOperand(context, Context::SlotOffset(index));
108 }
109 
110 
113 }
114 
115 
116 // Generate a MemOperand for loading a field from an object.
117 inline MemOperand FieldMemOperand(Register object, int offset) {
118  return MemOperand(object, offset - kHeapObjectTag);
119 }
120 
121 
122 inline MemOperand UntagSmiMemOperand(Register rm, int offset) {
123  // Assumes that Smis are shifted by 32 bits and little endianness.
124  STATIC_ASSERT(kSmiShift == 32);
125  return MemOperand(rm, offset + (kSmiShift / kBitsPerByte));
126 }
127 
128 
129 inline MemOperand UntagSmiFieldMemOperand(Register rm, int offset) {
130  return UntagSmiMemOperand(rm, offset - kHeapObjectTag);
131 }
132 
133 
134 // Generate a MemOperand for storing arguments 5..N on the stack
135 // when calling CallCFunction().
136 // TODO(plind): Currently ONLY used for O32. Should be fixed for
137 // n64, and used in RegExp code, and other places
138 // with more than 8 arguments.
139 inline MemOperand CFunctionArgumentOperand(int index) {
140  DCHECK(index > kCArgSlotCount);
141  // Argument 5 takes the slot just past the four Arg-slots.
142  int offset = (index - 5) * kPointerSize + kCArgsSlotsSize;
143  return MemOperand(sp, offset);
144 }
145 
146 
147 // MacroAssembler implements a collection of frequently used macros.
148 class MacroAssembler: public Assembler {
149  public:
150  // The isolate parameter can be NULL if the macro assembler should
151  // not use isolate-dependent functionality. In this case, it's the
152  // responsibility of the caller to never invoke such function on the
153  // macro assembler.
154  MacroAssembler(Isolate* isolate, void* buffer, int size);
155 
156  // Arguments macros.
157 #define COND_TYPED_ARGS Condition cond, Register r1, const Operand& r2
158 #define COND_ARGS cond, r1, r2
159 
160  // Cases when relocation is not needed.
161 #define DECLARE_NORELOC_PROTOTYPE(Name, target_type) \
162  void Name(target_type target, BranchDelaySlot bd = PROTECT); \
163  inline void Name(BranchDelaySlot bd, target_type target) { \
164  Name(target, bd); \
165  } \
166  void Name(target_type target, \
167  COND_TYPED_ARGS, \
168  BranchDelaySlot bd = PROTECT); \
169  inline void Name(BranchDelaySlot bd, \
170  target_type target, \
171  COND_TYPED_ARGS) { \
172  Name(target, COND_ARGS, bd); \
173  }
174 
175 #define DECLARE_BRANCH_PROTOTYPES(Name) \
176  DECLARE_NORELOC_PROTOTYPE(Name, Label*) \
177  DECLARE_NORELOC_PROTOTYPE(Name, int16_t)
178 
180  DECLARE_BRANCH_PROTOTYPES(BranchAndLink)
181  DECLARE_BRANCH_PROTOTYPES(BranchShort)
182 
183 #undef DECLARE_BRANCH_PROTOTYPES
184 #undef COND_TYPED_ARGS
185 #undef COND_ARGS
186 
187 
188  // Jump, Call, and Ret pseudo instructions implementing inter-working.
189 #define COND_ARGS Condition cond = al, Register rs = zero_reg, \
190  const Operand& rt = Operand(zero_reg), BranchDelaySlot bd = PROTECT
191 
192  void Jump(Register target, COND_ARGS);
193  void Jump(intptr_t target, RelocInfo::Mode rmode, COND_ARGS);
194  void Jump(Address target, RelocInfo::Mode rmode, COND_ARGS);
196  static int CallSize(Register target, COND_ARGS);
197  void Call(Register target, COND_ARGS);
198  static int CallSize(Address target, RelocInfo::Mode rmode, COND_ARGS);
199  void Call(Address target, RelocInfo::Mode rmode, COND_ARGS);
203  COND_ARGS);
204  void Call(Handle<Code> code,
207  COND_ARGS);
208  void Ret(COND_ARGS);
209  inline void Ret(BranchDelaySlot bd, Condition cond = al,
210  Register rs = zero_reg, const Operand& rt = Operand(zero_reg)) {
211  Ret(cond, rs, rt, bd);
212  }
213 
214  void Branch(Label* L,
215  Condition cond,
216  Register rs,
217  Heap::RootListIndex index,
218  BranchDelaySlot bdslot = PROTECT);
219 
220 #undef COND_ARGS
221 
222  // Emit code to discard a non-negative number of pointer-sized elements
223  // from the stack, clobbering only the sp register.
224  void Drop(int count,
225  Condition cond = cc_always,
226  Register reg = no_reg,
227  const Operand& op = Operand(no_reg));
228 
229  // Trivial case of DropAndRet that utilizes the delay slot and only emits
230  // 2 instructions.
231  void DropAndRet(int drop);
232 
233  void DropAndRet(int drop,
234  Condition cond,
235  Register reg,
236  const Operand& op);
237 
238  // Swap two registers. If the scratch register is omitted then a slightly
239  // less efficient form using xor instead of mov is emitted.
240  void Swap(Register reg1, Register reg2, Register scratch = no_reg);
241 
242  void Call(Label* target);
243 
244  inline void Move(Register dst, Register src) {
245  if (!dst.is(src)) {
246  mov(dst, src);
247  }
248  }
249 
250  inline void Move(FPURegister dst, FPURegister src) {
251  if (!dst.is(src)) {
252  mov_d(dst, src);
253  }
254  }
255 
256  inline void Move(Register dst_low, Register dst_high, FPURegister src) {
257  mfc1(dst_low, src);
258  mfhc1(dst_high, src);
259  }
260 
261  inline void FmoveHigh(Register dst_high, FPURegister src) {
262  mfhc1(dst_high, src);
263  }
264 
265  inline void FmoveLow(Register dst_low, FPURegister src) {
266  mfc1(dst_low, src);
267  }
268 
269  inline void Move(FPURegister dst, Register src_low, Register src_high) {
270  mtc1(src_low, dst);
271  mthc1(src_high, dst);
272  }
273 
274  // Conditional move.
275  void Move(FPURegister dst, double imm);
276  void Movz(Register rd, Register rs, Register rt);
277  void Movn(Register rd, Register rs, Register rt);
278  void Movt(Register rd, Register rs, uint16_t cc = 0);
279  void Movf(Register rd, Register rs, uint16_t cc = 0);
280 
281  void Clz(Register rd, Register rs);
282 
283  // Jump unconditionally to given label.
284  // We NEED a nop in the branch delay slot, as it used by v8, for example in
285  // CodeGenerator::ProcessDeferred().
286  // Currently the branch delay slot is filled by the MacroAssembler.
287  // Use rather b(Label) for code generation.
288  void jmp(Label* L) {
289  Branch(L);
290  }
291 
292  void Load(Register dst, const MemOperand& src, Representation r);
293  void Store(Register src, const MemOperand& dst, Representation r);
294 
295  // Load an object from the root table.
296  void LoadRoot(Register destination,
297  Heap::RootListIndex index);
298  void LoadRoot(Register destination,
299  Heap::RootListIndex index,
300  Condition cond, Register src1, const Operand& src2);
301 
302  // Store an object to the root table.
303  void StoreRoot(Register source,
304  Heap::RootListIndex index);
305  void StoreRoot(Register source,
306  Heap::RootListIndex index,
307  Condition cond, Register src1, const Operand& src2);
308 
309  // ---------------------------------------------------------------------------
310  // GC Support
311 
313  Register value,
314  Register address);
315 
317  kReturnAtEnd,
319  };
320 
321 
322  // Record in the remembered set the fact that we have a pointer to new space
323  // at the address pointed to by the addr register. Only works if addr is not
324  // in new space.
325  void RememberedSetHelper(Register object, // Used for debug code.
326  Register addr,
327  Register scratch,
328  SaveFPRegsMode save_fp,
329  RememberedSetFinalAction and_then);
330 
331  void CheckPageFlag(Register object,
332  Register scratch,
333  int mask,
334  Condition cc,
335  Label* condition_met);
336 
338  Register scratch,
339  Label* if_deprecated);
340 
341  // Check if object is in new space. Jumps if the object is not in new space.
342  // The register scratch can be object itself, but it will be clobbered.
344  Register scratch,
345  Label* branch) {
346  InNewSpace(object, scratch, ne, branch);
347  }
348 
349  // Check if object is in new space. Jumps if the object is in new space.
350  // The register scratch can be object itself, but scratch will be clobbered.
352  Register scratch,
353  Label* branch) {
354  InNewSpace(object, scratch, eq, branch);
355  }
356 
357  // Check if an object has a given incremental marking color.
358  void HasColor(Register object,
359  Register scratch0,
360  Register scratch1,
361  Label* has_color,
362  int first_bit,
363  int second_bit);
364 
365  void JumpIfBlack(Register object,
366  Register scratch0,
367  Register scratch1,
368  Label* on_black);
369 
370  // Checks the color of an object. If the object is already grey or black
371  // then we just fall through, since it is already live. If it is white and
372  // we can determine that it doesn't need to be scanned, then we just mark it
373  // black and fall through. For the rest we jump to the label so the
374  // incremental marker can fix its assumptions.
376  Register scratch1,
377  Register scratch2,
378  Register scratch3,
379  Label* object_is_white_and_not_data);
380 
381  // Detects conservatively whether an object is data-only, i.e. it does need to
382  // be scanned by the garbage collector.
384  Register scratch,
385  Label* not_data_object);
386 
387  // Notify the garbage collector that we wrote a pointer into an object.
388  // |object| is the object being stored into, |value| is the object being
389  // stored. value and scratch registers are clobbered by the operation.
390  // The offset is the offset from the start of the object, not the offset from
391  // the tagged HeapObject pointer. For use with FieldOperand(reg, off).
393  Register object,
394  int offset,
395  Register value,
396  Register scratch,
397  RAStatus ra_status,
398  SaveFPRegsMode save_fp,
399  RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
400  SmiCheck smi_check = INLINE_SMI_CHECK,
401  PointersToHereCheck pointers_to_here_check_for_value =
403 
404  // As above, but the offset has the tag presubtracted. For use with
405  // MemOperand(reg, off).
407  Register context,
408  int offset,
409  Register value,
410  Register scratch,
411  RAStatus ra_status,
412  SaveFPRegsMode save_fp,
413  RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
414  SmiCheck smi_check = INLINE_SMI_CHECK,
415  PointersToHereCheck pointers_to_here_check_for_value =
417  RecordWriteField(context,
418  offset + kHeapObjectTag,
419  value,
420  scratch,
421  ra_status,
422  save_fp,
423  remembered_set_action,
424  smi_check,
425  pointers_to_here_check_for_value);
426  }
427 
429  Register object,
430  Register map,
431  Register dst,
432  RAStatus ra_status,
433  SaveFPRegsMode save_fp);
434 
435  // For a given |object| notify the garbage collector that the slot |address|
436  // has been written. |value| is the object being stored. The value and
437  // address registers are clobbered by the operation.
439  Register object,
440  Register address,
441  Register value,
442  RAStatus ra_status,
443  SaveFPRegsMode save_fp,
444  RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
445  SmiCheck smi_check = INLINE_SMI_CHECK,
446  PointersToHereCheck pointers_to_here_check_for_value =
448 
449 
450  // ---------------------------------------------------------------------------
451  // Inline caching support.
452 
453  // Generate code for checking access rights - used for security checks
454  // on access to global objects across environments. The holder register
455  // is left untouched, whereas both scratch registers are clobbered.
457  Register scratch,
458  Label* miss);
459 
460  void GetNumberHash(Register reg0, Register scratch);
461 
462  void LoadFromNumberDictionary(Label* miss,
463  Register elements,
464  Register key,
465  Register result,
466  Register reg0,
467  Register reg1,
468  Register reg2);
469 
470 
471  inline void MarkCode(NopMarkerTypes type) {
472  nop(type);
473  }
474 
475  // Check if the given instruction is a 'type' marker.
476  // i.e. check if it is a sll zero_reg, zero_reg, <type> (referenced as
477  // nop(type)). These instructions are generated to mark special location in
478  // the code, like some special IC code.
479  static inline bool IsMarkedCode(Instr instr, int type) {
480  DCHECK((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER));
481  return IsNop(instr, type);
482  }
483 
484 
485  static inline int GetCodeMarker(Instr instr) {
486  uint32_t opcode = ((instr & kOpcodeMask));
487  uint32_t rt = ((instr & kRtFieldMask) >> kRtShift);
488  uint32_t rs = ((instr & kRsFieldMask) >> kRsShift);
489  uint32_t sa = ((instr & kSaFieldMask) >> kSaShift);
490 
491  // Return <n> if we have a sll zero_reg, zero_reg, n
492  // else return -1.
493  bool sllzz = (opcode == SLL &&
494  rt == static_cast<uint32_t>(ToNumber(zero_reg)) &&
495  rs == static_cast<uint32_t>(ToNumber(zero_reg)));
496  int type =
497  (sllzz && FIRST_IC_MARKER <= sa && sa < LAST_CODE_MARKER) ? sa : -1;
498  DCHECK((type == -1) ||
499  ((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER)));
500  return type;
501  }
502 
503 
504 
505  // ---------------------------------------------------------------------------
506  // Allocation support.
507 
508  // Allocate an object in new space or old pointer space. The object_size is
509  // specified either in bytes or in words if the allocation flag SIZE_IN_WORDS
510  // is passed. If the space is exhausted control continues at the gc_required
511  // label. The allocated object is returned in result. If the flag
512  // tag_allocated_object is true the result is tagged as as a heap object.
513  // All registers are clobbered also when control continues at the gc_required
514  // label.
515  void Allocate(int object_size,
516  Register result,
517  Register scratch1,
518  Register scratch2,
519  Label* gc_required,
521 
522  void Allocate(Register object_size,
523  Register result,
524  Register scratch1,
525  Register scratch2,
526  Label* gc_required,
528 
529  // Undo allocation in new space. The object passed and objects allocated after
530  // it will no longer be allocated. The caller must make sure that no pointers
531  // are left to the object(s) no longer allocated as they would be invalid when
532  // allocation is undone.
534 
535 
537  Register length,
538  Register scratch1,
539  Register scratch2,
540  Register scratch3,
541  Label* gc_required);
543  Register scratch1, Register scratch2,
544  Register scratch3, Label* gc_required);
546  Register length,
547  Register scratch1,
548  Register scratch2,
549  Label* gc_required);
551  Register scratch1, Register scratch2,
552  Label* gc_required);
554  Register length,
555  Register scratch1,
556  Register scratch2,
557  Label* gc_required);
559  Register scratch1, Register scratch2,
560  Label* gc_required);
561 
562  // Allocates a heap number or jumps to the gc_required label if the young
563  // space is full and a scavenge is needed. All registers are clobbered also
564  // when control continues at the gc_required label.
566  Register scratch1,
567  Register scratch2,
568  Register heap_number_map,
569  Label* gc_required,
570  TaggingMode tagging_mode = TAG_RESULT,
572 
574  FPURegister value,
575  Register scratch1,
576  Register scratch2,
577  Label* gc_required);
578 
579  // ---------------------------------------------------------------------------
580  // Instruction macros.
581 
582 #define DEFINE_INSTRUCTION(instr) \
583  void instr(Register rd, Register rs, const Operand& rt); \
584  void instr(Register rd, Register rs, Register rt) { \
585  instr(rd, rs, Operand(rt)); \
586  } \
587  void instr(Register rs, Register rt, int32_t j) { \
588  instr(rs, rt, Operand(j)); \
589  }
590 
591 #define DEFINE_INSTRUCTION2(instr) \
592  void instr(Register rs, const Operand& rt); \
593  void instr(Register rs, Register rt) { \
594  instr(rs, Operand(rt)); \
595  } \
596  void instr(Register rs, int32_t j) { \
597  instr(rs, Operand(j)); \
598  }
599 
618 
624 
627 
628  // MIPS32 R2 instruction macro.
631 
632 #undef DEFINE_INSTRUCTION
633 #undef DEFINE_INSTRUCTION2
634 
635  void Pref(int32_t hint, const MemOperand& rs);
636 
637 
638  // ---------------------------------------------------------------------------
639  // Pseudo-instructions.
640 
641  void mov(Register rd, Register rt) { or_(rd, rt, zero_reg); }
642 
643  void Ulw(Register rd, const MemOperand& rs);
644  void Usw(Register rd, const MemOperand& rs);
645  void Uld(Register rd, const MemOperand& rs, Register scratch = at);
646  void Usd(Register rd, const MemOperand& rs, Register scratch = at);
647 
648  // Load int32 in the rd register.
650  inline void li(Register rd, int64_t j, LiFlags mode = OPTIMIZE_SIZE) {
651  li(rd, Operand(j), mode);
652  }
654 
655  // Push multiple registers on the stack.
656  // Registers are saved in numerical order, with higher numbered registers
657  // saved in higher memory addresses.
658  void MultiPush(RegList regs);
660 
661  void MultiPushFPU(RegList regs);
663 
664  void push(Register src) {
665  Daddu(sp, sp, Operand(-kPointerSize));
666  sd(src, MemOperand(sp, 0));
667  }
668  void Push(Register src) { push(src); }
669 
670  // Push a handle.
672  void Push(Smi* smi) { Push(Handle<Smi>(smi, isolate())); }
673 
674  // Push two registers. Pushes leftmost register first (to highest address).
675  void Push(Register src1, Register src2) {
676  Dsubu(sp, sp, Operand(2 * kPointerSize));
677  sd(src1, MemOperand(sp, 1 * kPointerSize));
678  sd(src2, MemOperand(sp, 0 * kPointerSize));
679  }
680 
681  // Push three registers. Pushes leftmost register first (to highest address).
682  void Push(Register src1, Register src2, Register src3) {
683  Dsubu(sp, sp, Operand(3 * kPointerSize));
684  sd(src1, MemOperand(sp, 2 * kPointerSize));
685  sd(src2, MemOperand(sp, 1 * kPointerSize));
686  sd(src3, MemOperand(sp, 0 * kPointerSize));
687  }
688 
689  // Push four registers. Pushes leftmost register first (to highest address).
690  void Push(Register src1, Register src2, Register src3, Register src4) {
691  Dsubu(sp, sp, Operand(4 * kPointerSize));
692  sd(src1, MemOperand(sp, 3 * kPointerSize));
693  sd(src2, MemOperand(sp, 2 * kPointerSize));
694  sd(src3, MemOperand(sp, 1 * kPointerSize));
695  sd(src4, MemOperand(sp, 0 * kPointerSize));
696  }
697 
698  void Push(Register src, Condition cond, Register tst1, Register tst2) {
699  // Since we don't have conditional execution we use a Branch.
700  Branch(3, cond, tst1, Operand(tst2));
701  Dsubu(sp, sp, Operand(kPointerSize));
702  sd(src, MemOperand(sp, 0));
703  }
704 
705  void PushRegisterAsTwoSmis(Register src, Register scratch = at);
706  void PopRegisterAsTwoSmis(Register dst, Register scratch = at);
707 
708  // Pops multiple values from the stack and load them in the
709  // registers specified in regs. Pop order is the opposite as in MultiPush.
710  void MultiPop(RegList regs);
712 
713  void MultiPopFPU(RegList regs);
715 
716  void pop(Register dst) {
717  ld(dst, MemOperand(sp, 0));
718  Daddu(sp, sp, Operand(kPointerSize));
719  }
720  void Pop(Register dst) { pop(dst); }
721 
722  // Pop two registers. Pops rightmost register first (from lower address).
723  void Pop(Register src1, Register src2) {
724  DCHECK(!src1.is(src2));
725  ld(src2, MemOperand(sp, 0 * kPointerSize));
726  ld(src1, MemOperand(sp, 1 * kPointerSize));
727  Daddu(sp, sp, 2 * kPointerSize);
728  }
729 
730  // Pop three registers. Pops rightmost register first (from lower address).
731  void Pop(Register src1, Register src2, Register src3) {
732  ld(src3, MemOperand(sp, 0 * kPointerSize));
733  ld(src2, MemOperand(sp, 1 * kPointerSize));
734  ld(src1, MemOperand(sp, 2 * kPointerSize));
735  Daddu(sp, sp, 3 * kPointerSize);
736  }
737 
738  void Pop(uint32_t count = 1) {
739  Daddu(sp, sp, Operand(count * kPointerSize));
740  }
741 
742  // Push and pop the registers that can hold pointers, as defined by the
743  // RegList constant kSafepointSavedRegisters.
746  // Store value in register src in the safepoint stack slot for
747  // register dst.
749  // Load the value of the src register from its safepoint stack slot
750  // into register dst.
752 
753  // Flush the I-cache from asm code. You should use CpuFeatures::FlushICache
754  // from C.
755  // Does not handle errors.
756  void FlushICache(Register address, unsigned instructions);
757 
758  // MIPS64 R2 instruction macro.
761 
762  // ---------------------------------------------------------------------------
763  // FPU macros. These do not handle special cases like NaN or +- inf.
764 
765  // Convert unsigned word to double.
767  void Cvt_d_uw(FPURegister fd, Register rs, FPURegister scratch);
768 
769  // Convert double to unsigned long.
771 
776 
777  // Convert double to unsigned word.
780 
785 
787  FPURegister fr,
788  FPURegister fs,
789  FPURegister ft,
790  FPURegister scratch);
791 
792  // Wrapper function for the different cmp/branch types.
793  void BranchF(Label* target,
794  Label* nan,
795  Condition cc,
796  FPURegister cmp1,
797  FPURegister cmp2,
798  BranchDelaySlot bd = PROTECT);
799 
800  // Alternate (inline) version for better readability with USE_DELAY_SLOT.
801  inline void BranchF(BranchDelaySlot bd,
802  Label* target,
803  Label* nan,
804  Condition cc,
805  FPURegister cmp1,
806  FPURegister cmp2) {
807  BranchF(target, nan, cc, cmp1, cmp2, bd);
808  }
809 
810  // Truncates a double using a specific rounding mode, and writes the value
811  // to the result register.
812  // The except_flag will contain any exceptions caused by the instruction.
813  // If check_inexact is kDontCheckForInexactConversion, then the inexact
814  // exception is masked.
815  void EmitFPUTruncate(FPURoundingMode rounding_mode,
816  Register result,
817  DoubleRegister double_input,
818  Register scratch,
819  DoubleRegister double_scratch,
820  Register except_flag,
821  CheckForInexactConversion check_inexact
823 
824  // Performs a truncating conversion of a floating point number as used by
825  // the JS bitwise operations. See ECMA-262 9.5: ToInt32. Goes to 'done' if it
826  // succeeds, otherwise falls through if result is saturated. On return
827  // 'result' either holds answer, or is clobbered on fall through.
828  //
829  // Only public for the test code in test-code-stubs-arm.cc.
831  DoubleRegister input,
832  Label* done);
833 
834  // Performs a truncating conversion of a floating point number as used by
835  // the JS bitwise operations. See ECMA-262 9.5: ToInt32.
836  // Exits with 'result' holding the answer.
837  void TruncateDoubleToI(Register result, DoubleRegister double_input);
838 
839  // Performs a truncating conversion of a heap number as used by
840  // the JS bitwise operations. See ECMA-262 9.5: ToInt32. 'result' and 'input'
841  // must be different registers. Exits with 'result' holding the answer.
843 
844  // Converts the smi or heap number in object to an int32 using the rules
845  // for ToInt32 as described in ECMAScript 9.5.: the value is truncated
846  // and brought into the range -2^31 .. +2^31 - 1. 'result' and 'input' must be
847  // different registers.
849  Register result,
850  Register heap_number_map,
851  Register scratch,
852  Label* not_int32);
853 
854  // Loads the number from object into dst register.
855  // If |object| is neither smi nor heap number, |not_number| is jumped to
856  // with |object| still intact.
857  void LoadNumber(Register object,
858  FPURegister dst,
859  Register heap_number_map,
860  Register scratch,
861  Label* not_number);
862 
863  // Loads the number from object into double_dst in the double format.
864  // Control will jump to not_int32 if the value cannot be exactly represented
865  // by a 32-bit integer.
866  // Floating point value in the 32-bit integer range that are not exact integer
867  // won't be loaded.
869  DoubleRegister double_dst,
870  Register heap_number_map,
871  Register scratch1,
872  Register scratch2,
873  FPURegister double_scratch,
874  Label* not_int32);
875 
876  // Loads the number from object into dst as a 32-bit integer.
877  // Control will jump to not_int32 if the object cannot be exactly represented
878  // by a 32-bit integer.
879  // Floating point value in the 32-bit integer range that are not exact integer
880  // won't be converted.
882  Register dst,
883  Register heap_number_map,
884  Register scratch1,
885  Register scratch2,
886  FPURegister double_scratch0,
887  FPURegister double_scratch1,
888  Label* not_int32);
889 
890  // Enter exit frame.
891  // argc - argument count to be dropped by LeaveExitFrame.
892  // save_doubles - saves FPU registers on stack, currently disabled.
893  // stack_space - extra stack space.
894  void EnterExitFrame(bool save_doubles,
895  int stack_space = 0);
896 
897  // Leave the current exit frame.
898  void LeaveExitFrame(bool save_doubles,
899  Register arg_count,
900  bool restore_context,
901  bool do_return = NO_EMIT_RETURN);
902 
903  // Get the actual activation frame alignment for target environment.
905 
906  // Make sure the stack is aligned. Only emits code in debug mode.
908 
909  void LoadContext(Register dst, int context_chain_length);
910 
911  // Conditionally load the cached Array transitioned map of type
912  // transitioned_kind from the native context if the map in register
913  // map_in_out is the cached Array map in the native context of
914  // expected_kind.
916  ElementsKind expected_kind,
917  ElementsKind transitioned_kind,
918  Register map_in_out,
919  Register scratch,
920  Label* no_map_match);
921 
922  void LoadGlobalFunction(int index, Register function);
923 
924  // Load the initial map from the global function. The registers
925  // function and map can be the same, function is then overwritten.
927  Register map,
928  Register scratch);
929 
931  ExternalReference roots_array_start =
932  ExternalReference::roots_array_start(isolate());
933  li(kRootRegister, Operand(roots_array_start));
934  }
935 
936  // -------------------------------------------------------------------------
937  // JavaScript invokes.
938 
939  // Invoke the JavaScript function code by either calling or jumping.
940  void InvokeCode(Register code,
941  const ParameterCount& expected,
942  const ParameterCount& actual,
944  const CallWrapper& call_wrapper);
945 
946  // Invoke the JavaScript function in the given register. Changes the
947  // current context to the context in the function before invoking.
948  void InvokeFunction(Register function,
949  const ParameterCount& actual,
951  const CallWrapper& call_wrapper);
952 
953  void InvokeFunction(Register function,
954  const ParameterCount& expected,
955  const ParameterCount& actual,
957  const CallWrapper& call_wrapper);
958 
960  const ParameterCount& expected,
961  const ParameterCount& actual,
963  const CallWrapper& call_wrapper);
964 
965 
966  void IsObjectJSObjectType(Register heap_object,
967  Register map,
968  Register scratch,
969  Label* fail);
970 
972  Register scratch,
973  Label* fail);
974 
976  Register scratch,
977  Label* fail);
978 
980  Register scratch,
981  Label* fail);
982 
983  // -------------------------------------------------------------------------
984  // Debugger Support.
985 
986  void DebugBreak();
987 
988  // -------------------------------------------------------------------------
989  // Exception handling.
990 
991  // Push a new try handler and link into try handler chain.
992  void PushTryHandler(StackHandler::Kind kind, int handler_index);
993 
994  // Unlink the stack handler on top of the stack from the try handler chain.
995  // Must preserve the result register.
997 
998  // Passes thrown value to the handler of top of the try handler chain.
999  void Throw(Register value);
1000 
1001  // Propagates an uncatchable exception to the top of the current JS stack's
1002  // handler chain.
1004 
1005  // Copies a fixed number of fields of heap objects from src to dst.
1006  void CopyFields(Register dst, Register src, RegList temps, int field_count);
1007 
1008  // Copies a number of bytes from src to dst. All registers are clobbered. On
1009  // exit src and dst will point to the place just after where the last byte was
1010  // read or written and length will be zero.
1012  Register dst,
1013  Register length,
1014  Register scratch);
1015 
1016  // Initialize fields with filler values. Fields starting at |start_offset|
1017  // not including end_offset are overwritten with the value in |filler|. At
1018  // the end the loop, |start_offset| takes the value of |end_offset|.
1020  Register end_offset,
1021  Register filler);
1022 
1023  // -------------------------------------------------------------------------
1024  // Support functions.
1025 
1026  // Try to get function prototype of a function and puts the value in
1027  // the result register. Checks that the function really is a
1028  // function and jumps to the miss label if the fast checks fail. The
1029  // function register will be untouched; the other registers may be
1030  // clobbered.
1032  Register result,
1033  Register scratch,
1034  Label* miss,
1035  bool miss_on_bound_function = false);
1036 
1037  void GetObjectType(Register function,
1038  Register map,
1039  Register type_reg);
1040 
1041  // Check if a map for a JSObject indicates that the object has fast elements.
1042  // Jump to the specified label if it does not.
1044  Register scratch,
1045  Label* fail);
1046 
1047  // Check if a map for a JSObject indicates that the object can have both smi
1048  // and HeapObject elements. Jump to the specified label if it does not.
1050  Register scratch,
1051  Label* fail);
1052 
1053  // Check if a map for a JSObject indicates that the object has fast smi only
1054  // elements. Jump to the specified label if it does not.
1056  Register scratch,
1057  Label* fail);
1058 
1059  // Check to see if maybe_number can be stored as a double in
1060  // FastDoubleElements. If it can, store it at the index specified by key in
1061  // the FastDoubleElements array elements. Otherwise jump to fail.
1063  Register key_reg,
1064  Register elements_reg,
1065  Register scratch1,
1066  Register scratch2,
1067  Register scratch3,
1068  Label* fail,
1069  int elements_offset = 0);
1070 
1071  // Compare an object's map with the specified map and its transitioned
1072  // elements maps if mode is ALLOW_ELEMENT_TRANSITION_MAPS. Jumps to
1073  // "branch_to" if the result of the comparison is "cond". If multiple map
1074  // compares are required, the compare sequences branches to early_success.
1076  Register scratch,
1077  Handle<Map> map,
1078  Label* early_success,
1079  Condition cond,
1080  Label* branch_to);
1081 
1082  // As above, but the map of the object is already loaded into the register
1083  // which is preserved by the code generated.
1085  Handle<Map> map,
1086  Label* early_success,
1087  Condition cond,
1088  Label* branch_to);
1089 
1090  // Check if the map of an object is equal to a specified map and branch to
1091  // label if not. Skip the smi check if not required (object is known to be a
1092  // heap object). If mode is ALLOW_ELEMENT_TRANSITION_MAPS, then also match
1093  // against maps that are ElementsKind transition maps of the specificed map.
1094  void CheckMap(Register obj,
1095  Register scratch,
1096  Handle<Map> map,
1097  Label* fail,
1098  SmiCheckType smi_check_type);
1099 
1100 
1101  void CheckMap(Register obj,
1102  Register scratch,
1103  Heap::RootListIndex index,
1104  Label* fail,
1105  SmiCheckType smi_check_type);
1106 
1107  // Check if the map of an object is equal to a specified map and branch to a
1108  // specified target if equal. Skip the smi check if not required (object is
1109  // known to be a heap object)
1111  Register scratch,
1112  Handle<Map> map,
1113  Handle<Code> success,
1114  SmiCheckType smi_check_type);
1115 
1116 
1117  // Load and check the instance type of an object for being a string.
1118  // Loads the type into the second argument register.
1119  // Returns a condition that will be enabled if the object was a string.
1121  Register type,
1122  Register result) {
1125  And(type, type, Operand(kIsNotStringMask));
1126  DCHECK_EQ(0, kStringTag);
1127  return eq;
1128  }
1129 
1130 
1131  // Picks out an array index from the hash field.
1132  // Register use:
1133  // hash - holds the index's hash. Clobbered.
1134  // index - holds the overwritten index on exit.
1135  void IndexFromHash(Register hash, Register index);
1136 
1137  // Get the number of least significant bits from a register.
1138  void GetLeastBitsFromSmi(Register dst, Register src, int num_least_bits);
1139  void GetLeastBitsFromInt32(Register dst, Register src, int mun_least_bits);
1140 
1141  // Load the value of a number object into a FPU double register. If the
1142  // object is not a number a jump to the label not_number is performed
1143  // and the FPU double register is unchanged.
1145  Register object,
1146  FPURegister value,
1147  Register scratch1,
1148  Register scratch2,
1149  Register heap_number_map,
1150  Label* not_number,
1152 
1153  // Load the value of a smi object into a FPU double register. The register
1154  // scratch1 can be the same register as smi in which case smi will hold the
1155  // untagged value afterwards.
1157  FPURegister value,
1158  Register scratch1);
1159 
1160  // -------------------------------------------------------------------------
1161  // Overflow handling functions.
1162  // Usage: first call the appropriate arithmetic function, then call one of the
1163  // jump functions with the overflow_dst register as the second parameter.
1164 
1166  Register left,
1167  Register right,
1168  Register overflow_dst,
1169  Register scratch = at);
1170 
1172  Register left,
1173  Register right,
1174  Register overflow_dst,
1175  Register scratch = at);
1176 
1177  void BranchOnOverflow(Label* label,
1178  Register overflow_check,
1179  BranchDelaySlot bd = PROTECT) {
1180  Branch(label, lt, overflow_check, Operand(zero_reg), bd);
1181  }
1182 
1183  void BranchOnNoOverflow(Label* label,
1184  Register overflow_check,
1185  BranchDelaySlot bd = PROTECT) {
1186  Branch(label, ge, overflow_check, Operand(zero_reg), bd);
1187  }
1188 
1189  void RetOnOverflow(Register overflow_check, BranchDelaySlot bd = PROTECT) {
1190  Ret(lt, overflow_check, Operand(zero_reg), bd);
1191  }
1192 
1193  void RetOnNoOverflow(Register overflow_check, BranchDelaySlot bd = PROTECT) {
1194  Ret(ge, overflow_check, Operand(zero_reg), bd);
1195  }
1196 
1197  // -------------------------------------------------------------------------
1198  // Runtime calls.
1199 
1200  // See comments at the beginning of CEntryStub::Generate.
1201  inline void PrepareCEntryArgs(int num_args) {
1202  li(s0, num_args);
1203  li(s1, (num_args - 1) * kPointerSize);
1204  }
1205 
1206  inline void PrepareCEntryFunction(const ExternalReference& ref) {
1207  li(s2, Operand(ref));
1208  }
1209 
1210 #define COND_ARGS Condition cond = al, Register rs = zero_reg, \
1211 const Operand& rt = Operand(zero_reg), BranchDelaySlot bd = PROTECT
1212 
1213  // Call a code stub.
1214  void CallStub(CodeStub* stub,
1216  COND_ARGS);
1217 
1218  // Tail call a code stub (jump).
1220 
1221 #undef COND_ARGS
1222 
1224 
1225  // Call a runtime routine.
1227  int num_arguments,
1228  SaveFPRegsMode save_doubles = kDontSaveFPRegs);
1230  const Runtime::Function* function = Runtime::FunctionForId(id);
1231  CallRuntime(function, function->nargs, kSaveFPRegs);
1232  }
1233 
1234  // Convenience function: Same as above, but takes the fid instead.
1236  int num_arguments,
1237  SaveFPRegsMode save_doubles = kDontSaveFPRegs) {
1238  CallRuntime(Runtime::FunctionForId(id), num_arguments, save_doubles);
1239  }
1240 
1241  // Convenience function: call an external reference.
1242  void CallExternalReference(const ExternalReference& ext,
1243  int num_arguments,
1244  BranchDelaySlot bd = PROTECT);
1245 
1246  // Tail call of a runtime routine (jump).
1247  // Like JumpToExternalReference, but also takes care of passing the number
1248  // of parameters.
1249  void TailCallExternalReference(const ExternalReference& ext,
1250  int num_arguments,
1251  int result_size);
1252 
1253  // Convenience function: tail call a runtime routine (jump).
1255  int num_arguments,
1256  int result_size);
1257 
1258  int CalculateStackPassedWords(int num_reg_arguments,
1259  int num_double_arguments);
1260 
1261  // Before calling a C-function from generated code, align arguments on stack
1262  // and add space for the four mips argument slots.
1263  // After aligning the frame, non-register arguments must be stored on the
1264  // stack, after the argument-slots using helper: CFunctionArgumentOperand().
1265  // The argument count assumes all arguments are word sized.
1266  // Some compilers/platforms require the stack to be aligned when calling
1267  // C++ code.
1268  // Needs a scratch register to do some arithmetic. This register will be
1269  // trashed.
1270  void PrepareCallCFunction(int num_reg_arguments,
1271  int num_double_registers,
1272  Register scratch);
1273  void PrepareCallCFunction(int num_reg_arguments,
1274  Register scratch);
1275 
1276  // Arguments 1-4 are placed in registers a0 thru a3 respectively.
1277  // Arguments 5..n are stored to stack using following:
1278  // sw(a4, CFunctionArgumentOperand(5));
1279 
1280  // Calls a C function and cleans up the space for arguments allocated
1281  // by PrepareCallCFunction. The called function is not allowed to trigger a
1282  // garbage collection, since that might move the code and invalidate the
1283  // return address (unless this is somehow accounted for by the called
1284  // function).
1285  void CallCFunction(ExternalReference function, int num_arguments);
1286  void CallCFunction(Register function, int num_arguments);
1287  void CallCFunction(ExternalReference function,
1288  int num_reg_arguments,
1289  int num_double_arguments);
1290  void CallCFunction(Register function,
1291  int num_reg_arguments,
1292  int num_double_arguments);
1295 
1296  // There are two ways of passing double arguments on MIPS, depending on
1297  // whether soft or hard floating point ABI is used. These functions
1298  // abstract parameter passing for the three different ways we call
1299  // C functions from generated code.
1303 
1304  // Calls an API function. Allocates HandleScope, extracts returned value
1305  // from handle and propagates exceptions. Restores context. stack_space
1306  // - space to be unwound on exit (includes the call JS arguments space and
1307  // the additional space allocated for the fast call).
1308  void CallApiFunctionAndReturn(Register function_address,
1309  ExternalReference thunk_ref,
1310  int stack_space,
1311  MemOperand return_value_operand,
1312  MemOperand* context_restore_operand);
1313 
1314  // Jump to the builtin routine.
1315  void JumpToExternalReference(const ExternalReference& builtin,
1316  BranchDelaySlot bd = PROTECT);
1317 
1318  // Invoke specified builtin JavaScript function. Adds an entry to
1319  // the unresolved list if the name does not resolve.
1321  InvokeFlag flag,
1322  const CallWrapper& call_wrapper = NullCallWrapper());
1323 
1324  // Store the code object for the given builtin in the target register and
1325  // setup the function in a1.
1327 
1328  // Store the function for the given builtin in the target register.
1330 
1331  struct Unresolved {
1332  int pc;
1333  uint32_t flags; // See Bootstrapper::FixupFlags decoders/encoders.
1334  const char* name;
1335  };
1336 
1338  DCHECK(!code_object_.is_null());
1339  return code_object_;
1340  }
1341 
1342  // Emit code for a truncating division by a constant. The dividend register is
1343  // unchanged and at gets clobbered. Dividend and result must be different.
1344  void TruncatingDiv(Register result, Register dividend, int32_t divisor);
1345 
1346  // -------------------------------------------------------------------------
1347  // StatsCounter support.
1348 
1349  void SetCounter(StatsCounter* counter, int value,
1350  Register scratch1, Register scratch2);
1351  void IncrementCounter(StatsCounter* counter, int value,
1352  Register scratch1, Register scratch2);
1353  void DecrementCounter(StatsCounter* counter, int value,
1354  Register scratch1, Register scratch2);
1355 
1356 
1357  // -------------------------------------------------------------------------
1358  // Debugging.
1359 
1360  // Calls Abort(msg) if the condition cc is not satisfied.
1361  // Use --debug_code to enable.
1364 
1365  // Like Assert(), but always enabled.
1367 
1368  // Print a message to stdout and abort execution.
1370 
1371  // Verify restrictions about code generated in stubs.
1372  void set_generating_stub(bool value) { generating_stub_ = value; }
1374  void set_has_frame(bool value) { has_frame_ = value; }
1375  bool has_frame() { return has_frame_; }
1376  inline bool AllowThisStubCall(CodeStub* stub);
1377 
1378  // ---------------------------------------------------------------------------
1379  // Number utilities.
1380 
1381  // Check whether the value of reg is a power of two and not zero. If not
1382  // control continues at the label not_power_of_two. If reg is a power of two
1383  // the register scratch contains the value of (reg - 1) when control falls
1384  // through.
1386  Register scratch,
1387  Label* not_power_of_two_or_zero);
1388 
1389  // -------------------------------------------------------------------------
1390  // Smi utilities.
1391 
1392  // Test for overflow < 0: use BranchOnOverflow() or BranchOnNoOverflow().
1395 
1396  void SmiTag(Register dst, Register src) {
1397  STATIC_ASSERT(kSmiTag == 0);
1398  if (SmiValuesAre32Bits()) {
1399  STATIC_ASSERT(kSmiShift == 32);
1400  dsll32(dst, src, 0);
1401  } else {
1402  Addu(dst, src, src);
1403  }
1404  }
1405 
1406  void SmiTag(Register reg) {
1407  SmiTag(reg, reg);
1408  }
1409 
1410  // Try to convert int32 to smi. If the value is to large, preserve
1411  // the original value and jump to not_a_smi. Destroys scratch and
1412  // sets flags.
1413  void TrySmiTag(Register reg, Register scratch, Label* not_a_smi) {
1414  TrySmiTag(reg, reg, scratch, not_a_smi);
1415  }
1416 
1418  Register src,
1419  Register scratch,
1420  Label* not_a_smi) {
1421  if (SmiValuesAre32Bits()) {
1422  SmiTag(dst, src);
1423  } else {
1424  SmiTagCheckOverflow(at, src, scratch);
1425  BranchOnOverflow(not_a_smi, scratch);
1426  mov(dst, at);
1427  }
1428  }
1429 
1430  void SmiUntag(Register dst, Register src) {
1431  if (SmiValuesAre32Bits()) {
1432  STATIC_ASSERT(kSmiShift == 32);
1433  dsra32(dst, src, 0);
1434  } else {
1435  sra(dst, src, kSmiTagSize);
1436  }
1437  }
1438 
1439  void SmiUntag(Register reg) {
1440  SmiUntag(reg, reg);
1441  }
1442 
1443  // Left-shifted from int32 equivalent of Smi.
1444  void SmiScale(Register dst, Register src, int scale) {
1445  if (SmiValuesAre32Bits()) {
1446  // The int portion is upper 32-bits of 64-bit word.
1447  dsra(dst, src, kSmiShift - scale);
1448  } else {
1449  DCHECK(scale >= kSmiTagSize);
1450  sll(dst, src, scale - kSmiTagSize);
1451  }
1452  }
1453 
1454  // Combine load with untagging or scaling.
1456 
1457  void SmiLoadScale(Register dst, MemOperand src, int scale);
1458 
1459  // Returns 2 values: the Smi and a scaled version of the int within the Smi.
1461  Register d_scaled,
1462  MemOperand src,
1463  int scale);
1464 
1465  // Returns 2 values: the untagged Smi (int32) and scaled version of that int.
1467  Register d_scaled,
1468  MemOperand src,
1469  int scale);
1470 
1471 
1472  // Test if the register contains a smi.
1473  inline void SmiTst(Register value, Register scratch) {
1474  And(scratch, value, Operand(kSmiTagMask));
1475  }
1476  inline void NonNegativeSmiTst(Register value, Register scratch) {
1477  And(scratch, value, Operand(kSmiTagMask | kSmiSignMask));
1478  }
1479 
1480  // Untag the source value into destination and jump if source is a smi.
1481  // Source and destination can be the same register.
1482  void UntagAndJumpIfSmi(Register dst, Register src, Label* smi_case);
1483 
1484  // Untag the source value into destination and jump if source is not a smi.
1485  // Source and destination can be the same register.
1486  void UntagAndJumpIfNotSmi(Register dst, Register src, Label* non_smi_case);
1487 
1488  // Jump the register contains a smi.
1489  void JumpIfSmi(Register value,
1490  Label* smi_label,
1491  Register scratch = at,
1492  BranchDelaySlot bd = PROTECT);
1493 
1494  // Jump if the register contains a non-smi.
1496  Label* not_smi_label,
1497  Register scratch = at,
1498  BranchDelaySlot bd = PROTECT);
1499 
1500  // Jump if either of the registers contain a non-smi.
1501  void JumpIfNotBothSmi(Register reg1, Register reg2, Label* on_not_both_smi);
1502  // Jump if either of the registers contain a smi.
1503  void JumpIfEitherSmi(Register reg1, Register reg2, Label* on_either_smi);
1504 
1505  // Abort execution if argument is a smi, enabled via --debug-code.
1506  void AssertNotSmi(Register object);
1507  void AssertSmi(Register object);
1508 
1509  // Abort execution if argument is not a string, enabled via --debug-code.
1510  void AssertString(Register object);
1511 
1512  // Abort execution if argument is not a name, enabled via --debug-code.
1513  void AssertName(Register object);
1514 
1515  // Abort execution if argument is not undefined or an AllocationSite, enabled
1516  // via --debug-code.
1518 
1519  // Abort execution if reg is not the root value with the given index,
1520  // enabled via --debug-code.
1522 
1523  // ---------------------------------------------------------------------------
1524  // HeapNumber utilities.
1525 
1527  Register heap_number_map,
1528  Register scratch,
1529  Label* on_not_heap_number);
1530 
1531  // -------------------------------------------------------------------------
1532  // String utilities.
1533 
1534  // Generate code to do a lookup in the number string cache. If the number in
1535  // the register object is found in the cache the generated code falls through
1536  // with the result in the result register. The object and the result register
1537  // can be the same. If the number is not found in the cache the code jumps to
1538  // the label not_found with only the content of register object unchanged.
1540  Register result,
1541  Register scratch1,
1542  Register scratch2,
1543  Register scratch3,
1544  Label* not_found);
1545 
1546  // Checks if both instance types are sequential one-byte strings and jumps to
1547  // label if either is not.
1549  Register first_object_instance_type, Register second_object_instance_type,
1550  Register scratch1, Register scratch2, Label* failure);
1551 
1552  // Check if instance type is sequential one-byte string and jump to label if
1553  // it is not.
1555  Label* failure);
1556 
1557  void JumpIfNotUniqueNameInstanceType(Register reg, Label* not_unique_name);
1558 
1560  Register index,
1561  Register value,
1562  Register scratch,
1563  uint32_t encoding_mask);
1564 
1565  // Checks if both objects are sequential one-byte strings and jumps to label
1566  // if either is not. Assumes that neither object is a smi.
1568  Register second,
1569  Register scratch1,
1570  Register scratch2,
1571  Label* failure);
1572 
1573  // Checks if both objects are sequential one-byte strings and jumps to label
1574  // if either is not.
1576  Register scratch1,
1577  Register scratch2,
1578  Label* not_flat_one_byte_strings);
1579 
1580  void ClampUint8(Register output_reg, Register input_reg);
1581 
1582  void ClampDoubleToUint8(Register result_reg,
1583  DoubleRegister input_reg,
1584  DoubleRegister temp_double_reg);
1585 
1586 
1590 
1591  template<typename Field>
1592  void DecodeField(Register dst, Register src) {
1593  Ext(dst, src, Field::kShift, Field::kSize);
1594  }
1595 
1596  template<typename Field>
1597  void DecodeField(Register reg) {
1598  DecodeField<Field>(reg, reg);
1599  }
1600 
1601  template<typename Field>
1603  static const int shift = Field::kShift;
1604  static const int mask = Field::kMask >> shift;
1605  dsrl(dst, src, shift);
1606  And(dst, dst, Operand(mask));
1607  dsll32(dst, dst, 0);
1608  }
1609 
1610  template<typename Field>
1612  DecodeField<Field>(reg, reg);
1613  }
1614  // Generates function and stub prologue code.
1616  void Prologue(bool code_pre_aging);
1617 
1618  // Activation support.
1621 
1622  // Patch the relocated value (lui/ori pair).
1623  void PatchRelocatedValue(Register li_location,
1624  Register scratch,
1625  Register new_value);
1626  // Get the relocatad value (loaded data) from the lui/ori pair.
1627  void GetRelocatedValue(Register li_location,
1628  Register value,
1629  Register scratch);
1630 
1631  // Expects object in a0 and returns map with validated enum cache
1632  // in a0. Assumes that any other register can be used as a scratch.
1633  void CheckEnumCache(Register null_value, Label* call_runtime);
1634 
1635  // AllocationMemento support. Arrays may have an associated
1636  // AllocationMemento object that can be checked for in order to pretransition
1637  // to another type.
1638  // On entry, receiver_reg should point to the array object.
1639  // scratch_reg gets clobbered.
1640  // If allocation info is present, jump to allocation_memento_present.
1642  Register receiver_reg,
1643  Register scratch_reg,
1644  Label* no_memento_found,
1645  Condition cond = al,
1646  Label* allocation_memento_present = NULL);
1647 
1649  Register scratch_reg,
1650  Label* memento_found) {
1651  Label no_memento_found;
1652  TestJSArrayForAllocationMemento(receiver_reg, scratch_reg,
1653  &no_memento_found, eq, memento_found);
1654  bind(&no_memento_found);
1655  }
1656 
1657  // Jumps to found label if a prototype map has dictionary elements.
1659  Register scratch1, Label* found);
1660 
1661  private:
1663  int num_reg_arguments,
1664  int num_double_arguments);
1665 
1668  const Operand& rt,
1669  BranchDelaySlot bdslot = PROTECT);
1671  void BranchAndLinkShort(Label* L, Condition cond, Register rs,
1672  const Operand& rt,
1673  BranchDelaySlot bdslot = PROTECT);
1674  void J(Label* L, BranchDelaySlot bdslot);
1675  void Jr(Label* L, BranchDelaySlot bdslot);
1676  void Jalr(Label* L, BranchDelaySlot bdslot);
1677 
1678  // Helper functions for generating invokes.
1679  void InvokePrologue(const ParameterCount& expected,
1680  const ParameterCount& actual,
1681  Handle<Code> code_constant,
1682  Register code_reg,
1683  Label* done,
1684  bool* definitely_mismatches,
1685  InvokeFlag flag,
1686  const CallWrapper& call_wrapper);
1687 
1688  // Get the code for the given builtin. Returns if able to resolve
1689  // the function in the 'resolved' flag.
1691 
1693  Register length,
1694  Heap::RootListIndex map_index,
1695  Register scratch1,
1696  Register scratch2);
1697 
1698  // Helper for implementing JumpIfNotInNewSpace and JumpIfInNewSpace.
1699  void InNewSpace(Register object,
1700  Register scratch,
1701  Condition cond, // eq for new space, ne otherwise.
1702  Label* branch);
1703 
1704  // Helper for finding the mark bits for an address. Afterwards, the
1705  // bitmap register points at the word with the mark bits and the mask
1706  // the position of the first bit. Leaves addr_reg unchanged.
1707  inline void GetMarkBits(Register addr_reg,
1708  Register bitmap_reg,
1709  Register mask_reg);
1710 
1711  // Helper for throwing exceptions. Compute a handler address and jump to
1712  // it. See the implementation for register usage.
1714 
1715  // Compute memory operands for safepoint stack slots.
1716  static int SafepointRegisterStackIndex(int reg_code);
1719 
1720  bool generating_stub_;
1721  bool has_frame_;
1722  // This handle will be patched with the code object on installation.
1724 
1725  // Needs access to SafepointRegisterStackIndex for compiled frame
1726  // traversal.
1727  friend class StandardFrame;
1728 };
1729 
1730 
1731 // The code patcher is used to patch (typically) small parts of code e.g. for
1732 // debugging and other types of instrumentation. When using the code patcher
1733 // the exact number of bytes specified must be emitted. It is not legal to emit
1734 // relocation information. If any of these constraints are violated it causes
1735 // an assertion to fail.
1736 class CodePatcher {
1737  public:
1739  FLUSH,
1740  DONT_FLUSH
1741  };
1742 
1743  CodePatcher(byte* address,
1744  int instructions,
1745  FlushICache flush_cache = FLUSH);
1746  virtual ~CodePatcher();
1747 
1748  // Macro assembler to emit code.
1749  MacroAssembler* masm() { return &masm_; }
1750 
1751  // Emit an instruction directly.
1752  void Emit(Instr instr);
1753 
1754  // Emit an address directly.
1755  void Emit(Address addr);
1756 
1757  // Change the condition part of an instruction leaving the rest of the current
1758  // instruction unchanged.
1760 
1761  private:
1762  byte* address_; // The address of the code being patched.
1763  int size_; // Number of bytes of the expected patch size.
1764  MacroAssembler masm_; // Macro assembler used to generate the code.
1765  FlushICache flush_cache_; // Whether to flush the I cache after patching.
1766 };
1767 
1768 
1769 
1770 #ifdef GENERATED_CODE_COVERAGE
1771 #define CODE_COVERAGE_STRINGIFY(x) #x
1772 #define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x)
1773 #define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__)
1774 #define ACCESS_MASM(masm) masm->stop(__FILE_LINE__); masm->
1775 #else
1776 #define ACCESS_MASM(masm) masm->
1777 #endif
1778 
1779 } } // namespace v8::internal
1780 
1781 #endif // V8_MIPS_MACRO_ASSEMBLER_MIPS_H_
Isolate * isolate() const
Definition: assembler.h:62
void ld(Register rd, const MemOperand &rs)
void sd(Register rd, const MemOperand &rs)
void lbu(Register rd, const MemOperand &rs)
void mfhc1(Register rt, FPURegister fs)
void dsra(Register rt, Register rd, uint16_t sa)
void hint(SystemHint code)
void mov_d(FPURegister fd, FPURegister fs)
void j(Condition cc, Label *L, Label::Distance distance=Label::kFar)
static bool IsNop(Instr instr, int type=NON_MARKING_NOP)
void dsrl(Register rd, Register rt, uint16_t sa)
void mtc1(Register rt, FPURegister fs)
void shift(Register dst, Immediate shift_amount, int subcode, int size)
void dsra32(Register rt, Register rd, uint16_t sa)
void or_(Register dst, int32_t imm32)
void sll(Register rd, Register rt, uint16_t sa, bool coming_from_nop=false)
void mfc1(Register rt, FPURegister fs)
void mthc1(Register rt, FPURegister fs)
void dsll32(Register rt, Register rd, uint16_t sa)
void sra(Register rt, Register rd, uint16_t sa)
void Emit(Address addr)
void ChangeBranchCondition(Condition cond)
void Emit(Instr instr)
CodePatcher(byte *address, int instructions, FlushICache flush_cache=FLUSH)
static int SlotOffset(int index)
Definition: contexts.h:552
static const int kMapOffset
Definition: objects.h:1427
void Clz(Register rd, Register rs)
void Mul(const Register &rd, const Register &rn, const Register &rm)
void Trunc_uw_d(FPURegister fd, Register rs, FPURegister scratch)
void MovToFloatParameters(DoubleRegister src1, DoubleRegister src2)
void Ret(BranchDelaySlot bd, Condition cond=al, Register rs=zero_reg, const Operand &rt=Operand(zero_reg))
void CopyBytes(Register src, Register dst, Register length, Register scratch)
void Pop(Register src1, Register src2, Register src3)
void GetObjectType(Register function, Register map, Register type_reg)
void JumpIfDataObject(Register value, Register scratch, Label *not_data_object)
void CompareMapAndBranch(Register obj_map, Handle< Map > map, Label *early_success, Condition cond, Label *branch_to)
void Store(Register src, const MemOperand &dst, Representation r)
void Check(Condition cc, BailoutReason reason, Register rs, Operand rt)
void BranchAndLinkShort(int16_t offset, Condition cond, Register rs, const Operand &rt, BranchDelaySlot bdslot=PROTECT)
void RetOnNoOverflow(Register overflow_check, BranchDelaySlot bd=PROTECT)
void BranchAndLinkShort(Label *L, BranchDelaySlot bdslot=PROTECT)
void JumpIfBothInstanceTypesAreNotSequentialOneByte(Register first_object_instance_type, Register second_object_instance_type, Register scratch1, Register scratch2, Label *failure)
void GetLeastBitsFromInt32(Register dst, Register src, int mun_least_bits)
void PushTryHandler(StackHandler::Kind kind, int handler_index)
void TrySmiTag(Register dst, Register src, Register scratch, Label *not_a_smi)
void Jalr(Label *L, BranchDelaySlot bdslot)
void LoadRoot(Register destination, Heap::RootListIndex index, Condition cond, Register src1, const Operand &src2)
void InitializeNewString(Register string, Register length, Heap::RootListIndex map_index, Register scratch1, Register scratch2)
void Move(FPURegister dst, FPURegister src)
void GetLeastBitsFromSmi(Register dst, Register src, int num_least_bits)
void Swap(Register reg1, Register reg2, Register scratch=no_reg)
void CallCFunction(ExternalReference function, int num_arguments)
void AssertName(Register object)
int CalculateStackPassedWords(int num_reg_arguments, int num_double_arguments)
void GetRelocatedValue(Register li_location, Register value, Register scratch)
void InvokeFunction(Handle< JSFunction > function, const ParameterCount &expected, const ParameterCount &actual, InvokeFlag flag, const CallWrapper &call_wrapper)
void Neg(const Register &rd, const Operand &operand)
void AllocateOneByteString(Register result, Register length, Register scratch1, Register scratch2, Register scratch3, Label *gc_required)
void Uld(Register rd, const MemOperand &rs, Register scratch=at)
void TruncateDoubleToI(Register result, DoubleRegister double_input)
void Trunc_l_d(FPURegister fd, FPURegister fs)
void RecordWriteForMap(Register object, Register map, Register dst, RAStatus ra_status, SaveFPRegsMode save_fp)
void EnterFrame(StackFrame::Type type)
void IsObjectNameType(Register object, Register scratch, Label *fail)
void CheckFastSmiElements(Register map, Register scratch, Label *fail)
void LoadContext(Register dst, int context_chain_length)
void LoadTransitionedArrayMapConditional(ElementsKind expected_kind, ElementsKind transitioned_kind, Register map_in_out, Register scratch, Label *no_map_match)
void MultiPushReversedFPU(RegList regs)
void LoadNumberAsInt32(Register object, Register dst, Register heap_number_map, Register scratch1, Register scratch2, FPURegister double_scratch0, FPURegister double_scratch1, Label *not_int32)
void SmiUntag(Register reg, SBit s=LeaveCC)
void Move(FPURegister dst, double imm)
void IsObjectJSStringType(Register object, Register scratch, Label *fail)
void DecodeField(Register dst, Register src)
void LeaveExitFrame(bool save_doubles, Register arg_count, bool restore_context, bool do_return=NO_EMIT_RETURN)
void AllocateHeapNumberWithValue(Register result, FPURegister value, Register scratch1, Register scratch2, Label *gc_required)
void Call(Register target, COND_ARGS)
int CallSize(Handle< Code > code, RelocInfo::Mode rmode=RelocInfo::CODE_TARGET, TypeFeedbackId ast_id=TypeFeedbackId::None(), COND_ARGS)
void Ceil_l_d(FPURegister fd, FPURegister fs)
void LoadRoot(Register destination, Heap::RootListIndex index)
void InitializeFieldsWithFiller(Register start_offset, Register end_offset, Register filler)
void CallRuntime(Runtime::FunctionId id, int num_arguments, SaveFPRegsMode save_doubles=kDontSaveFPRegs)
void Movz(Register rd, Register rs, Register rt)
void PatchRelocatedValue(Register li_location, Register scratch, Register new_value)
void ClampUint8(Register output_reg, Register input_reg)
void Floor_l_d(FPURegister fd, FPURegister fs)
void JumpIfNotUniqueNameInstanceType(Register reg, Label *not_unique_name)
void MultiPushFPU(RegList regs)
void UndoAllocationInNewSpace(Register object, Register scratch)
void CallRuntime(const Runtime::Function *f, int num_arguments, SaveFPRegsMode save_doubles=kDontSaveFPRegs)
void Call(Handle< Code > code, RelocInfo::Mode rmode=RelocInfo::CODE_TARGET, TypeFeedbackId ast_id=TypeFeedbackId::None(), COND_ARGS)
void Move(Register dst, Register src)
void EnsureNotWhite(Register object, Register scratch1, Register scratch2, Register scratch3, Label *object_is_white_and_not_data)
void InvokeFunction(Register function, const ParameterCount &expected, const ParameterCount &actual, InvokeFlag flag, const CallWrapper &call_wrapper)
void Jr(Label *L, BranchDelaySlot bdslot)
void Jump(intptr_t target, RelocInfo::Mode rmode, COND_ARGS)
void StoreRoot(Register source, Heap::RootListIndex index, Condition cond, Register src1, const Operand &src2)
void JumpIfInNewSpace(Register object, Register scratch, Label *branch)
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, PointersToHereCheck pointers_to_here_check_for_value=kPointersToHereMaybeInteresting)
Condition IsObjectStringType(Register obj, Register type, Register result)
void PushRegisterAsTwoSmis(Register src, Register scratch=at)
void InNewSpace(Register object, Register scratch, Condition cond, Label *branch)
static bool IsMarkedCode(Instr instr, int type)
void mov(Register rd, Register rt)
void Trunc_l_ud(FPURegister fd, FPURegister fs, FPURegister scratch)
void CheckMapDeprecated(Handle< Map > map, Register scratch, Label *if_deprecated)
void TryGetFunctionPrototype(Register function, Register result, Register scratch, Label *miss, bool miss_on_bound_function=false)
void SmiTagCheckOverflow(Register dst, Register src, Register overflow)
void UntagAndJumpIfNotSmi(Register dst, Register src, Label *non_smi_case)
static int ActivationFrameAlignment()
void AllocateTwoByteString(Register result, Register length, Register scratch1, Register scratch2, Register scratch3, Label *gc_required)
void PrepareCallCFunction(int num_reg_arguments, Register scratch)
void MultiPush(RegList regs)
void InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag, const CallWrapper &call_wrapper=NullCallWrapper())
void BranchAndLinkShort(int16_t offset, BranchDelaySlot bdslot=PROTECT)
void JumpIfNotInNewSpace(Register object, Register scratch, Label *branch)
void Jump(Register target, COND_ARGS)
void FmoveHigh(Register dst_high, FPURegister src)
void EnumLength(Register dst, Register map)
void Ror(const Register &rd, const Register &rs, unsigned shift)
void BranchF(BranchDelaySlot bd, Label *target, Label *nan, Condition cc, FPURegister cmp1, FPURegister cmp2)
void SmiUntag(Register dst, Register src)
void Move(FPURegister dst, Register src_low, Register src_high)
void CallJSExitStub(CodeStub *stub)
void MultiPopReversed(RegList regs)
void AllocateOneByteSlicedString(Register result, Register length, Register scratch1, Register scratch2, Label *gc_required)
void SmiLoadScale(Register dst, MemOperand src, int scale)
void RecordWriteContextSlot(Register context, int offset, Register value, Register scratch, RAStatus ra_status, SaveFPRegsMode save_fp, RememberedSetAction remembered_set_action=EMIT_REMEMBERED_SET, SmiCheck smi_check=INLINE_SMI_CHECK, PointersToHereCheck pointers_to_here_check_for_value=kPointersToHereMaybeInteresting)
static int SafepointRegisterStackIndex(int reg_code)
void Trunc_w_d(FPURegister fd, FPURegister fs)
Handle< Code > ResolveBuiltin(Builtins::JavaScript id, bool *resolved)
void NonNegativeSmiTst(Register value, Register scratch)
STATIC_ASSERT((reg_zero==(reg_not_zero ^ 1)) &&(reg_bit_clear==(reg_bit_set ^ 1)) &&(always==(never ^ 1)))
void LoadGlobalFunctionInitialMap(Register function, Register map, Register scratch)
void CheckEnumCache(Register null_value, Label *call_runtime)
void TailCallStub(CodeStub *stub, COND_ARGS)
void JumpToExternalReference(const ExternalReference &builtin, BranchDelaySlot bd=PROTECT)
void JumpIfNotSmi(Register value, Label *not_smi_label, Register scratch=at, BranchDelaySlot bd=PROTECT)
void SmiLoadUntagWithScale(Register d_int, Register d_scaled, MemOperand src, int scale)
static int GetCodeMarker(Instr instr)
void Assert(Condition cc, BailoutReason reason, Register rs, Operand rt)
void Throw(Register value)
void Allocate(int object_size, Register result, Register scratch1, Register scratch2, Label *gc_required, AllocationFlags flags)
void StoreRoot(Register source, Heap::RootListIndex index)
void Branch(Label *L, Condition cond, Register rs, Heap::RootListIndex index, BranchDelaySlot bdslot=PROTECT)
void SmiTag(Register reg, SBit s=LeaveCC)
void Push(Register src1, Register src2, Register src3)
void Call(Address target, RelocInfo::Mode rmode, COND_ARGS)
void MultiPopFPU(RegList regs)
void IsInstanceJSObjectType(Register map, Register scratch, Label *fail)
void Drop(int count, Condition cond=cc_always, Register reg=no_reg, const Operand &op=Operand(no_reg))
void Allocate(Register object_size, Register result, Register scratch1, Register scratch2, Label *gc_required, AllocationFlags flags)
void AssertString(Register object)
void SmiTag(Register dst, Register src)
void CheckFastObjectElements(Register map, Register scratch, Label *fail)
void SmiLoadWithScale(Register d_smi, Register d_scaled, MemOperand src, int scale)
void StoreToSafepointRegisterSlot(Register src, Register dst)
void AssertFastElements(Register elements)
void AllocateTwoByteConsString(Register result, Register length, Register scratch1, Register scratch2, Label *gc_required)
bool AllowThisStubCall(CodeStub *stub)
void JumpIfEitherSmi(Register reg1, Register reg2, Label *on_either_smi)
void Abort(BailoutReason msg)
void CallApiFunctionAndReturn(Register function_address, ExternalReference thunk_ref, int stack_space, MemOperand return_value_operand, MemOperand *context_restore_operand)
void IncrementCounter(StatsCounter *counter, int value, Register scratch1, Register scratch2)
void DropAndRet(int drop, Condition cond, Register reg, const Operand &op)
void TruncateNumberToI(Register object, Register result, Register heap_number_map, Register scratch, Label *not_int32)
void MovFromFloatParameter(DoubleRegister dst)
void IndexFromHash(Register hash, Register index)
void GetNumberHash(Register reg0, Register scratch)
void GetBuiltinFunction(Register target, Builtins::JavaScript id)
void LeaveFrame(StackFrame::Type type)
void li(Register rd, Operand j, LiFlags mode=OPTIMIZE_SIZE)
void CallExternalReference(const ExternalReference &ext, int num_arguments, BranchDelaySlot bd=PROTECT)
void Movt(Register rd, Register rs, uint16_t cc=0)
void And(Register dst, Register src1, const Operand &src2, Condition cond=al)
void BranchAndLinkShort(Label *L, Condition cond, Register rs, const Operand &rt, BranchDelaySlot bdslot=PROTECT)
void TailCallExternalReference(const ExternalReference &ext, int num_arguments, int result_size)
void Cvt_d_uw(FPURegister fd, Register rs, FPURegister scratch)
void InvokeFunction(Register function, const ParameterCount &actual, InvokeFlag flag, const CallWrapper &call_wrapper)
void RetOnOverflow(Register overflow_check, BranchDelaySlot bd=PROTECT)
void StoreNumberToDoubleElements(Register value_reg, Register key_reg, Register elements_reg, Register scratch1, Register scratch2, Register scratch3, Label *fail, int elements_offset=0)
void CheckAccessGlobalProxy(Register holder_reg, Register scratch, Label *miss)
void DispatchMap(Register obj, Register scratch, Handle< Map > map, Handle< Code > success, SmiCheckType smi_check_type)
static int CallSize(Register target, COND_ARGS)
void MultiPop(RegList regs)
void BranchOnOverflow(Label *label, Register overflow_check, BranchDelaySlot bd=PROTECT)
void JumpIfNotBothSmi(Register reg1, Register reg2, Label *on_not_both_smi)
void InvokeCode(Register code, const ParameterCount &expected, const ParameterCount &actual, InvokeFlag flag, const CallWrapper &call_wrapper)
void li(Register rd, int64_t j, LiFlags mode=OPTIMIZE_SIZE)
void FmoveLow(Register dst_low, FPURegister src)
void MovToFloatParameter(DoubleRegister src)
void Push(Register src, Condition cond, Register tst1, Register tst2)
void SmiTagCheckOverflow(Register reg, Register overflow)
void Usw(Register rd, const MemOperand &rs)
void MovToFloatResult(DoubleRegister src)
void SubuAndCheckForOverflow(Register dst, Register left, Register right, Register overflow_dst, Register scratch=at)
void TrySmiTag(Register reg, Register scratch, Label *not_a_smi)
void Pop(Register src1, Register src2)
void CallCFunctionHelper(Register function, int num_reg_arguments, int num_double_arguments)
void LoadInstanceDescriptors(Register map, Register descriptors)
void Trunc_uw_d(FPURegister fd, FPURegister fs, FPURegister scratch)
void Usd(Register rd, const MemOperand &rs, Register scratch=at)
void Ceil_w_d(FPURegister fd, FPURegister fs)
void CallCFunction(ExternalReference function, int num_reg_arguments, int num_double_arguments)
void Load(Register dst, const MemOperand &src, Representation r)
void DecrementCounter(StatsCounter *counter, int value, Register scratch1, Register scratch2)
void Ext(Register rt, Register rs, uint16_t pos, uint16_t size)
void CheckMap(Register obj, Register scratch, Heap::RootListIndex index, Label *fail, SmiCheckType smi_check_type)
void SmiLoadUntag(Register dst, MemOperand src)
void UntagAndJumpIfSmi(Register dst, Register src, Label *smi_case)
void CallCFunction(Register function, int num_arguments)
void LoadFromNumberDictionary(Label *miss, Register elements, Register key, Register result, Register reg0, Register reg1, Register reg2)
void TailCallRuntime(Runtime::FunctionId fid, int num_arguments, int result_size)
void PrepareCEntryFunction(const ExternalReference &ref)
void AllocateTwoByteSlicedString(Register result, Register length, Register scratch1, Register scratch2, Label *gc_required)
void Ins(Register rt, Register rs, uint16_t pos, uint16_t size)
void JumpIfInstanceTypeIsNotSequentialOneByte(Register type, Register scratch, Label *failure)
void Jump(Handle< Code > code, RelocInfo::Mode rmode, COND_ARGS)
void DecodeFieldToSmi(Register dst, Register src)
void SmiTst(Register value, Register scratch)
void LookupNumberStringCache(Register object, Register result, Register scratch1, Register scratch2, Register scratch3, Label *not_found)
void Prologue(bool code_pre_aging)
void CheckFastElements(Register map, Register scratch, Label *fail)
void SetCounter(StatsCounter *counter, int value, Register scratch1, Register scratch2)
void GetMarkBits(Register addr_reg, Register bitmap_reg, Register mask_reg)
void BranchOnNoOverflow(Label *label, Register overflow_check, BranchDelaySlot bd=PROTECT)
void TestJSArrayForAllocationMemento(Register receiver_reg, Register scratch_reg, Label *no_memento_found, Condition cond=al, Label *allocation_memento_present=NULL)
void Madd_d(FPURegister fd, FPURegister fr, FPURegister fs, FPURegister ft, FPURegister scratch)
void TruncatingDiv(Register result, Register dividend, int32_t divisor)
void CallStub(CodeStub *stub, TypeFeedbackId ast_id=TypeFeedbackId::None(), COND_ARGS)
void EnterExitFrame(bool save_doubles, int stack_space=0)
MacroAssembler(Isolate *isolate, void *buffer, int size)
MemOperand SafepointRegisterSlot(Register reg)
void J(Label *L, BranchDelaySlot bdslot)
void LoadFromSafepointRegisterSlot(Register dst, Register src)
void IncrementalMarkingRecordWriteHelper(Register object, Register value, Register address)
void JumpIfNotHeapNumber(Register object, Register heap_number_map, Register scratch, Label *on_not_heap_number)
void RecordWrite(Register object, Register address, Register value, RAStatus ra_status, SaveFPRegsMode save_fp, RememberedSetAction remembered_set_action=EMIT_REMEMBERED_SET, SmiCheck smi_check=INLINE_SMI_CHECK, PointersToHereCheck pointers_to_here_check_for_value=kPointersToHereMaybeInteresting)
void Call(Label *target)
void Cvt_d_uw(FPURegister fd, FPURegister fs, FPURegister scratch)
void IsObjectJSObjectType(Register heap_object, Register map, Register scratch, Label *fail)
void InvokePrologue(const ParameterCount &expected, const ParameterCount &actual, Handle< Code > code_constant, Register code_reg, Label *done, bool *definitely_mismatches, InvokeFlag flag, const CallWrapper &call_wrapper)
void AssertIsRoot(Register reg, Heap::RootListIndex index)
void AssertUndefinedOrAllocationSite(Register object, Register scratch)
void CallCFunction(Register function, int num_reg_arguments, int num_double_arguments)
void LoadGlobalFunction(int index, Register function)
static int CallSize(Address target, RelocInfo::Mode rmode, COND_ARGS)
void AllocateOneByteConsString(Register result, Register length, Register scratch1, Register scratch2, Label *gc_required)
void Round_l_d(FPURegister fd, FPURegister fs)
void AssertSmi(Register object)
void Push(Register src1, Register src2, Register src3, Register src4)
void Jump(Address target, RelocInfo::Mode rmode, COND_ARGS)
void LoadNumber(Register object, FPURegister dst, Register heap_number_map, Register scratch, Label *not_number)
void EmitSeqStringSetCharCheck(Register string, Register index, Register value, Register scratch, uint32_t encoding_mask)
void FlushICache(Register address, unsigned instructions)
void LoadNumberAsInt32Double(Register object, DoubleRegister double_dst, Register heap_number_map, Register scratch1, Register scratch2, FPURegister double_scratch, Label *not_int32)
void RecordWriteField(Register object, int offset, Register value, Register scratch, RAStatus ra_status, SaveFPRegsMode save_fp, RememberedSetAction remembered_set_action=EMIT_REMEMBERED_SET, SmiCheck smi_check=INLINE_SMI_CHECK, PointersToHereCheck pointers_to_here_check_for_value=kPointersToHereMaybeInteresting)
MemOperand SafepointRegistersAndDoublesSlot(Register reg)
void JumpIfSmi(Register value, Label *smi_label, Register scratch=at, BranchDelaySlot bd=PROTECT)
void TruncateHeapNumberToI(Register result, Register object)
void Movn(Register rd, Register rs, Register rt)
void Ulw(Register rd, const MemOperand &rs)
void li(Register dst, Handle< Object > value, LiFlags mode=OPTIMIZE_SIZE)
void Movf(Register rd, Register rs, uint16_t cc=0)
void ClampDoubleToUint8(Register result_reg, DoubleRegister input_reg, DoubleRegister temp_double_reg)
void MarkCode(NopMarkerTypes type)
void ThrowUncatchable(Register value)
void RememberedSetHelper(Register object, Register addr, Register scratch, SaveFPRegsMode save_fp, RememberedSetFinalAction and_then)
void PopRegisterAsTwoSmis(Register dst, Register scratch=at)
void PrepareCallCFunction(int num_reg_arguments, int num_double_registers, Register scratch)
void GetBuiltinEntry(Register target, Builtins::JavaScript id)
void TestJSArrayForAllocationMemento(Register receiver_reg, Register scratch_reg, Label *no_memento_found)
void JumpIfJSArrayHasAllocationMemento(Register receiver_reg, Register scratch_reg, Label *memento_found)
void BranchF(Label *target, Label *nan, Condition cc, FPURegister cmp1, FPURegister cmp2, BranchDelaySlot bd=PROTECT)
void Pref(int32_t hint, const MemOperand &rs)
void Round_w_d(FPURegister fd, FPURegister fs)
void JumpIfNotPowerOfTwoOrZero(Register reg, Register scratch, Label *not_power_of_two_or_zero)
void JumpIfNonSmisNotBothSequentialOneByteStrings(Register first, Register second, Register scratch1, Register scratch2, Label *failure)
void JumpIfNotBothSequentialOneByteStrings(Register first, Register second, Register scratch1, Register scratch2, Label *not_flat_one_byte_strings)
void TrySmiTag(Register reg, Label *not_a_smi)
void Push(Register src1, Register src2)
void NumberOfOwnDescriptors(Register dst, Register map)
void MovFromFloatResult(DoubleRegister dst)
void AllocateHeapNumber(Register result, Register scratch1, Register scratch2, Register heap_number_map, Label *gc_required, TaggingMode tagging_mode=TAG_RESULT, MutableMode mode=IMMUTABLE)
void SmiToDoubleFPURegister(Register smi, FPURegister value, Register scratch1)
void HasColor(Register object, Register scratch0, Register scratch1, Label *has_color, int first_bit, int second_bit)
void TryInlineTruncateDoubleToI(Register result, DoubleRegister input, Label *done)
void CompareMapAndBranch(Register obj, Register scratch, Handle< Map > map, Label *early_success, Condition cond, Label *branch_to)
void ObjectToDoubleFPURegister(Register object, FPURegister value, Register scratch1, Register scratch2, Register heap_number_map, Label *not_number, ObjectToDoubleFlags flags=NO_OBJECT_TO_DOUBLE_FLAGS)
void JumpIfDictionaryInPrototypeChain(Register object, Register scratch0, Register scratch1, Label *found)
void AssertNotSmi(Register object)
void Floor_w_d(FPURegister fd, FPURegister fs)
void AdduAndCheckForOverflow(Register dst, Register left, Register right, Register overflow_dst, Register scratch=at)
void Move(Register dst_low, Register dst_high, FPURegister src)
void EmitFPUTruncate(FPURoundingMode rounding_mode, Register result, DoubleRegister double_input, Register scratch, DoubleRegister double_scratch, Register except_flag, CheckForInexactConversion check_inexact=kDontCheckForInexactConversion)
void JumpIfBlack(Register object, Register scratch0, Register scratch1, Label *on_black)
void CheckPageFlag(Register object, Register scratch, int mask, Condition cc, Label *condition_met)
void CheckMap(Register obj, Register scratch, Handle< Map > map, Label *fail, SmiCheckType smi_check_type)
void MultiPopReversedFPU(RegList regs)
void MultiPushReversed(RegList regs)
void CallRuntimeSaveDoubles(Runtime::FunctionId id)
void Push(Handle< Object > handle)
void CopyFields(Register dst, Register src, RegList temps, int field_count)
void SmiScale(Register dst, Register src, int scale)
static const int kInstanceTypeOffset
Definition: objects.h:6229
static const Function * FunctionForId(FunctionId id)
Definition: runtime.cc:9312
static TypeFeedbackId None()
Definition: utils.h:945
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf map
enable harmony numeric enable harmony object literal extensions Optimize object size
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long mode(MIPS only)") DEFINE_BOOL(enable_always_align_csp
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define DCHECK(condition)
Definition: logging.h:205
#define DCHECK_EQ(v1, v2)
Definition: logging.h:206
#define DECLARE_BRANCH_PROTOTYPES(Name)
#define COND_ARGS
InvokeFlag
AllocationFlags
unsigned short uint16_t
Definition: unicode.cc:23
signed short int16_t
Definition: unicode.cc:22
int int32_t
Definition: unicode.cc:24
const int kPointerSize
Definition: globals.h:129
const Register kRootRegister
const int kRtShift
MemOperand ContextOperand(Register context, int index)
const int kSmiShift
bool AreAliased(const CPURegister &reg1, const CPURegister &reg2, const CPURegister &reg3=NoReg, const CPURegister &reg4=NoReg, const CPURegister &reg5=NoReg, const CPURegister &reg6=NoReg, const CPURegister &reg7=NoReg, const CPURegister &reg8=NoReg)
const Register cp
TypeImpl< ZoneTypeConfig > Type
@ kDontCheckForInexactConversion
const intptr_t kSmiSignMask
Definition: globals.h:223
const SwVfpRegister s1
const int kSmiTagSize
Definition: v8.h:5743
const SwVfpRegister s2
const SwVfpRegister s0
const int kRsFieldMask
int ToNumber(Register reg)
const Register sp
const uint32_t kStringTag
Definition: objects.h:544
Handle< T > handle(T *t, Isolate *isolate)
Definition: handles.h:146
MemOperand FieldMemOperand(Register object, int offset)
const int kRsShift
MemOperand CFunctionArgumentOperand(int index)
byte * Address
Definition: globals.h:101
static bool SmiValuesAre32Bits()
Definition: v8.h:5808
const int kCArgsSlotsSize
const int kHeapObjectTag
Definition: v8.h:5737
const Register no_reg
MemOperand UntagSmiFieldMemOperand(Register object, int offset)
kFeedbackVectorOffset flag
Definition: objects-inl.h:5418
const int kRtFieldMask
MemOperand GlobalObjectOperand()
STATIC_ASSERT(sizeof(CPURegister)==sizeof(Register))
const int kBitsPerByte
Definition: globals.h:162
const intptr_t kSmiTagMask
Definition: v8.h:5744
const int kOpcodeMask
const int kSaFieldMask
const int kSmiTag
Definition: v8.h:5742
Register GetRegisterThatIsNotOneOf(Register reg1, Register reg2=no_reg, Register reg3=no_reg, Register reg4=no_reg, Register reg5=no_reg, Register reg6=no_reg)
const uint32_t kIsNotStringMask
Definition: objects.h:543
@ kPointersToHereAreAlwaysInteresting
const int kSaShift
MemOperand UntagSmiMemOperand(Register object, int offset)
const int kCArgSlotCount
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20
bool is(FPURegister creg) const
bool is(Register reg) const