Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(220)

Side by Side Diff: src/arm/macro-assembler-arm.cc

Issue 6697023: Merge 6800:7180 from the bleeding edge branch to the experimental/gc branch. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/arm/macro-assembler-arm.h ('k') | src/arm/simulator-arm.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
96 96
97 97
98 void MacroAssembler::Jump(Handle<Code> code, RelocInfo::Mode rmode, 98 void MacroAssembler::Jump(Handle<Code> code, RelocInfo::Mode rmode,
99 Condition cond) { 99 Condition cond) {
100 ASSERT(RelocInfo::IsCodeTarget(rmode)); 100 ASSERT(RelocInfo::IsCodeTarget(rmode));
101 // 'code' is always generated ARM code, never THUMB code 101 // 'code' is always generated ARM code, never THUMB code
102 Jump(reinterpret_cast<intptr_t>(code.location()), rmode, cond); 102 Jump(reinterpret_cast<intptr_t>(code.location()), rmode, cond);
103 } 103 }
104 104
105 105
106 int MacroAssembler::CallSize(Register target, Condition cond) {
107 #if USE_BLX
108 return kInstrSize;
109 #else
110 return 2 * kInstrSize;
111 #endif
112 }
113
114
106 void MacroAssembler::Call(Register target, Condition cond) { 115 void MacroAssembler::Call(Register target, Condition cond) {
116 // Block constant pool for the call instruction sequence.
117 BlockConstPoolScope block_const_pool(this);
118 #ifdef DEBUG
119 int pre_position = pc_offset();
120 #endif
121
107 #if USE_BLX 122 #if USE_BLX
108 blx(target, cond); 123 blx(target, cond);
109 #else 124 #else
110 // set lr for return at current pc + 8 125 // set lr for return at current pc + 8
111 mov(lr, Operand(pc), LeaveCC, cond); 126 mov(lr, Operand(pc), LeaveCC, cond);
112 mov(pc, Operand(target), LeaveCC, cond); 127 mov(pc, Operand(target), LeaveCC, cond);
113 #endif 128 #endif
129
130 #ifdef DEBUG
131 int post_position = pc_offset();
132 CHECK_EQ(pre_position + CallSize(target, cond), post_position);
133 #endif
114 } 134 }
115 135
116 136
117 void MacroAssembler::Call(intptr_t target, RelocInfo::Mode rmode, 137 int MacroAssembler::CallSize(
118 Condition cond) { 138 intptr_t target, RelocInfo::Mode rmode, Condition cond) {
139 int size = 2 * kInstrSize;
140 Instr mov_instr = cond | MOV | LeaveCC;
141 if (!Operand(target, rmode).is_single_instruction(mov_instr)) {
142 size += kInstrSize;
143 }
144 return size;
145 }
146
147
148 void MacroAssembler::Call(
149 intptr_t target, RelocInfo::Mode rmode, Condition cond) {
150 // Block constant pool for the call instruction sequence.
151 BlockConstPoolScope block_const_pool(this);
152 #ifdef DEBUG
153 int pre_position = pc_offset();
154 #endif
155
119 #if USE_BLX 156 #if USE_BLX
120 // On ARMv5 and after the recommended call sequence is: 157 // On ARMv5 and after the recommended call sequence is:
121 // ldr ip, [pc, #...] 158 // ldr ip, [pc, #...]
122 // blx ip 159 // blx ip
123 160
124 // The two instructions (ldr and blx) could be separated by a constant 161 // Statement positions are expected to be recorded when the target
125 // pool and the code would still work. The issue comes from the 162 // address is loaded. The mov method will automatically record
126 // patching code which expect the ldr to be just above the blx. 163 // positions when pc is the target, since this is not the case here
127 { BlockConstPoolScope block_const_pool(this); 164 // we have to do it explicitly.
128 // Statement positions are expected to be recorded when the target 165 positions_recorder()->WriteRecordedPositions();
129 // address is loaded. The mov method will automatically record
130 // positions when pc is the target, since this is not the case here
131 // we have to do it explicitly.
132 positions_recorder()->WriteRecordedPositions();
133 166
134 mov(ip, Operand(target, rmode), LeaveCC, cond); 167 mov(ip, Operand(target, rmode), LeaveCC, cond);
135 blx(ip, cond); 168 blx(ip, cond);
136 }
137 169
138 ASSERT(kCallTargetAddressOffset == 2 * kInstrSize); 170 ASSERT(kCallTargetAddressOffset == 2 * kInstrSize);
139 #else 171 #else
140 // Set lr for return at current pc + 8. 172 // Set lr for return at current pc + 8.
141 mov(lr, Operand(pc), LeaveCC, cond); 173 mov(lr, Operand(pc), LeaveCC, cond);
142 // Emit a ldr<cond> pc, [pc + offset of target in constant pool]. 174 // Emit a ldr<cond> pc, [pc + offset of target in constant pool].
143 mov(pc, Operand(target, rmode), LeaveCC, cond); 175 mov(pc, Operand(target, rmode), LeaveCC, cond);
176 ASSERT(kCallTargetAddressOffset == kInstrSize);
177 #endif
144 178
145 ASSERT(kCallTargetAddressOffset == kInstrSize); 179 #ifdef DEBUG
180 int post_position = pc_offset();
181 CHECK_EQ(pre_position + CallSize(target, rmode, cond), post_position);
146 #endif 182 #endif
147 } 183 }
148 184
149 185
150 void MacroAssembler::Call(byte* target, RelocInfo::Mode rmode, 186 int MacroAssembler::CallSize(
151 Condition cond) { 187 byte* target, RelocInfo::Mode rmode, Condition cond) {
152 ASSERT(!RelocInfo::IsCodeTarget(rmode)); 188 return CallSize(reinterpret_cast<intptr_t>(target), rmode);
153 Call(reinterpret_cast<intptr_t>(target), rmode, cond);
154 } 189 }
155 190
156 191
157 void MacroAssembler::Call(Handle<Code> code, RelocInfo::Mode rmode, 192 void MacroAssembler::Call(
158 Condition cond) { 193 byte* target, RelocInfo::Mode rmode, Condition cond) {
194 #ifdef DEBUG
195 int pre_position = pc_offset();
196 #endif
197
198 ASSERT(!RelocInfo::IsCodeTarget(rmode));
199 Call(reinterpret_cast<intptr_t>(target), rmode, cond);
200
201 #ifdef DEBUG
202 int post_position = pc_offset();
203 CHECK_EQ(pre_position + CallSize(target, rmode, cond), post_position);
204 #endif
205 }
206
207
208 int MacroAssembler::CallSize(
209 Handle<Code> code, RelocInfo::Mode rmode, Condition cond) {
210 return CallSize(reinterpret_cast<intptr_t>(code.location()), rmode, cond);
211 }
212
213
214 void MacroAssembler::Call(
215 Handle<Code> code, RelocInfo::Mode rmode, Condition cond) {
216 #ifdef DEBUG
217 int pre_position = pc_offset();
218 #endif
219
159 ASSERT(RelocInfo::IsCodeTarget(rmode)); 220 ASSERT(RelocInfo::IsCodeTarget(rmode));
160 // 'code' is always generated ARM code, never THUMB code 221 // 'code' is always generated ARM code, never THUMB code
161 Call(reinterpret_cast<intptr_t>(code.location()), rmode, cond); 222 Call(reinterpret_cast<intptr_t>(code.location()), rmode, cond);
223
224 #ifdef DEBUG
225 int post_position = pc_offset();
226 CHECK_EQ(pre_position + CallSize(code, rmode, cond), post_position);
227 #endif
162 } 228 }
163 229
164 230
165 void MacroAssembler::Ret(Condition cond) { 231 void MacroAssembler::Ret(Condition cond) {
166 #if USE_BX 232 #if USE_BX
167 bx(lr, cond); 233 bx(lr, cond);
168 #else 234 #else
169 mov(pc, Operand(lr), LeaveCC, cond); 235 mov(pc, Operand(lr), LeaveCC, cond);
170 #endif 236 #endif
171 } 237 }
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
264 } 330 }
265 if (shift_down != 0) { 331 if (shift_down != 0) {
266 mov(dst, Operand(dst, ASR, shift_down), LeaveCC, cond); 332 mov(dst, Operand(dst, ASR, shift_down), LeaveCC, cond);
267 } 333 }
268 } else { 334 } else {
269 sbfx(dst, src1, lsb, width, cond); 335 sbfx(dst, src1, lsb, width, cond);
270 } 336 }
271 } 337 }
272 338
273 339
340 void MacroAssembler::Bfi(Register dst,
341 Register src,
342 Register scratch,
343 int lsb,
344 int width,
345 Condition cond) {
346 ASSERT(0 <= lsb && lsb < 32);
347 ASSERT(0 <= width && width < 32);
348 ASSERT(lsb + width < 32);
349 ASSERT(!scratch.is(dst));
350 if (width == 0) return;
351 if (!CpuFeatures::IsSupported(ARMv7)) {
352 int mask = (1 << (width + lsb)) - 1 - ((1 << lsb) - 1);
353 bic(dst, dst, Operand(mask));
354 and_(scratch, src, Operand((1 << width) - 1));
355 mov(scratch, Operand(scratch, LSL, lsb));
356 orr(dst, dst, scratch);
357 } else {
358 bfi(dst, src, lsb, width, cond);
359 }
360 }
361
362
274 void MacroAssembler::Bfc(Register dst, int lsb, int width, Condition cond) { 363 void MacroAssembler::Bfc(Register dst, int lsb, int width, Condition cond) {
275 ASSERT(lsb < 32); 364 ASSERT(lsb < 32);
276 if (!CpuFeatures::IsSupported(ARMv7)) { 365 if (!CpuFeatures::IsSupported(ARMv7)) {
277 int mask = (1 << (width + lsb)) - 1 - ((1 << lsb) - 1); 366 int mask = (1 << (width + lsb)) - 1 - ((1 << lsb) - 1);
278 bic(dst, dst, Operand(mask)); 367 bic(dst, dst, Operand(mask));
279 } else { 368 } else {
280 bfc(dst, lsb, width, cond); 369 bfc(dst, lsb, width, cond);
281 } 370 }
282 } 371 }
283 372
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
338 Heap::RootListIndex index, 427 Heap::RootListIndex index,
339 Condition cond) { 428 Condition cond) {
340 str(source, MemOperand(roots, index << kPointerSizeLog2), cond); 429 str(source, MemOperand(roots, index << kPointerSizeLog2), cond);
341 } 430 }
342 431
343 432
344 #ifdef ENABLE_CARDMARKING_WRITE_BARRIER 433 #ifdef ENABLE_CARDMARKING_WRITE_BARRIER
345 void MacroAssembler::RecordWriteHelper(Register object, 434 void MacroAssembler::RecordWriteHelper(Register object,
346 Register address, 435 Register address,
347 Register scratch) { 436 Register scratch) {
348 if (FLAG_debug_code) { 437 if (emit_debug_code()) {
349 // Check that the object is not in new space. 438 // Check that the object is not in new space.
350 Label not_in_new_space; 439 Label not_in_new_space;
351 InNewSpace(object, scratch, ne, &not_in_new_space); 440 InNewSpace(object, scratch, ne, &not_in_new_space);
352 Abort("new-space object passed to RecordWriteHelper"); 441 Abort("new-space object passed to RecordWriteHelper");
353 bind(&not_in_new_space); 442 bind(&not_in_new_space);
354 } 443 }
355 444
356 // Calculate page address. 445 // Calculate page address.
357 Bfc(object, 0, kPageSizeBits); 446 Bfc(object, 0, kPageSizeBits);
358 447
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
400 // Add offset into the object. 489 // Add offset into the object.
401 add(scratch0, object, offset); 490 add(scratch0, object, offset);
402 491
403 // Record the actual write. 492 // Record the actual write.
404 RecordWriteHelper(object, scratch0, scratch1); 493 RecordWriteHelper(object, scratch0, scratch1);
405 494
406 bind(&done); 495 bind(&done);
407 496
408 // Clobber all input registers when running with the debug-code flag 497 // Clobber all input registers when running with the debug-code flag
409 // turned on to provoke errors. 498 // turned on to provoke errors.
410 if (FLAG_debug_code) { 499 if (emit_debug_code()) {
411 mov(object, Operand(BitCast<int32_t>(kZapValue))); 500 mov(object, Operand(BitCast<int32_t>(kZapValue)));
412 mov(scratch0, Operand(BitCast<int32_t>(kZapValue))); 501 mov(scratch0, Operand(BitCast<int32_t>(kZapValue)));
413 mov(scratch1, Operand(BitCast<int32_t>(kZapValue))); 502 mov(scratch1, Operand(BitCast<int32_t>(kZapValue)));
414 } 503 }
415 } 504 }
416 505
417 506
418 // Will clobber 4 registers: object, address, scratch, ip. The 507 // Will clobber 4 registers: object, address, scratch, ip. The
419 // register 'object' contains a heap object pointer. The heap object 508 // register 'object' contains a heap object pointer. The heap object
420 // tag is shifted away. 509 // tag is shifted away.
(...skipping 11 matching lines...) Expand all
432 // region marks for new space pages. 521 // region marks for new space pages.
433 InNewSpace(object, scratch, eq, &done); 522 InNewSpace(object, scratch, eq, &done);
434 523
435 // Record the actual write. 524 // Record the actual write.
436 RecordWriteHelper(object, address, scratch); 525 RecordWriteHelper(object, address, scratch);
437 526
438 bind(&done); 527 bind(&done);
439 528
440 // Clobber all input registers when running with the debug-code flag 529 // Clobber all input registers when running with the debug-code flag
441 // turned on to provoke errors. 530 // turned on to provoke errors.
442 if (FLAG_debug_code) { 531 if (emit_debug_code()) {
443 mov(object, Operand(BitCast<int32_t>(kZapValue))); 532 mov(object, Operand(BitCast<int32_t>(kZapValue)));
444 mov(address, Operand(BitCast<int32_t>(kZapValue))); 533 mov(address, Operand(BitCast<int32_t>(kZapValue)));
445 mov(scratch, Operand(BitCast<int32_t>(kZapValue))); 534 mov(scratch, Operand(BitCast<int32_t>(kZapValue)));
446 } 535 }
447 } 536 }
448 #endif 537 #endif
449 538
450 // Push and pop all registers that can hold pointers. 539 // Push and pop all registers that can hold pointers.
451 void MacroAssembler::PushSafepointRegisters() { 540 void MacroAssembler::PushSafepointRegisters() {
452 // Safepoints expect a block of contiguous register values starting with r0: 541 // Safepoints expect a block of contiguous register values starting with r0:
(...skipping 26 matching lines...) Expand all
479 568
480 void MacroAssembler::PopSafepointRegistersAndDoubles() { 569 void MacroAssembler::PopSafepointRegistersAndDoubles() {
481 for (int i = 0; i < DwVfpRegister::kNumAllocatableRegisters; i++) { 570 for (int i = 0; i < DwVfpRegister::kNumAllocatableRegisters; i++) {
482 vldr(DwVfpRegister::FromAllocationIndex(i), sp, i * kDoubleSize); 571 vldr(DwVfpRegister::FromAllocationIndex(i), sp, i * kDoubleSize);
483 } 572 }
484 add(sp, sp, Operand(DwVfpRegister::kNumAllocatableRegisters * 573 add(sp, sp, Operand(DwVfpRegister::kNumAllocatableRegisters *
485 kDoubleSize)); 574 kDoubleSize));
486 PopSafepointRegisters(); 575 PopSafepointRegisters();
487 } 576 }
488 577
489 void MacroAssembler::StoreToSafepointRegistersAndDoublesSlot(Register reg) { 578 void MacroAssembler::StoreToSafepointRegistersAndDoublesSlot(Register src,
490 str(reg, SafepointRegistersAndDoublesSlot(reg)); 579 Register dst) {
580 str(src, SafepointRegistersAndDoublesSlot(dst));
491 } 581 }
492 582
493 583
494 void MacroAssembler::StoreToSafepointRegisterSlot(Register reg) { 584 void MacroAssembler::StoreToSafepointRegisterSlot(Register src, Register dst) {
495 str(reg, SafepointRegisterSlot(reg)); 585 str(src, SafepointRegisterSlot(dst));
496 } 586 }
497 587
498 588
499 void MacroAssembler::LoadFromSafepointRegisterSlot(Register reg) { 589 void MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) {
500 ldr(reg, SafepointRegisterSlot(reg)); 590 ldr(dst, SafepointRegisterSlot(src));
501 } 591 }
502 592
503 593
504 int MacroAssembler::SafepointRegisterStackIndex(int reg_code) { 594 int MacroAssembler::SafepointRegisterStackIndex(int reg_code) {
505 // The registers are pushed starting with the highest encoding, 595 // The registers are pushed starting with the highest encoding,
506 // which means that lowest encodings are closest to the stack pointer. 596 // which means that lowest encodings are closest to the stack pointer.
507 ASSERT(reg_code >= 0 && reg_code < kNumSafepointRegisters); 597 ASSERT(reg_code >= 0 && reg_code < kNumSafepointRegisters);
508 return reg_code; 598 return reg_code;
509 } 599 }
510 600
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
635 725
636 void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space) { 726 void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space) {
637 // Setup the frame structure on the stack. 727 // Setup the frame structure on the stack.
638 ASSERT_EQ(2 * kPointerSize, ExitFrameConstants::kCallerSPDisplacement); 728 ASSERT_EQ(2 * kPointerSize, ExitFrameConstants::kCallerSPDisplacement);
639 ASSERT_EQ(1 * kPointerSize, ExitFrameConstants::kCallerPCOffset); 729 ASSERT_EQ(1 * kPointerSize, ExitFrameConstants::kCallerPCOffset);
640 ASSERT_EQ(0 * kPointerSize, ExitFrameConstants::kCallerFPOffset); 730 ASSERT_EQ(0 * kPointerSize, ExitFrameConstants::kCallerFPOffset);
641 Push(lr, fp); 731 Push(lr, fp);
642 mov(fp, Operand(sp)); // Setup new frame pointer. 732 mov(fp, Operand(sp)); // Setup new frame pointer.
643 // Reserve room for saved entry sp and code object. 733 // Reserve room for saved entry sp and code object.
644 sub(sp, sp, Operand(2 * kPointerSize)); 734 sub(sp, sp, Operand(2 * kPointerSize));
645 if (FLAG_debug_code) { 735 if (emit_debug_code()) {
646 mov(ip, Operand(0)); 736 mov(ip, Operand(0));
647 str(ip, MemOperand(fp, ExitFrameConstants::kSPOffset)); 737 str(ip, MemOperand(fp, ExitFrameConstants::kSPOffset));
648 } 738 }
649 mov(ip, Operand(CodeObject())); 739 mov(ip, Operand(CodeObject()));
650 str(ip, MemOperand(fp, ExitFrameConstants::kCodeOffset)); 740 str(ip, MemOperand(fp, ExitFrameConstants::kCodeOffset));
651 741
652 // Save the frame pointer and the context in top. 742 // Save the frame pointer and the context in top.
653 mov(ip, Operand(ExternalReference(Top::k_c_entry_fp_address))); 743 mov(ip, Operand(ExternalReference(Top::k_c_entry_fp_address)));
654 str(fp, MemOperand(ip)); 744 str(fp, MemOperand(ip));
655 mov(ip, Operand(ExternalReference(Top::k_context_address))); 745 mov(ip, Operand(ExternalReference(Top::k_context_address)));
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
739 #endif 829 #endif
740 830
741 // Tear down the exit frame, pop the arguments, and return. 831 // Tear down the exit frame, pop the arguments, and return.
742 mov(sp, Operand(fp)); 832 mov(sp, Operand(fp));
743 ldm(ia_w, sp, fp.bit() | lr.bit()); 833 ldm(ia_w, sp, fp.bit() | lr.bit());
744 if (argument_count.is_valid()) { 834 if (argument_count.is_valid()) {
745 add(sp, sp, Operand(argument_count, LSL, kPointerSizeLog2)); 835 add(sp, sp, Operand(argument_count, LSL, kPointerSizeLog2));
746 } 836 }
747 } 837 }
748 838
839 void MacroAssembler::GetCFunctionDoubleResult(const DoubleRegister dst) {
840 #if !defined(USE_ARM_EABI)
841 UNREACHABLE();
842 #else
843 vmov(dst, r0, r1);
844 #endif
845 }
846
749 847
750 void MacroAssembler::InvokePrologue(const ParameterCount& expected, 848 void MacroAssembler::InvokePrologue(const ParameterCount& expected,
751 const ParameterCount& actual, 849 const ParameterCount& actual,
752 Handle<Code> code_constant, 850 Handle<Code> code_constant,
753 Register code_reg, 851 Register code_reg,
754 Label* done, 852 Label* done,
755 InvokeFlag flag, 853 InvokeFlag flag,
756 PostCallGenerator* post_call_generator) { 854 CallWrapper* call_wrapper) {
757 bool definitely_matches = false; 855 bool definitely_matches = false;
758 Label regular_invoke; 856 Label regular_invoke;
759 857
760 // Check whether the expected and actual arguments count match. If not, 858 // Check whether the expected and actual arguments count match. If not,
761 // setup registers according to contract with ArgumentsAdaptorTrampoline: 859 // setup registers according to contract with ArgumentsAdaptorTrampoline:
762 // r0: actual arguments count 860 // r0: actual arguments count
763 // r1: function (passed through to callee) 861 // r1: function (passed through to callee)
764 // r2: expected arguments count 862 // r2: expected arguments count
765 // r3: callee code entry 863 // r3: callee code entry
766 864
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
801 899
802 if (!definitely_matches) { 900 if (!definitely_matches) {
803 if (!code_constant.is_null()) { 901 if (!code_constant.is_null()) {
804 mov(r3, Operand(code_constant)); 902 mov(r3, Operand(code_constant));
805 add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag)); 903 add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag));
806 } 904 }
807 905
808 Handle<Code> adaptor = 906 Handle<Code> adaptor =
809 Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)); 907 Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline));
810 if (flag == CALL_FUNCTION) { 908 if (flag == CALL_FUNCTION) {
909 if (call_wrapper != NULL) {
910 call_wrapper->BeforeCall(CallSize(adaptor, RelocInfo::CODE_TARGET));
911 }
811 Call(adaptor, RelocInfo::CODE_TARGET); 912 Call(adaptor, RelocInfo::CODE_TARGET);
812 if (post_call_generator != NULL) post_call_generator->Generate(); 913 if (call_wrapper != NULL) call_wrapper->AfterCall();
813 b(done); 914 b(done);
814 } else { 915 } else {
815 Jump(adaptor, RelocInfo::CODE_TARGET); 916 Jump(adaptor, RelocInfo::CODE_TARGET);
816 } 917 }
817 bind(&regular_invoke); 918 bind(&regular_invoke);
818 } 919 }
819 } 920 }
820 921
821 922
822 void MacroAssembler::InvokeCode(Register code, 923 void MacroAssembler::InvokeCode(Register code,
823 const ParameterCount& expected, 924 const ParameterCount& expected,
824 const ParameterCount& actual, 925 const ParameterCount& actual,
825 InvokeFlag flag, 926 InvokeFlag flag,
826 PostCallGenerator* post_call_generator) { 927 CallWrapper* call_wrapper) {
827 Label done; 928 Label done;
828 929
829 InvokePrologue(expected, actual, Handle<Code>::null(), code, &done, flag, 930 InvokePrologue(expected, actual, Handle<Code>::null(), code, &done, flag,
830 post_call_generator); 931 call_wrapper);
831 if (flag == CALL_FUNCTION) { 932 if (flag == CALL_FUNCTION) {
933 if (call_wrapper != NULL) call_wrapper->BeforeCall(CallSize(code));
832 Call(code); 934 Call(code);
833 if (post_call_generator != NULL) post_call_generator->Generate(); 935 if (call_wrapper != NULL) call_wrapper->AfterCall();
834 } else { 936 } else {
835 ASSERT(flag == JUMP_FUNCTION); 937 ASSERT(flag == JUMP_FUNCTION);
836 Jump(code); 938 Jump(code);
837 } 939 }
838 940
839 // Continue here if InvokePrologue does handle the invocation due to 941 // Continue here if InvokePrologue does handle the invocation due to
840 // mismatched parameter counts. 942 // mismatched parameter counts.
841 bind(&done); 943 bind(&done);
842 } 944 }
843 945
(...skipping 14 matching lines...) Expand all
858 960
859 // Continue here if InvokePrologue does handle the invocation due to 961 // Continue here if InvokePrologue does handle the invocation due to
860 // mismatched parameter counts. 962 // mismatched parameter counts.
861 bind(&done); 963 bind(&done);
862 } 964 }
863 965
864 966
865 void MacroAssembler::InvokeFunction(Register fun, 967 void MacroAssembler::InvokeFunction(Register fun,
866 const ParameterCount& actual, 968 const ParameterCount& actual,
867 InvokeFlag flag, 969 InvokeFlag flag,
868 PostCallGenerator* post_call_generator) { 970 CallWrapper* call_wrapper) {
869 // Contract with called JS functions requires that function is passed in r1. 971 // Contract with called JS functions requires that function is passed in r1.
870 ASSERT(fun.is(r1)); 972 ASSERT(fun.is(r1));
871 973
872 Register expected_reg = r2; 974 Register expected_reg = r2;
873 Register code_reg = r3; 975 Register code_reg = r3;
874 976
875 ldr(code_reg, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); 977 ldr(code_reg, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
876 ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); 978 ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
877 ldr(expected_reg, 979 ldr(expected_reg,
878 FieldMemOperand(code_reg, 980 FieldMemOperand(code_reg,
879 SharedFunctionInfo::kFormalParameterCountOffset)); 981 SharedFunctionInfo::kFormalParameterCountOffset));
880 mov(expected_reg, Operand(expected_reg, ASR, kSmiTagSize)); 982 mov(expected_reg, Operand(expected_reg, ASR, kSmiTagSize));
881 ldr(code_reg, 983 ldr(code_reg,
882 FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); 984 FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
883 985
884 ParameterCount expected(expected_reg); 986 ParameterCount expected(expected_reg);
885 InvokeCode(code_reg, expected, actual, flag, post_call_generator); 987 InvokeCode(code_reg, expected, actual, flag, call_wrapper);
886 } 988 }
887 989
888 990
889 void MacroAssembler::InvokeFunction(JSFunction* function, 991 void MacroAssembler::InvokeFunction(JSFunction* function,
890 const ParameterCount& actual, 992 const ParameterCount& actual,
891 InvokeFlag flag) { 993 InvokeFlag flag) {
892 ASSERT(function->is_compiled()); 994 ASSERT(function->is_compiled());
893 995
894 // Get the function and setup the context. 996 // Get the function and setup the context.
895 mov(r1, Operand(Handle<JSFunction>(function))); 997 mov(r1, Operand(Handle<JSFunction>(function)));
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
1029 1131
1030 // Before returning we restore the context from the frame pointer if 1132 // Before returning we restore the context from the frame pointer if
1031 // not NULL. The frame pointer is NULL in the exception handler of a 1133 // not NULL. The frame pointer is NULL in the exception handler of a
1032 // JS entry frame. 1134 // JS entry frame.
1033 cmp(fp, Operand(0, RelocInfo::NONE)); 1135 cmp(fp, Operand(0, RelocInfo::NONE));
1034 // Set cp to NULL if fp is NULL. 1136 // Set cp to NULL if fp is NULL.
1035 mov(cp, Operand(0, RelocInfo::NONE), LeaveCC, eq); 1137 mov(cp, Operand(0, RelocInfo::NONE), LeaveCC, eq);
1036 // Restore cp otherwise. 1138 // Restore cp otherwise.
1037 ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne); 1139 ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne);
1038 #ifdef DEBUG 1140 #ifdef DEBUG
1039 if (FLAG_debug_code) { 1141 if (emit_debug_code()) {
1040 mov(lr, Operand(pc)); 1142 mov(lr, Operand(pc));
1041 } 1143 }
1042 #endif 1144 #endif
1043 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize); 1145 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize);
1044 pop(pc); 1146 pop(pc);
1045 } 1147 }
1046 1148
1047 1149
1048 void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type, 1150 void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type,
1049 Register value) { 1151 Register value) {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1102 ldm(ia_w, sp, r2.bit() | fp.bit()); // r2: discarded state. 1204 ldm(ia_w, sp, r2.bit() | fp.bit()); // r2: discarded state.
1103 // Before returning we restore the context from the frame pointer if 1205 // Before returning we restore the context from the frame pointer if
1104 // not NULL. The frame pointer is NULL in the exception handler of a 1206 // not NULL. The frame pointer is NULL in the exception handler of a
1105 // JS entry frame. 1207 // JS entry frame.
1106 cmp(fp, Operand(0, RelocInfo::NONE)); 1208 cmp(fp, Operand(0, RelocInfo::NONE));
1107 // Set cp to NULL if fp is NULL. 1209 // Set cp to NULL if fp is NULL.
1108 mov(cp, Operand(0, RelocInfo::NONE), LeaveCC, eq); 1210 mov(cp, Operand(0, RelocInfo::NONE), LeaveCC, eq);
1109 // Restore cp otherwise. 1211 // Restore cp otherwise.
1110 ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne); 1212 ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne);
1111 #ifdef DEBUG 1213 #ifdef DEBUG
1112 if (FLAG_debug_code) { 1214 if (emit_debug_code()) {
1113 mov(lr, Operand(pc)); 1215 mov(lr, Operand(pc));
1114 } 1216 }
1115 #endif 1217 #endif
1116 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize); 1218 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize);
1117 pop(pc); 1219 pop(pc);
1118 } 1220 }
1119 1221
1120 1222
1121 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, 1223 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
1122 Register scratch, 1224 Register scratch,
(...skipping 11 matching lines...) Expand all
1134 cmp(scratch, Operand(0, RelocInfo::NONE)); 1236 cmp(scratch, Operand(0, RelocInfo::NONE));
1135 Check(ne, "we should not have an empty lexical context"); 1237 Check(ne, "we should not have an empty lexical context");
1136 #endif 1238 #endif
1137 1239
1138 // Load the global context of the current context. 1240 // Load the global context of the current context.
1139 int offset = Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; 1241 int offset = Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
1140 ldr(scratch, FieldMemOperand(scratch, offset)); 1242 ldr(scratch, FieldMemOperand(scratch, offset));
1141 ldr(scratch, FieldMemOperand(scratch, GlobalObject::kGlobalContextOffset)); 1243 ldr(scratch, FieldMemOperand(scratch, GlobalObject::kGlobalContextOffset));
1142 1244
1143 // Check the context is a global context. 1245 // Check the context is a global context.
1144 if (FLAG_debug_code) { 1246 if (emit_debug_code()) {
1145 // TODO(119): avoid push(holder_reg)/pop(holder_reg) 1247 // TODO(119): avoid push(holder_reg)/pop(holder_reg)
1146 // Cannot use ip as a temporary in this verification code. Due to the fact 1248 // Cannot use ip as a temporary in this verification code. Due to the fact
1147 // that ip is clobbered as part of cmp with an object Operand. 1249 // that ip is clobbered as part of cmp with an object Operand.
1148 push(holder_reg); // Temporarily save holder on the stack. 1250 push(holder_reg); // Temporarily save holder on the stack.
1149 // Read the first word and compare to the global_context_map. 1251 // Read the first word and compare to the global_context_map.
1150 ldr(holder_reg, FieldMemOperand(scratch, HeapObject::kMapOffset)); 1252 ldr(holder_reg, FieldMemOperand(scratch, HeapObject::kMapOffset));
1151 LoadRoot(ip, Heap::kGlobalContextMapRootIndex); 1253 LoadRoot(ip, Heap::kGlobalContextMapRootIndex);
1152 cmp(holder_reg, ip); 1254 cmp(holder_reg, ip);
1153 Check(eq, "JSGlobalObject::global_context should be a global context."); 1255 Check(eq, "JSGlobalObject::global_context should be a global context.");
1154 pop(holder_reg); // Restore holder. 1256 pop(holder_reg); // Restore holder.
1155 } 1257 }
1156 1258
1157 // Check if both contexts are the same. 1259 // Check if both contexts are the same.
1158 ldr(ip, FieldMemOperand(holder_reg, JSGlobalProxy::kContextOffset)); 1260 ldr(ip, FieldMemOperand(holder_reg, JSGlobalProxy::kContextOffset));
1159 cmp(scratch, Operand(ip)); 1261 cmp(scratch, Operand(ip));
1160 b(eq, &same_contexts); 1262 b(eq, &same_contexts);
1161 1263
1162 // Check the context is a global context. 1264 // Check the context is a global context.
1163 if (FLAG_debug_code) { 1265 if (emit_debug_code()) {
1164 // TODO(119): avoid push(holder_reg)/pop(holder_reg) 1266 // TODO(119): avoid push(holder_reg)/pop(holder_reg)
1165 // Cannot use ip as a temporary in this verification code. Due to the fact 1267 // Cannot use ip as a temporary in this verification code. Due to the fact
1166 // that ip is clobbered as part of cmp with an object Operand. 1268 // that ip is clobbered as part of cmp with an object Operand.
1167 push(holder_reg); // Temporarily save holder on the stack. 1269 push(holder_reg); // Temporarily save holder on the stack.
1168 mov(holder_reg, ip); // Move ip to its holding place. 1270 mov(holder_reg, ip); // Move ip to its holding place.
1169 LoadRoot(ip, Heap::kNullValueRootIndex); 1271 LoadRoot(ip, Heap::kNullValueRootIndex);
1170 cmp(holder_reg, ip); 1272 cmp(holder_reg, ip);
1171 Check(ne, "JSGlobalProxy::context() should not be null."); 1273 Check(ne, "JSGlobalProxy::context() should not be null.");
1172 1274
1173 ldr(holder_reg, FieldMemOperand(holder_reg, HeapObject::kMapOffset)); 1275 ldr(holder_reg, FieldMemOperand(holder_reg, HeapObject::kMapOffset));
(...skipping 21 matching lines...) Expand all
1195 } 1297 }
1196 1298
1197 1299
1198 void MacroAssembler::AllocateInNewSpace(int object_size, 1300 void MacroAssembler::AllocateInNewSpace(int object_size,
1199 Register result, 1301 Register result,
1200 Register scratch1, 1302 Register scratch1,
1201 Register scratch2, 1303 Register scratch2,
1202 Label* gc_required, 1304 Label* gc_required,
1203 AllocationFlags flags) { 1305 AllocationFlags flags) {
1204 if (!FLAG_inline_new) { 1306 if (!FLAG_inline_new) {
1205 if (FLAG_debug_code) { 1307 if (emit_debug_code()) {
1206 // Trash the registers to simulate an allocation failure. 1308 // Trash the registers to simulate an allocation failure.
1207 mov(result, Operand(0x7091)); 1309 mov(result, Operand(0x7091));
1208 mov(scratch1, Operand(0x7191)); 1310 mov(scratch1, Operand(0x7191));
1209 mov(scratch2, Operand(0x7291)); 1311 mov(scratch2, Operand(0x7291));
1210 } 1312 }
1211 jmp(gc_required); 1313 jmp(gc_required);
1212 return; 1314 return;
1213 } 1315 }
1214 1316
1215 ASSERT(!result.is(scratch1)); 1317 ASSERT(!result.is(scratch1));
1216 ASSERT(!result.is(scratch2)); 1318 ASSERT(!result.is(scratch2));
1217 ASSERT(!scratch1.is(scratch2)); 1319 ASSERT(!scratch1.is(scratch2));
1320 ASSERT(!scratch1.is(ip));
1321 ASSERT(!scratch2.is(ip));
1218 1322
1219 // Make object size into bytes. 1323 // Make object size into bytes.
1220 if ((flags & SIZE_IN_WORDS) != 0) { 1324 if ((flags & SIZE_IN_WORDS) != 0) {
1221 object_size *= kPointerSize; 1325 object_size *= kPointerSize;
1222 } 1326 }
1223 ASSERT_EQ(0, object_size & kObjectAlignmentMask); 1327 ASSERT_EQ(0, object_size & kObjectAlignmentMask);
1224 1328
1225 // Check relative positions of allocation top and limit addresses. 1329 // Check relative positions of allocation top and limit addresses.
1226 // The values must be adjacent in memory to allow the use of LDM. 1330 // The values must be adjacent in memory to allow the use of LDM.
1227 // Also, assert that the registers are numbered such that the values 1331 // Also, assert that the registers are numbered such that the values
(...skipping 14 matching lines...) Expand all
1242 Register obj_size_reg = scratch2; 1346 Register obj_size_reg = scratch2;
1243 mov(topaddr, Operand(new_space_allocation_top)); 1347 mov(topaddr, Operand(new_space_allocation_top));
1244 mov(obj_size_reg, Operand(object_size)); 1348 mov(obj_size_reg, Operand(object_size));
1245 1349
1246 // This code stores a temporary value in ip. This is OK, as the code below 1350 // This code stores a temporary value in ip. This is OK, as the code below
1247 // does not need ip for implicit literal generation. 1351 // does not need ip for implicit literal generation.
1248 if ((flags & RESULT_CONTAINS_TOP) == 0) { 1352 if ((flags & RESULT_CONTAINS_TOP) == 0) {
1249 // Load allocation top into result and allocation limit into ip. 1353 // Load allocation top into result and allocation limit into ip.
1250 ldm(ia, topaddr, result.bit() | ip.bit()); 1354 ldm(ia, topaddr, result.bit() | ip.bit());
1251 } else { 1355 } else {
1252 if (FLAG_debug_code) { 1356 if (emit_debug_code()) {
1253 // Assert that result actually contains top on entry. ip is used 1357 // Assert that result actually contains top on entry. ip is used
1254 // immediately below so this use of ip does not cause difference with 1358 // immediately below so this use of ip does not cause difference with
1255 // respect to register content between debug and release mode. 1359 // respect to register content between debug and release mode.
1256 ldr(ip, MemOperand(topaddr)); 1360 ldr(ip, MemOperand(topaddr));
1257 cmp(result, ip); 1361 cmp(result, ip);
1258 Check(eq, "Unexpected allocation top"); 1362 Check(eq, "Unexpected allocation top");
1259 } 1363 }
1260 // Load allocation limit into ip. Result already contains allocation top. 1364 // Load allocation limit into ip. Result already contains allocation top.
1261 ldr(ip, MemOperand(topaddr, limit - top)); 1365 ldr(ip, MemOperand(topaddr, limit - top));
1262 } 1366 }
(...skipping 13 matching lines...) Expand all
1276 } 1380 }
1277 1381
1278 1382
1279 void MacroAssembler::AllocateInNewSpace(Register object_size, 1383 void MacroAssembler::AllocateInNewSpace(Register object_size,
1280 Register result, 1384 Register result,
1281 Register scratch1, 1385 Register scratch1,
1282 Register scratch2, 1386 Register scratch2,
1283 Label* gc_required, 1387 Label* gc_required,
1284 AllocationFlags flags) { 1388 AllocationFlags flags) {
1285 if (!FLAG_inline_new) { 1389 if (!FLAG_inline_new) {
1286 if (FLAG_debug_code) { 1390 if (emit_debug_code()) {
1287 // Trash the registers to simulate an allocation failure. 1391 // Trash the registers to simulate an allocation failure.
1288 mov(result, Operand(0x7091)); 1392 mov(result, Operand(0x7091));
1289 mov(scratch1, Operand(0x7191)); 1393 mov(scratch1, Operand(0x7191));
1290 mov(scratch2, Operand(0x7291)); 1394 mov(scratch2, Operand(0x7291));
1291 } 1395 }
1292 jmp(gc_required); 1396 jmp(gc_required);
1293 return; 1397 return;
1294 } 1398 }
1295 1399
1296 // Assert that the register arguments are different and that none of 1400 // Assert that the register arguments are different and that none of
(...skipping 23 matching lines...) Expand all
1320 // Set up allocation top address. 1424 // Set up allocation top address.
1321 Register topaddr = scratch1; 1425 Register topaddr = scratch1;
1322 mov(topaddr, Operand(new_space_allocation_top)); 1426 mov(topaddr, Operand(new_space_allocation_top));
1323 1427
1324 // This code stores a temporary value in ip. This is OK, as the code below 1428 // This code stores a temporary value in ip. This is OK, as the code below
1325 // does not need ip for implicit literal generation. 1429 // does not need ip for implicit literal generation.
1326 if ((flags & RESULT_CONTAINS_TOP) == 0) { 1430 if ((flags & RESULT_CONTAINS_TOP) == 0) {
1327 // Load allocation top into result and allocation limit into ip. 1431 // Load allocation top into result and allocation limit into ip.
1328 ldm(ia, topaddr, result.bit() | ip.bit()); 1432 ldm(ia, topaddr, result.bit() | ip.bit());
1329 } else { 1433 } else {
1330 if (FLAG_debug_code) { 1434 if (emit_debug_code()) {
1331 // Assert that result actually contains top on entry. ip is used 1435 // Assert that result actually contains top on entry. ip is used
1332 // immediately below so this use of ip does not cause difference with 1436 // immediately below so this use of ip does not cause difference with
1333 // respect to register content between debug and release mode. 1437 // respect to register content between debug and release mode.
1334 ldr(ip, MemOperand(topaddr)); 1438 ldr(ip, MemOperand(topaddr));
1335 cmp(result, ip); 1439 cmp(result, ip);
1336 Check(eq, "Unexpected allocation top"); 1440 Check(eq, "Unexpected allocation top");
1337 } 1441 }
1338 // Load allocation limit into ip. Result already contains allocation top. 1442 // Load allocation limit into ip. Result already contains allocation top.
1339 ldr(ip, MemOperand(topaddr, limit - top)); 1443 ldr(ip, MemOperand(topaddr, limit - top));
1340 } 1444 }
1341 1445
1342 // Calculate new top and bail out if new space is exhausted. Use result 1446 // Calculate new top and bail out if new space is exhausted. Use result
1343 // to calculate the new top. Object size may be in words so a shift is 1447 // to calculate the new top. Object size may be in words so a shift is
1344 // required to get the number of bytes. 1448 // required to get the number of bytes.
1345 if ((flags & SIZE_IN_WORDS) != 0) { 1449 if ((flags & SIZE_IN_WORDS) != 0) {
1346 add(scratch2, result, Operand(object_size, LSL, kPointerSizeLog2), SetCC); 1450 add(scratch2, result, Operand(object_size, LSL, kPointerSizeLog2), SetCC);
1347 } else { 1451 } else {
1348 add(scratch2, result, Operand(object_size), SetCC); 1452 add(scratch2, result, Operand(object_size), SetCC);
1349 } 1453 }
1350 b(cs, gc_required); 1454 b(cs, gc_required);
1351 cmp(scratch2, Operand(ip)); 1455 cmp(scratch2, Operand(ip));
1352 b(hi, gc_required); 1456 b(hi, gc_required);
1353 1457
1354 // Update allocation top. result temporarily holds the new top. 1458 // Update allocation top. result temporarily holds the new top.
1355 if (FLAG_debug_code) { 1459 if (emit_debug_code()) {
1356 tst(scratch2, Operand(kObjectAlignmentMask)); 1460 tst(scratch2, Operand(kObjectAlignmentMask));
1357 Check(eq, "Unaligned allocation in new space"); 1461 Check(eq, "Unaligned allocation in new space");
1358 } 1462 }
1359 str(scratch2, MemOperand(topaddr)); 1463 str(scratch2, MemOperand(topaddr));
1360 1464
1361 // Tag object if requested. 1465 // Tag object if requested.
1362 if ((flags & TAG_OBJECT) != 0) { 1466 if ((flags & TAG_OBJECT) != 0) {
1363 add(result, result, Operand(kHeapObjectTag)); 1467 add(result, result, Operand(kHeapObjectTag));
1364 } 1468 }
1365 } 1469 }
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
1497 1601
1498 1602
1499 void MacroAssembler::CompareInstanceType(Register map, 1603 void MacroAssembler::CompareInstanceType(Register map,
1500 Register type_reg, 1604 Register type_reg,
1501 InstanceType type) { 1605 InstanceType type) {
1502 ldrb(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset)); 1606 ldrb(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset));
1503 cmp(type_reg, Operand(type)); 1607 cmp(type_reg, Operand(type));
1504 } 1608 }
1505 1609
1506 1610
1611 void MacroAssembler::CompareRoot(Register obj,
1612 Heap::RootListIndex index) {
1613 ASSERT(!obj.is(ip));
1614 LoadRoot(ip, index);
1615 cmp(obj, ip);
1616 }
1617
1618
1507 void MacroAssembler::CheckMap(Register obj, 1619 void MacroAssembler::CheckMap(Register obj,
1508 Register scratch, 1620 Register scratch,
1509 Handle<Map> map, 1621 Handle<Map> map,
1510 Label* fail, 1622 Label* fail,
1511 bool is_heap_object) { 1623 bool is_heap_object) {
1512 if (!is_heap_object) { 1624 if (!is_heap_object) {
1513 JumpIfSmi(obj, fail); 1625 JumpIfSmi(obj, fail);
1514 } 1626 }
1515 ldr(scratch, FieldMemOperand(obj, HeapObject::kMapOffset)); 1627 ldr(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
1516 mov(ip, Operand(map)); 1628 mov(ip, Operand(map));
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
1603 return result; 1715 return result;
1604 } 1716 }
1605 1717
1606 1718
1607 static int AddressOffset(ExternalReference ref0, ExternalReference ref1) { 1719 static int AddressOffset(ExternalReference ref0, ExternalReference ref1) {
1608 return ref0.address() - ref1.address(); 1720 return ref0.address() - ref1.address();
1609 } 1721 }
1610 1722
1611 1723
1612 MaybeObject* MacroAssembler::TryCallApiFunctionAndReturn( 1724 MaybeObject* MacroAssembler::TryCallApiFunctionAndReturn(
1613 ApiFunction* function, int stack_space) { 1725 ExternalReference function, int stack_space) {
1614 ExternalReference next_address = 1726 ExternalReference next_address =
1615 ExternalReference::handle_scope_next_address(); 1727 ExternalReference::handle_scope_next_address();
1616 const int kNextOffset = 0; 1728 const int kNextOffset = 0;
1617 const int kLimitOffset = AddressOffset( 1729 const int kLimitOffset = AddressOffset(
1618 ExternalReference::handle_scope_limit_address(), 1730 ExternalReference::handle_scope_limit_address(),
1619 next_address); 1731 next_address);
1620 const int kLevelOffset = AddressOffset( 1732 const int kLevelOffset = AddressOffset(
1621 ExternalReference::handle_scope_level_address(), 1733 ExternalReference::handle_scope_level_address(),
1622 next_address); 1734 next_address);
1623 1735
(...skipping 17 matching lines...) Expand all
1641 1753
1642 // If result is non-zero, dereference to get the result value 1754 // If result is non-zero, dereference to get the result value
1643 // otherwise set it to undefined. 1755 // otherwise set it to undefined.
1644 cmp(r0, Operand(0)); 1756 cmp(r0, Operand(0));
1645 LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); 1757 LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq);
1646 ldr(r0, MemOperand(r0), ne); 1758 ldr(r0, MemOperand(r0), ne);
1647 1759
1648 // No more valid handles (the result handle was the last one). Restore 1760 // No more valid handles (the result handle was the last one). Restore
1649 // previous handle scope. 1761 // previous handle scope.
1650 str(r4, MemOperand(r7, kNextOffset)); 1762 str(r4, MemOperand(r7, kNextOffset));
1651 if (FLAG_debug_code) { 1763 if (emit_debug_code()) {
1652 ldr(r1, MemOperand(r7, kLevelOffset)); 1764 ldr(r1, MemOperand(r7, kLevelOffset));
1653 cmp(r1, r6); 1765 cmp(r1, r6);
1654 Check(eq, "Unexpected level after return from api call"); 1766 Check(eq, "Unexpected level after return from api call");
1655 } 1767 }
1656 sub(r6, r6, Operand(1)); 1768 sub(r6, r6, Operand(1));
1657 str(r6, MemOperand(r7, kLevelOffset)); 1769 str(r6, MemOperand(r7, kLevelOffset));
1658 ldr(ip, MemOperand(r7, kLimitOffset)); 1770 ldr(ip, MemOperand(r7, kLimitOffset));
1659 cmp(r5, ip); 1771 cmp(r5, ip);
1660 b(ne, &delete_allocated_handles); 1772 b(ne, &delete_allocated_handles);
1661 1773
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
1803 // This code is faster for doubles that are in the ranges -0x7fffffff to 1915 // This code is faster for doubles that are in the ranges -0x7fffffff to
1804 // -0x40000000 or 0x40000000 to 0x7fffffff. This corresponds almost to 1916 // -0x40000000 or 0x40000000 to 0x7fffffff. This corresponds almost to
1805 // the range of signed int32 values that are not Smis. Jumps to the label 1917 // the range of signed int32 values that are not Smis. Jumps to the label
1806 // 'not_int32' if the double isn't in the range -0x80000000.0 to 1918 // 'not_int32' if the double isn't in the range -0x80000000.0 to
1807 // 0x80000000.0 (excluding the endpoints). 1919 // 0x80000000.0 (excluding the endpoints).
1808 Label right_exponent, done; 1920 Label right_exponent, done;
1809 // Get exponent word. 1921 // Get exponent word.
1810 ldr(scratch, FieldMemOperand(source, HeapNumber::kExponentOffset)); 1922 ldr(scratch, FieldMemOperand(source, HeapNumber::kExponentOffset));
1811 // Get exponent alone in scratch2. 1923 // Get exponent alone in scratch2.
1812 Ubfx(scratch2, 1924 Ubfx(scratch2,
1813 scratch, 1925 scratch,
1814 HeapNumber::kExponentShift, 1926 HeapNumber::kExponentShift,
1815 HeapNumber::kExponentBits); 1927 HeapNumber::kExponentBits);
1816 // Load dest with zero. We use this either for the final shift or 1928 // Load dest with zero. We use this either for the final shift or
1817 // for the answer. 1929 // for the answer.
1818 mov(dest, Operand(0, RelocInfo::NONE)); 1930 mov(dest, Operand(0, RelocInfo::NONE));
1819 // Check whether the exponent matches a 32 bit signed int that is not a Smi. 1931 // Check whether the exponent matches a 32 bit signed int that is not a Smi.
1820 // A non-Smi integer is 1.xxx * 2^30 so the exponent is 30 (biased). This is 1932 // A non-Smi integer is 1.xxx * 2^30 so the exponent is 30 (biased). This is
1821 // the exponent that we are fastest at and also the highest exponent we can 1933 // the exponent that we are fastest at and also the highest exponent we can
1822 // handle here. 1934 // handle here.
1823 const uint32_t non_smi_exponent = HeapNumber::kExponentBias + 30; 1935 const uint32_t non_smi_exponent = HeapNumber::kExponentBias + 30;
1824 // The non_smi_exponent, 0x41d, is too big for ARM's immediate field so we 1936 // The non_smi_exponent, 0x41d, is too big for ARM's immediate field so we
1825 // split it up to avoid a constant pool entry. You can't do that in general 1937 // split it up to avoid a constant pool entry. You can't do that in general
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1868 orr(scratch, scratch2, Operand(scratch, LSR, 32 - shift_distance)); 1980 orr(scratch, scratch2, Operand(scratch, LSR, 32 - shift_distance));
1869 // Move down according to the exponent. 1981 // Move down according to the exponent.
1870 mov(dest, Operand(scratch, LSR, dest)); 1982 mov(dest, Operand(scratch, LSR, dest));
1871 // Fix sign if sign bit was set. 1983 // Fix sign if sign bit was set.
1872 rsb(dest, dest, Operand(0, RelocInfo::NONE), LeaveCC, ne); 1984 rsb(dest, dest, Operand(0, RelocInfo::NONE), LeaveCC, ne);
1873 bind(&done); 1985 bind(&done);
1874 } 1986 }
1875 } 1987 }
1876 1988
1877 1989
1990 void MacroAssembler::EmitVFPTruncate(VFPRoundingMode rounding_mode,
1991 SwVfpRegister result,
1992 DwVfpRegister double_input,
1993 Register scratch1,
1994 Register scratch2,
1995 CheckForInexactConversion check_inexact) {
1996 ASSERT(CpuFeatures::IsSupported(VFP3));
1997 CpuFeatures::Scope scope(VFP3);
1998 Register prev_fpscr = scratch1;
1999 Register scratch = scratch2;
2000
2001 int32_t check_inexact_conversion =
2002 (check_inexact == kCheckForInexactConversion) ? kVFPInexactExceptionBit : 0;
2003
2004 // Set custom FPCSR:
2005 // - Set rounding mode.
2006 // - Clear vfp cumulative exception flags.
2007 // - Make sure Flush-to-zero mode control bit is unset.
2008 vmrs(prev_fpscr);
2009 bic(scratch,
2010 prev_fpscr,
2011 Operand(kVFPExceptionMask |
2012 check_inexact_conversion |
2013 kVFPRoundingModeMask |
2014 kVFPFlushToZeroMask));
2015 // 'Round To Nearest' is encoded by 0b00 so no bits need to be set.
2016 if (rounding_mode != kRoundToNearest) {
2017 orr(scratch, scratch, Operand(rounding_mode));
2018 }
2019 vmsr(scratch);
2020
2021 // Convert the argument to an integer.
2022 vcvt_s32_f64(result,
2023 double_input,
2024 (rounding_mode == kRoundToZero) ? kDefaultRoundToZero
2025 : kFPSCRRounding);
2026
2027 // Retrieve FPSCR.
2028 vmrs(scratch);
2029 // Restore FPSCR.
2030 vmsr(prev_fpscr);
2031 // Check for vfp exceptions.
2032 tst(scratch, Operand(kVFPExceptionMask | check_inexact_conversion));
2033 }
2034
2035
2036 void MacroAssembler::EmitOutOfInt32RangeTruncate(Register result,
2037 Register input_high,
2038 Register input_low,
2039 Register scratch) {
2040 Label done, normal_exponent, restore_sign;
2041
2042 // Extract the biased exponent in result.
2043 Ubfx(result,
2044 input_high,
2045 HeapNumber::kExponentShift,
2046 HeapNumber::kExponentBits);
2047
2048 // Check for Infinity and NaNs, which should return 0.
2049 cmp(result, Operand(HeapNumber::kExponentMask));
2050 mov(result, Operand(0), LeaveCC, eq);
2051 b(eq, &done);
2052
2053 // Express exponent as delta to (number of mantissa bits + 31).
2054 sub(result,
2055 result,
2056 Operand(HeapNumber::kExponentBias + HeapNumber::kMantissaBits + 31),
2057 SetCC);
2058
2059 // If the delta is strictly positive, all bits would be shifted away,
2060 // which means that we can return 0.
2061 b(le, &normal_exponent);
2062 mov(result, Operand(0));
2063 b(&done);
2064
2065 bind(&normal_exponent);
2066 const int kShiftBase = HeapNumber::kNonMantissaBitsInTopWord - 1;
2067 // Calculate shift.
2068 add(scratch, result, Operand(kShiftBase + HeapNumber::kMantissaBits), SetCC);
2069
2070 // Save the sign.
2071 Register sign = result;
2072 result = no_reg;
2073 and_(sign, input_high, Operand(HeapNumber::kSignMask));
2074
2075 // Set the implicit 1 before the mantissa part in input_high.
2076 orr(input_high,
2077 input_high,
2078 Operand(1 << HeapNumber::kMantissaBitsInTopWord));
2079 // Shift the mantissa bits to the correct position.
2080 // We don't need to clear non-mantissa bits as they will be shifted away.
2081 // If they weren't, it would mean that the answer is in the 32bit range.
2082 mov(input_high, Operand(input_high, LSL, scratch));
2083
2084 // Replace the shifted bits with bits from the lower mantissa word.
2085 Label pos_shift, shift_done;
2086 rsb(scratch, scratch, Operand(32), SetCC);
2087 b(&pos_shift, ge);
2088
2089 // Negate scratch.
2090 rsb(scratch, scratch, Operand(0));
2091 mov(input_low, Operand(input_low, LSL, scratch));
2092 b(&shift_done);
2093
2094 bind(&pos_shift);
2095 mov(input_low, Operand(input_low, LSR, scratch));
2096
2097 bind(&shift_done);
2098 orr(input_high, input_high, Operand(input_low));
2099 // Restore sign if necessary.
2100 cmp(sign, Operand(0));
2101 result = sign;
2102 sign = no_reg;
2103 rsb(result, input_high, Operand(0), LeaveCC, ne);
2104 mov(result, input_high, LeaveCC, eq);
2105 bind(&done);
2106 }
2107
2108
2109 void MacroAssembler::EmitECMATruncate(Register result,
2110 DwVfpRegister double_input,
2111 SwVfpRegister single_scratch,
2112 Register scratch,
2113 Register input_high,
2114 Register input_low) {
2115 CpuFeatures::Scope scope(VFP3);
2116 ASSERT(!input_high.is(result));
2117 ASSERT(!input_low.is(result));
2118 ASSERT(!input_low.is(input_high));
2119 ASSERT(!scratch.is(result) &&
2120 !scratch.is(input_high) &&
2121 !scratch.is(input_low));
2122 ASSERT(!single_scratch.is(double_input.low()) &&
2123 !single_scratch.is(double_input.high()));
2124
2125 Label done;
2126
2127 // Clear cumulative exception flags.
2128 ClearFPSCRBits(kVFPExceptionMask, scratch);
2129 // Try a conversion to a signed integer.
2130 vcvt_s32_f64(single_scratch, double_input);
2131 vmov(result, single_scratch);
2132 // Retrieve he FPSCR.
2133 vmrs(scratch);
2134 // Check for overflow and NaNs.
2135 tst(scratch, Operand(kVFPOverflowExceptionBit |
2136 kVFPUnderflowExceptionBit |
2137 kVFPInvalidOpExceptionBit));
2138 // If we had no exceptions we are done.
2139 b(eq, &done);
2140
2141 // Load the double value and perform a manual truncation.
2142 vmov(input_low, input_high, double_input);
2143 EmitOutOfInt32RangeTruncate(result,
2144 input_high,
2145 input_low,
2146 scratch);
2147 bind(&done);
2148 }
2149
2150
1878 void MacroAssembler::GetLeastBitsFromSmi(Register dst, 2151 void MacroAssembler::GetLeastBitsFromSmi(Register dst,
1879 Register src, 2152 Register src,
1880 int num_least_bits) { 2153 int num_least_bits) {
1881 if (CpuFeatures::IsSupported(ARMv7)) { 2154 if (CpuFeatures::IsSupported(ARMv7)) {
1882 ubfx(dst, src, kSmiTagSize, num_least_bits); 2155 ubfx(dst, src, kSmiTagSize, num_least_bits);
1883 } else { 2156 } else {
1884 mov(dst, Operand(src, ASR, kSmiTagSize)); 2157 mov(dst, Operand(src, ASR, kSmiTagSize));
1885 and_(dst, dst, Operand((1 << num_least_bits) - 1)); 2158 and_(dst, dst, Operand((1 << num_least_bits) - 1));
1886 } 2159 }
1887 } 2160 }
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
1989 ASSERT((reinterpret_cast<intptr_t>(builtin.address()) & 1) == 1); 2262 ASSERT((reinterpret_cast<intptr_t>(builtin.address()) & 1) == 1);
1990 #endif 2263 #endif
1991 mov(r1, Operand(builtin)); 2264 mov(r1, Operand(builtin));
1992 CEntryStub stub(1); 2265 CEntryStub stub(1);
1993 return TryTailCallStub(&stub); 2266 return TryTailCallStub(&stub);
1994 } 2267 }
1995 2268
1996 2269
1997 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, 2270 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id,
1998 InvokeJSFlags flags, 2271 InvokeJSFlags flags,
1999 PostCallGenerator* post_call_generator) { 2272 CallWrapper* call_wrapper) {
2000 GetBuiltinEntry(r2, id); 2273 GetBuiltinEntry(r2, id);
2001 if (flags == CALL_JS) { 2274 if (flags == CALL_JS) {
2275 if (call_wrapper != NULL) call_wrapper->BeforeCall(CallSize(r2));
2002 Call(r2); 2276 Call(r2);
2003 if (post_call_generator != NULL) post_call_generator->Generate(); 2277 if (call_wrapper != NULL) call_wrapper->AfterCall();
2004 } else { 2278 } else {
2005 ASSERT(flags == JUMP_JS); 2279 ASSERT(flags == JUMP_JS);
2006 Jump(r2); 2280 Jump(r2);
2007 } 2281 }
2008 } 2282 }
2009 2283
2010 2284
2011 void MacroAssembler::GetBuiltinFunction(Register target, 2285 void MacroAssembler::GetBuiltinFunction(Register target,
2012 Builtins::JavaScript id) { 2286 Builtins::JavaScript id) {
2013 // Load the builtins object into target register. 2287 // Load the builtins object into target register.
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
2055 if (FLAG_native_code_counters && counter->Enabled()) { 2329 if (FLAG_native_code_counters && counter->Enabled()) {
2056 mov(scratch2, Operand(ExternalReference(counter))); 2330 mov(scratch2, Operand(ExternalReference(counter)));
2057 ldr(scratch1, MemOperand(scratch2)); 2331 ldr(scratch1, MemOperand(scratch2));
2058 sub(scratch1, scratch1, Operand(value)); 2332 sub(scratch1, scratch1, Operand(value));
2059 str(scratch1, MemOperand(scratch2)); 2333 str(scratch1, MemOperand(scratch2));
2060 } 2334 }
2061 } 2335 }
2062 2336
2063 2337
2064 void MacroAssembler::Assert(Condition cond, const char* msg) { 2338 void MacroAssembler::Assert(Condition cond, const char* msg) {
2065 if (FLAG_debug_code) 2339 if (emit_debug_code())
2066 Check(cond, msg); 2340 Check(cond, msg);
2067 } 2341 }
2068 2342
2069 2343
2070 void MacroAssembler::AssertRegisterIsRoot(Register reg, 2344 void MacroAssembler::AssertRegisterIsRoot(Register reg,
2071 Heap::RootListIndex index) { 2345 Heap::RootListIndex index) {
2072 if (FLAG_debug_code) { 2346 if (emit_debug_code()) {
2073 LoadRoot(ip, index); 2347 LoadRoot(ip, index);
2074 cmp(reg, ip); 2348 cmp(reg, ip);
2075 Check(eq, "Register did not match expected root"); 2349 Check(eq, "Register did not match expected root");
2076 } 2350 }
2077 } 2351 }
2078 2352
2079 2353
2080 void MacroAssembler::AssertFastElements(Register elements) { 2354 void MacroAssembler::AssertFastElements(Register elements) {
2081 if (FLAG_debug_code) { 2355 if (emit_debug_code()) {
2082 ASSERT(!elements.is(ip)); 2356 ASSERT(!elements.is(ip));
2083 Label ok; 2357 Label ok;
2084 push(elements); 2358 push(elements);
2085 ldr(elements, FieldMemOperand(elements, HeapObject::kMapOffset)); 2359 ldr(elements, FieldMemOperand(elements, HeapObject::kMapOffset));
2086 LoadRoot(ip, Heap::kFixedArrayMapRootIndex); 2360 LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
2087 cmp(elements, ip); 2361 cmp(elements, ip);
2088 b(eq, &ok); 2362 b(eq, &ok);
2089 LoadRoot(ip, Heap::kFixedCOWArrayMapRootIndex); 2363 LoadRoot(ip, Heap::kFixedCOWArrayMapRootIndex);
2090 cmp(elements, ip); 2364 cmp(elements, ip);
2091 b(eq, &ok); 2365 b(eq, &ok);
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
2148 void MacroAssembler::LoadContext(Register dst, int context_chain_length) { 2422 void MacroAssembler::LoadContext(Register dst, int context_chain_length) {
2149 if (context_chain_length > 0) { 2423 if (context_chain_length > 0) {
2150 // Move up the chain of contexts to the context containing the slot. 2424 // Move up the chain of contexts to the context containing the slot.
2151 ldr(dst, MemOperand(cp, Context::SlotOffset(Context::CLOSURE_INDEX))); 2425 ldr(dst, MemOperand(cp, Context::SlotOffset(Context::CLOSURE_INDEX)));
2152 // Load the function context (which is the incoming, outer context). 2426 // Load the function context (which is the incoming, outer context).
2153 ldr(dst, FieldMemOperand(dst, JSFunction::kContextOffset)); 2427 ldr(dst, FieldMemOperand(dst, JSFunction::kContextOffset));
2154 for (int i = 1; i < context_chain_length; i++) { 2428 for (int i = 1; i < context_chain_length; i++) {
2155 ldr(dst, MemOperand(dst, Context::SlotOffset(Context::CLOSURE_INDEX))); 2429 ldr(dst, MemOperand(dst, Context::SlotOffset(Context::CLOSURE_INDEX)));
2156 ldr(dst, FieldMemOperand(dst, JSFunction::kContextOffset)); 2430 ldr(dst, FieldMemOperand(dst, JSFunction::kContextOffset));
2157 } 2431 }
2158 // The context may be an intermediate context, not a function context. 2432 } else {
2159 ldr(dst, MemOperand(dst, Context::SlotOffset(Context::FCONTEXT_INDEX))); 2433 // Slot is in the current function context. Move it into the
2160 } else { // Slot is in the current function context. 2434 // destination register in case we store into it (the write barrier
2161 // The context may be an intermediate context, not a function context. 2435 // cannot be allowed to destroy the context in esi).
2162 ldr(dst, MemOperand(cp, Context::SlotOffset(Context::FCONTEXT_INDEX))); 2436 mov(dst, cp);
2437 }
2438
2439 // We should not have found a 'with' context by walking the context chain
2440 // (i.e., the static scope chain and runtime context chain do not agree).
2441 // A variable occurring in such a scope should have slot type LOOKUP and
2442 // not CONTEXT.
2443 if (emit_debug_code()) {
2444 ldr(ip, MemOperand(dst, Context::SlotOffset(Context::FCONTEXT_INDEX)));
2445 cmp(dst, ip);
2446 Check(eq, "Yo dawg, I heard you liked function contexts "
2447 "so I put function contexts in all your contexts");
2163 } 2448 }
2164 } 2449 }
2165 2450
2166 2451
2167 void MacroAssembler::LoadGlobalFunction(int index, Register function) { 2452 void MacroAssembler::LoadGlobalFunction(int index, Register function) {
2168 // Load the global or builtins object from the current context. 2453 // Load the global or builtins object from the current context.
2169 ldr(function, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); 2454 ldr(function, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
2170 // Load the global context from the global or builtins object. 2455 // Load the global context from the global or builtins object.
2171 ldr(function, FieldMemOperand(function, 2456 ldr(function, FieldMemOperand(function,
2172 GlobalObject::kGlobalContextOffset)); 2457 GlobalObject::kGlobalContextOffset));
2173 // Load the function from the global context. 2458 // Load the function from the global context.
2174 ldr(function, MemOperand(function, Context::SlotOffset(index))); 2459 ldr(function, MemOperand(function, Context::SlotOffset(index)));
2175 } 2460 }
2176 2461
2177 2462
2178 void MacroAssembler::LoadGlobalFunctionInitialMap(Register function, 2463 void MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
2179 Register map, 2464 Register map,
2180 Register scratch) { 2465 Register scratch) {
2181 // Load the initial map. The global functions all have initial maps. 2466 // Load the initial map. The global functions all have initial maps.
2182 ldr(map, FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); 2467 ldr(map, FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
2183 if (FLAG_debug_code) { 2468 if (emit_debug_code()) {
2184 Label ok, fail; 2469 Label ok, fail;
2185 CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, false); 2470 CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, false);
2186 b(&ok); 2471 b(&ok);
2187 bind(&fail); 2472 bind(&fail);
2188 Abort("Global functions must have initial map"); 2473 Abort("Global functions must have initial map");
2189 bind(&ok); 2474 bind(&ok);
2190 } 2475 }
2191 } 2476 }
2192 2477
2193 2478
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
2245 CompareInstanceType(object, object, FIRST_NONSTRING_TYPE); 2530 CompareInstanceType(object, object, FIRST_NONSTRING_TYPE);
2246 pop(object); 2531 pop(object);
2247 Assert(lo, "Operand is not a string"); 2532 Assert(lo, "Operand is not a string");
2248 } 2533 }
2249 2534
2250 2535
2251 2536
2252 void MacroAssembler::AbortIfNotRootValue(Register src, 2537 void MacroAssembler::AbortIfNotRootValue(Register src,
2253 Heap::RootListIndex root_value_index, 2538 Heap::RootListIndex root_value_index,
2254 const char* message) { 2539 const char* message) {
2255 ASSERT(!src.is(ip)); 2540 CompareRoot(src, root_value_index);
2256 LoadRoot(ip, root_value_index);
2257 cmp(src, ip);
2258 Assert(eq, message); 2541 Assert(eq, message);
2259 } 2542 }
2260 2543
2261 2544
2262 void MacroAssembler::JumpIfNotHeapNumber(Register object, 2545 void MacroAssembler::JumpIfNotHeapNumber(Register object,
2263 Register heap_number_map, 2546 Register heap_number_map,
2264 Register scratch, 2547 Register scratch,
2265 Label* on_not_heap_number) { 2548 Label* on_not_heap_number) {
2266 ldr(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); 2549 ldr(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
2267 AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); 2550 AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
2363 } 2646 }
2364 ASSERT(!tmp.is(no_reg)); 2647 ASSERT(!tmp.is(no_reg));
2365 2648
2366 for (int i = 0; i < field_count; i++) { 2649 for (int i = 0; i < field_count; i++) {
2367 ldr(tmp, FieldMemOperand(src, i * kPointerSize)); 2650 ldr(tmp, FieldMemOperand(src, i * kPointerSize));
2368 str(tmp, FieldMemOperand(dst, i * kPointerSize)); 2651 str(tmp, FieldMemOperand(dst, i * kPointerSize));
2369 } 2652 }
2370 } 2653 }
2371 2654
2372 2655
2656 void MacroAssembler::CopyBytes(Register src,
2657 Register dst,
2658 Register length,
2659 Register scratch) {
2660 Label align_loop, align_loop_1, word_loop, byte_loop, byte_loop_1, done;
2661
2662 // Align src before copying in word size chunks.
2663 bind(&align_loop);
2664 cmp(length, Operand(0));
2665 b(eq, &done);
2666 bind(&align_loop_1);
2667 tst(src, Operand(kPointerSize - 1));
2668 b(eq, &word_loop);
2669 ldrb(scratch, MemOperand(src, 1, PostIndex));
2670 strb(scratch, MemOperand(dst, 1, PostIndex));
2671 sub(length, length, Operand(1), SetCC);
2672 b(ne, &byte_loop_1);
2673
2674 // Copy bytes in word size chunks.
2675 bind(&word_loop);
2676 if (emit_debug_code()) {
2677 tst(src, Operand(kPointerSize - 1));
2678 Assert(eq, "Expecting alignment for CopyBytes");
2679 }
2680 cmp(length, Operand(kPointerSize));
2681 b(lt, &byte_loop);
2682 ldr(scratch, MemOperand(src, kPointerSize, PostIndex));
2683 #if CAN_USE_UNALIGNED_ACCESSES
2684 str(scratch, MemOperand(dst, kPointerSize, PostIndex));
2685 #else
2686 strb(scratch, MemOperand(dst, 1, PostIndex));
2687 mov(scratch, Operand(scratch, LSR, 8));
2688 strb(scratch, MemOperand(dst, 1, PostIndex));
2689 mov(scratch, Operand(scratch, LSR, 8));
2690 strb(scratch, MemOperand(dst, 1, PostIndex));
2691 mov(scratch, Operand(scratch, LSR, 8));
2692 strb(scratch, MemOperand(dst, 1, PostIndex));
2693 #endif
2694 sub(length, length, Operand(kPointerSize));
2695 b(&word_loop);
2696
2697 // Copy the last bytes if any left.
2698 bind(&byte_loop);
2699 cmp(length, Operand(0));
2700 b(eq, &done);
2701 bind(&byte_loop_1);
2702 ldrb(scratch, MemOperand(src, 1, PostIndex));
2703 strb(scratch, MemOperand(dst, 1, PostIndex));
2704 sub(length, length, Operand(1), SetCC);
2705 b(ne, &byte_loop_1);
2706 bind(&done);
2707 }
2708
2709
2373 void MacroAssembler::CountLeadingZeros(Register zeros, // Answer. 2710 void MacroAssembler::CountLeadingZeros(Register zeros, // Answer.
2374 Register source, // Input. 2711 Register source, // Input.
2375 Register scratch) { 2712 Register scratch) {
2376 ASSERT(!zeros.is(source) || !source.is(scratch)); 2713 ASSERT(!zeros.is(source) || !source.is(scratch));
2377 ASSERT(!zeros.is(scratch)); 2714 ASSERT(!zeros.is(scratch));
2378 ASSERT(!scratch.is(ip)); 2715 ASSERT(!scratch.is(ip));
2379 ASSERT(!source.is(ip)); 2716 ASSERT(!source.is(ip));
2380 ASSERT(!zeros.is(ip)); 2717 ASSERT(!zeros.is(ip));
2381 #ifdef CAN_USE_ARMV5_INSTRUCTIONS 2718 #ifdef CAN_USE_ARMV5_INSTRUCTIONS
2382 clz(zeros, source); // This instruction is only supported after ARM5. 2719 clz(zeros, source); // This instruction is only supported after ARM5.
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
2459 mov(ip, Operand(function)); 2796 mov(ip, Operand(function));
2460 CallCFunction(ip, num_arguments); 2797 CallCFunction(ip, num_arguments);
2461 } 2798 }
2462 2799
2463 2800
2464 void MacroAssembler::CallCFunction(Register function, int num_arguments) { 2801 void MacroAssembler::CallCFunction(Register function, int num_arguments) {
2465 // Make sure that the stack is aligned before calling a C function unless 2802 // Make sure that the stack is aligned before calling a C function unless
2466 // running in the simulator. The simulator has its own alignment check which 2803 // running in the simulator. The simulator has its own alignment check which
2467 // provides more information. 2804 // provides more information.
2468 #if defined(V8_HOST_ARCH_ARM) 2805 #if defined(V8_HOST_ARCH_ARM)
2469 if (FLAG_debug_code) { 2806 if (emit_debug_code()) {
2470 int frame_alignment = OS::ActivationFrameAlignment(); 2807 int frame_alignment = OS::ActivationFrameAlignment();
2471 int frame_alignment_mask = frame_alignment - 1; 2808 int frame_alignment_mask = frame_alignment - 1;
2472 if (frame_alignment > kPointerSize) { 2809 if (frame_alignment > kPointerSize) {
2473 ASSERT(IsPowerOf2(frame_alignment)); 2810 ASSERT(IsPowerOf2(frame_alignment));
2474 Label alignment_as_expected; 2811 Label alignment_as_expected;
2475 tst(sp, Operand(frame_alignment_mask)); 2812 tst(sp, Operand(frame_alignment_mask));
2476 b(eq, &alignment_as_expected); 2813 b(eq, &alignment_as_expected);
2477 // Don't use Check here, as it will call Runtime_Abort possibly 2814 // Don't use Check here, as it will call Runtime_Abort possibly
2478 // re-entering here. 2815 // re-entering here.
2479 stop("Unexpected alignment"); 2816 stop("Unexpected alignment");
(...skipping 13 matching lines...) Expand all
2493 add(sp, sp, Operand(stack_passed_arguments * sizeof(kPointerSize))); 2830 add(sp, sp, Operand(stack_passed_arguments * sizeof(kPointerSize)));
2494 } 2831 }
2495 } 2832 }
2496 2833
2497 2834
2498 void MacroAssembler::GetRelocatedValueLocation(Register ldr_location, 2835 void MacroAssembler::GetRelocatedValueLocation(Register ldr_location,
2499 Register result) { 2836 Register result) {
2500 const uint32_t kLdrOffsetMask = (1 << 12) - 1; 2837 const uint32_t kLdrOffsetMask = (1 << 12) - 1;
2501 const int32_t kPCRegOffset = 2 * kPointerSize; 2838 const int32_t kPCRegOffset = 2 * kPointerSize;
2502 ldr(result, MemOperand(ldr_location)); 2839 ldr(result, MemOperand(ldr_location));
2503 if (FLAG_debug_code) { 2840 if (emit_debug_code()) {
2504 // Check that the instruction is a ldr reg, [pc + offset] . 2841 // Check that the instruction is a ldr reg, [pc + offset] .
2505 and_(result, result, Operand(kLdrPCPattern)); 2842 and_(result, result, Operand(kLdrPCPattern));
2506 cmp(result, Operand(kLdrPCPattern)); 2843 cmp(result, Operand(kLdrPCPattern));
2507 Check(eq, "The instruction to patch should be a load from pc."); 2844 Check(eq, "The instruction to patch should be a load from pc.");
2508 // Result was clobbered. Restore it. 2845 // Result was clobbered. Restore it.
2509 ldr(result, MemOperand(ldr_location)); 2846 ldr(result, MemOperand(ldr_location));
2510 } 2847 }
2511 // Get the address of the constant. 2848 // Get the address of the constant.
2512 and_(result, result, Operand(kLdrOffsetMask)); 2849 and_(result, result, Operand(kLdrOffsetMask));
2513 add(result, ldr_location, Operand(result)); 2850 add(result, ldr_location, Operand(result));
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
2550 void CodePatcher::EmitCondition(Condition cond) { 2887 void CodePatcher::EmitCondition(Condition cond) {
2551 Instr instr = Assembler::instr_at(masm_.pc_); 2888 Instr instr = Assembler::instr_at(masm_.pc_);
2552 instr = (instr & ~kCondMask) | cond; 2889 instr = (instr & ~kCondMask) | cond;
2553 masm_.emit(instr); 2890 masm_.emit(instr);
2554 } 2891 }
2555 2892
2556 2893
2557 } } // namespace v8::internal 2894 } } // namespace v8::internal
2558 2895
2559 #endif // V8_TARGET_ARCH_ARM 2896 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/macro-assembler-arm.h ('k') | src/arm/simulator-arm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698