| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 124 #ifdef _MSC_VER | 124 #ifdef _MSC_VER |
| 125 void LCodeGen::MakeSureStackPagesMapped(int offset) { | 125 void LCodeGen::MakeSureStackPagesMapped(int offset) { |
| 126 const int kPageSize = 4 * KB; | 126 const int kPageSize = 4 * KB; |
| 127 for (offset -= kPageSize; offset > 0; offset -= kPageSize) { | 127 for (offset -= kPageSize; offset > 0; offset -= kPageSize) { |
| 128 __ movq(Operand(rsp, offset), rax); | 128 __ movq(Operand(rsp, offset), rax); |
| 129 } | 129 } |
| 130 } | 130 } |
| 131 #endif | 131 #endif |
| 132 | 132 |
| 133 | 133 |
| 134 void LCodeGen::SaveCallerDoubles() { |
| 135 ASSERT(info()->saves_caller_doubles()); |
| 136 ASSERT(NeedsEagerFrame()); |
| 137 Comment(";;; Save clobbered callee double registers"); |
| 138 int count = 0; |
| 139 BitVector* doubles = chunk()->allocated_double_registers(); |
| 140 BitVector::Iterator save_iterator(doubles); |
| 141 while (!save_iterator.Done()) { |
| 142 __ movsd(MemOperand(rsp, count * kDoubleSize), |
| 143 XMMRegister::FromAllocationIndex(save_iterator.Current())); |
| 144 save_iterator.Advance(); |
| 145 count++; |
| 146 } |
| 147 } |
| 148 |
| 149 |
| 150 void LCodeGen::RestoreCallerDoubles() { |
| 151 ASSERT(info()->saves_caller_doubles()); |
| 152 ASSERT(NeedsEagerFrame()); |
| 153 Comment(";;; Restore clobbered callee double registers"); |
| 154 BitVector* doubles = chunk()->allocated_double_registers(); |
| 155 BitVector::Iterator save_iterator(doubles); |
| 156 int count = 0; |
| 157 while (!save_iterator.Done()) { |
| 158 __ movsd(XMMRegister::FromAllocationIndex(save_iterator.Current()), |
| 159 MemOperand(rsp, count * kDoubleSize)); |
| 160 save_iterator.Advance(); |
| 161 count++; |
| 162 } |
| 163 } |
| 164 |
| 165 |
| 134 bool LCodeGen::GeneratePrologue() { | 166 bool LCodeGen::GeneratePrologue() { |
| 135 ASSERT(is_generating()); | 167 ASSERT(is_generating()); |
| 136 | 168 |
| 137 if (info()->IsOptimizing()) { | 169 if (info()->IsOptimizing()) { |
| 138 ProfileEntryHookStub::MaybeCallEntryHook(masm_); | 170 ProfileEntryHookStub::MaybeCallEntryHook(masm_); |
| 139 | 171 |
| 140 #ifdef DEBUG | 172 #ifdef DEBUG |
| 141 if (strlen(FLAG_stop_at) > 0 && | 173 if (strlen(FLAG_stop_at) > 0 && |
| 142 info_->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { | 174 info_->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { |
| 143 __ int3(); | 175 __ int3(); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 194 __ j(not_zero, &loop); | 226 __ j(not_zero, &loop); |
| 195 __ pop(rax); | 227 __ pop(rax); |
| 196 } else { | 228 } else { |
| 197 __ subq(rsp, Immediate(slots * kPointerSize)); | 229 __ subq(rsp, Immediate(slots * kPointerSize)); |
| 198 #ifdef _MSC_VER | 230 #ifdef _MSC_VER |
| 199 MakeSureStackPagesMapped(slots * kPointerSize); | 231 MakeSureStackPagesMapped(slots * kPointerSize); |
| 200 #endif | 232 #endif |
| 201 } | 233 } |
| 202 | 234 |
| 203 if (info()->saves_caller_doubles()) { | 235 if (info()->saves_caller_doubles()) { |
| 204 Comment(";;; Save clobbered callee double registers"); | 236 SaveCallerDoubles(); |
| 205 int count = 0; | |
| 206 BitVector* doubles = chunk()->allocated_double_registers(); | |
| 207 BitVector::Iterator save_iterator(doubles); | |
| 208 while (!save_iterator.Done()) { | |
| 209 __ movsd(MemOperand(rsp, count * kDoubleSize), | |
| 210 XMMRegister::FromAllocationIndex(save_iterator.Current())); | |
| 211 save_iterator.Advance(); | |
| 212 count++; | |
| 213 } | |
| 214 } | 237 } |
| 215 } | 238 } |
| 216 | 239 |
| 217 // Possibly allocate a local context. | 240 // Possibly allocate a local context. |
| 218 int heap_slots = info_->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 241 int heap_slots = info_->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
| 219 if (heap_slots > 0) { | 242 if (heap_slots > 0) { |
| 220 Comment(";;; Allocate local context"); | 243 Comment(";;; Allocate local context"); |
| 221 // Argument to NewContext is the function, which is still in rdi. | 244 // Argument to NewContext is the function, which is still in rdi. |
| 222 __ push(rdi); | 245 __ push(rdi); |
| 223 if (heap_slots <= FastNewContextStub::kMaximumSlots) { | 246 if (heap_slots <= FastNewContextStub::kMaximumSlots) { |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 312 __ bind(&jump_table_[i].label); | 335 __ bind(&jump_table_[i].label); |
| 313 Address entry = jump_table_[i].address; | 336 Address entry = jump_table_[i].address; |
| 314 Deoptimizer::BailoutType type = jump_table_[i].bailout_type; | 337 Deoptimizer::BailoutType type = jump_table_[i].bailout_type; |
| 315 int id = Deoptimizer::GetDeoptimizationId(isolate(), entry, type); | 338 int id = Deoptimizer::GetDeoptimizationId(isolate(), entry, type); |
| 316 if (id == Deoptimizer::kNotDeoptimizationEntry) { | 339 if (id == Deoptimizer::kNotDeoptimizationEntry) { |
| 317 Comment(";;; jump table entry %d.", i); | 340 Comment(";;; jump table entry %d.", i); |
| 318 } else { | 341 } else { |
| 319 Comment(";;; jump table entry %d: deoptimization bailout %d.", i, id); | 342 Comment(";;; jump table entry %d: deoptimization bailout %d.", i, id); |
| 320 } | 343 } |
| 321 if (jump_table_[i].needs_frame) { | 344 if (jump_table_[i].needs_frame) { |
| 345 ASSERT(!info()->saves_caller_doubles()); |
| 322 __ movq(kScratchRegister, ExternalReference::ForDeoptEntry(entry)); | 346 __ movq(kScratchRegister, ExternalReference::ForDeoptEntry(entry)); |
| 323 if (needs_frame.is_bound()) { | 347 if (needs_frame.is_bound()) { |
| 324 __ jmp(&needs_frame); | 348 __ jmp(&needs_frame); |
| 325 } else { | 349 } else { |
| 326 __ bind(&needs_frame); | 350 __ bind(&needs_frame); |
| 327 __ push(rbp); | 351 __ push(rbp); |
| 328 __ movq(rbp, rsp); | 352 __ movq(rbp, rsp); |
| 329 __ push(rsi); | 353 __ push(rsi); |
| 330 // This variant of deopt can only be used with stubs. Since we don't | 354 // This variant of deopt can only be used with stubs. Since we don't |
| 331 // have a function pointer to install in the stack frame that we're | 355 // have a function pointer to install in the stack frame that we're |
| 332 // building, install a special marker there instead. | 356 // building, install a special marker there instead. |
| 333 ASSERT(info()->IsStub()); | 357 ASSERT(info()->IsStub()); |
| 334 __ Move(rsi, Smi::FromInt(StackFrame::STUB)); | 358 __ Move(rsi, Smi::FromInt(StackFrame::STUB)); |
| 335 __ push(rsi); | 359 __ push(rsi); |
| 336 __ movq(rsi, MemOperand(rsp, kPointerSize)); | 360 __ movq(rsi, MemOperand(rsp, kPointerSize)); |
| 337 __ call(kScratchRegister); | 361 __ call(kScratchRegister); |
| 338 } | 362 } |
| 339 } else { | 363 } else { |
| 364 if (info()->saves_caller_doubles()) { |
| 365 ASSERT(info()->IsStub()); |
| 366 RestoreCallerDoubles(); |
| 367 } |
| 340 __ call(entry, RelocInfo::RUNTIME_ENTRY); | 368 __ call(entry, RelocInfo::RUNTIME_ENTRY); |
| 341 } | 369 } |
| 342 } | 370 } |
| 343 return !is_aborted(); | 371 return !is_aborted(); |
| 344 } | 372 } |
| 345 | 373 |
| 346 | 374 |
| 347 bool LCodeGen::GenerateDeferredCode() { | 375 bool LCodeGen::GenerateDeferredCode() { |
| 348 ASSERT(is_generating()); | 376 ASSERT(is_generating()); |
| 349 if (deferred_.length() > 0) { | 377 if (deferred_.length() > 0) { |
| (...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 713 if (info()->ShouldTrapOnDeopt()) { | 741 if (info()->ShouldTrapOnDeopt()) { |
| 714 Label done; | 742 Label done; |
| 715 if (cc != no_condition) { | 743 if (cc != no_condition) { |
| 716 __ j(NegateCondition(cc), &done, Label::kNear); | 744 __ j(NegateCondition(cc), &done, Label::kNear); |
| 717 } | 745 } |
| 718 __ int3(); | 746 __ int3(); |
| 719 __ bind(&done); | 747 __ bind(&done); |
| 720 } | 748 } |
| 721 | 749 |
| 722 ASSERT(info()->IsStub() || frame_is_built_); | 750 ASSERT(info()->IsStub() || frame_is_built_); |
| 723 if (cc == no_condition && frame_is_built_) { | 751 // Go through jump table if we need to handle condition, build frame, or |
| 752 // restore caller doubles. |
| 753 if (cc == no_condition && frame_is_built_ && |
| 754 !info()->saves_caller_doubles()) { |
| 724 __ call(entry, RelocInfo::RUNTIME_ENTRY); | 755 __ call(entry, RelocInfo::RUNTIME_ENTRY); |
| 725 } else { | 756 } else { |
| 726 // We often have several deopts to the same entry, reuse the last | 757 // We often have several deopts to the same entry, reuse the last |
| 727 // jump entry if this is the case. | 758 // jump entry if this is the case. |
| 728 if (jump_table_.is_empty() || | 759 if (jump_table_.is_empty() || |
| 729 jump_table_.last().address != entry || | 760 jump_table_.last().address != entry || |
| 730 jump_table_.last().needs_frame != !frame_is_built_ || | 761 jump_table_.last().needs_frame != !frame_is_built_ || |
| 731 jump_table_.last().bailout_type != bailout_type) { | 762 jump_table_.last().bailout_type != bailout_type) { |
| 732 Deoptimizer::JumpTableEntry table_entry(entry, | 763 Deoptimizer::JumpTableEntry table_entry(entry, |
| 733 bailout_type, | 764 bailout_type, |
| (...skipping 1903 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2637 | 2668 |
| 2638 | 2669 |
| 2639 void LCodeGen::DoReturn(LReturn* instr) { | 2670 void LCodeGen::DoReturn(LReturn* instr) { |
| 2640 if (FLAG_trace && info()->IsOptimizing()) { | 2671 if (FLAG_trace && info()->IsOptimizing()) { |
| 2641 // Preserve the return value on the stack and rely on the runtime | 2672 // Preserve the return value on the stack and rely on the runtime |
| 2642 // call to return the value in the same register. | 2673 // call to return the value in the same register. |
| 2643 __ push(rax); | 2674 __ push(rax); |
| 2644 __ CallRuntime(Runtime::kTraceExit, 1); | 2675 __ CallRuntime(Runtime::kTraceExit, 1); |
| 2645 } | 2676 } |
| 2646 if (info()->saves_caller_doubles()) { | 2677 if (info()->saves_caller_doubles()) { |
| 2647 ASSERT(NeedsEagerFrame()); | 2678 RestoreCallerDoubles(); |
| 2648 BitVector* doubles = chunk()->allocated_double_registers(); | |
| 2649 BitVector::Iterator save_iterator(doubles); | |
| 2650 int count = 0; | |
| 2651 while (!save_iterator.Done()) { | |
| 2652 __ movsd(XMMRegister::FromAllocationIndex(save_iterator.Current()), | |
| 2653 MemOperand(rsp, count * kDoubleSize)); | |
| 2654 save_iterator.Advance(); | |
| 2655 count++; | |
| 2656 } | |
| 2657 } | 2679 } |
| 2658 int no_frame_start = -1; | 2680 int no_frame_start = -1; |
| 2659 if (NeedsEagerFrame()) { | 2681 if (NeedsEagerFrame()) { |
| 2660 __ movq(rsp, rbp); | 2682 __ movq(rsp, rbp); |
| 2661 __ pop(rbp); | 2683 __ pop(rbp); |
| 2662 no_frame_start = masm_->pc_offset(); | 2684 no_frame_start = masm_->pc_offset(); |
| 2663 } | 2685 } |
| 2664 if (instr->has_constant_parameter_count()) { | 2686 if (instr->has_constant_parameter_count()) { |
| 2665 __ Ret((ToInteger32(instr->constant_parameter_count()) + 1) * kPointerSize, | 2687 __ Ret((ToInteger32(instr->constant_parameter_count()) + 1) * kPointerSize, |
| 2666 rcx); | 2688 rcx); |
| (...skipping 2842 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5509 FixedArray::kHeaderSize - kPointerSize)); | 5531 FixedArray::kHeaderSize - kPointerSize)); |
| 5510 __ bind(&done); | 5532 __ bind(&done); |
| 5511 } | 5533 } |
| 5512 | 5534 |
| 5513 | 5535 |
| 5514 #undef __ | 5536 #undef __ |
| 5515 | 5537 |
| 5516 } } // namespace v8::internal | 5538 } } // namespace v8::internal |
| 5517 | 5539 |
| 5518 #endif // V8_TARGET_ARCH_X64 | 5540 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |