| OLD | NEW |
| 1 // Copyright 2011 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 |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 84 Condition cond) { | 84 Condition cond) { |
| 85 #if USE_BX | 85 #if USE_BX |
| 86 mov(ip, Operand(target, rmode)); | 86 mov(ip, Operand(target, rmode)); |
| 87 bx(ip, cond); | 87 bx(ip, cond); |
| 88 #else | 88 #else |
| 89 mov(pc, Operand(target, rmode), LeaveCC, cond); | 89 mov(pc, Operand(target, rmode), LeaveCC, cond); |
| 90 #endif | 90 #endif |
| 91 } | 91 } |
| 92 | 92 |
| 93 | 93 |
| 94 void MacroAssembler::Jump(byte* target, RelocInfo::Mode rmode, | 94 void MacroAssembler::Jump(Address target, RelocInfo::Mode rmode, |
| 95 Condition cond) { | 95 Condition cond) { |
| 96 ASSERT(!RelocInfo::IsCodeTarget(rmode)); | 96 ASSERT(!RelocInfo::IsCodeTarget(rmode)); |
| 97 Jump(reinterpret_cast<intptr_t>(target), rmode, cond); | 97 Jump(reinterpret_cast<intptr_t>(target), rmode, cond); |
| 98 } | 98 } |
| 99 | 99 |
| 100 | 100 |
| 101 void MacroAssembler::Jump(Handle<Code> code, RelocInfo::Mode rmode, | 101 void MacroAssembler::Jump(Handle<Code> code, RelocInfo::Mode rmode, |
| 102 Condition cond) { | 102 Condition cond) { |
| 103 ASSERT(RelocInfo::IsCodeTarget(rmode)); | 103 ASSERT(RelocInfo::IsCodeTarget(rmode)); |
| 104 // 'code' is always generated ARM code, never THUMB code | 104 // 'code' is always generated ARM code, never THUMB code |
| 105 Jump(reinterpret_cast<intptr_t>(code.location()), rmode, cond); | 105 Jump(reinterpret_cast<intptr_t>(code.location()), rmode, cond); |
| 106 } | 106 } |
| 107 | 107 |
| 108 | 108 |
| 109 int MacroAssembler::CallSize(Register target, Condition cond) { | 109 int MacroAssembler::CallSize(Register target, Condition cond) { |
| 110 #if USE_BLX | 110 #if USE_BLX |
| 111 return kInstrSize; | 111 return kInstrSize; |
| 112 #else | 112 #else |
| 113 return 2 * kInstrSize; | 113 return 2 * kInstrSize; |
| 114 #endif | 114 #endif |
| 115 } | 115 } |
| 116 | 116 |
| 117 | 117 |
| 118 void MacroAssembler::Call(Register target, Condition cond) { | 118 void MacroAssembler::Call(Register target, Condition cond) { |
| 119 // Block constant pool for the call instruction sequence. | 119 // Block constant pool for the call instruction sequence. |
| 120 BlockConstPoolScope block_const_pool(this); | 120 BlockConstPoolScope block_const_pool(this); |
| 121 #ifdef DEBUG | 121 Label start; |
| 122 int pre_position = pc_offset(); | 122 bind(&start); |
| 123 #endif | |
| 124 | |
| 125 #if USE_BLX | 123 #if USE_BLX |
| 126 blx(target, cond); | 124 blx(target, cond); |
| 127 #else | 125 #else |
| 128 // set lr for return at current pc + 8 | 126 // set lr for return at current pc + 8 |
| 129 mov(lr, Operand(pc), LeaveCC, cond); | 127 mov(lr, Operand(pc), LeaveCC, cond); |
| 130 mov(pc, Operand(target), LeaveCC, cond); | 128 mov(pc, Operand(target), LeaveCC, cond); |
| 131 #endif | 129 #endif |
| 132 | 130 ASSERT_EQ(CallSize(target, cond), SizeOfCodeGeneratedSince(&start)); |
| 133 #ifdef DEBUG | |
| 134 int post_position = pc_offset(); | |
| 135 CHECK_EQ(pre_position + CallSize(target, cond), post_position); | |
| 136 #endif | |
| 137 } | 131 } |
| 138 | 132 |
| 139 | 133 |
| 140 int MacroAssembler::CallSize( | 134 int MacroAssembler::CallSize( |
| 141 intptr_t target, RelocInfo::Mode rmode, Condition cond) { | 135 Address target, RelocInfo::Mode rmode, Condition cond) { |
| 142 int size = 2 * kInstrSize; | 136 int size = 2 * kInstrSize; |
| 143 Instr mov_instr = cond | MOV | LeaveCC; | 137 Instr mov_instr = cond | MOV | LeaveCC; |
| 144 if (!Operand(target, rmode).is_single_instruction(mov_instr)) { | 138 intptr_t immediate = reinterpret_cast<intptr_t>(target); |
| 139 if (!Operand(immediate, rmode).is_single_instruction(mov_instr)) { |
| 145 size += kInstrSize; | 140 size += kInstrSize; |
| 146 } | 141 } |
| 147 return size; | 142 return size; |
| 148 } | 143 } |
| 149 | 144 |
| 150 | 145 |
| 151 void MacroAssembler::Call(intptr_t target, | 146 void MacroAssembler::Call(Address target, |
| 152 RelocInfo::Mode rmode, | 147 RelocInfo::Mode rmode, |
| 153 Condition cond) { | 148 Condition cond) { |
| 154 // Block constant pool for the call instruction sequence. | 149 // Block constant pool for the call instruction sequence. |
| 155 BlockConstPoolScope block_const_pool(this); | 150 BlockConstPoolScope block_const_pool(this); |
| 156 #ifdef DEBUG | 151 Label start; |
| 157 int pre_position = pc_offset(); | 152 bind(&start); |
| 158 #endif | |
| 159 | |
| 160 #if USE_BLX | 153 #if USE_BLX |
| 161 // On ARMv5 and after the recommended call sequence is: | 154 // On ARMv5 and after the recommended call sequence is: |
| 162 // ldr ip, [pc, #...] | 155 // ldr ip, [pc, #...] |
| 163 // blx ip | 156 // blx ip |
| 164 | 157 |
| 165 // Statement positions are expected to be recorded when the target | 158 // Statement positions are expected to be recorded when the target |
| 166 // address is loaded. The mov method will automatically record | 159 // address is loaded. The mov method will automatically record |
| 167 // positions when pc is the target, since this is not the case here | 160 // positions when pc is the target, since this is not the case here |
| 168 // we have to do it explicitly. | 161 // we have to do it explicitly. |
| 169 positions_recorder()->WriteRecordedPositions(); | 162 positions_recorder()->WriteRecordedPositions(); |
| 170 | 163 |
| 171 mov(ip, Operand(target, rmode)); | 164 mov(ip, Operand(reinterpret_cast<int32_t>(target), rmode)); |
| 172 blx(ip, cond); | 165 blx(ip, cond); |
| 173 | 166 |
| 174 ASSERT(kCallTargetAddressOffset == 2 * kInstrSize); | 167 ASSERT(kCallTargetAddressOffset == 2 * kInstrSize); |
| 175 #else | 168 #else |
| 176 // Set lr for return at current pc + 8. | 169 // Set lr for return at current pc + 8. |
| 177 mov(lr, Operand(pc), LeaveCC, cond); | 170 mov(lr, Operand(pc), LeaveCC, cond); |
| 178 // Emit a ldr<cond> pc, [pc + offset of target in constant pool]. | 171 // Emit a ldr<cond> pc, [pc + offset of target in constant pool]. |
| 179 mov(pc, Operand(target, rmode), LeaveCC, cond); | 172 mov(pc, Operand(reinterpret_cast<int32_t>(target), rmode), LeaveCC, cond); |
| 180 ASSERT(kCallTargetAddressOffset == kInstrSize); | 173 ASSERT(kCallTargetAddressOffset == kInstrSize); |
| 181 #endif | 174 #endif |
| 182 | 175 ASSERT_EQ(CallSize(target, rmode, cond), SizeOfCodeGeneratedSince(&start)); |
| 183 #ifdef DEBUG | |
| 184 int post_position = pc_offset(); | |
| 185 CHECK_EQ(pre_position + CallSize(target, rmode, cond), post_position); | |
| 186 #endif | |
| 187 } | 176 } |
| 188 | 177 |
| 189 | 178 |
| 190 int MacroAssembler::CallSize( | 179 int MacroAssembler::CallSize(Handle<Code> code, |
| 191 byte* target, RelocInfo::Mode rmode, Condition cond) { | 180 RelocInfo::Mode rmode, |
| 192 return CallSize(reinterpret_cast<intptr_t>(target), rmode); | 181 unsigned ast_id, |
| 193 } | 182 Condition cond) { |
| 194 | 183 return CallSize(reinterpret_cast<Address>(code.location()), rmode, cond); |
| 195 | |
| 196 void MacroAssembler::Call( | |
| 197 byte* target, RelocInfo::Mode rmode, Condition cond) { | |
| 198 #ifdef DEBUG | |
| 199 int pre_position = pc_offset(); | |
| 200 #endif | |
| 201 | |
| 202 ASSERT(!RelocInfo::IsCodeTarget(rmode)); | |
| 203 Call(reinterpret_cast<intptr_t>(target), rmode, cond); | |
| 204 | |
| 205 #ifdef DEBUG | |
| 206 int post_position = pc_offset(); | |
| 207 CHECK_EQ(pre_position + CallSize(target, rmode, cond), post_position); | |
| 208 #endif | |
| 209 } | |
| 210 | |
| 211 | |
| 212 int MacroAssembler::CallSize( | |
| 213 Handle<Code> code, RelocInfo::Mode rmode, Condition cond) { | |
| 214 return CallSize(reinterpret_cast<intptr_t>(code.location()), rmode, cond); | |
| 215 } | |
| 216 | |
| 217 | |
| 218 void MacroAssembler::CallWithAstId(Handle<Code> code, | |
| 219 RelocInfo::Mode rmode, | |
| 220 unsigned ast_id, | |
| 221 Condition cond) { | |
| 222 #ifdef DEBUG | |
| 223 int pre_position = pc_offset(); | |
| 224 #endif | |
| 225 | |
| 226 ASSERT(rmode == RelocInfo::CODE_TARGET_WITH_ID); | |
| 227 ASSERT(ast_id != kNoASTId); | |
| 228 ASSERT(ast_id_for_reloc_info_ == kNoASTId); | |
| 229 ast_id_for_reloc_info_ = ast_id; | |
| 230 // 'code' is always generated ARM code, never THUMB code | |
| 231 Call(reinterpret_cast<intptr_t>(code.location()), rmode, cond); | |
| 232 | |
| 233 #ifdef DEBUG | |
| 234 int post_position = pc_offset(); | |
| 235 CHECK_EQ(pre_position + CallSize(code, rmode, cond), post_position); | |
| 236 #endif | |
| 237 } | 184 } |
| 238 | 185 |
| 239 | 186 |
| 240 void MacroAssembler::Call(Handle<Code> code, | 187 void MacroAssembler::Call(Handle<Code> code, |
| 241 RelocInfo::Mode rmode, | 188 RelocInfo::Mode rmode, |
| 189 unsigned ast_id, |
| 242 Condition cond) { | 190 Condition cond) { |
| 243 #ifdef DEBUG | 191 Label start; |
| 244 int pre_position = pc_offset(); | 192 bind(&start); |
| 245 #endif | |
| 246 | |
| 247 ASSERT(RelocInfo::IsCodeTarget(rmode)); | 193 ASSERT(RelocInfo::IsCodeTarget(rmode)); |
| 194 if (rmode == RelocInfo::CODE_TARGET && ast_id != kNoASTId) { |
| 195 ASSERT(ast_id_for_reloc_info_ == kNoASTId); |
| 196 ast_id_for_reloc_info_ = ast_id; |
| 197 rmode = RelocInfo::CODE_TARGET_WITH_ID; |
| 198 } |
| 248 // 'code' is always generated ARM code, never THUMB code | 199 // 'code' is always generated ARM code, never THUMB code |
| 249 Call(reinterpret_cast<intptr_t>(code.location()), rmode, cond); | 200 Call(reinterpret_cast<Address>(code.location()), rmode, cond); |
| 250 | 201 ASSERT_EQ(CallSize(code, rmode, cond), SizeOfCodeGeneratedSince(&start)); |
| 251 #ifdef DEBUG | |
| 252 int post_position = pc_offset(); | |
| 253 CHECK_EQ(pre_position + CallSize(code, rmode, cond), post_position); | |
| 254 #endif | |
| 255 } | 202 } |
| 256 | 203 |
| 257 | 204 |
| 258 void MacroAssembler::Ret(Condition cond) { | 205 void MacroAssembler::Ret(Condition cond) { |
| 259 #if USE_BX | 206 #if USE_BX |
| 260 bx(lr, cond); | 207 bx(lr, cond); |
| 261 #else | 208 #else |
| 262 mov(pc, Operand(lr), LeaveCC, cond); | 209 mov(pc, Operand(lr), LeaveCC, cond); |
| 263 #endif | 210 #endif |
| 264 } | 211 } |
| (...skipping 26 matching lines...) Expand all Loading... |
| 291 mov(reg2, scratch, LeaveCC, cond); | 238 mov(reg2, scratch, LeaveCC, cond); |
| 292 } | 239 } |
| 293 } | 240 } |
| 294 | 241 |
| 295 | 242 |
| 296 void MacroAssembler::Call(Label* target) { | 243 void MacroAssembler::Call(Label* target) { |
| 297 bl(target); | 244 bl(target); |
| 298 } | 245 } |
| 299 | 246 |
| 300 | 247 |
| 248 void MacroAssembler::Push(Handle<Object> handle) { |
| 249 mov(ip, Operand(handle)); |
| 250 push(ip); |
| 251 } |
| 252 |
| 253 |
| 301 void MacroAssembler::Move(Register dst, Handle<Object> value) { | 254 void MacroAssembler::Move(Register dst, Handle<Object> value) { |
| 302 mov(dst, Operand(value)); | 255 mov(dst, Operand(value)); |
| 303 } | 256 } |
| 304 | 257 |
| 305 | 258 |
| 306 void MacroAssembler::Move(Register dst, Register src) { | 259 void MacroAssembler::Move(Register dst, Register src, Condition cond) { |
| 307 if (!dst.is(src)) { | 260 if (!dst.is(src)) { |
| 308 mov(dst, src); | 261 mov(dst, src, LeaveCC, cond); |
| 309 } | 262 } |
| 310 } | 263 } |
| 311 | 264 |
| 312 | 265 |
| 313 void MacroAssembler::Move(DoubleRegister dst, DoubleRegister src) { | 266 void MacroAssembler::Move(DoubleRegister dst, DoubleRegister src) { |
| 314 ASSERT(CpuFeatures::IsSupported(VFP3)); | 267 ASSERT(CpuFeatures::IsSupported(VFP3)); |
| 315 CpuFeatures::Scope scope(VFP3); | 268 CpuFeatures::Scope scope(VFP3); |
| 316 if (!dst.is(src)) { | 269 if (!dst.is(src)) { |
| 317 vmov(dst, src); | 270 vmov(dst, src); |
| 318 } | 271 } |
| 319 } | 272 } |
| 320 | 273 |
| 321 | 274 |
| 322 void MacroAssembler::And(Register dst, Register src1, const Operand& src2, | 275 void MacroAssembler::And(Register dst, Register src1, const Operand& src2, |
| 323 Condition cond) { | 276 Condition cond) { |
| 324 if (!src2.is_reg() && | 277 if (!src2.is_reg() && |
| 325 !src2.must_use_constant_pool() && | 278 !src2.must_use_constant_pool() && |
| 326 src2.immediate() == 0) { | 279 src2.immediate() == 0) { |
| 327 mov(dst, Operand(0, RelocInfo::NONE), LeaveCC, cond); | 280 mov(dst, Operand(0, RelocInfo::NONE), LeaveCC, cond); |
| 328 | 281 |
| 329 } else if (!src2.is_single_instruction() && | 282 } else if (!src2.is_single_instruction() && |
| 330 !src2.must_use_constant_pool() && | 283 !src2.must_use_constant_pool() && |
| 331 CpuFeatures::IsSupported(ARMv7) && | 284 CpuFeatures::IsSupported(ARMv7) && |
| 332 IsPowerOf2(src2.immediate() + 1)) { | 285 IsPowerOf2(src2.immediate() + 1)) { |
| 333 ubfx(dst, src1, 0, WhichPowerOf2(src2.immediate() + 1), cond); | 286 ubfx(dst, src1, 0, |
| 287 WhichPowerOf2(static_cast<uint32_t>(src2.immediate()) + 1), cond); |
| 334 | 288 |
| 335 } else { | 289 } else { |
| 336 and_(dst, src1, src2, LeaveCC, cond); | 290 and_(dst, src1, src2, LeaveCC, cond); |
| 337 } | 291 } |
| 338 } | 292 } |
| 339 | 293 |
| 340 | 294 |
| 341 void MacroAssembler::Ubfx(Register dst, Register src1, int lsb, int width, | 295 void MacroAssembler::Ubfx(Register dst, Register src1, int lsb, int width, |
| 342 Condition cond) { | 296 Condition cond) { |
| 343 ASSERT(lsb < 32); | 297 ASSERT(lsb < 32); |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 431 b(eq, &done); | 385 b(eq, &done); |
| 432 mov(dst, Operand(0, RelocInfo::NONE), LeaveCC, mi); // 0 if negative. | 386 mov(dst, Operand(0, RelocInfo::NONE), LeaveCC, mi); // 0 if negative. |
| 433 mov(dst, Operand(satval), LeaveCC, pl); // satval if positive. | 387 mov(dst, Operand(satval), LeaveCC, pl); // satval if positive. |
| 434 bind(&done); | 388 bind(&done); |
| 435 } else { | 389 } else { |
| 436 usat(dst, satpos, src, cond); | 390 usat(dst, satpos, src, cond); |
| 437 } | 391 } |
| 438 } | 392 } |
| 439 | 393 |
| 440 | 394 |
| 441 void MacroAssembler::SmiJumpTable(Register index, Vector<Label*> targets) { | |
| 442 // Empty the const pool. | |
| 443 CheckConstPool(true, true); | |
| 444 add(pc, pc, Operand(index, | |
| 445 LSL, | |
| 446 Instruction::kInstrSizeLog2 - kSmiTagSize)); | |
| 447 BlockConstPoolBefore(pc_offset() + (targets.length() + 1) * kInstrSize); | |
| 448 nop(); // Jump table alignment. | |
| 449 for (int i = 0; i < targets.length(); i++) { | |
| 450 b(targets[i]); | |
| 451 } | |
| 452 } | |
| 453 | |
| 454 | |
| 455 void MacroAssembler::LoadRoot(Register destination, | 395 void MacroAssembler::LoadRoot(Register destination, |
| 456 Heap::RootListIndex index, | 396 Heap::RootListIndex index, |
| 457 Condition cond) { | 397 Condition cond) { |
| 458 ldr(destination, MemOperand(roots, index << kPointerSizeLog2), cond); | 398 ldr(destination, MemOperand(roots, index << kPointerSizeLog2), cond); |
| 459 } | 399 } |
| 460 | 400 |
| 461 | 401 |
| 462 void MacroAssembler::StoreRoot(Register source, | 402 void MacroAssembler::StoreRoot(Register source, |
| 463 Heap::RootListIndex index, | 403 Heap::RootListIndex index, |
| 464 Condition cond) { | 404 Condition cond) { |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 692 } | 632 } |
| 693 | 633 |
| 694 | 634 |
| 695 void MacroAssembler::Ldrd(Register dst1, Register dst2, | 635 void MacroAssembler::Ldrd(Register dst1, Register dst2, |
| 696 const MemOperand& src, Condition cond) { | 636 const MemOperand& src, Condition cond) { |
| 697 ASSERT(src.rm().is(no_reg)); | 637 ASSERT(src.rm().is(no_reg)); |
| 698 ASSERT(!dst1.is(lr)); // r14. | 638 ASSERT(!dst1.is(lr)); // r14. |
| 699 ASSERT_EQ(0, dst1.code() % 2); | 639 ASSERT_EQ(0, dst1.code() % 2); |
| 700 ASSERT_EQ(dst1.code() + 1, dst2.code()); | 640 ASSERT_EQ(dst1.code() + 1, dst2.code()); |
| 701 | 641 |
| 642 // V8 does not use this addressing mode, so the fallback code |
| 643 // below doesn't support it yet. |
| 644 ASSERT((src.am() != PreIndex) && (src.am() != NegPreIndex)); |
| 645 |
| 702 // Generate two ldr instructions if ldrd is not available. | 646 // Generate two ldr instructions if ldrd is not available. |
| 703 if (CpuFeatures::IsSupported(ARMv7)) { | 647 if (CpuFeatures::IsSupported(ARMv7)) { |
| 704 CpuFeatures::Scope scope(ARMv7); | 648 CpuFeatures::Scope scope(ARMv7); |
| 705 ldrd(dst1, dst2, src, cond); | 649 ldrd(dst1, dst2, src, cond); |
| 706 } else { | 650 } else { |
| 707 MemOperand src2(src); | 651 if ((src.am() == Offset) || (src.am() == NegOffset)) { |
| 708 src2.set_offset(src2.offset() + 4); | 652 MemOperand src2(src); |
| 709 if (dst1.is(src.rn())) { | 653 src2.set_offset(src2.offset() + 4); |
| 710 ldr(dst2, src2, cond); | 654 if (dst1.is(src.rn())) { |
| 711 ldr(dst1, src, cond); | 655 ldr(dst2, src2, cond); |
| 712 } else { | 656 ldr(dst1, src, cond); |
| 713 ldr(dst1, src, cond); | 657 } else { |
| 714 ldr(dst2, src2, cond); | 658 ldr(dst1, src, cond); |
| 659 ldr(dst2, src2, cond); |
| 660 } |
| 661 } else { // PostIndex or NegPostIndex. |
| 662 ASSERT((src.am() == PostIndex) || (src.am() == NegPostIndex)); |
| 663 if (dst1.is(src.rn())) { |
| 664 ldr(dst2, MemOperand(src.rn(), 4, Offset), cond); |
| 665 ldr(dst1, src, cond); |
| 666 } else { |
| 667 MemOperand src2(src); |
| 668 src2.set_offset(src2.offset() - 4); |
| 669 ldr(dst1, MemOperand(src.rn(), 4, PostIndex), cond); |
| 670 ldr(dst2, src2, cond); |
| 671 } |
| 715 } | 672 } |
| 716 } | 673 } |
| 717 } | 674 } |
| 718 | 675 |
| 719 | 676 |
| 720 void MacroAssembler::Strd(Register src1, Register src2, | 677 void MacroAssembler::Strd(Register src1, Register src2, |
| 721 const MemOperand& dst, Condition cond) { | 678 const MemOperand& dst, Condition cond) { |
| 722 ASSERT(dst.rm().is(no_reg)); | 679 ASSERT(dst.rm().is(no_reg)); |
| 723 ASSERT(!src1.is(lr)); // r14. | 680 ASSERT(!src1.is(lr)); // r14. |
| 724 ASSERT_EQ(0, src1.code() % 2); | 681 ASSERT_EQ(0, src1.code() % 2); |
| 725 ASSERT_EQ(src1.code() + 1, src2.code()); | 682 ASSERT_EQ(src1.code() + 1, src2.code()); |
| 726 | 683 |
| 684 // V8 does not use this addressing mode, so the fallback code |
| 685 // below doesn't support it yet. |
| 686 ASSERT((dst.am() != PreIndex) && (dst.am() != NegPreIndex)); |
| 687 |
| 727 // Generate two str instructions if strd is not available. | 688 // Generate two str instructions if strd is not available. |
| 728 if (CpuFeatures::IsSupported(ARMv7)) { | 689 if (CpuFeatures::IsSupported(ARMv7)) { |
| 729 CpuFeatures::Scope scope(ARMv7); | 690 CpuFeatures::Scope scope(ARMv7); |
| 730 strd(src1, src2, dst, cond); | 691 strd(src1, src2, dst, cond); |
| 731 } else { | 692 } else { |
| 732 MemOperand dst2(dst); | 693 MemOperand dst2(dst); |
| 733 dst2.set_offset(dst2.offset() + 4); | 694 if ((dst.am() == Offset) || (dst.am() == NegOffset)) { |
| 734 str(src1, dst, cond); | 695 dst2.set_offset(dst2.offset() + 4); |
| 735 str(src2, dst2, cond); | 696 str(src1, dst, cond); |
| 697 str(src2, dst2, cond); |
| 698 } else { // PostIndex or NegPostIndex. |
| 699 ASSERT((dst.am() == PostIndex) || (dst.am() == NegPostIndex)); |
| 700 dst2.set_offset(dst2.offset() - 4); |
| 701 str(src1, MemOperand(dst.rn(), 4, PostIndex), cond); |
| 702 str(src2, dst2, cond); |
| 703 } |
| 736 } | 704 } |
| 737 } | 705 } |
| 738 | 706 |
| 739 | 707 |
| 740 void MacroAssembler::ClearFPSCRBits(const uint32_t bits_to_clear, | 708 void MacroAssembler::ClearFPSCRBits(const uint32_t bits_to_clear, |
| 741 const Register scratch, | 709 const Register scratch, |
| 742 const Condition cond) { | 710 const Condition cond) { |
| 743 vmrs(scratch, cond); | 711 vmrs(scratch, cond); |
| 744 bic(scratch, scratch, Operand(bits_to_clear), LeaveCC, cond); | 712 bic(scratch, scratch, Operand(bits_to_clear), LeaveCC, cond); |
| 745 vmsr(scratch, cond); | 713 vmsr(scratch, cond); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 772 | 740 |
| 773 void MacroAssembler::VFPCompareAndLoadFlags(const DwVfpRegister src1, | 741 void MacroAssembler::VFPCompareAndLoadFlags(const DwVfpRegister src1, |
| 774 const double src2, | 742 const double src2, |
| 775 const Register fpscr_flags, | 743 const Register fpscr_flags, |
| 776 const Condition cond) { | 744 const Condition cond) { |
| 777 // Compare and load FPSCR. | 745 // Compare and load FPSCR. |
| 778 vcmp(src1, src2, cond); | 746 vcmp(src1, src2, cond); |
| 779 vmrs(fpscr_flags, cond); | 747 vmrs(fpscr_flags, cond); |
| 780 } | 748 } |
| 781 | 749 |
| 750 void MacroAssembler::Vmov(const DwVfpRegister dst, |
| 751 const double imm, |
| 752 const Condition cond) { |
| 753 ASSERT(CpuFeatures::IsEnabled(VFP3)); |
| 754 static const DoubleRepresentation minus_zero(-0.0); |
| 755 static const DoubleRepresentation zero(0.0); |
| 756 DoubleRepresentation value(imm); |
| 757 // Handle special values first. |
| 758 if (value.bits == zero.bits) { |
| 759 vmov(dst, kDoubleRegZero, cond); |
| 760 } else if (value.bits == minus_zero.bits) { |
| 761 vneg(dst, kDoubleRegZero, cond); |
| 762 } else { |
| 763 vmov(dst, imm, cond); |
| 764 } |
| 765 } |
| 766 |
| 782 | 767 |
| 783 void MacroAssembler::EnterFrame(StackFrame::Type type) { | 768 void MacroAssembler::EnterFrame(StackFrame::Type type) { |
| 784 // r0-r3: preserved | 769 // r0-r3: preserved |
| 785 stm(db_w, sp, cp.bit() | fp.bit() | lr.bit()); | 770 stm(db_w, sp, cp.bit() | fp.bit() | lr.bit()); |
| 786 mov(ip, Operand(Smi::FromInt(type))); | 771 mov(ip, Operand(Smi::FromInt(type))); |
| 787 push(ip); | 772 push(ip); |
| 788 mov(ip, Operand(CodeObject())); | 773 mov(ip, Operand(CodeObject())); |
| 789 push(ip); | 774 push(ip); |
| 790 add(fp, sp, Operand(3 * kPointerSize)); // Adjust FP to point to saved FP. | 775 add(fp, sp, Operand(3 * kPointerSize)); // Adjust FP to point to saved FP. |
| 791 } | 776 } |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 994 | 979 |
| 995 if (!definitely_matches) { | 980 if (!definitely_matches) { |
| 996 if (!code_constant.is_null()) { | 981 if (!code_constant.is_null()) { |
| 997 mov(r3, Operand(code_constant)); | 982 mov(r3, Operand(code_constant)); |
| 998 add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag)); | 983 add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag)); |
| 999 } | 984 } |
| 1000 | 985 |
| 1001 Handle<Code> adaptor = | 986 Handle<Code> adaptor = |
| 1002 isolate()->builtins()->ArgumentsAdaptorTrampoline(); | 987 isolate()->builtins()->ArgumentsAdaptorTrampoline(); |
| 1003 if (flag == CALL_FUNCTION) { | 988 if (flag == CALL_FUNCTION) { |
| 1004 call_wrapper.BeforeCall(CallSize(adaptor, RelocInfo::CODE_TARGET)); | 989 call_wrapper.BeforeCall(CallSize(adaptor)); |
| 1005 SetCallKind(r5, call_kind); | 990 SetCallKind(r5, call_kind); |
| 1006 Call(adaptor, RelocInfo::CODE_TARGET); | 991 Call(adaptor); |
| 1007 call_wrapper.AfterCall(); | 992 call_wrapper.AfterCall(); |
| 1008 b(done); | 993 b(done); |
| 1009 } else { | 994 } else { |
| 1010 SetCallKind(r5, call_kind); | 995 SetCallKind(r5, call_kind); |
| 1011 Jump(adaptor, RelocInfo::CODE_TARGET); | 996 Jump(adaptor, RelocInfo::CODE_TARGET); |
| 1012 } | 997 } |
| 1013 bind(®ular_invoke); | 998 bind(®ular_invoke); |
| 1014 } | 999 } |
| 1015 } | 1000 } |
| 1016 | 1001 |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1086 ldr(code_reg, | 1071 ldr(code_reg, |
| 1087 FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); | 1072 FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); |
| 1088 | 1073 |
| 1089 ParameterCount expected(expected_reg); | 1074 ParameterCount expected(expected_reg); |
| 1090 InvokeCode(code_reg, expected, actual, flag, call_wrapper, call_kind); | 1075 InvokeCode(code_reg, expected, actual, flag, call_wrapper, call_kind); |
| 1091 } | 1076 } |
| 1092 | 1077 |
| 1093 | 1078 |
| 1094 void MacroAssembler::InvokeFunction(JSFunction* function, | 1079 void MacroAssembler::InvokeFunction(JSFunction* function, |
| 1095 const ParameterCount& actual, | 1080 const ParameterCount& actual, |
| 1096 InvokeFlag flag) { | 1081 InvokeFlag flag, |
| 1082 CallKind call_kind) { |
| 1097 ASSERT(function->is_compiled()); | 1083 ASSERT(function->is_compiled()); |
| 1098 | 1084 |
| 1099 // Get the function and setup the context. | 1085 // Get the function and setup the context. |
| 1100 mov(r1, Operand(Handle<JSFunction>(function))); | 1086 mov(r1, Operand(Handle<JSFunction>(function))); |
| 1101 ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); | 1087 ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); |
| 1102 | 1088 |
| 1103 // Invoke the cached code. | 1089 // Invoke the cached code. |
| 1104 Handle<Code> code(function->code()); | 1090 Handle<Code> code(function->code()); |
| 1105 ParameterCount expected(function->shared()->formal_parameter_count()); | 1091 ParameterCount expected(function->shared()->formal_parameter_count()); |
| 1106 if (V8::UseCrankshaft()) { | 1092 if (V8::UseCrankshaft()) { |
| 1107 // TODO(kasperl): For now, we always call indirectly through the | 1093 // TODO(kasperl): For now, we always call indirectly through the |
| 1108 // code field in the function to allow recompilation to take effect | 1094 // code field in the function to allow recompilation to take effect |
| 1109 // without changing any of the call sites. | 1095 // without changing any of the call sites. |
| 1110 ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); | 1096 ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); |
| 1111 InvokeCode(r3, expected, actual, flag); | 1097 InvokeCode(r3, expected, actual, flag, NullCallWrapper(), call_kind); |
| 1112 } else { | 1098 } else { |
| 1113 InvokeCode(code, expected, actual, RelocInfo::CODE_TARGET, flag); | 1099 InvokeCode(code, expected, actual, RelocInfo::CODE_TARGET, flag, call_kind); |
| 1114 } | 1100 } |
| 1115 } | 1101 } |
| 1116 | 1102 |
| 1117 | 1103 |
| 1118 void MacroAssembler::IsObjectJSObjectType(Register heap_object, | 1104 void MacroAssembler::IsObjectJSObjectType(Register heap_object, |
| 1119 Register map, | 1105 Register map, |
| 1120 Register scratch, | 1106 Register scratch, |
| 1121 Label* fail) { | 1107 Label* fail) { |
| 1122 ldr(map, FieldMemOperand(heap_object, HeapObject::kMapOffset)); | 1108 ldr(map, FieldMemOperand(heap_object, HeapObject::kMapOffset)); |
| 1123 IsInstanceJSObjectType(map, scratch, fail); | 1109 IsInstanceJSObjectType(map, scratch, fail); |
| 1124 } | 1110 } |
| 1125 | 1111 |
| 1126 | 1112 |
| 1127 void MacroAssembler::IsInstanceJSObjectType(Register map, | 1113 void MacroAssembler::IsInstanceJSObjectType(Register map, |
| 1128 Register scratch, | 1114 Register scratch, |
| 1129 Label* fail) { | 1115 Label* fail) { |
| 1130 ldrb(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset)); | 1116 ldrb(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset)); |
| 1131 cmp(scratch, Operand(FIRST_JS_OBJECT_TYPE)); | 1117 cmp(scratch, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
| 1132 b(lt, fail); | 1118 b(lt, fail); |
| 1133 cmp(scratch, Operand(LAST_JS_OBJECT_TYPE)); | 1119 cmp(scratch, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
| 1134 b(gt, fail); | 1120 b(gt, fail); |
| 1135 } | 1121 } |
| 1136 | 1122 |
| 1137 | 1123 |
| 1138 void MacroAssembler::IsObjectJSStringType(Register object, | 1124 void MacroAssembler::IsObjectJSStringType(Register object, |
| 1139 Register scratch, | 1125 Register scratch, |
| 1140 Label* fail) { | 1126 Label* fail) { |
| 1141 ASSERT(kNotStringTag != 0); | 1127 ASSERT(kNotStringTag != 0); |
| 1142 | 1128 |
| 1143 ldr(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); | 1129 ldr(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1395 | 1381 |
| 1396 ldr(scratch, FieldMemOperand(scratch, token_offset)); | 1382 ldr(scratch, FieldMemOperand(scratch, token_offset)); |
| 1397 ldr(ip, FieldMemOperand(ip, token_offset)); | 1383 ldr(ip, FieldMemOperand(ip, token_offset)); |
| 1398 cmp(scratch, Operand(ip)); | 1384 cmp(scratch, Operand(ip)); |
| 1399 b(ne, miss); | 1385 b(ne, miss); |
| 1400 | 1386 |
| 1401 bind(&same_contexts); | 1387 bind(&same_contexts); |
| 1402 } | 1388 } |
| 1403 | 1389 |
| 1404 | 1390 |
| 1391 void MacroAssembler::LoadFromNumberDictionary(Label* miss, |
| 1392 Register elements, |
| 1393 Register key, |
| 1394 Register result, |
| 1395 Register t0, |
| 1396 Register t1, |
| 1397 Register t2) { |
| 1398 // Register use: |
| 1399 // |
| 1400 // elements - holds the slow-case elements of the receiver on entry. |
| 1401 // Unchanged unless 'result' is the same register. |
| 1402 // |
| 1403 // key - holds the smi key on entry. |
| 1404 // Unchanged unless 'result' is the same register. |
| 1405 // |
| 1406 // result - holds the result on exit if the load succeeded. |
| 1407 // Allowed to be the same as 'key' or 'result'. |
| 1408 // Unchanged on bailout so 'key' or 'result' can be used |
| 1409 // in further computation. |
| 1410 // |
| 1411 // Scratch registers: |
| 1412 // |
| 1413 // t0 - holds the untagged key on entry and holds the hash once computed. |
| 1414 // |
| 1415 // t1 - used to hold the capacity mask of the dictionary |
| 1416 // |
| 1417 // t2 - used for the index into the dictionary. |
| 1418 Label done; |
| 1419 |
| 1420 // Compute the hash code from the untagged key. This must be kept in sync |
| 1421 // with ComputeIntegerHash in utils.h. |
| 1422 // |
| 1423 // hash = ~hash + (hash << 15); |
| 1424 mvn(t1, Operand(t0)); |
| 1425 add(t0, t1, Operand(t0, LSL, 15)); |
| 1426 // hash = hash ^ (hash >> 12); |
| 1427 eor(t0, t0, Operand(t0, LSR, 12)); |
| 1428 // hash = hash + (hash << 2); |
| 1429 add(t0, t0, Operand(t0, LSL, 2)); |
| 1430 // hash = hash ^ (hash >> 4); |
| 1431 eor(t0, t0, Operand(t0, LSR, 4)); |
| 1432 // hash = hash * 2057; |
| 1433 mov(t1, Operand(2057)); |
| 1434 mul(t0, t0, t1); |
| 1435 // hash = hash ^ (hash >> 16); |
| 1436 eor(t0, t0, Operand(t0, LSR, 16)); |
| 1437 |
| 1438 // Compute the capacity mask. |
| 1439 ldr(t1, FieldMemOperand(elements, NumberDictionary::kCapacityOffset)); |
| 1440 mov(t1, Operand(t1, ASR, kSmiTagSize)); // convert smi to int |
| 1441 sub(t1, t1, Operand(1)); |
| 1442 |
| 1443 // Generate an unrolled loop that performs a few probes before giving up. |
| 1444 static const int kProbes = 4; |
| 1445 for (int i = 0; i < kProbes; i++) { |
| 1446 // Use t2 for index calculations and keep the hash intact in t0. |
| 1447 mov(t2, t0); |
| 1448 // Compute the masked index: (hash + i + i * i) & mask. |
| 1449 if (i > 0) { |
| 1450 add(t2, t2, Operand(NumberDictionary::GetProbeOffset(i))); |
| 1451 } |
| 1452 and_(t2, t2, Operand(t1)); |
| 1453 |
| 1454 // Scale the index by multiplying by the element size. |
| 1455 ASSERT(NumberDictionary::kEntrySize == 3); |
| 1456 add(t2, t2, Operand(t2, LSL, 1)); // t2 = t2 * 3 |
| 1457 |
| 1458 // Check if the key is identical to the name. |
| 1459 add(t2, elements, Operand(t2, LSL, kPointerSizeLog2)); |
| 1460 ldr(ip, FieldMemOperand(t2, NumberDictionary::kElementsStartOffset)); |
| 1461 cmp(key, Operand(ip)); |
| 1462 if (i != kProbes - 1) { |
| 1463 b(eq, &done); |
| 1464 } else { |
| 1465 b(ne, miss); |
| 1466 } |
| 1467 } |
| 1468 |
| 1469 bind(&done); |
| 1470 // Check that the value is a normal property. |
| 1471 // t2: elements + (index * kPointerSize) |
| 1472 const int kDetailsOffset = |
| 1473 NumberDictionary::kElementsStartOffset + 2 * kPointerSize; |
| 1474 ldr(t1, FieldMemOperand(t2, kDetailsOffset)); |
| 1475 tst(t1, Operand(Smi::FromInt(PropertyDetails::TypeField::mask()))); |
| 1476 b(ne, miss); |
| 1477 |
| 1478 // Get the value at the masked, scaled index and return. |
| 1479 const int kValueOffset = |
| 1480 NumberDictionary::kElementsStartOffset + kPointerSize; |
| 1481 ldr(result, FieldMemOperand(t2, kValueOffset)); |
| 1482 } |
| 1483 |
| 1484 |
| 1405 void MacroAssembler::AllocateInNewSpace(int object_size, | 1485 void MacroAssembler::AllocateInNewSpace(int object_size, |
| 1406 Register result, | 1486 Register result, |
| 1407 Register scratch1, | 1487 Register scratch1, |
| 1408 Register scratch2, | 1488 Register scratch2, |
| 1409 Label* gc_required, | 1489 Label* gc_required, |
| 1410 AllocationFlags flags) { | 1490 AllocationFlags flags) { |
| 1411 if (!FLAG_inline_new) { | 1491 if (!FLAG_inline_new) { |
| 1412 if (emit_debug_code()) { | 1492 if (emit_debug_code()) { |
| 1413 // Trash the registers to simulate an allocation failure. | 1493 // Trash the registers to simulate an allocation failure. |
| 1414 mov(result, Operand(0x7091)); | 1494 mov(result, Operand(0x7091)); |
| (...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1714 | 1794 |
| 1715 | 1795 |
| 1716 void MacroAssembler::CompareRoot(Register obj, | 1796 void MacroAssembler::CompareRoot(Register obj, |
| 1717 Heap::RootListIndex index) { | 1797 Heap::RootListIndex index) { |
| 1718 ASSERT(!obj.is(ip)); | 1798 ASSERT(!obj.is(ip)); |
| 1719 LoadRoot(ip, index); | 1799 LoadRoot(ip, index); |
| 1720 cmp(obj, ip); | 1800 cmp(obj, ip); |
| 1721 } | 1801 } |
| 1722 | 1802 |
| 1723 | 1803 |
| 1804 void MacroAssembler::CheckFastElements(Register map, |
| 1805 Register scratch, |
| 1806 Label* fail) { |
| 1807 STATIC_ASSERT(JSObject::FAST_ELEMENTS == 0); |
| 1808 ldrb(scratch, FieldMemOperand(map, Map::kBitField2Offset)); |
| 1809 cmp(scratch, Operand(Map::kMaximumBitField2FastElementValue)); |
| 1810 b(hi, fail); |
| 1811 } |
| 1812 |
| 1813 |
| 1724 void MacroAssembler::CheckMap(Register obj, | 1814 void MacroAssembler::CheckMap(Register obj, |
| 1725 Register scratch, | 1815 Register scratch, |
| 1726 Handle<Map> map, | 1816 Handle<Map> map, |
| 1727 Label* fail, | 1817 Label* fail, |
| 1728 SmiCheckType smi_check_type) { | 1818 SmiCheckType smi_check_type) { |
| 1729 if (smi_check_type == DO_SMI_CHECK) { | 1819 if (smi_check_type == DO_SMI_CHECK) { |
| 1730 JumpIfSmi(obj, fail); | 1820 JumpIfSmi(obj, fail); |
| 1731 } | 1821 } |
| 1732 ldr(scratch, FieldMemOperand(obj, HeapObject::kMapOffset)); | 1822 ldr(scratch, FieldMemOperand(obj, HeapObject::kMapOffset)); |
| 1733 mov(ip, Operand(map)); | 1823 mov(ip, Operand(map)); |
| (...skipping 673 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2407 return TryTailCallStub(&stub); | 2497 return TryTailCallStub(&stub); |
| 2408 } | 2498 } |
| 2409 | 2499 |
| 2410 | 2500 |
| 2411 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, | 2501 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, |
| 2412 InvokeFlag flag, | 2502 InvokeFlag flag, |
| 2413 const CallWrapper& call_wrapper) { | 2503 const CallWrapper& call_wrapper) { |
| 2414 GetBuiltinEntry(r2, id); | 2504 GetBuiltinEntry(r2, id); |
| 2415 if (flag == CALL_FUNCTION) { | 2505 if (flag == CALL_FUNCTION) { |
| 2416 call_wrapper.BeforeCall(CallSize(r2)); | 2506 call_wrapper.BeforeCall(CallSize(r2)); |
| 2507 SetCallKind(r5, CALL_AS_METHOD); |
| 2417 Call(r2); | 2508 Call(r2); |
| 2418 call_wrapper.AfterCall(); | 2509 call_wrapper.AfterCall(); |
| 2419 } else { | 2510 } else { |
| 2420 ASSERT(flag == JUMP_FUNCTION); | 2511 ASSERT(flag == JUMP_FUNCTION); |
| 2512 SetCallKind(r5, CALL_AS_METHOD); |
| 2421 Jump(r2); | 2513 Jump(r2); |
| 2422 } | 2514 } |
| 2423 } | 2515 } |
| 2424 | 2516 |
| 2425 | 2517 |
| 2426 void MacroAssembler::GetBuiltinFunction(Register target, | 2518 void MacroAssembler::GetBuiltinFunction(Register target, |
| 2427 Builtins::JavaScript id) { | 2519 Builtins::JavaScript id) { |
| 2428 // Load the builtins object into target register. | 2520 // Load the builtins object into target register. |
| 2429 ldr(target, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); | 2521 ldr(target, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); |
| 2430 ldr(target, FieldMemOperand(target, GlobalObject::kBuiltinsOffset)); | 2522 ldr(target, FieldMemOperand(target, GlobalObject::kBuiltinsOffset)); |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2556 while (abort_instructions++ < kExpectedAbortInstructions) { | 2648 while (abort_instructions++ < kExpectedAbortInstructions) { |
| 2557 nop(); | 2649 nop(); |
| 2558 } | 2650 } |
| 2559 } | 2651 } |
| 2560 } | 2652 } |
| 2561 | 2653 |
| 2562 | 2654 |
| 2563 void MacroAssembler::LoadContext(Register dst, int context_chain_length) { | 2655 void MacroAssembler::LoadContext(Register dst, int context_chain_length) { |
| 2564 if (context_chain_length > 0) { | 2656 if (context_chain_length > 0) { |
| 2565 // Move up the chain of contexts to the context containing the slot. | 2657 // Move up the chain of contexts to the context containing the slot. |
| 2566 ldr(dst, MemOperand(cp, Context::SlotOffset(Context::CLOSURE_INDEX))); | 2658 ldr(dst, MemOperand(cp, Context::SlotOffset(Context::PREVIOUS_INDEX))); |
| 2567 // Load the function context (which is the incoming, outer context). | |
| 2568 ldr(dst, FieldMemOperand(dst, JSFunction::kContextOffset)); | |
| 2569 for (int i = 1; i < context_chain_length; i++) { | 2659 for (int i = 1; i < context_chain_length; i++) { |
| 2570 ldr(dst, MemOperand(dst, Context::SlotOffset(Context::CLOSURE_INDEX))); | 2660 ldr(dst, MemOperand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX))); |
| 2571 ldr(dst, FieldMemOperand(dst, JSFunction::kContextOffset)); | |
| 2572 } | 2661 } |
| 2573 } else { | 2662 } else { |
| 2574 // Slot is in the current function context. Move it into the | 2663 // Slot is in the current function context. Move it into the |
| 2575 // destination register in case we store into it (the write barrier | 2664 // destination register in case we store into it (the write barrier |
| 2576 // cannot be allowed to destroy the context in esi). | 2665 // cannot be allowed to destroy the context in esi). |
| 2577 mov(dst, cp); | 2666 mov(dst, cp); |
| 2578 } | 2667 } |
| 2579 | |
| 2580 // We should not have found a 'with' context by walking the context chain | |
| 2581 // (i.e., the static scope chain and runtime context chain do not agree). | |
| 2582 // A variable occurring in such a scope should have slot type LOOKUP and | |
| 2583 // not CONTEXT. | |
| 2584 if (emit_debug_code()) { | |
| 2585 ldr(ip, MemOperand(dst, Context::SlotOffset(Context::FCONTEXT_INDEX))); | |
| 2586 cmp(dst, ip); | |
| 2587 Check(eq, "Yo dawg, I heard you liked function contexts " | |
| 2588 "so I put function contexts in all your contexts"); | |
| 2589 } | |
| 2590 } | 2668 } |
| 2591 | 2669 |
| 2592 | 2670 |
| 2593 void MacroAssembler::LoadGlobalFunction(int index, Register function) { | 2671 void MacroAssembler::LoadGlobalFunction(int index, Register function) { |
| 2594 // Load the global or builtins object from the current context. | 2672 // Load the global or builtins object from the current context. |
| 2595 ldr(function, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); | 2673 ldr(function, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); |
| 2596 // Load the global context from the global or builtins object. | 2674 // Load the global context from the global or builtins object. |
| 2597 ldr(function, FieldMemOperand(function, | 2675 ldr(function, FieldMemOperand(function, |
| 2598 GlobalObject::kGlobalContextOffset)); | 2676 GlobalObject::kGlobalContextOffset)); |
| 2599 // Load the function from the global context. | 2677 // Load the function from the global context. |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2727 } | 2805 } |
| 2728 | 2806 |
| 2729 void MacroAssembler::JumpIfNotBothSequentialAsciiStrings(Register first, | 2807 void MacroAssembler::JumpIfNotBothSequentialAsciiStrings(Register first, |
| 2730 Register second, | 2808 Register second, |
| 2731 Register scratch1, | 2809 Register scratch1, |
| 2732 Register scratch2, | 2810 Register scratch2, |
| 2733 Label* failure) { | 2811 Label* failure) { |
| 2734 // Check that neither is a smi. | 2812 // Check that neither is a smi. |
| 2735 STATIC_ASSERT(kSmiTag == 0); | 2813 STATIC_ASSERT(kSmiTag == 0); |
| 2736 and_(scratch1, first, Operand(second)); | 2814 and_(scratch1, first, Operand(second)); |
| 2737 tst(scratch1, Operand(kSmiTagMask)); | 2815 JumpIfSmi(scratch1, failure); |
| 2738 b(eq, failure); | |
| 2739 JumpIfNonSmisNotBothSequentialAsciiStrings(first, | 2816 JumpIfNonSmisNotBothSequentialAsciiStrings(first, |
| 2740 second, | 2817 second, |
| 2741 scratch1, | 2818 scratch1, |
| 2742 scratch2, | 2819 scratch2, |
| 2743 failure); | 2820 failure); |
| 2744 } | 2821 } |
| 2745 | 2822 |
| 2746 | 2823 |
| 2747 // Allocates a heap number or jumps to the need_gc label if the young space | 2824 // Allocates a heap number or jumps to the need_gc label if the young space |
| 2748 // is full and a scavenge is needed. | 2825 // is full and a scavenge is needed. |
| (...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3206 } | 3283 } |
| 3207 | 3284 |
| 3208 | 3285 |
| 3209 void MacroAssembler::ClampDoubleToUint8(Register result_reg, | 3286 void MacroAssembler::ClampDoubleToUint8(Register result_reg, |
| 3210 DoubleRegister input_reg, | 3287 DoubleRegister input_reg, |
| 3211 DoubleRegister temp_double_reg) { | 3288 DoubleRegister temp_double_reg) { |
| 3212 Label above_zero; | 3289 Label above_zero; |
| 3213 Label done; | 3290 Label done; |
| 3214 Label in_bounds; | 3291 Label in_bounds; |
| 3215 | 3292 |
| 3216 vmov(temp_double_reg, 0.0); | 3293 Vmov(temp_double_reg, 0.0); |
| 3217 VFPCompareAndSetFlags(input_reg, temp_double_reg); | 3294 VFPCompareAndSetFlags(input_reg, temp_double_reg); |
| 3218 b(gt, &above_zero); | 3295 b(gt, &above_zero); |
| 3219 | 3296 |
| 3220 // Double value is less than zero, NaN or Inf, return 0. | 3297 // Double value is less than zero, NaN or Inf, return 0. |
| 3221 mov(result_reg, Operand(0)); | 3298 mov(result_reg, Operand(0)); |
| 3222 b(al, &done); | 3299 b(al, &done); |
| 3223 | 3300 |
| 3224 // Double value is >= 255, return 255. | 3301 // Double value is >= 255, return 255. |
| 3225 bind(&above_zero); | 3302 bind(&above_zero); |
| 3226 vmov(temp_double_reg, 255.0); | 3303 Vmov(temp_double_reg, 255.0); |
| 3227 VFPCompareAndSetFlags(input_reg, temp_double_reg); | 3304 VFPCompareAndSetFlags(input_reg, temp_double_reg); |
| 3228 b(le, &in_bounds); | 3305 b(le, &in_bounds); |
| 3229 mov(result_reg, Operand(255)); | 3306 mov(result_reg, Operand(255)); |
| 3230 b(al, &done); | 3307 b(al, &done); |
| 3231 | 3308 |
| 3232 // In 0-255 range, round and truncate. | 3309 // In 0-255 range, round and truncate. |
| 3233 bind(&in_bounds); | 3310 bind(&in_bounds); |
| 3234 vmov(temp_double_reg, 0.5); | 3311 Vmov(temp_double_reg, 0.5); |
| 3235 vadd(temp_double_reg, input_reg, temp_double_reg); | 3312 vadd(temp_double_reg, input_reg, temp_double_reg); |
| 3236 vcvt_u32_f64(s0, temp_double_reg); | 3313 vcvt_u32_f64(s0, temp_double_reg); |
| 3237 vmov(result_reg, s0); | 3314 vmov(result_reg, s0); |
| 3238 bind(&done); | 3315 bind(&done); |
| 3239 } | 3316 } |
| 3240 | 3317 |
| 3241 | 3318 |
| 3242 void MacroAssembler::LoadInstanceDescriptors(Register map, | 3319 void MacroAssembler::LoadInstanceDescriptors(Register map, |
| 3243 Register descriptors) { | 3320 Register descriptors) { |
| 3244 ldr(descriptors, | 3321 ldr(descriptors, |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3296 void CodePatcher::EmitCondition(Condition cond) { | 3373 void CodePatcher::EmitCondition(Condition cond) { |
| 3297 Instr instr = Assembler::instr_at(masm_.pc_); | 3374 Instr instr = Assembler::instr_at(masm_.pc_); |
| 3298 instr = (instr & ~kCondMask) | cond; | 3375 instr = (instr & ~kCondMask) | cond; |
| 3299 masm_.emit(instr); | 3376 masm_.emit(instr); |
| 3300 } | 3377 } |
| 3301 | 3378 |
| 3302 | 3379 |
| 3303 } } // namespace v8::internal | 3380 } } // namespace v8::internal |
| 3304 | 3381 |
| 3305 #endif // V8_TARGET_ARCH_ARM | 3382 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |