OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #if V8_TARGET_ARCH_IA32 | 5 #if V8_TARGET_ARCH_IA32 |
6 | 6 |
7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
8 #include "src/base/division-by-constant.h" | 8 #include "src/base/division-by-constant.h" |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
113 DCHECK(isolate()->heap()->RootCanBeTreatedAsConstant(index)); | 113 DCHECK(isolate()->heap()->RootCanBeTreatedAsConstant(index)); |
114 cmp(with, isolate()->heap()->root_handle(index)); | 114 cmp(with, isolate()->heap()->root_handle(index)); |
115 } | 115 } |
116 | 116 |
117 | 117 |
118 void MacroAssembler::PushRoot(Heap::RootListIndex index) { | 118 void MacroAssembler::PushRoot(Heap::RootListIndex index) { |
119 DCHECK(isolate()->heap()->RootCanBeTreatedAsConstant(index)); | 119 DCHECK(isolate()->heap()->RootCanBeTreatedAsConstant(index)); |
120 Push(isolate()->heap()->root_handle(index)); | 120 Push(isolate()->heap()->root_handle(index)); |
121 } | 121 } |
122 | 122 |
| 123 #define REG(Name) \ |
| 124 { Register::kCode_##Name } |
| 125 |
| 126 static const Register saved_regs[] = {REG(eax), REG(ecx), REG(edx)}; |
| 127 |
| 128 #undef REG |
| 129 |
| 130 static const int kNumberOfSavedRegs = sizeof(saved_regs) / sizeof(Register); |
| 131 |
| 132 void MacroAssembler::PushCallerSaved(SaveFPRegsMode fp_mode, |
| 133 Register exclusion1, Register exclusion2, |
| 134 Register exclusion3) { |
| 135 // We don't allow a GC during a store buffer overflow so there is no need to |
| 136 // store the registers in any particular way, but we do have to store and |
| 137 // restore them. |
| 138 for (int i = 0; i < kNumberOfSavedRegs; i++) { |
| 139 Register reg = saved_regs[i]; |
| 140 if (!reg.is(exclusion1) && !reg.is(exclusion2) && !reg.is(exclusion3)) { |
| 141 push(reg); |
| 142 } |
| 143 } |
| 144 if (fp_mode == kSaveFPRegs) { |
| 145 sub(esp, Immediate(kDoubleSize * (XMMRegister::kMaxNumRegisters - 1))); |
| 146 // Save all XMM registers except XMM0. |
| 147 for (int i = XMMRegister::kMaxNumRegisters - 1; i > 0; i--) { |
| 148 XMMRegister reg = XMMRegister::from_code(i); |
| 149 movsd(Operand(esp, (i - 1) * kDoubleSize), reg); |
| 150 } |
| 151 } |
| 152 } |
| 153 |
| 154 void MacroAssembler::PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1, |
| 155 Register exclusion2, Register exclusion3) { |
| 156 if (fp_mode == kSaveFPRegs) { |
| 157 // Restore all XMM registers except XMM0. |
| 158 for (int i = XMMRegister::kMaxNumRegisters - 1; i > 0; i--) { |
| 159 XMMRegister reg = XMMRegister::from_code(i); |
| 160 movsd(reg, Operand(esp, (i - 1) * kDoubleSize)); |
| 161 } |
| 162 add(esp, Immediate(kDoubleSize * (XMMRegister::kMaxNumRegisters - 1))); |
| 163 } |
| 164 |
| 165 for (int i = kNumberOfSavedRegs - 1; i >= 0; i--) { |
| 166 Register reg = saved_regs[i]; |
| 167 if (!reg.is(exclusion1) && !reg.is(exclusion2) && !reg.is(exclusion3)) { |
| 168 pop(reg); |
| 169 } |
| 170 } |
| 171 } |
123 | 172 |
124 void MacroAssembler::InNewSpace( | 173 void MacroAssembler::InNewSpace( |
125 Register object, | 174 Register object, |
126 Register scratch, | 175 Register scratch, |
127 Condition cc, | 176 Condition cc, |
128 Label* condition_met, | 177 Label* condition_met, |
129 Label::Distance condition_met_distance) { | 178 Label::Distance condition_met_distance) { |
130 DCHECK(cc == equal || cc == not_equal); | 179 DCHECK(cc == equal || cc == not_equal); |
131 if (scratch.is(object)) { | 180 if (scratch.is(object)) { |
132 and_(scratch, Immediate(~Page::kPageAlignmentMask)); | 181 and_(scratch, Immediate(~Page::kPageAlignmentMask)); |
(...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
564 IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1); | 613 IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1); |
565 | 614 |
566 // Clobber clobbered registers when running with the debug-code flag | 615 // Clobber clobbered registers when running with the debug-code flag |
567 // turned on to provoke errors. | 616 // turned on to provoke errors. |
568 if (emit_debug_code()) { | 617 if (emit_debug_code()) { |
569 mov(address, Immediate(bit_cast<int32_t>(kZapValue))); | 618 mov(address, Immediate(bit_cast<int32_t>(kZapValue))); |
570 mov(value, Immediate(bit_cast<int32_t>(kZapValue))); | 619 mov(value, Immediate(bit_cast<int32_t>(kZapValue))); |
571 } | 620 } |
572 } | 621 } |
573 | 622 |
| 623 void MacroAssembler::RecordWriteCodeEntryField(Register js_function, |
| 624 Register code_entry, |
| 625 Register scratch) { |
| 626 const int offset = JSFunction::kCodeEntryOffset; |
| 627 |
| 628 // Since a code entry (value) is always in old space, we don't need to update |
| 629 // remembered set. If incremental marking is off, there is nothing for us to |
| 630 // do. |
| 631 if (!FLAG_incremental_marking) return; |
| 632 |
| 633 DCHECK(!js_function.is(code_entry)); |
| 634 DCHECK(!js_function.is(scratch)); |
| 635 DCHECK(!code_entry.is(scratch)); |
| 636 AssertNotSmi(js_function); |
| 637 |
| 638 if (emit_debug_code()) { |
| 639 Label ok; |
| 640 lea(scratch, FieldOperand(js_function, offset)); |
| 641 cmp(code_entry, Operand(scratch, 0)); |
| 642 j(equal, &ok, Label::kNear); |
| 643 int3(); |
| 644 bind(&ok); |
| 645 } |
| 646 |
| 647 // First, check if a write barrier is even needed. The tests below |
| 648 // catch stores of Smis and stores into young gen. |
| 649 Label done; |
| 650 |
| 651 CheckPageFlag(code_entry, scratch, |
| 652 MemoryChunk::kPointersToHereAreInterestingMask, zero, &done, |
| 653 Label::kNear); |
| 654 CheckPageFlag(js_function, scratch, |
| 655 MemoryChunk::kPointersFromHereAreInterestingMask, zero, &done, |
| 656 Label::kNear); |
| 657 |
| 658 // Save input registers. |
| 659 push(js_function); |
| 660 push(code_entry); |
| 661 |
| 662 const Register dst = scratch; |
| 663 lea(dst, FieldOperand(js_function, offset)); |
| 664 |
| 665 // Save caller-saved registers. |
| 666 PushCallerSaved(kDontSaveFPRegs, js_function, code_entry); |
| 667 |
| 668 int argument_count = 3; |
| 669 PrepareCallCFunction(argument_count, code_entry); |
| 670 mov(Operand(esp, 0 * kPointerSize), js_function); |
| 671 mov(Operand(esp, 1 * kPointerSize), dst); // Slot. |
| 672 mov(Operand(esp, 2 * kPointerSize), |
| 673 Immediate(ExternalReference::isolate_address(isolate()))); |
| 674 |
| 675 { |
| 676 AllowExternalCallThatCantCauseGC scope(this); |
| 677 CallCFunction( |
| 678 ExternalReference::incremental_marking_record_write_code_entry_function( |
| 679 isolate()), |
| 680 argument_count); |
| 681 } |
| 682 |
| 683 // Restore caller-saved registers. |
| 684 PopCallerSaved(kDontSaveFPRegs, js_function, code_entry); |
| 685 |
| 686 // Restore input registers. |
| 687 pop(code_entry); |
| 688 pop(js_function); |
| 689 |
| 690 bind(&done); |
| 691 } |
574 | 692 |
575 void MacroAssembler::DebugBreak() { | 693 void MacroAssembler::DebugBreak() { |
576 Move(eax, Immediate(0)); | 694 Move(eax, Immediate(0)); |
577 mov(ebx, Immediate(ExternalReference(Runtime::kHandleDebuggerStatement, | 695 mov(ebx, Immediate(ExternalReference(Runtime::kHandleDebuggerStatement, |
578 isolate()))); | 696 isolate()))); |
579 CEntryStub ces(isolate(), 1); | 697 CEntryStub ces(isolate(), 1); |
580 call(ces.GetCode(), RelocInfo::DEBUGGER_STATEMENT); | 698 call(ces.GetCode(), RelocInfo::DEBUGGER_STATEMENT); |
581 } | 699 } |
582 | 700 |
583 | 701 |
(...skipping 2512 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3096 mov(eax, dividend); | 3214 mov(eax, dividend); |
3097 shr(eax, 31); | 3215 shr(eax, 31); |
3098 add(edx, eax); | 3216 add(edx, eax); |
3099 } | 3217 } |
3100 | 3218 |
3101 | 3219 |
3102 } // namespace internal | 3220 } // namespace internal |
3103 } // namespace v8 | 3221 } // namespace v8 |
3104 | 3222 |
3105 #endif // V8_TARGET_ARCH_IA32 | 3223 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |