| OLD | NEW | 
|---|
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. | 
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without | 
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are | 
| 4 // met: | 4 // met: | 
| 5 // | 5 // | 
| 6 //     * Redistributions of source code must retain the above copyright | 6 //     * Redistributions of source code must retain the above copyright | 
| 7 //       notice, this list of conditions and the following disclaimer. | 7 //       notice, this list of conditions and the following disclaimer. | 
| 8 //     * Redistributions in binary form must reproduce the above | 8 //     * Redistributions in binary form must reproduce the above | 
| 9 //       copyright notice, this list of conditions and the following | 9 //       copyright notice, this list of conditions and the following | 
| 10 //       disclaimer in the documentation and/or other materials provided | 10 //       disclaimer in the documentation and/or other materials provided | 
| 11 //       with the distribution. | 11 //       with the distribution. | 
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 45 // but won't touch other registers except in special cases. | 45 // but won't touch other registers except in special cases. | 
| 46 // | 46 // | 
| 47 // Per the MIPS ABI, register t9 must be used for indirect function call | 47 // Per the MIPS ABI, register t9 must be used for indirect function call | 
| 48 // via 'jalr t9' or 'jr t9' instructions. This is relied upon by gcc when | 48 // via 'jalr t9' or 'jr t9' instructions. This is relied upon by gcc when | 
| 49 // trying to update gp register for position-independent-code. Whenever | 49 // trying to update gp register for position-independent-code. Whenever | 
| 50 // MIPS generated code calls C code, it must be via t9 register. | 50 // MIPS generated code calls C code, it must be via t9 register. | 
| 51 | 51 | 
| 52 // Registers aliases | 52 // Registers aliases | 
| 53 // cp is assumed to be a callee saved register. | 53 // cp is assumed to be a callee saved register. | 
| 54 const Register roots = s6;  // Roots array pointer. | 54 const Register roots = s6;  // Roots array pointer. | 
| 55 const Register cp = s7;     // JavaScript context pointer | 55 const Register cp = s7;     // JavaScript context pointer. | 
| 56 const Register fp = s8_fp;  // Alias fp | 56 const Register fp = s8_fp;  // Alias for fp. | 
| 57 // Register used for condition evaluation. | 57 // Registers used for condition evaluation. | 
| 58 const Register condReg1 = s4; | 58 const Register condReg1 = s4; | 
| 59 const Register condReg2 = s5; | 59 const Register condReg2 = s5; | 
| 60 | 60 | 
| 61 | 61 | 
| 62 // Flags used for the AllocateInNewSpace functions. | 62 // Flags used for the AllocateInNewSpace functions. | 
| 63 enum AllocationFlags { | 63 enum AllocationFlags { | 
| 64   // No special flags. | 64   // No special flags. | 
| 65   NO_ALLOCATION_FLAGS = 0, | 65   NO_ALLOCATION_FLAGS = 0, | 
| 66   // Return the pointer to the allocated already tagged as a heap object. | 66   // Return the pointer to the allocated already tagged as a heap object. | 
| 67   TAG_OBJECT = 1 << 0, | 67   TAG_OBJECT = 1 << 0, | 
| (...skipping 17 matching lines...) Expand all  Loading... | 
| 85 | 85 | 
| 86 // Allow programmer to use Branch Delay Slot of Branches, Jumps, Calls. | 86 // Allow programmer to use Branch Delay Slot of Branches, Jumps, Calls. | 
| 87 enum BranchDelaySlot { | 87 enum BranchDelaySlot { | 
| 88   USE_DELAY_SLOT, | 88   USE_DELAY_SLOT, | 
| 89   PROTECT | 89   PROTECT | 
| 90 }; | 90 }; | 
| 91 | 91 | 
| 92 // MacroAssembler implements a collection of frequently used macros. | 92 // MacroAssembler implements a collection of frequently used macros. | 
| 93 class MacroAssembler: public Assembler { | 93 class MacroAssembler: public Assembler { | 
| 94  public: | 94  public: | 
| 95   MacroAssembler(void* buffer, int size); | 95   // The isolate parameter can be NULL if the macro assembler should | 
|  | 96   // not use isolate-dependent functionality. In this case, it's the | 
|  | 97   // responsibility of the caller to never invoke such function on the | 
|  | 98   // macro assembler. | 
|  | 99   MacroAssembler(Isolate* isolate, void* buffer, int size); | 
| 96 | 100 | 
| 97 // Arguments macros | 101 // Arguments macros. | 
| 98 #define COND_TYPED_ARGS Condition cond, Register r1, const Operand& r2 | 102 #define COND_TYPED_ARGS Condition cond, Register r1, const Operand& r2 | 
| 99 #define COND_ARGS cond, r1, r2 | 103 #define COND_ARGS cond, r1, r2 | 
| 100 | 104 | 
| 101 // ** Prototypes | 105 // Prototypes. | 
| 102 | 106 | 
| 103 // * Prototypes for functions with no target (eg Ret()). | 107 // Prototypes for functions with no target (eg Ret()). | 
| 104 #define DECLARE_NOTARGET_PROTOTYPE(Name) \ | 108 #define DECLARE_NOTARGET_PROTOTYPE(Name) \ | 
| 105   void Name(BranchDelaySlot bd = PROTECT); \ | 109   void Name(BranchDelaySlot bd = PROTECT); \ | 
| 106   void Name(COND_TYPED_ARGS, BranchDelaySlot bd = PROTECT); \ | 110   void Name(COND_TYPED_ARGS, BranchDelaySlot bd = PROTECT); \ | 
| 107   inline void Name(BranchDelaySlot bd, COND_TYPED_ARGS) { \ | 111   inline void Name(BranchDelaySlot bd, COND_TYPED_ARGS) { \ | 
| 108     Name(COND_ARGS, bd); \ | 112     Name(COND_ARGS, bd); \ | 
| 109   } | 113   } | 
| 110 | 114 | 
| 111 // * Prototypes for functions with a target. | 115 // Prototypes for functions with a target. | 
| 112 | 116 | 
| 113 // Cases when relocation may be needed. | 117 // Cases when relocation may be needed. | 
| 114 #define DECLARE_RELOC_PROTOTYPE(Name, target_type) \ | 118 #define DECLARE_RELOC_PROTOTYPE(Name, target_type) \ | 
| 115   void Name(target_type target, \ | 119   void Name(target_type target, \ | 
| 116             RelocInfo::Mode rmode, \ | 120             RelocInfo::Mode rmode, \ | 
| 117             BranchDelaySlot bd = PROTECT); \ | 121             BranchDelaySlot bd = PROTECT); \ | 
| 118   inline void Name(BranchDelaySlot bd, \ | 122   inline void Name(BranchDelaySlot bd, \ | 
| 119                    target_type target, \ | 123                    target_type target, \ | 
| 120                    RelocInfo::Mode rmode) { \ | 124                    RelocInfo::Mode rmode) { \ | 
| 121     Name(target, rmode, bd); \ | 125     Name(target, rmode, bd); \ | 
| (...skipping 17 matching lines...) Expand all  Loading... | 
| 139   } \ | 143   } \ | 
| 140   void Name(target_type target, \ | 144   void Name(target_type target, \ | 
| 141             COND_TYPED_ARGS, \ | 145             COND_TYPED_ARGS, \ | 
| 142             BranchDelaySlot bd = PROTECT); \ | 146             BranchDelaySlot bd = PROTECT); \ | 
| 143   inline void Name(BranchDelaySlot bd, \ | 147   inline void Name(BranchDelaySlot bd, \ | 
| 144                    target_type target, \ | 148                    target_type target, \ | 
| 145                    COND_TYPED_ARGS) { \ | 149                    COND_TYPED_ARGS) { \ | 
| 146     Name(target, COND_ARGS, bd); \ | 150     Name(target, COND_ARGS, bd); \ | 
| 147   } | 151   } | 
| 148 | 152 | 
| 149 // ** Target prototypes. | 153 // Target prototypes. | 
| 150 | 154 | 
| 151 #define DECLARE_JUMP_CALL_PROTOTYPES(Name) \ | 155 #define DECLARE_JUMP_CALL_PROTOTYPES(Name) \ | 
| 152   DECLARE_NORELOC_PROTOTYPE(Name, Register) \ | 156   DECLARE_NORELOC_PROTOTYPE(Name, Register) \ | 
| 153   DECLARE_NORELOC_PROTOTYPE(Name, const Operand&) \ | 157   DECLARE_NORELOC_PROTOTYPE(Name, const Operand&) \ | 
| 154   DECLARE_RELOC_PROTOTYPE(Name, byte*) \ | 158   DECLARE_RELOC_PROTOTYPE(Name, byte*) \ | 
| 155   DECLARE_RELOC_PROTOTYPE(Name, Handle<Code>) | 159   DECLARE_RELOC_PROTOTYPE(Name, Handle<Code>) | 
| 156 | 160 | 
| 157 #define DECLARE_BRANCH_PROTOTYPES(Name) \ | 161 #define DECLARE_BRANCH_PROTOTYPES(Name) \ | 
| 158   DECLARE_NORELOC_PROTOTYPE(Name, Label*) \ | 162   DECLARE_NORELOC_PROTOTYPE(Name, Label*) \ | 
| 159   DECLARE_NORELOC_PROTOTYPE(Name, int16_t) | 163   DECLARE_NORELOC_PROTOTYPE(Name, int16_t) | 
| 160 | 164 | 
| 161 | 165 | 
| 162 DECLARE_JUMP_CALL_PROTOTYPES(Jump) | 166 DECLARE_JUMP_CALL_PROTOTYPES(Jump) | 
| 163 DECLARE_JUMP_CALL_PROTOTYPES(Call) | 167 DECLARE_JUMP_CALL_PROTOTYPES(Call) | 
| 164 | 168 | 
| 165 DECLARE_BRANCH_PROTOTYPES(Branch) | 169 DECLARE_BRANCH_PROTOTYPES(Branch) | 
| 166 DECLARE_BRANCH_PROTOTYPES(BranchAndLink) | 170 DECLARE_BRANCH_PROTOTYPES(BranchAndLink) | 
| 167 | 171 | 
| 168 DECLARE_NOTARGET_PROTOTYPE(Ret) | 172 DECLARE_NOTARGET_PROTOTYPE(Ret) | 
| 169 | 173 | 
| 170 #undef COND_TYPED_ARGS | 174 #undef COND_TYPED_ARGS | 
| 171 #undef COND_ARGS | 175 #undef COND_ARGS | 
| 172 #undef DECLARE_NOTARGET_PROTOTYPE | 176 #undef DECLARE_NOTARGET_PROTOTYPE | 
| 173 #undef DECLARE_NORELOC_PROTOTYPE | 177 #undef DECLARE_NORELOC_PROTOTYPE | 
| 174 #undef DECLARE_RELOC_PROTOTYPE | 178 #undef DECLARE_RELOC_PROTOTYPE | 
| 175 #undef DECLARE_JUMP_CALL_PROTOTYPES | 179 #undef DECLARE_JUMP_CALL_PROTOTYPES | 
| 176 #undef DECLARE_BRANCH_PROTOTYPES | 180 #undef DECLARE_BRANCH_PROTOTYPES | 
| 177 | 181 | 
|  | 182   void CallWithAstId(Handle<Code> code, | 
|  | 183                      RelocInfo::Mode rmode, | 
|  | 184                      unsigned ast_id, | 
|  | 185                      Condition cond = al, | 
|  | 186                      Register r1 = zero_reg, | 
|  | 187                      const Operand& r2 = Operand(zero_reg)); | 
|  | 188 | 
|  | 189   int CallSize(Register reg); | 
|  | 190   int CallSize(Handle<Code> code, RelocInfo::Mode rmode); | 
|  | 191 | 
| 178   // Emit code to discard a non-negative number of pointer-sized elements | 192   // Emit code to discard a non-negative number of pointer-sized elements | 
| 179   // from the stack, clobbering only the sp register. | 193   // from the stack, clobbering only the sp register. | 
| 180   void Drop(int count, | 194   void Drop(int count, | 
| 181             Condition cond = cc_always, | 195             Condition cond = cc_always, | 
| 182             Register reg = no_reg, | 196             Register reg = no_reg, | 
| 183             const Operand& op = Operand(no_reg)); | 197             const Operand& op = Operand(no_reg)); | 
| 184 | 198 | 
| 185   void DropAndRet(int drop = 0, | 199   void DropAndRet(int drop = 0, | 
| 186                   Condition cond = cc_always, | 200                   Condition cond = cc_always, | 
| 187                   Register reg = no_reg, | 201                   Register reg = no_reg, | 
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 249   // [address] dirty. The object address must be in the first 8K of an | 263   // [address] dirty. The object address must be in the first 8K of an | 
| 250   // allocated page.  All 3 registers are clobbered by the operation, | 264   // allocated page.  All 3 registers are clobbered by the operation, | 
| 251   // as well as the ip register. RecordWrite updates the write barrier | 265   // as well as the ip register. RecordWrite updates the write barrier | 
| 252   // even when storing smis. | 266   // even when storing smis. | 
| 253   void RecordWrite(Register object, | 267   void RecordWrite(Register object, | 
| 254                    Register address, | 268                    Register address, | 
| 255                    Register scratch); | 269                    Register scratch); | 
| 256 | 270 | 
| 257 | 271 | 
| 258   // --------------------------------------------------------------------------- | 272   // --------------------------------------------------------------------------- | 
| 259   // Inline caching support | 273   // Inline caching support. | 
| 260 | 274 | 
| 261   // Generate code for checking access rights - used for security checks | 275   // Generate code for checking access rights - used for security checks | 
| 262   // on access to global objects across environments. The holder register | 276   // on access to global objects across environments. The holder register | 
| 263   // is left untouched, whereas both scratch registers are clobbered. | 277   // is left untouched, whereas both scratch registers are clobbered. | 
| 264   void CheckAccessGlobalProxy(Register holder_reg, | 278   void CheckAccessGlobalProxy(Register holder_reg, | 
| 265                               Register scratch, | 279                               Register scratch, | 
| 266                               Label* miss); | 280                               Label* miss); | 
| 267 | 281 | 
| 268   inline void MarkCode(NopMarkerTypes type) { | 282   inline void MarkCode(NopMarkerTypes type) { | 
| 269     nop(type); | 283     nop(type); | 
| (...skipping 23 matching lines...) Expand all  Loading... | 
| 293     int type = | 307     int type = | 
| 294         (sllzz && FIRST_IC_MARKER <= sa && sa < LAST_CODE_MARKER) ? sa : -1; | 308         (sllzz && FIRST_IC_MARKER <= sa && sa < LAST_CODE_MARKER) ? sa : -1; | 
| 295     ASSERT((type == -1) || | 309     ASSERT((type == -1) || | 
| 296            ((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER))); | 310            ((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER))); | 
| 297     return type; | 311     return type; | 
| 298   } | 312   } | 
| 299 | 313 | 
| 300 | 314 | 
| 301 | 315 | 
| 302   // --------------------------------------------------------------------------- | 316   // --------------------------------------------------------------------------- | 
| 303   // Allocation support | 317   // Allocation support. | 
| 304 | 318 | 
| 305   // Allocate an object in new space. The object_size is specified | 319   // Allocate an object in new space. The object_size is specified | 
| 306   // either in bytes or in words if the allocation flag SIZE_IN_WORDS | 320   // either in bytes or in words if the allocation flag SIZE_IN_WORDS | 
| 307   // is passed. If the new space is exhausted control continues at the | 321   // is passed. If the new space is exhausted control continues at the | 
| 308   // gc_required label. The allocated object is returned in result. If | 322   // gc_required label. The allocated object is returned in result. If | 
| 309   // the flag tag_allocated_object is true the result is tagged as as | 323   // the flag tag_allocated_object is true the result is tagged as as | 
| 310   // a heap object. All registers are clobbered also when control | 324   // a heap object. All registers are clobbered also when control | 
| 311   // continues at the gc_required label. | 325   // continues at the gc_required label. | 
| 312   void AllocateInNewSpace(int object_size, | 326   void AllocateInNewSpace(int object_size, | 
| 313                           Register result, | 327                           Register result, | 
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 360                           Register scratch2, | 374                           Register scratch2, | 
| 361                           Register heap_number_map, | 375                           Register heap_number_map, | 
| 362                           Label* gc_required); | 376                           Label* gc_required); | 
| 363   void AllocateHeapNumberWithValue(Register result, | 377   void AllocateHeapNumberWithValue(Register result, | 
| 364                                    FPURegister value, | 378                                    FPURegister value, | 
| 365                                    Register scratch1, | 379                                    Register scratch1, | 
| 366                                    Register scratch2, | 380                                    Register scratch2, | 
| 367                                    Label* gc_required); | 381                                    Label* gc_required); | 
| 368 | 382 | 
| 369   // --------------------------------------------------------------------------- | 383   // --------------------------------------------------------------------------- | 
| 370   // Instruction macros | 384   // Instruction macros. | 
| 371 | 385 | 
| 372 #define DEFINE_INSTRUCTION(instr)                                              \ | 386 #define DEFINE_INSTRUCTION(instr)                                              \ | 
| 373   void instr(Register rd, Register rs, const Operand& rt);                     \ | 387   void instr(Register rd, Register rs, const Operand& rt);                     \ | 
| 374   void instr(Register rd, Register rs, Register rt) {                          \ | 388   void instr(Register rd, Register rs, Register rt) {                          \ | 
| 375     instr(rd, rs, Operand(rt));                                                \ | 389     instr(rd, rs, Operand(rt));                                                \ | 
| 376   }                                                                            \ | 390   }                                                                            \ | 
| 377   void instr(Register rs, Register rt, int32_t j) {                            \ | 391   void instr(Register rs, Register rt, int32_t j) {                            \ | 
| 378     instr(rs, rt, Operand(j));                                                 \ | 392     instr(rs, rt, Operand(j));                                                 \ | 
| 379   } | 393   } | 
| 380 | 394 | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
| 392   DEFINE_INSTRUCTION(Mul); | 406   DEFINE_INSTRUCTION(Mul); | 
| 393   DEFINE_INSTRUCTION2(Mult); | 407   DEFINE_INSTRUCTION2(Mult); | 
| 394   DEFINE_INSTRUCTION2(Multu); | 408   DEFINE_INSTRUCTION2(Multu); | 
| 395   DEFINE_INSTRUCTION2(Div); | 409   DEFINE_INSTRUCTION2(Div); | 
| 396   DEFINE_INSTRUCTION2(Divu); | 410   DEFINE_INSTRUCTION2(Divu); | 
| 397 | 411 | 
| 398   DEFINE_INSTRUCTION(And); | 412   DEFINE_INSTRUCTION(And); | 
| 399   DEFINE_INSTRUCTION(Or); | 413   DEFINE_INSTRUCTION(Or); | 
| 400   DEFINE_INSTRUCTION(Xor); | 414   DEFINE_INSTRUCTION(Xor); | 
| 401   DEFINE_INSTRUCTION(Nor); | 415   DEFINE_INSTRUCTION(Nor); | 
|  | 416   DEFINE_INSTRUCTION2(Neg); | 
| 402 | 417 | 
| 403   DEFINE_INSTRUCTION(Slt); | 418   DEFINE_INSTRUCTION(Slt); | 
| 404   DEFINE_INSTRUCTION(Sltu); | 419   DEFINE_INSTRUCTION(Sltu); | 
| 405 | 420 | 
| 406   // MIPS32 R2 instruction macro. | 421   // MIPS32 R2 instruction macro. | 
| 407   DEFINE_INSTRUCTION(Ror); | 422   DEFINE_INSTRUCTION(Ror); | 
| 408 | 423 | 
| 409 #undef DEFINE_INSTRUCTION | 424 #undef DEFINE_INSTRUCTION | 
| 410 #undef DEFINE_INSTRUCTION2 | 425 #undef DEFINE_INSTRUCTION2 | 
| 411 | 426 | 
| 412 | 427 | 
| 413   //------------Pseudo-instructions------------- | 428   // --------------------------------------------------------------------------- | 
|  | 429   // Pseudo-instructions. | 
| 414 | 430 | 
| 415   void mov(Register rd, Register rt) { or_(rd, rt, zero_reg); } | 431   void mov(Register rd, Register rt) { or_(rd, rt, zero_reg); } | 
| 416 | 432 | 
| 417 | 433   // Load int32 in the rd register. | 
| 418   // load int32 in the rd register |  | 
| 419   void li(Register rd, Operand j, bool gen2instr = false); | 434   void li(Register rd, Operand j, bool gen2instr = false); | 
| 420   inline void li(Register rd, int32_t j, bool gen2instr = false) { | 435   inline void li(Register rd, int32_t j, bool gen2instr = false) { | 
| 421     li(rd, Operand(j), gen2instr); | 436     li(rd, Operand(j), gen2instr); | 
| 422   } | 437   } | 
| 423   inline void li(Register dst, Handle<Object> value, bool gen2instr = false) { | 438   inline void li(Register dst, Handle<Object> value, bool gen2instr = false) { | 
| 424     li(dst, Operand(value), gen2instr); | 439     li(dst, Operand(value), gen2instr); | 
| 425   } | 440   } | 
| 426 | 441 | 
| 427   // Exception-generating instructions and debugging support | 442   // Exception-generating instructions and debugging support. | 
| 428   void stop(const char* msg); | 443   void stop(const char* msg); | 
| 429 | 444 | 
| 430 |  | 
| 431   // Push multiple registers on the stack. | 445   // Push multiple registers on the stack. | 
| 432   // Registers are saved in numerical order, with higher numbered registers | 446   // Registers are saved in numerical order, with higher numbered registers | 
| 433   // saved in higher memory addresses | 447   // saved in higher memory addresses. | 
| 434   void MultiPush(RegList regs); | 448   void MultiPush(RegList regs); | 
| 435   void MultiPushReversed(RegList regs); | 449   void MultiPushReversed(RegList regs); | 
| 436 | 450 | 
| 437   void Push(Register src) { | 451   // Lower case push() for compatibility with arch-independent code. | 
|  | 452   void push(Register src) { | 
| 438     Addu(sp, sp, Operand(-kPointerSize)); | 453     Addu(sp, sp, Operand(-kPointerSize)); | 
| 439     sw(src, MemOperand(sp, 0)); | 454     sw(src, MemOperand(sp, 0)); | 
| 440   } | 455   } | 
| 441 | 456 | 
| 442   // Push two registers.  Pushes leftmost register first (to highest address). | 457   // Push two registers. Pushes leftmost register first (to highest address). | 
| 443   void Push(Register src1, Register src2, Condition cond = al) { | 458   void Push(Register src1, Register src2) { | 
| 444     ASSERT(cond == al);  // Do not support conditional versions yet. |  | 
| 445     Subu(sp, sp, Operand(2 * kPointerSize)); | 459     Subu(sp, sp, Operand(2 * kPointerSize)); | 
| 446     sw(src1, MemOperand(sp, 1 * kPointerSize)); | 460     sw(src1, MemOperand(sp, 1 * kPointerSize)); | 
| 447     sw(src2, MemOperand(sp, 0 * kPointerSize)); | 461     sw(src2, MemOperand(sp, 0 * kPointerSize)); | 
| 448   } | 462   } | 
| 449 | 463 | 
| 450   // Push three registers.  Pushes leftmost register first (to highest address). | 464   // Push three registers. Pushes leftmost register first (to highest address). | 
| 451   void Push(Register src1, Register src2, Register src3, Condition cond = al) { | 465   void Push(Register src1, Register src2, Register src3) { | 
| 452     ASSERT(cond == al);  // Do not support conditional versions yet. | 466     Subu(sp, sp, Operand(3 * kPointerSize)); | 
| 453     Addu(sp, sp, Operand(3 * -kPointerSize)); |  | 
| 454     sw(src1, MemOperand(sp, 2 * kPointerSize)); | 467     sw(src1, MemOperand(sp, 2 * kPointerSize)); | 
| 455     sw(src2, MemOperand(sp, 1 * kPointerSize)); | 468     sw(src2, MemOperand(sp, 1 * kPointerSize)); | 
| 456     sw(src3, MemOperand(sp, 0 * kPointerSize)); | 469     sw(src3, MemOperand(sp, 0 * kPointerSize)); | 
| 457   } | 470   } | 
| 458 | 471 | 
| 459   // Push four registers.  Pushes leftmost register first (to highest address). | 472   // Push four registers. Pushes leftmost register first (to highest address). | 
| 460   void Push(Register src1, Register src2, | 473   void Push(Register src1, Register src2, Register src3, Register src4) { | 
| 461             Register src3, Register src4, Condition cond = al) { | 474     Subu(sp, sp, Operand(4 * kPointerSize)); | 
| 462     ASSERT(cond == al);  // Do not support conditional versions yet. |  | 
| 463     Addu(sp, sp, Operand(4 * -kPointerSize)); |  | 
| 464     sw(src1, MemOperand(sp, 3 * kPointerSize)); | 475     sw(src1, MemOperand(sp, 3 * kPointerSize)); | 
| 465     sw(src2, MemOperand(sp, 2 * kPointerSize)); | 476     sw(src2, MemOperand(sp, 2 * kPointerSize)); | 
| 466     sw(src3, MemOperand(sp, 1 * kPointerSize)); | 477     sw(src3, MemOperand(sp, 1 * kPointerSize)); | 
| 467     sw(src4, MemOperand(sp, 0 * kPointerSize)); | 478     sw(src4, MemOperand(sp, 0 * kPointerSize)); | 
| 468   } | 479   } | 
| 469 | 480 | 
| 470   inline void push(Register src) { Push(src); } |  | 
| 471   inline void pop(Register src) { Pop(src); } |  | 
| 472 |  | 
| 473   void Push(Register src, Condition cond, Register tst1, Register tst2) { | 481   void Push(Register src, Condition cond, Register tst1, Register tst2) { | 
| 474     // Since we don't have conditionnal execution we use a Branch. | 482     // Since we don't have conditional execution we use a Branch. | 
| 475     Branch(3, cond, tst1, Operand(tst2)); | 483     Branch(3, cond, tst1, Operand(tst2)); | 
| 476     Addu(sp, sp, Operand(-kPointerSize)); | 484     Subu(sp, sp, Operand(kPointerSize)); | 
| 477     sw(src, MemOperand(sp, 0)); | 485     sw(src, MemOperand(sp, 0)); | 
| 478   } | 486   } | 
| 479 | 487 | 
| 480 |  | 
| 481   // Pops multiple values from the stack and load them in the | 488   // Pops multiple values from the stack and load them in the | 
| 482   // registers specified in regs. Pop order is the opposite as in MultiPush. | 489   // registers specified in regs. Pop order is the opposite as in MultiPush. | 
| 483   void MultiPop(RegList regs); | 490   void MultiPop(RegList regs); | 
| 484   void MultiPopReversed(RegList regs); | 491   void MultiPopReversed(RegList regs); | 
| 485   void Pop(Register dst) { | 492 | 
|  | 493   // Lower case pop() for compatibility with arch-independent code. | 
|  | 494   void pop(Register dst) { | 
| 486     lw(dst, MemOperand(sp, 0)); | 495     lw(dst, MemOperand(sp, 0)); | 
| 487     Addu(sp, sp, Operand(kPointerSize)); | 496     Addu(sp, sp, Operand(kPointerSize)); | 
| 488   } | 497   } | 
|  | 498 | 
|  | 499   // Pop two registers. Pops rightmost register first (from lower address). | 
|  | 500   void Pop(Register src1, Register src2) { | 
|  | 501     ASSERT(!src1.is(src2)); | 
|  | 502     lw(src2, MemOperand(sp, 0 * kPointerSize)); | 
|  | 503     lw(src1, MemOperand(sp, 1 * kPointerSize)); | 
|  | 504     Addu(sp, sp, 2 * kPointerSize); | 
|  | 505   } | 
|  | 506 | 
| 489   void Pop(uint32_t count = 1) { | 507   void Pop(uint32_t count = 1) { | 
| 490     Addu(sp, sp, Operand(count * kPointerSize)); | 508     Addu(sp, sp, Operand(count * kPointerSize)); | 
| 491   } | 509   } | 
| 492 | 510 | 
| 493   // --------------------------------------------------------------------------- | 511   // --------------------------------------------------------------------------- | 
| 494   // These functions are only used by crankshaft, so they are currently | 512   // These functions are only used by crankshaft, so they are currently | 
| 495   // unimplemented. | 513   // unimplemented. | 
| 496 | 514 | 
| 497   // Push and pop the registers that can hold pointers, as defined by the | 515   // Push and pop the registers that can hold pointers, as defined by the | 
| 498   // RegList constant kSafepointSavedRegisters. | 516   // RegList constant kSafepointSavedRegisters. | 
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 535   // dest. If the HeapNumber does not fit into a 32bits signed integer branch | 553   // dest. If the HeapNumber does not fit into a 32bits signed integer branch | 
| 536   // to not_int32 label. If FPU is available double_scratch is used but not | 554   // to not_int32 label. If FPU is available double_scratch is used but not | 
| 537   // scratch2. | 555   // scratch2. | 
| 538   void ConvertToInt32(Register source, | 556   void ConvertToInt32(Register source, | 
| 539                       Register dest, | 557                       Register dest, | 
| 540                       Register scratch, | 558                       Register scratch, | 
| 541                       Register scratch2, | 559                       Register scratch2, | 
| 542                       FPURegister double_scratch, | 560                       FPURegister double_scratch, | 
| 543                       Label *not_int32); | 561                       Label *not_int32); | 
| 544 | 562 | 
|  | 563   // Helper for EmitECMATruncate. | 
|  | 564   // This will truncate a floating-point value outside of the singed 32bit | 
|  | 565   // integer range to a 32bit signed integer. | 
|  | 566   // Expects the double value loaded in input_high and input_low. | 
|  | 567   // Exits with the answer in 'result'. | 
|  | 568   // Note that this code does not work for values in the 32bit range! | 
|  | 569   void EmitOutOfInt32RangeTruncate(Register result, | 
|  | 570                                    Register input_high, | 
|  | 571                                    Register input_low, | 
|  | 572                                    Register scratch); | 
|  | 573 | 
| 545   // ------------------------------------------------------------------------- | 574   // ------------------------------------------------------------------------- | 
| 546   // Activation frames | 575   // Activation frames. | 
| 547 | 576 | 
| 548   void EnterInternalFrame() { EnterFrame(StackFrame::INTERNAL); } | 577   void EnterInternalFrame() { EnterFrame(StackFrame::INTERNAL); } | 
| 549   void LeaveInternalFrame() { LeaveFrame(StackFrame::INTERNAL); } | 578   void LeaveInternalFrame() { LeaveFrame(StackFrame::INTERNAL); } | 
| 550 | 579 | 
| 551   void EnterConstructFrame() { EnterFrame(StackFrame::CONSTRUCT); } | 580   void EnterConstructFrame() { EnterFrame(StackFrame::CONSTRUCT); } | 
| 552   void LeaveConstructFrame() { LeaveFrame(StackFrame::CONSTRUCT); } | 581   void LeaveConstructFrame() { LeaveFrame(StackFrame::CONSTRUCT); } | 
| 553 | 582 | 
| 554   // Enter exit frame. | 583   // Enter exit frame. | 
| 555   // Expects the number of arguments in register a0 and | 584   // Expects the number of arguments in register a0 and | 
| 556   // the builtin function to call in register a1. | 585   // the builtin function to call in register a1. | 
| (...skipping 16 matching lines...) Expand all  Loading... | 
| 573 | 602 | 
| 574   void LoadGlobalFunction(int index, Register function); | 603   void LoadGlobalFunction(int index, Register function); | 
| 575 | 604 | 
| 576   // Load the initial map from the global function. The registers | 605   // Load the initial map from the global function. The registers | 
| 577   // function and map can be the same, function is then overwritten. | 606   // function and map can be the same, function is then overwritten. | 
| 578   void LoadGlobalFunctionInitialMap(Register function, | 607   void LoadGlobalFunctionInitialMap(Register function, | 
| 579                                     Register map, | 608                                     Register map, | 
| 580                                     Register scratch); | 609                                     Register scratch); | 
| 581 | 610 | 
| 582   // ------------------------------------------------------------------------- | 611   // ------------------------------------------------------------------------- | 
| 583   // JavaScript invokes | 612   // JavaScript invokes. | 
| 584 | 613 | 
| 585   // Invoke the JavaScript function code by either calling or jumping. | 614   // Invoke the JavaScript function code by either calling or jumping. | 
| 586   void InvokeCode(Register code, | 615   void InvokeCode(Register code, | 
| 587                   const ParameterCount& expected, | 616                   const ParameterCount& expected, | 
| 588                   const ParameterCount& actual, | 617                   const ParameterCount& actual, | 
| 589                   InvokeFlag flag, | 618                   InvokeFlag flag, | 
| 590                   const CallWrapper& call_wrapper = NullCallWrapper()); | 619                   const CallWrapper& call_wrapper = NullCallWrapper()); | 
| 591 | 620 | 
| 592   void InvokeCode(Handle<Code> code, | 621   void InvokeCode(Handle<Code> code, | 
| 593                   const ParameterCount& expected, | 622                   const ParameterCount& expected, | 
| (...skipping 21 matching lines...) Expand all  Loading... | 
| 615   void IsInstanceJSObjectType(Register map, | 644   void IsInstanceJSObjectType(Register map, | 
| 616                               Register scratch, | 645                               Register scratch, | 
| 617                               Label* fail); | 646                               Label* fail); | 
| 618 | 647 | 
| 619   void IsObjectJSStringType(Register object, | 648   void IsObjectJSStringType(Register object, | 
| 620                             Register scratch, | 649                             Register scratch, | 
| 621                             Label* fail); | 650                             Label* fail); | 
| 622 | 651 | 
| 623 #ifdef ENABLE_DEBUGGER_SUPPORT | 652 #ifdef ENABLE_DEBUGGER_SUPPORT | 
| 624   // ------------------------------------------------------------------------- | 653   // ------------------------------------------------------------------------- | 
| 625   // Debugger Support | 654   // Debugger Support. | 
| 626 | 655 | 
| 627   void DebugBreak(); | 656   void DebugBreak(); | 
| 628 #endif | 657 #endif | 
| 629 | 658 | 
| 630 | 659 | 
| 631   // ------------------------------------------------------------------------- | 660   // ------------------------------------------------------------------------- | 
| 632   // Exception handling | 661   // Exception handling. | 
| 633 | 662 | 
| 634   // Push a new try handler and link into try handler chain. | 663   // Push a new try handler and link into try handler chain. | 
| 635   // The return address must be passed in register ra. | 664   // The return address must be passed in register ra. | 
| 636   // Clobber t0, t1, t2. | 665   // Clobber t0, t1, t2. | 
| 637   void PushTryHandler(CodeLocation try_location, HandlerType type); | 666   void PushTryHandler(CodeLocation try_location, HandlerType type); | 
| 638 | 667 | 
| 639   // Unlink the stack handler on top of the stack from the try handler chain. | 668   // Unlink the stack handler on top of the stack from the try handler chain. | 
| 640   // Must preserve the result register. | 669   // Must preserve the result register. | 
| 641   void PopTryHandler(); | 670   void PopTryHandler(); | 
| 642 | 671 | 
| 643   // Copies a fixed number of fields of heap objects from src to dst. | 672   // Copies a fixed number of fields of heap objects from src to dst. | 
| 644   void CopyFields(Register dst, Register src, RegList temps, int field_count); | 673   void CopyFields(Register dst, Register src, RegList temps, int field_count); | 
| 645 | 674 | 
|  | 675   // Copies a number of bytes from src to dst. All registers are clobbered. On | 
|  | 676   // exit src and dst will point to the place just after where the last byte was | 
|  | 677   // read or written and length will be zero. | 
|  | 678   void CopyBytes(Register src, | 
|  | 679                  Register dst, | 
|  | 680                  Register length, | 
|  | 681                  Register scratch); | 
|  | 682 | 
| 646   // ------------------------------------------------------------------------- | 683   // ------------------------------------------------------------------------- | 
| 647   // Support functions. | 684   // Support functions. | 
| 648 | 685 | 
| 649   // Try to get function prototype of a function and puts the value in | 686   // Try to get function prototype of a function and puts the value in | 
| 650   // the result register. Checks that the function really is a | 687   // the result register. Checks that the function really is a | 
| 651   // function and jumps to the miss label if the fast checks fail. The | 688   // function and jumps to the miss label if the fast checks fail. The | 
| 652   // function register will be untouched; the other registers may be | 689   // function register will be untouched; the other registers may be | 
| 653   // clobbered. | 690   // clobbered. | 
| 654   void TryGetFunctionPrototype(Register function, | 691   void TryGetFunctionPrototype(Register function, | 
| 655                                Register result, | 692                                Register result, | 
| 656                                Register scratch, | 693                                Register scratch, | 
| 657                                Label* miss); | 694                                Label* miss); | 
| 658 | 695 | 
| 659   void GetObjectType(Register function, | 696   void GetObjectType(Register function, | 
| 660                      Register map, | 697                      Register map, | 
| 661                      Register type_reg); | 698                      Register type_reg); | 
| 662 | 699 | 
| 663   // Check if the map of an object is equal to a specified map (either | 700   // Check if the map of an object is equal to a specified map (either | 
| 664   // given directly or as an index into the root list) and branch to | 701   // given directly or as an index into the root list) and branch to | 
| 665   // label if not. Skip the smi check if not required (object is known | 702   // label if not. Skip the smi check if not required (object is known | 
| 666   // to be a heap object) | 703   // to be a heap object). | 
| 667   void CheckMap(Register obj, | 704   void CheckMap(Register obj, | 
| 668                 Register scratch, | 705                 Register scratch, | 
| 669                 Handle<Map> map, | 706                 Handle<Map> map, | 
| 670                 Label* fail, | 707                 Label* fail, | 
| 671                 bool is_heap_object); | 708                 bool is_heap_object); | 
| 672 | 709 | 
| 673   void CheckMap(Register obj, | 710   void CheckMap(Register obj, | 
| 674                 Register scratch, | 711                 Register scratch, | 
| 675                 Heap::RootListIndex index, | 712                 Heap::RootListIndex index, | 
| 676                 Label* fail, | 713                 Label* fail, | 
| 677                 bool is_heap_object); | 714                 bool is_heap_object); | 
| 678 | 715 | 
| 679   // Generates code for reporting that an illegal operation has | 716   // Generates code for reporting that an illegal operation has | 
| 680   // occurred. | 717   // occurred. | 
| 681   void IllegalOperation(int num_arguments); | 718   void IllegalOperation(int num_arguments); | 
| 682 | 719 | 
| 683   // Picks out an array index from the hash field. | 720   // Picks out an array index from the hash field. | 
| 684   // Register use: | 721   // Register use: | 
| 685   //   hash - holds the index's hash. Clobbered. | 722   //   hash - holds the index's hash. Clobbered. | 
| 686   //   index - holds the overwritten index on exit. | 723   //   index - holds the overwritten index on exit. | 
| 687   void IndexFromHash(Register hash, Register index); | 724   void IndexFromHash(Register hash, Register index); | 
| 688 | 725 | 
|  | 726   // Get the number of least significant bits from a register. | 
|  | 727   void GetLeastBitsFromSmi(Register dst, Register src, int num_least_bits); | 
|  | 728   void GetLeastBitsFromInt32(Register dst, Register src, int mun_least_bits); | 
|  | 729 | 
| 689   // Load the value of a number object into a FPU double register. If the | 730   // Load the value of a number object into a FPU double register. If the | 
| 690   // object is not a number a jump to the label not_number is performed | 731   // object is not a number a jump to the label not_number is performed | 
| 691   // and the FPU double register is unchanged. | 732   // and the FPU double register is unchanged. | 
| 692   void ObjectToDoubleFPURegister( | 733   void ObjectToDoubleFPURegister( | 
| 693       Register object, | 734       Register object, | 
| 694       FPURegister value, | 735       FPURegister value, | 
| 695       Register scratch1, | 736       Register scratch1, | 
| 696       Register scratch2, | 737       Register scratch2, | 
| 697       Register heap_number_map, | 738       Register heap_number_map, | 
| 698       Label* not_number, | 739       Label* not_number, | 
| 699       ObjectToDoubleFlags flags = NO_OBJECT_TO_DOUBLE_FLAGS); | 740       ObjectToDoubleFlags flags = NO_OBJECT_TO_DOUBLE_FLAGS); | 
| 700 | 741 | 
| 701   // Load the value of a smi object into a FPU double register. The register | 742   // Load the value of a smi object into a FPU double register. The register | 
| 702   // scratch1 can be the same register as smi in which case smi will hold the | 743   // scratch1 can be the same register as smi in which case smi will hold the | 
| 703   // untagged value afterwards. | 744   // untagged value afterwards. | 
| 704   void SmiToDoubleFPURegister(Register smi, | 745   void SmiToDoubleFPURegister(Register smi, | 
| 705                               FPURegister value, | 746                               FPURegister value, | 
| 706                               Register scratch1); | 747                               Register scratch1); | 
| 707 | 748 | 
| 708   // ------------------------------------------------------------------------- | 749   // ------------------------------------------------------------------------- | 
| 709   // Runtime calls | 750   // Overflow handling functions. | 
|  | 751   // Usage: first call the appropriate arithmetic function, then call one of the | 
|  | 752   // jump functions with the overflow_dst register as the second parameter. | 
|  | 753 | 
|  | 754   void AdduAndCheckForOverflow(Register dst, | 
|  | 755                                Register left, | 
|  | 756                                Register right, | 
|  | 757                                Register overflow_dst, | 
|  | 758                                Register scratch = at); | 
|  | 759 | 
|  | 760   void SubuAndCheckForOverflow(Register dst, | 
|  | 761                                Register left, | 
|  | 762                                Register right, | 
|  | 763                                Register overflow_dst, | 
|  | 764                                Register scratch = at); | 
|  | 765 | 
|  | 766   void BranchOnOverflow(Label* label, | 
|  | 767                         Register overflow_check, | 
|  | 768                         BranchDelaySlot bd = PROTECT) { | 
|  | 769     Branch(label, lt, overflow_check, Operand(zero_reg), bd); | 
|  | 770   } | 
|  | 771 | 
|  | 772   void BranchOnNoOverflow(Label* label, | 
|  | 773                           Register overflow_check, | 
|  | 774                           BranchDelaySlot bd = PROTECT) { | 
|  | 775     Branch(label, ge, overflow_check, Operand(zero_reg), bd); | 
|  | 776   } | 
|  | 777 | 
|  | 778   void RetOnOverflow(Register overflow_check, BranchDelaySlot bd = PROTECT) { | 
|  | 779     Ret(lt, overflow_check, Operand(zero_reg), bd); | 
|  | 780   } | 
|  | 781 | 
|  | 782   void RetOnNoOverflow(Register overflow_check, BranchDelaySlot bd = PROTECT) { | 
|  | 783     Ret(ge, overflow_check, Operand(zero_reg), bd); | 
|  | 784   } | 
|  | 785 | 
|  | 786   // ------------------------------------------------------------------------- | 
|  | 787   // Runtime calls. | 
| 710 | 788 | 
| 711   // Call a code stub. | 789   // Call a code stub. | 
| 712   void CallStub(CodeStub* stub, Condition cond = cc_always, | 790   void CallStub(CodeStub* stub, Condition cond = cc_always, | 
| 713                 Register r1 = zero_reg, const Operand& r2 = Operand(zero_reg)); | 791                 Register r1 = zero_reg, const Operand& r2 = Operand(zero_reg)); | 
| 714 | 792 | 
| 715   // Tail call a code stub (jump). | 793   // Tail call a code stub (jump). | 
| 716   void TailCallStub(CodeStub* stub); | 794   void TailCallStub(CodeStub* stub); | 
| 717 | 795 | 
| 718   void CallJSExitStub(CodeStub* stub); | 796   void CallJSExitStub(CodeStub* stub); | 
| 719 | 797 | 
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 756   //  sw(t0, CFunctionArgumentOperand(5)); | 834   //  sw(t0, CFunctionArgumentOperand(5)); | 
| 757 | 835 | 
| 758   // Calls a C function and cleans up the space for arguments allocated | 836   // Calls a C function and cleans up the space for arguments allocated | 
| 759   // by PrepareCallCFunction. The called function is not allowed to trigger a | 837   // by PrepareCallCFunction. The called function is not allowed to trigger a | 
| 760   // garbage collection, since that might move the code and invalidate the | 838   // garbage collection, since that might move the code and invalidate the | 
| 761   // return address (unless this is somehow accounted for by the called | 839   // return address (unless this is somehow accounted for by the called | 
| 762   // function). | 840   // function). | 
| 763   void CallCFunction(ExternalReference function, int num_arguments); | 841   void CallCFunction(ExternalReference function, int num_arguments); | 
| 764   void CallCFunction(Register function, Register scratch, int num_arguments); | 842   void CallCFunction(Register function, Register scratch, int num_arguments); | 
| 765 | 843 | 
|  | 844   void GetCFunctionDoubleResult(const DoubleRegister dst); | 
|  | 845 | 
| 766   // Jump to the builtin routine. | 846   // Jump to the builtin routine. | 
| 767   void JumpToExternalReference(const ExternalReference& builtin); | 847   void JumpToExternalReference(const ExternalReference& builtin); | 
| 768 | 848 | 
| 769   // Invoke specified builtin JavaScript function. Adds an entry to | 849   // Invoke specified builtin JavaScript function. Adds an entry to | 
| 770   // the unresolved list if the name does not resolve. | 850   // the unresolved list if the name does not resolve. | 
| 771   void InvokeBuiltin(Builtins::JavaScript id, | 851   void InvokeBuiltin(Builtins::JavaScript id, | 
| 772                      InvokeFlag flag, | 852                      InvokeFlag flag, | 
| 773                      const CallWrapper& call_wrapper = NullCallWrapper()); | 853                      const CallWrapper& call_wrapper = NullCallWrapper()); | 
| 774 | 854 | 
| 775   // Store the code object for the given builtin in the target register and | 855   // Store the code object for the given builtin in the target register and | 
| 776   // setup the function in a1. | 856   // setup the function in a1. | 
| 777   void GetBuiltinEntry(Register target, Builtins::JavaScript id); | 857   void GetBuiltinEntry(Register target, Builtins::JavaScript id); | 
| 778 | 858 | 
| 779   // Store the function for the given builtin in the target register. | 859   // Store the function for the given builtin in the target register. | 
| 780   void GetBuiltinFunction(Register target, Builtins::JavaScript id); | 860   void GetBuiltinFunction(Register target, Builtins::JavaScript id); | 
| 781 | 861 | 
| 782   struct Unresolved { | 862   struct Unresolved { | 
| 783     int pc; | 863     int pc; | 
| 784     uint32_t flags;  // see Bootstrapper::FixupFlags decoders/encoders. | 864     uint32_t flags;  // See Bootstrapper::FixupFlags decoders/encoders. | 
| 785     const char* name; | 865     const char* name; | 
| 786   }; | 866   }; | 
| 787 | 867 | 
| 788   Handle<Object> CodeObject() { return code_object_; } | 868   Handle<Object> CodeObject() { | 
|  | 869     ASSERT(!code_object_.is_null()); | 
|  | 870     return code_object_; | 
|  | 871   } | 
| 789 | 872 | 
| 790   // ------------------------------------------------------------------------- | 873   // ------------------------------------------------------------------------- | 
| 791   // StatsCounter support | 874   // StatsCounter support. | 
| 792 | 875 | 
| 793   void SetCounter(StatsCounter* counter, int value, | 876   void SetCounter(StatsCounter* counter, int value, | 
| 794                   Register scratch1, Register scratch2); | 877                   Register scratch1, Register scratch2); | 
| 795   void IncrementCounter(StatsCounter* counter, int value, | 878   void IncrementCounter(StatsCounter* counter, int value, | 
| 796                         Register scratch1, Register scratch2); | 879                         Register scratch1, Register scratch2); | 
| 797   void DecrementCounter(StatsCounter* counter, int value, | 880   void DecrementCounter(StatsCounter* counter, int value, | 
| 798                         Register scratch1, Register scratch2); | 881                         Register scratch1, Register scratch2); | 
| 799 | 882 | 
| 800 | 883 | 
| 801   // ------------------------------------------------------------------------- | 884   // ------------------------------------------------------------------------- | 
| 802   // Debugging | 885   // Debugging. | 
| 803 | 886 | 
| 804   // Calls Abort(msg) if the condition cc is not satisfied. | 887   // Calls Abort(msg) if the condition cc is not satisfied. | 
| 805   // Use --debug_code to enable. | 888   // Use --debug_code to enable. | 
| 806   void Assert(Condition cc, const char* msg, Register rs, Operand rt); | 889   void Assert(Condition cc, const char* msg, Register rs, Operand rt); | 
| 807   void AssertRegisterIsRoot(Register reg, Heap::RootListIndex index); | 890   void AssertRegisterIsRoot(Register reg, Heap::RootListIndex index); | 
| 808   void AssertFastElements(Register elements); | 891   void AssertFastElements(Register elements); | 
| 809 | 892 | 
| 810   // Like Assert(), but always enabled. | 893   // Like Assert(), but always enabled. | 
| 811   void Check(Condition cc, const char* msg, Register rs, Operand rt); | 894   void Check(Condition cc, const char* msg, Register rs, Operand rt); | 
| 812 | 895 | 
| 813   // Print a message to stdout and abort execution. | 896   // Print a message to stdout and abort execution. | 
| 814   void Abort(const char* msg); | 897   void Abort(const char* msg); | 
| 815 | 898 | 
| 816   // Verify restrictions about code generated in stubs. | 899   // Verify restrictions about code generated in stubs. | 
| 817   void set_generating_stub(bool value) { generating_stub_ = value; } | 900   void set_generating_stub(bool value) { generating_stub_ = value; } | 
| 818   bool generating_stub() { return generating_stub_; } | 901   bool generating_stub() { return generating_stub_; } | 
| 819   void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; } | 902   void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; } | 
| 820   bool allow_stub_calls() { return allow_stub_calls_; } | 903   bool allow_stub_calls() { return allow_stub_calls_; } | 
| 821 | 904 | 
| 822   // --------------------------------------------------------------------------- | 905   // --------------------------------------------------------------------------- | 
| 823   // Number utilities | 906   // Number utilities. | 
| 824 | 907 | 
| 825   // Check whether the value of reg is a power of two and not zero. If not | 908   // Check whether the value of reg is a power of two and not zero. If not | 
| 826   // control continues at the label not_power_of_two. If reg is a power of two | 909   // control continues at the label not_power_of_two. If reg is a power of two | 
| 827   // the register scratch contains the value of (reg - 1) when control falls | 910   // the register scratch contains the value of (reg - 1) when control falls | 
| 828   // through. | 911   // through. | 
| 829   void JumpIfNotPowerOfTwoOrZero(Register reg, | 912   void JumpIfNotPowerOfTwoOrZero(Register reg, | 
| 830                                  Register scratch, | 913                                  Register scratch, | 
| 831                                  Label* not_power_of_two_or_zero); | 914                                  Label* not_power_of_two_or_zero); | 
| 832 | 915 | 
| 833   // ------------------------------------------------------------------------- | 916   // ------------------------------------------------------------------------- | 
| 834   // Smi utilities | 917   // Smi utilities. | 
| 835 | 918 | 
| 836   // Try to convert int32 to smi. If the value is to large, preserve | 919   // Try to convert int32 to smi. If the value is to large, preserve | 
| 837   // the original value and jump to not_a_smi. Destroys scratch and | 920   // the original value and jump to not_a_smi. Destroys scratch and | 
| 838   // sets flags. | 921   // sets flags. | 
| 839   // This is only used by crankshaft atm so it is unimplemented on MIPS. | 922   // This is only used by crankshaft atm so it is unimplemented on MIPS. | 
| 840   void TrySmiTag(Register reg, Label* not_a_smi, Register scratch) { | 923   void TrySmiTag(Register reg, Label* not_a_smi, Register scratch) { | 
| 841     UNIMPLEMENTED_MIPS(); | 924     UNIMPLEMENTED_MIPS(); | 
| 842   } | 925   } | 
| 843 | 926 | 
| 844   void SmiTag(Register reg) { | 927   void SmiTag(Register reg) { | 
| (...skipping 30 matching lines...) Expand all  Loading... | 
| 875 | 958 | 
| 876   // Jump if either of the registers contain a non-smi. | 959   // Jump if either of the registers contain a non-smi. | 
| 877   void JumpIfNotBothSmi(Register reg1, Register reg2, Label* on_not_both_smi); | 960   void JumpIfNotBothSmi(Register reg1, Register reg2, Label* on_not_both_smi); | 
| 878   // Jump if either of the registers contain a smi. | 961   // Jump if either of the registers contain a smi. | 
| 879   void JumpIfEitherSmi(Register reg1, Register reg2, Label* on_either_smi); | 962   void JumpIfEitherSmi(Register reg1, Register reg2, Label* on_either_smi); | 
| 880 | 963 | 
| 881   // Abort execution if argument is a smi. Used in debug code. | 964   // Abort execution if argument is a smi. Used in debug code. | 
| 882   void AbortIfSmi(Register object); | 965   void AbortIfSmi(Register object); | 
| 883   void AbortIfNotSmi(Register object); | 966   void AbortIfNotSmi(Register object); | 
| 884 | 967 | 
|  | 968   // Abort execution if argument is a string. Used in debug code. | 
|  | 969   void AbortIfNotString(Register object); | 
|  | 970 | 
| 885   // Abort execution if argument is not the root value with the given index. | 971   // Abort execution if argument is not the root value with the given index. | 
| 886   void AbortIfNotRootValue(Register src, | 972   void AbortIfNotRootValue(Register src, | 
| 887                            Heap::RootListIndex root_value_index, | 973                            Heap::RootListIndex root_value_index, | 
| 888                            const char* message); | 974                            const char* message); | 
| 889 | 975 | 
| 890   // --------------------------------------------------------------------------- | 976   // --------------------------------------------------------------------------- | 
| 891   // HeapNumber utilities | 977   // HeapNumber utilities. | 
| 892 | 978 | 
| 893   void JumpIfNotHeapNumber(Register object, | 979   void JumpIfNotHeapNumber(Register object, | 
| 894                            Register heap_number_map, | 980                            Register heap_number_map, | 
| 895                            Register scratch, | 981                            Register scratch, | 
| 896                            Label* on_not_heap_number); | 982                            Label* on_not_heap_number); | 
| 897 | 983 | 
| 898   // ------------------------------------------------------------------------- | 984   // ------------------------------------------------------------------------- | 
| 899   // String utilities | 985   // String utilities. | 
| 900 | 986 | 
| 901   // Checks if both instance types are sequential ASCII strings and jumps to | 987   // Checks if both instance types are sequential ASCII strings and jumps to | 
| 902   // label if either is not. | 988   // label if either is not. | 
| 903   void JumpIfBothInstanceTypesAreNotSequentialAscii( | 989   void JumpIfBothInstanceTypesAreNotSequentialAscii( | 
| 904       Register first_object_instance_type, | 990       Register first_object_instance_type, | 
| 905       Register second_object_instance_type, | 991       Register second_object_instance_type, | 
| 906       Register scratch1, | 992       Register scratch1, | 
| 907       Register scratch2, | 993       Register scratch2, | 
| 908       Label* failure); | 994       Label* failure); | 
| 909 | 995 | 
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 970                            Register scratch2); | 1056                            Register scratch2); | 
| 971 | 1057 | 
| 972 | 1058 | 
| 973   bool generating_stub_; | 1059   bool generating_stub_; | 
| 974   bool allow_stub_calls_; | 1060   bool allow_stub_calls_; | 
| 975   // This handle will be patched with the code object on installation. | 1061   // This handle will be patched with the code object on installation. | 
| 976   Handle<Object> code_object_; | 1062   Handle<Object> code_object_; | 
| 977 }; | 1063 }; | 
| 978 | 1064 | 
| 979 | 1065 | 
| 980 #ifdef ENABLE_DEBUGGER_SUPPORT |  | 
| 981 // The code patcher is used to patch (typically) small parts of code e.g. for | 1066 // The code patcher is used to patch (typically) small parts of code e.g. for | 
| 982 // debugging and other types of instrumentation. When using the code patcher | 1067 // debugging and other types of instrumentation. When using the code patcher | 
| 983 // the exact number of bytes specified must be emitted. It is not legal to emit | 1068 // the exact number of bytes specified must be emitted. It is not legal to emit | 
| 984 // relocation information. If any of these constraints are violated it causes | 1069 // relocation information. If any of these constraints are violated it causes | 
| 985 // an assertion to fail. | 1070 // an assertion to fail. | 
| 986 class CodePatcher { | 1071 class CodePatcher { | 
| 987  public: | 1072  public: | 
| 988   CodePatcher(byte* address, int instructions); | 1073   CodePatcher(byte* address, int instructions); | 
| 989   virtual ~CodePatcher(); | 1074   virtual ~CodePatcher(); | 
| 990 | 1075 | 
| 991   // Macro assembler to emit code. | 1076   // Macro assembler to emit code. | 
| 992   MacroAssembler* masm() { return &masm_; } | 1077   MacroAssembler* masm() { return &masm_; } | 
| 993 | 1078 | 
| 994   // Emit an instruction directly. | 1079   // Emit an instruction directly. | 
| 995   void Emit(Instr x); | 1080   void Emit(Instr instr); | 
| 996 | 1081 | 
| 997   // Emit an address directly. | 1082   // Emit an address directly. | 
| 998   void Emit(Address addr); | 1083   void Emit(Address addr); | 
| 999 | 1084 | 
|  | 1085   // Change the condition part of an instruction leaving the rest of the current | 
|  | 1086   // instruction unchanged. | 
|  | 1087   void ChangeBranchCondition(Condition cond); | 
|  | 1088 | 
| 1000  private: | 1089  private: | 
| 1001   byte* address_;  // The address of the code being patched. | 1090   byte* address_;  // The address of the code being patched. | 
| 1002   int instructions_;  // Number of instructions of the expected patch size. | 1091   int instructions_;  // Number of instructions of the expected patch size. | 
| 1003   int size_;  // Number of bytes of the expected patch size. | 1092   int size_;  // Number of bytes of the expected patch size. | 
| 1004   MacroAssembler masm_;  // Macro assembler used to generate the code. | 1093   MacroAssembler masm_;  // Macro assembler used to generate the code. | 
| 1005 }; | 1094 }; | 
| 1006 #endif  // ENABLE_DEBUGGER_SUPPORT |  | 
| 1007 | 1095 | 
| 1008 | 1096 | 
| 1009 // ----------------------------------------------------------------------------- | 1097 // ----------------------------------------------------------------------------- | 
| 1010 // Static helper functions. | 1098 // Static helper functions. | 
| 1011 | 1099 | 
| 1012 static MemOperand ContextOperand(Register context, int index) { | 1100 static MemOperand ContextOperand(Register context, int index) { | 
| 1013   return MemOperand(context, Context::SlotOffset(index)); | 1101   return MemOperand(context, Context::SlotOffset(index)); | 
| 1014 } | 1102 } | 
| 1015 | 1103 | 
| 1016 | 1104 | 
| 1017 static inline MemOperand GlobalObjectOperand()  { | 1105 static inline MemOperand GlobalObjectOperand()  { | 
| 1018   return ContextOperand(cp, Context::GLOBAL_INDEX); | 1106   return ContextOperand(cp, Context::GLOBAL_INDEX); | 
| 1019 } | 1107 } | 
| 1020 | 1108 | 
| 1021 | 1109 | 
| 1022 // Generate a MemOperand for loading a field from an object. | 1110 // Generate a MemOperand for loading a field from an object. | 
| 1023 static inline MemOperand FieldMemOperand(Register object, int offset) { | 1111 static inline MemOperand FieldMemOperand(Register object, int offset) { | 
| 1024   return MemOperand(object, offset - kHeapObjectTag); | 1112   return MemOperand(object, offset - kHeapObjectTag); | 
| 1025 } | 1113 } | 
| 1026 | 1114 | 
| 1027 | 1115 | 
|  | 1116 // Generate a MemOperand for storing arguments 5..N on the stack | 
|  | 1117 // when calling CallCFunction(). | 
|  | 1118 static inline MemOperand CFunctionArgumentOperand(int index) { | 
|  | 1119   ASSERT(index > StandardFrameConstants::kCArgSlotCount); | 
|  | 1120   // Argument 5 takes the slot just past the four Arg-slots. | 
|  | 1121   int offset = | 
|  | 1122       (index - 5) * kPointerSize + StandardFrameConstants::kCArgsSlotsSize; | 
|  | 1123   return MemOperand(sp, offset); | 
|  | 1124 } | 
|  | 1125 | 
| 1028 | 1126 | 
| 1029 #ifdef GENERATED_CODE_COVERAGE | 1127 #ifdef GENERATED_CODE_COVERAGE | 
| 1030 #define CODE_COVERAGE_STRINGIFY(x) #x | 1128 #define CODE_COVERAGE_STRINGIFY(x) #x | 
| 1031 #define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x) | 1129 #define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x) | 
| 1032 #define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__) | 1130 #define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__) | 
| 1033 #define ACCESS_MASM(masm) masm->stop(__FILE_LINE__); masm-> | 1131 #define ACCESS_MASM(masm) masm->stop(__FILE_LINE__); masm-> | 
| 1034 #else | 1132 #else | 
| 1035 #define ACCESS_MASM(masm) masm-> | 1133 #define ACCESS_MASM(masm) masm-> | 
| 1036 #endif | 1134 #endif | 
| 1037 | 1135 | 
| 1038 } }  // namespace v8::internal | 1136 } }  // namespace v8::internal | 
| 1039 | 1137 | 
| 1040 #endif  // V8_MIPS_MACRO_ASSEMBLER_MIPS_H_ | 1138 #endif  // V8_MIPS_MACRO_ASSEMBLER_MIPS_H_ | 
| 1041 | 1139 | 
| OLD | NEW | 
|---|