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

Side by Side Diff: src/ia32/deoptimizer-ia32.cc

Issue 8139027: Version 3.6.5 (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
Patch Set: '' Created 9 years, 2 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/ia32/debug-ia32.cc ('k') | src/ia32/disasm-ia32.cc » ('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 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 factory->NewByteArray(reloc_length + padding, TENURED); 109 factory->NewByteArray(reloc_length + padding, TENURED);
110 memcpy(new_reloc->GetDataStartAddress() + padding, 110 memcpy(new_reloc->GetDataStartAddress() + padding,
111 code->relocation_info()->GetDataStartAddress(), 111 code->relocation_info()->GetDataStartAddress(),
112 reloc_length); 112 reloc_length);
113 // Create a relocation writer to write the comments in the padding 113 // Create a relocation writer to write the comments in the padding
114 // space. Use position 0 for everything to ensure short encoding. 114 // space. Use position 0 for everything to ensure short encoding.
115 RelocInfoWriter reloc_info_writer( 115 RelocInfoWriter reloc_info_writer(
116 new_reloc->GetDataStartAddress() + padding, 0); 116 new_reloc->GetDataStartAddress() + padding, 0);
117 intptr_t comment_string 117 intptr_t comment_string
118 = reinterpret_cast<intptr_t>(RelocInfo::kFillerCommentString); 118 = reinterpret_cast<intptr_t>(RelocInfo::kFillerCommentString);
119 RelocInfo rinfo(0, RelocInfo::COMMENT, comment_string); 119 RelocInfo rinfo(0, RelocInfo::COMMENT, comment_string, NULL);
120 for (int i = 0; i < additional_comments; ++i) { 120 for (int i = 0; i < additional_comments; ++i) {
121 #ifdef DEBUG 121 #ifdef DEBUG
122 byte* pos_before = reloc_info_writer.pos(); 122 byte* pos_before = reloc_info_writer.pos();
123 #endif 123 #endif
124 reloc_info_writer.Write(&rinfo); 124 reloc_info_writer.Write(&rinfo);
125 ASSERT(RelocInfo::kMinRelocCommentSize == 125 ASSERT(RelocInfo::kMinRelocCommentSize ==
126 pos_before - reloc_info_writer.pos()); 126 pos_before - reloc_info_writer.pos());
127 } 127 }
128 // Replace relocation information on the code object. 128 // Replace relocation information on the code object.
129 code->set_relocation_info(*new_reloc); 129 code->set_relocation_info(*new_reloc);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 // The gap code is needed to get to the state expected at the bailout. 167 // The gap code is needed to get to the state expected at the bailout.
168 curr_address += safepoint_entry.gap_code_size(); 168 curr_address += safepoint_entry.gap_code_size();
169 169
170 CodePatcher patcher(curr_address, patch_size()); 170 CodePatcher patcher(curr_address, patch_size());
171 Address deopt_entry = GetDeoptimizationEntry(deoptimization_index, LAZY); 171 Address deopt_entry = GetDeoptimizationEntry(deoptimization_index, LAZY);
172 patcher.masm()->call(deopt_entry, RelocInfo::NONE); 172 patcher.masm()->call(deopt_entry, RelocInfo::NONE);
173 173
174 // We use RUNTIME_ENTRY for deoptimization bailouts. 174 // We use RUNTIME_ENTRY for deoptimization bailouts.
175 RelocInfo rinfo(curr_address + 1, // 1 after the call opcode. 175 RelocInfo rinfo(curr_address + 1, // 1 after the call opcode.
176 RelocInfo::RUNTIME_ENTRY, 176 RelocInfo::RUNTIME_ENTRY,
177 reinterpret_cast<intptr_t>(deopt_entry)); 177 reinterpret_cast<intptr_t>(deopt_entry),
178 NULL);
178 reloc_info_writer.Write(&rinfo); 179 reloc_info_writer.Write(&rinfo);
179 ASSERT_GE(reloc_info_writer.pos(), 180 ASSERT_GE(reloc_info_writer.pos(),
180 reloc_info->address() + ByteArray::kHeaderSize); 181 reloc_info->address() + ByteArray::kHeaderSize);
181 curr_address += patch_size(); 182 curr_address += patch_size();
182 } 183 }
183 prev_address = curr_address; 184 prev_address = curr_address;
184 } 185 }
185 ZapCodeRange(prev_address, 186 ZapCodeRange(prev_address,
186 code_start_address + code->safepoint_table_offset()); 187 code_start_address + code->safepoint_table_offset());
187 188
(...skipping 10 matching lines...) Expand all
198 ASSERT(junk_address <= reloc_end_address); 199 ASSERT(junk_address <= reloc_end_address);
199 isolate->heap()->CreateFillerObjectAt(junk_address, 200 isolate->heap()->CreateFillerObjectAt(junk_address,
200 reloc_end_address - junk_address); 201 reloc_end_address - junk_address);
201 202
202 // Add the deoptimizing code to the list. 203 // Add the deoptimizing code to the list.
203 DeoptimizingCodeListNode* node = new DeoptimizingCodeListNode(code); 204 DeoptimizingCodeListNode* node = new DeoptimizingCodeListNode(code);
204 DeoptimizerData* data = isolate->deoptimizer_data(); 205 DeoptimizerData* data = isolate->deoptimizer_data();
205 node->set_next(data->deoptimizing_code_list_); 206 node->set_next(data->deoptimizing_code_list_);
206 data->deoptimizing_code_list_ = node; 207 data->deoptimizing_code_list_ = node;
207 208
209 // We might be in the middle of incremental marking with compaction.
210 // Tell collector to treat this code object in a special way and
211 // ignore all slots that might have been recorded on it.
212 isolate->heap()->mark_compact_collector()->InvalidateCode(code);
213
208 // Set the code for the function to non-optimized version. 214 // Set the code for the function to non-optimized version.
209 function->ReplaceCode(function->shared()->code()); 215 function->ReplaceCode(function->shared()->code());
210 216
211 if (FLAG_trace_deopt) { 217 if (FLAG_trace_deopt) {
212 PrintF("[forced deoptimization: "); 218 PrintF("[forced deoptimization: ");
213 function->PrintName(); 219 function->PrintName();
214 PrintF(" / %x]\n", reinterpret_cast<uint32_t>(function)); 220 PrintF(" / %x]\n", reinterpret_cast<uint32_t>(function));
215 #ifdef DEBUG 221 #ifdef DEBUG
216 if (FLAG_print_code) { 222 if (FLAG_print_code) {
217 code->PrintLn(); 223 code->PrintLn();
218 } 224 }
219 #endif 225 #endif
220 } 226 }
221 } 227 }
222 228
223 229
224 void Deoptimizer::PatchStackCheckCodeAt(Address pc_after, 230 void Deoptimizer::PatchStackCheckCodeAt(Code* unoptimized_code,
231 Address pc_after,
225 Code* check_code, 232 Code* check_code,
226 Code* replacement_code) { 233 Code* replacement_code) {
227 Address call_target_address = pc_after - kIntSize; 234 Address call_target_address = pc_after - kIntSize;
228 ASSERT(check_code->entry() == 235 ASSERT(check_code->entry() ==
229 Assembler::target_address_at(call_target_address)); 236 Assembler::target_address_at(call_target_address));
230 // The stack check code matches the pattern: 237 // The stack check code matches the pattern:
231 // 238 //
232 // cmp esp, <limit> 239 // cmp esp, <limit>
233 // jae ok 240 // jae ok
234 // call <stack guard> 241 // call <stack guard>
235 // test eax, <loop nesting depth> 242 // test eax, <loop nesting depth>
236 // ok: ... 243 // ok: ...
237 // 244 //
238 // We will patch away the branch so the code is: 245 // We will patch away the branch so the code is:
239 // 246 //
240 // cmp esp, <limit> ;; Not changed 247 // cmp esp, <limit> ;; Not changed
241 // nop 248 // nop
242 // nop 249 // nop
243 // call <on-stack replacment> 250 // call <on-stack replacment>
244 // test eax, <loop nesting depth> 251 // test eax, <loop nesting depth>
245 // ok: 252 // ok:
246 ASSERT(*(call_target_address - 3) == 0x73 && // jae 253 ASSERT(*(call_target_address - 3) == 0x73 && // jae
247 *(call_target_address - 2) == 0x07 && // offset 254 *(call_target_address - 2) == 0x07 && // offset
248 *(call_target_address - 1) == 0xe8); // call 255 *(call_target_address - 1) == 0xe8); // call
249 *(call_target_address - 3) = 0x90; // nop 256 *(call_target_address - 3) = 0x90; // nop
250 *(call_target_address - 2) = 0x90; // nop 257 *(call_target_address - 2) = 0x90; // nop
251 Assembler::set_target_address_at(call_target_address, 258 Assembler::set_target_address_at(call_target_address,
252 replacement_code->entry()); 259 replacement_code->entry());
260
261 RelocInfo rinfo(call_target_address,
262 RelocInfo::CODE_TARGET,
263 0,
264 unoptimized_code);
265 unoptimized_code->GetHeap()->incremental_marking()->RecordWriteIntoCode(
266 unoptimized_code, &rinfo, replacement_code);
253 } 267 }
254 268
255 269
256 void Deoptimizer::RevertStackCheckCodeAt(Address pc_after, 270 void Deoptimizer::RevertStackCheckCodeAt(Address pc_after,
257 Code* check_code, 271 Code* check_code,
258 Code* replacement_code) { 272 Code* replacement_code) {
259 Address call_target_address = pc_after - kIntSize; 273 Address call_target_address = pc_after - kIntSize;
260 ASSERT(replacement_code->entry() == 274 ASSERT(replacement_code->entry() ==
261 Assembler::target_address_at(call_target_address)); 275 Assembler::target_address_at(call_target_address));
262 // Replace the nops from patching (Deoptimizer::PatchStackCheckCode) to 276 // Replace the nops from patching (Deoptimizer::PatchStackCheckCode) to
263 // restore the conditional branch. 277 // restore the conditional branch.
264 ASSERT(*(call_target_address - 3) == 0x90 && // nop 278 ASSERT(*(call_target_address - 3) == 0x90 && // nop
265 *(call_target_address - 2) == 0x90 && // nop 279 *(call_target_address - 2) == 0x90 && // nop
266 *(call_target_address - 1) == 0xe8); // call 280 *(call_target_address - 1) == 0xe8); // call
267 *(call_target_address - 3) = 0x73; // jae 281 *(call_target_address - 3) = 0x73; // jae
268 *(call_target_address - 2) = 0x07; // offset 282 *(call_target_address - 2) = 0x07; // offset
269 Assembler::set_target_address_at(call_target_address, 283 Assembler::set_target_address_at(call_target_address,
270 check_code->entry()); 284 check_code->entry());
285
286 check_code->GetHeap()->incremental_marking()->
287 RecordCodeTargetPatch(call_target_address, check_code);
271 } 288 }
272 289
273 290
274 static int LookupBailoutId(DeoptimizationInputData* data, unsigned ast_id) { 291 static int LookupBailoutId(DeoptimizationInputData* data, unsigned ast_id) {
275 ByteArray* translations = data->TranslationByteArray(); 292 ByteArray* translations = data->TranslationByteArray();
276 int length = data->DeoptCount(); 293 int length = data->DeoptCount();
277 for (int i = 0; i < length; i++) { 294 for (int i = 0; i < length; i++) {
278 if (static_cast<unsigned>(data->AstId(i)->value()) == ast_id) { 295 if (static_cast<unsigned>(data->AstId(i)->value()) == ast_id) {
279 TranslationIterator it(translations, data->TranslationIndex(i)->value()); 296 TranslationIterator it(translations, data->TranslationIndex(i)->value());
280 int value = it.Next(); 297 int value = it.Next();
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
408 ok = DoOsrTranslateCommand(&iterator, &input_offset); 425 ok = DoOsrTranslateCommand(&iterator, &input_offset);
409 } 426 }
410 427
411 // If translation of any command failed, continue using the input frame. 428 // If translation of any command failed, continue using the input frame.
412 if (!ok) { 429 if (!ok) {
413 delete output_[0]; 430 delete output_[0];
414 output_[0] = input_; 431 output_[0] = input_;
415 output_[0]->SetPc(reinterpret_cast<uint32_t>(from_)); 432 output_[0]->SetPc(reinterpret_cast<uint32_t>(from_));
416 } else { 433 } else {
417 // Setup the frame pointer and the context pointer. 434 // Setup the frame pointer and the context pointer.
418 output_[0]->SetRegister(ebp.code(), input_->GetRegister(ebp.code())); 435 // All OSR stack frames are dynamically aligned to an 8-byte boundary.
436 int frame_pointer = input_->GetRegister(ebp.code());
437 if ((frame_pointer & 0x4) == 0) {
438 // Return address at FP + 4 should be aligned, so FP mod 8 should be 4.
439 frame_pointer -= kPointerSize;
440 has_alignment_padding_ = 1;
441 }
442 output_[0]->SetRegister(ebp.code(), frame_pointer);
419 output_[0]->SetRegister(esi.code(), input_->GetRegister(esi.code())); 443 output_[0]->SetRegister(esi.code(), input_->GetRegister(esi.code()));
420 444
421 unsigned pc_offset = data->OsrPcOffset()->value(); 445 unsigned pc_offset = data->OsrPcOffset()->value();
422 uint32_t pc = reinterpret_cast<uint32_t>( 446 uint32_t pc = reinterpret_cast<uint32_t>(
423 optimized_code_->entry() + pc_offset); 447 optimized_code_->entry() + pc_offset);
424 output_[0]->SetPc(pc); 448 output_[0]->SetPc(pc);
425 } 449 }
426 Code* continuation = 450 Code* continuation =
427 function->GetIsolate()->builtins()->builtin(Builtins::kNotifyOSR); 451 function->GetIsolate()->builtins()->builtin(Builtins::kNotifyOSR);
428 output_[0]->SetContinuation( 452 output_[0]->SetContinuation(
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
473 ASSERT(frame_index >= 0 && frame_index < output_count_); 497 ASSERT(frame_index >= 0 && frame_index < output_count_);
474 ASSERT(output_[frame_index] == NULL); 498 ASSERT(output_[frame_index] == NULL);
475 output_[frame_index] = output_frame; 499 output_[frame_index] = output_frame;
476 500
477 // The top address for the bottommost output frame can be computed from 501 // The top address for the bottommost output frame can be computed from
478 // the input frame pointer and the output frame's height. For all 502 // the input frame pointer and the output frame's height. For all
479 // subsequent output frames, it can be computed from the previous one's 503 // subsequent output frames, it can be computed from the previous one's
480 // top address and the current frame's size. 504 // top address and the current frame's size.
481 uint32_t top_address; 505 uint32_t top_address;
482 if (is_bottommost) { 506 if (is_bottommost) {
483 // 2 = context and function in the frame. 507 // If the optimized frame had alignment padding, adjust the frame pointer
484 top_address = 508 // to point to the new position of the old frame pointer after padding
485 input_->GetRegister(ebp.code()) - (2 * kPointerSize) - height_in_bytes; 509 // is removed. Subtract 2 * kPointerSize for the context and function slots.
510 top_address = input_->GetRegister(ebp.code()) - (2 * kPointerSize) -
511 height_in_bytes + has_alignment_padding_ * kPointerSize;
486 } else { 512 } else {
487 top_address = output_[frame_index - 1]->GetTop() - output_frame_size; 513 top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
488 } 514 }
489 output_frame->SetTop(top_address); 515 output_frame->SetTop(top_address);
490 516
491 // Compute the incoming parameter translation. 517 // Compute the incoming parameter translation.
492 int parameter_count = function->shared()->formal_parameter_count() + 1; 518 int parameter_count = function->shared()->formal_parameter_count() + 1;
493 unsigned output_offset = output_frame_size; 519 unsigned output_offset = output_frame_size;
494 unsigned input_offset = input_frame_size; 520 unsigned input_offset = input_frame_size;
495 for (int i = 0; i < parameter_count; ++i) { 521 for (int i = 0; i < parameter_count; ++i) {
(...skipping 30 matching lines...) Expand all
526 // pointer. 552 // pointer.
527 output_offset -= kPointerSize; 553 output_offset -= kPointerSize;
528 input_offset -= kPointerSize; 554 input_offset -= kPointerSize;
529 if (is_bottommost) { 555 if (is_bottommost) {
530 value = input_->GetFrameSlot(input_offset); 556 value = input_->GetFrameSlot(input_offset);
531 } else { 557 } else {
532 value = output_[frame_index - 1]->GetFp(); 558 value = output_[frame_index - 1]->GetFp();
533 } 559 }
534 output_frame->SetFrameSlot(output_offset, value); 560 output_frame->SetFrameSlot(output_offset, value);
535 intptr_t fp_value = top_address + output_offset; 561 intptr_t fp_value = top_address + output_offset;
536 ASSERT(!is_bottommost || input_->GetRegister(ebp.code()) == fp_value); 562 ASSERT(!is_bottommost ||
563 input_->GetRegister(ebp.code()) + has_alignment_padding_ * kPointerSize
564 == fp_value);
537 output_frame->SetFp(fp_value); 565 output_frame->SetFp(fp_value);
538 if (is_topmost) output_frame->SetRegister(ebp.code(), fp_value); 566 if (is_topmost) output_frame->SetRegister(ebp.code(), fp_value);
539 if (FLAG_trace_deopt) { 567 if (FLAG_trace_deopt) {
540 PrintF(" 0x%08x: [top + %d] <- 0x%08x ; caller's fp\n", 568 PrintF(" 0x%08x: [top + %d] <- 0x%08x ; caller's fp\n",
541 fp_value, output_offset, value); 569 fp_value, output_offset, value);
542 } 570 }
543 571
544 // For the bottommost output frame the context can be gotten from the input 572 // For the bottommost output frame the context can be gotten from the input
545 // frame. For all subsequent output frames it can be gotten from the function 573 // frame. For all subsequent output frames it can be gotten from the function
546 // so long as we don't inline functions that need local contexts. 574 // so long as we don't inline functions that need local contexts.
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
631 GeneratePrologue(); 659 GeneratePrologue();
632 CpuFeatures::Scope scope(SSE2); 660 CpuFeatures::Scope scope(SSE2);
633 661
634 Isolate* isolate = masm()->isolate(); 662 Isolate* isolate = masm()->isolate();
635 663
636 // Save all general purpose registers before messing with them. 664 // Save all general purpose registers before messing with them.
637 const int kNumberOfRegisters = Register::kNumRegisters; 665 const int kNumberOfRegisters = Register::kNumRegisters;
638 666
639 const int kDoubleRegsSize = kDoubleSize * 667 const int kDoubleRegsSize = kDoubleSize *
640 XMMRegister::kNumAllocatableRegisters; 668 XMMRegister::kNumAllocatableRegisters;
641 __ sub(Operand(esp), Immediate(kDoubleRegsSize)); 669 __ sub(esp, Immediate(kDoubleRegsSize));
642 for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) { 670 for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) {
643 XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i); 671 XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i);
644 int offset = i * kDoubleSize; 672 int offset = i * kDoubleSize;
645 __ movdbl(Operand(esp, offset), xmm_reg); 673 __ movdbl(Operand(esp, offset), xmm_reg);
646 } 674 }
647 675
648 __ pushad(); 676 __ pushad();
649 677
650 const int kSavedRegistersAreaSize = kNumberOfRegisters * kPointerSize + 678 const int kSavedRegistersAreaSize = kNumberOfRegisters * kPointerSize +
651 kDoubleRegsSize; 679 kDoubleRegsSize;
652 680
653 // Get the bailout id from the stack. 681 // Get the bailout id from the stack.
654 __ mov(ebx, Operand(esp, kSavedRegistersAreaSize)); 682 __ mov(ebx, Operand(esp, kSavedRegistersAreaSize));
655 683
656 // Get the address of the location in the code object if possible 684 // Get the address of the location in the code object if possible
657 // and compute the fp-to-sp delta in register edx. 685 // and compute the fp-to-sp delta in register edx.
658 if (type() == EAGER) { 686 if (type() == EAGER) {
659 __ Set(ecx, Immediate(0)); 687 __ Set(ecx, Immediate(0));
660 __ lea(edx, Operand(esp, kSavedRegistersAreaSize + 1 * kPointerSize)); 688 __ lea(edx, Operand(esp, kSavedRegistersAreaSize + 1 * kPointerSize));
661 } else { 689 } else {
662 __ mov(ecx, Operand(esp, kSavedRegistersAreaSize + 1 * kPointerSize)); 690 __ mov(ecx, Operand(esp, kSavedRegistersAreaSize + 1 * kPointerSize));
663 __ lea(edx, Operand(esp, kSavedRegistersAreaSize + 2 * kPointerSize)); 691 __ lea(edx, Operand(esp, kSavedRegistersAreaSize + 2 * kPointerSize));
664 } 692 }
665 __ sub(edx, Operand(ebp)); 693 __ sub(edx, ebp);
666 __ neg(edx); 694 __ neg(edx);
667 695
668 // Allocate a new deoptimizer object. 696 // Allocate a new deoptimizer object.
669 __ PrepareCallCFunction(6, eax); 697 __ PrepareCallCFunction(6, eax);
670 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 698 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
671 __ mov(Operand(esp, 0 * kPointerSize), eax); // Function. 699 __ mov(Operand(esp, 0 * kPointerSize), eax); // Function.
672 __ mov(Operand(esp, 1 * kPointerSize), Immediate(type())); // Bailout type. 700 __ mov(Operand(esp, 1 * kPointerSize), Immediate(type())); // Bailout type.
673 __ mov(Operand(esp, 2 * kPointerSize), ebx); // Bailout id. 701 __ mov(Operand(esp, 2 * kPointerSize), ebx); // Bailout id.
674 __ mov(Operand(esp, 3 * kPointerSize), ecx); // Code address or 0. 702 __ mov(Operand(esp, 3 * kPointerSize), ecx); // Code address or 0.
675 __ mov(Operand(esp, 4 * kPointerSize), edx); // Fp-to-sp delta. 703 __ mov(Operand(esp, 4 * kPointerSize), edx); // Fp-to-sp delta.
676 __ mov(Operand(esp, 5 * kPointerSize), 704 __ mov(Operand(esp, 5 * kPointerSize),
677 Immediate(ExternalReference::isolate_address())); 705 Immediate(ExternalReference::isolate_address()));
678 __ CallCFunction(ExternalReference::new_deoptimizer_function(isolate), 6); 706 {
707 AllowExternalCallThatCantCauseGC scope(masm());
708 __ CallCFunction(ExternalReference::new_deoptimizer_function(isolate), 6);
709 }
679 710
680 // Preserve deoptimizer object in register eax and get the input 711 // Preserve deoptimizer object in register eax and get the input
681 // frame descriptor pointer. 712 // frame descriptor pointer.
682 __ mov(ebx, Operand(eax, Deoptimizer::input_offset())); 713 __ mov(ebx, Operand(eax, Deoptimizer::input_offset()));
683 714
684 // Fill in the input registers. 715 // Fill in the input registers.
685 for (int i = kNumberOfRegisters - 1; i >= 0; i--) { 716 for (int i = kNumberOfRegisters - 1; i >= 0; i--) {
686 int offset = (i * kPointerSize) + FrameDescription::registers_offset(); 717 int offset = (i * kPointerSize) + FrameDescription::registers_offset();
687 __ pop(Operand(ebx, offset)); 718 __ pop(Operand(ebx, offset));
688 } 719 }
689 720
690 // Fill in the double input registers. 721 // Fill in the double input registers.
691 int double_regs_offset = FrameDescription::double_registers_offset(); 722 int double_regs_offset = FrameDescription::double_registers_offset();
692 for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) { 723 for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) {
693 int dst_offset = i * kDoubleSize + double_regs_offset; 724 int dst_offset = i * kDoubleSize + double_regs_offset;
694 int src_offset = i * kDoubleSize; 725 int src_offset = i * kDoubleSize;
695 __ movdbl(xmm0, Operand(esp, src_offset)); 726 __ movdbl(xmm0, Operand(esp, src_offset));
696 __ movdbl(Operand(ebx, dst_offset), xmm0); 727 __ movdbl(Operand(ebx, dst_offset), xmm0);
697 } 728 }
698 729
699 // Remove the bailout id and the double registers from the stack. 730 // Remove the bailout id and the double registers from the stack.
700 if (type() == EAGER) { 731 if (type() == EAGER) {
701 __ add(Operand(esp), Immediate(kDoubleRegsSize + kPointerSize)); 732 __ add(esp, Immediate(kDoubleRegsSize + kPointerSize));
702 } else { 733 } else {
703 __ add(Operand(esp), Immediate(kDoubleRegsSize + 2 * kPointerSize)); 734 __ add(esp, Immediate(kDoubleRegsSize + 2 * kPointerSize));
704 } 735 }
705 736
706 // Compute a pointer to the unwinding limit in register ecx; that is 737 // Compute a pointer to the unwinding limit in register ecx; that is
707 // the first stack slot not part of the input frame. 738 // the first stack slot not part of the input frame.
708 __ mov(ecx, Operand(ebx, FrameDescription::frame_size_offset())); 739 __ mov(ecx, Operand(ebx, FrameDescription::frame_size_offset()));
709 __ add(ecx, Operand(esp)); 740 __ add(ecx, esp);
710 741
711 // Unwind the stack down to - but not including - the unwinding 742 // Unwind the stack down to - but not including - the unwinding
712 // limit and copy the contents of the activation frame to the input 743 // limit and copy the contents of the activation frame to the input
713 // frame description. 744 // frame description.
714 __ lea(edx, Operand(ebx, FrameDescription::frame_content_offset())); 745 __ lea(edx, Operand(ebx, FrameDescription::frame_content_offset()));
715 Label pop_loop; 746 Label pop_loop;
716 __ bind(&pop_loop); 747 __ bind(&pop_loop);
717 __ pop(Operand(edx, 0)); 748 __ pop(Operand(edx, 0));
718 __ add(Operand(edx), Immediate(sizeof(uint32_t))); 749 __ add(edx, Immediate(sizeof(uint32_t)));
719 __ cmp(ecx, Operand(esp)); 750 __ cmp(ecx, esp);
720 __ j(not_equal, &pop_loop); 751 __ j(not_equal, &pop_loop);
721 752
753 // If frame was dynamically aligned, pop padding.
754 Label sentinel, sentinel_done;
755 __ pop(ecx);
756 __ cmp(ecx, Operand(eax, Deoptimizer::frame_alignment_marker_offset()));
757 __ j(equal, &sentinel);
758 __ push(ecx);
759 __ jmp(&sentinel_done);
760 __ bind(&sentinel);
761 __ mov(Operand(eax, Deoptimizer::has_alignment_padding_offset()),
762 Immediate(1));
763 __ bind(&sentinel_done);
722 // Compute the output frame in the deoptimizer. 764 // Compute the output frame in the deoptimizer.
723 __ push(eax); 765 __ push(eax);
724 __ PrepareCallCFunction(1, ebx); 766 __ PrepareCallCFunction(1, ebx);
725 __ mov(Operand(esp, 0 * kPointerSize), eax); 767 __ mov(Operand(esp, 0 * kPointerSize), eax);
726 __ CallCFunction( 768 {
727 ExternalReference::compute_output_frames_function(isolate), 1); 769 AllowExternalCallThatCantCauseGC scope(masm());
770 __ CallCFunction(
771 ExternalReference::compute_output_frames_function(isolate), 1);
772 }
728 __ pop(eax); 773 __ pop(eax);
729 774
775 if (type() == OSR) {
776 // If alignment padding is added, push the sentinel.
777 Label no_osr_padding;
778 __ cmp(Operand(eax, Deoptimizer::has_alignment_padding_offset()),
779 Immediate(0));
780 __ j(equal, &no_osr_padding, Label::kNear);
781 __ push(Operand(eax, Deoptimizer::frame_alignment_marker_offset()));
782 __ bind(&no_osr_padding);
783 }
784
785
730 // Replace the current frame with the output frames. 786 // Replace the current frame with the output frames.
731 Label outer_push_loop, inner_push_loop; 787 Label outer_push_loop, inner_push_loop;
732 // Outer loop state: eax = current FrameDescription**, edx = one past the 788 // Outer loop state: eax = current FrameDescription**, edx = one past the
733 // last FrameDescription**. 789 // last FrameDescription**.
734 __ mov(edx, Operand(eax, Deoptimizer::output_count_offset())); 790 __ mov(edx, Operand(eax, Deoptimizer::output_count_offset()));
735 __ mov(eax, Operand(eax, Deoptimizer::output_offset())); 791 __ mov(eax, Operand(eax, Deoptimizer::output_offset()));
736 __ lea(edx, Operand(eax, edx, times_4, 0)); 792 __ lea(edx, Operand(eax, edx, times_4, 0));
737 __ bind(&outer_push_loop); 793 __ bind(&outer_push_loop);
738 // Inner loop state: ebx = current FrameDescription*, ecx = loop index. 794 // Inner loop state: ebx = current FrameDescription*, ecx = loop index.
739 __ mov(ebx, Operand(eax, 0)); 795 __ mov(ebx, Operand(eax, 0));
740 __ mov(ecx, Operand(ebx, FrameDescription::frame_size_offset())); 796 __ mov(ecx, Operand(ebx, FrameDescription::frame_size_offset()));
741 __ bind(&inner_push_loop); 797 __ bind(&inner_push_loop);
742 __ sub(Operand(ecx), Immediate(sizeof(uint32_t))); 798 __ sub(ecx, Immediate(sizeof(uint32_t)));
743 __ push(Operand(ebx, ecx, times_1, FrameDescription::frame_content_offset())); 799 __ push(Operand(ebx, ecx, times_1, FrameDescription::frame_content_offset()));
744 __ test(ecx, Operand(ecx)); 800 __ test(ecx, ecx);
745 __ j(not_zero, &inner_push_loop); 801 __ j(not_zero, &inner_push_loop);
746 __ add(Operand(eax), Immediate(kPointerSize)); 802 __ add(eax, Immediate(kPointerSize));
747 __ cmp(eax, Operand(edx)); 803 __ cmp(eax, edx);
748 __ j(below, &outer_push_loop); 804 __ j(below, &outer_push_loop);
749 805
750 // In case of OSR, we have to restore the XMM registers. 806 // In case of OSR, we have to restore the XMM registers.
751 if (type() == OSR) { 807 if (type() == OSR) {
752 for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) { 808 for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) {
753 XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i); 809 XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i);
754 int src_offset = i * kDoubleSize + double_regs_offset; 810 int src_offset = i * kDoubleSize + double_regs_offset;
755 __ movdbl(xmm_reg, Operand(ebx, src_offset)); 811 __ movdbl(xmm_reg, Operand(ebx, src_offset));
756 } 812 }
757 } 813 }
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
790 } 846 }
791 __ bind(&done); 847 __ bind(&done);
792 } 848 }
793 849
794 #undef __ 850 #undef __
795 851
796 852
797 } } // namespace v8::internal 853 } } // namespace v8::internal
798 854
799 #endif // V8_TARGET_ARCH_IA32 855 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/debug-ia32.cc ('k') | src/ia32/disasm-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698