| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 262 ast_id, | 262 ast_id, |
| 263 input_frame_size, | 263 input_frame_size, |
| 264 output_frame_size); | 264 output_frame_size); |
| 265 } | 265 } |
| 266 | 266 |
| 267 // There's only one output frame in the OSR case. | 267 // There's only one output frame in the OSR case. |
| 268 output_count_ = 1; | 268 output_count_ = 1; |
| 269 output_ = new FrameDescription*[1]; | 269 output_ = new FrameDescription*[1]; |
| 270 output_[0] = new(output_frame_size) FrameDescription( | 270 output_[0] = new(output_frame_size) FrameDescription( |
| 271 output_frame_size, function_); | 271 output_frame_size, function_); |
| 272 #ifdef DEBUG |
| 273 output_[0]->SetKind(Code::OPTIMIZED_FUNCTION); |
| 274 #endif |
| 272 | 275 |
| 273 // Clear the incoming parameters in the optimized frame to avoid | 276 // Clear the incoming parameters in the optimized frame to avoid |
| 274 // confusing the garbage collector. | 277 // confusing the garbage collector. |
| 275 unsigned output_offset = output_frame_size - kPointerSize; | 278 unsigned output_offset = output_frame_size - kPointerSize; |
| 276 int parameter_count = function_->shared()->formal_parameter_count() + 1; | 279 int parameter_count = function_->shared()->formal_parameter_count() + 1; |
| 277 for (int i = 0; i < parameter_count; ++i) { | 280 for (int i = 0; i < parameter_count; ++i) { |
| 278 output_[0]->SetFrameSlot(output_offset, 0); | 281 output_[0]->SetFrameSlot(output_offset, 0); |
| 279 output_offset -= kPointerSize; | 282 output_offset -= kPointerSize; |
| 280 } | 283 } |
| 281 | 284 |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 377 | 380 |
| 378 // The 'fixed' part of the frame consists of the incoming parameters and | 381 // The 'fixed' part of the frame consists of the incoming parameters and |
| 379 // the part described by JavaScriptFrameConstants. | 382 // the part described by JavaScriptFrameConstants. |
| 380 unsigned fixed_frame_size = ComputeFixedSize(function); | 383 unsigned fixed_frame_size = ComputeFixedSize(function); |
| 381 unsigned input_frame_size = input_->GetFrameSize(); | 384 unsigned input_frame_size = input_->GetFrameSize(); |
| 382 unsigned output_frame_size = height_in_bytes + fixed_frame_size; | 385 unsigned output_frame_size = height_in_bytes + fixed_frame_size; |
| 383 | 386 |
| 384 // Allocate and store the output frame description. | 387 // Allocate and store the output frame description. |
| 385 FrameDescription* output_frame = | 388 FrameDescription* output_frame = |
| 386 new(output_frame_size) FrameDescription(output_frame_size, function); | 389 new(output_frame_size) FrameDescription(output_frame_size, function); |
| 390 #ifdef DEBUG |
| 391 output_frame->SetKind(Code::FUNCTION); |
| 392 #endif |
| 387 | 393 |
| 388 bool is_bottommost = (0 == frame_index); | 394 bool is_bottommost = (0 == frame_index); |
| 389 bool is_topmost = (output_count_ - 1 == frame_index); | 395 bool is_topmost = (output_count_ - 1 == frame_index); |
| 390 ASSERT(frame_index >= 0 && frame_index < output_count_); | 396 ASSERT(frame_index >= 0 && frame_index < output_count_); |
| 391 ASSERT(output_[frame_index] == NULL); | 397 ASSERT(output_[frame_index] == NULL); |
| 392 output_[frame_index] = output_frame; | 398 output_[frame_index] = output_frame; |
| 393 | 399 |
| 394 // The top address for the bottommost output frame can be computed from | 400 // The top address for the bottommost output frame can be computed from |
| 395 // the input frame pointer and the output frame's height. For all | 401 // the input frame pointer and the output frame's height. For all |
| 396 // subsequent output frames, it can be computed from the previous one's | 402 // subsequent output frames, it can be computed from the previous one's |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 511 if (is_topmost) { | 517 if (is_topmost) { |
| 512 output_frame->SetRegister(pc.code(), pc_value); | 518 output_frame->SetRegister(pc.code(), pc_value); |
| 513 } | 519 } |
| 514 | 520 |
| 515 FullCodeGenerator::State state = | 521 FullCodeGenerator::State state = |
| 516 FullCodeGenerator::StateField::decode(pc_and_state); | 522 FullCodeGenerator::StateField::decode(pc_and_state); |
| 517 output_frame->SetState(Smi::FromInt(state)); | 523 output_frame->SetState(Smi::FromInt(state)); |
| 518 | 524 |
| 519 | 525 |
| 520 // Set the continuation for the topmost frame. | 526 // Set the continuation for the topmost frame. |
| 521 if (is_topmost) { | 527 if (is_topmost && bailout_type_ != DEBUGGER) { |
| 522 Builtins* builtins = isolate_->builtins(); | 528 Builtins* builtins = isolate_->builtins(); |
| 523 Code* continuation = (bailout_type_ == EAGER) | 529 Code* continuation = (bailout_type_ == EAGER) |
| 524 ? builtins->builtin(Builtins::kNotifyDeoptimized) | 530 ? builtins->builtin(Builtins::kNotifyDeoptimized) |
| 525 : builtins->builtin(Builtins::kNotifyLazyDeoptimized); | 531 : builtins->builtin(Builtins::kNotifyLazyDeoptimized); |
| 526 output_frame->SetContinuation( | 532 output_frame->SetContinuation( |
| 527 reinterpret_cast<uint32_t>(continuation->entry())); | 533 reinterpret_cast<uint32_t>(continuation->entry())); |
| 528 } | 534 } |
| 529 | 535 |
| 530 if (output_count_ - 1 == frame_index) iterator->Done(); | 536 if (output_count_ - 1 == frame_index) iterator->Done(); |
| 531 } | 537 } |
| 532 | 538 |
| 533 | 539 |
| 540 void Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) { |
| 541 // Set the register values. The values are not important as there are no |
| 542 // callee saved registers in JavaScript frames, so all registers are |
| 543 // spilled. Registers fp and sp are set to the correct values though. |
| 544 |
| 545 for (int i = 0; i < Register::kNumRegisters; i++) { |
| 546 input_->SetRegister(i, i * 4); |
| 547 } |
| 548 input_->SetRegister(sp.code(), reinterpret_cast<intptr_t>(frame->sp())); |
| 549 input_->SetRegister(fp.code(), reinterpret_cast<intptr_t>(frame->fp())); |
| 550 for (int i = 0; i < DoubleRegister::kNumAllocatableRegisters; i++) { |
| 551 input_->SetDoubleRegister(i, 0.0); |
| 552 } |
| 553 |
| 554 // Fill the frame content from the actual data on the frame. |
| 555 for (unsigned i = 0; i < input_->GetFrameSize(); i += kPointerSize) { |
| 556 input_->SetFrameSlot(i, Memory::uint32_at(tos + i)); |
| 557 } |
| 558 } |
| 559 |
| 560 |
| 534 #define __ masm()-> | 561 #define __ masm()-> |
| 535 | 562 |
| 536 | |
| 537 // This code tries to be close to ia32 code so that any changes can be | 563 // This code tries to be close to ia32 code so that any changes can be |
| 538 // easily ported. | 564 // easily ported. |
| 539 void Deoptimizer::EntryGenerator::Generate() { | 565 void Deoptimizer::EntryGenerator::Generate() { |
| 540 GeneratePrologue(); | 566 GeneratePrologue(); |
| 541 | 567 |
| 542 Isolate* isolate = masm()->isolate(); | 568 Isolate* isolate = masm()->isolate(); |
| 543 | 569 |
| 544 CpuFeatures::Scope scope(VFP3); | 570 CpuFeatures::Scope scope(VFP3); |
| 545 // Save all general purpose registers before messing with them. | 571 // Save all general purpose registers before messing with them. |
| 546 const int kNumberOfRegisters = Register::kNumRegisters; | 572 const int kNumberOfRegisters = Register::kNumRegisters; |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 606 __ str(r5, MemOperand(sp, 1 * kPointerSize)); // Isolate. | 632 __ str(r5, MemOperand(sp, 1 * kPointerSize)); // Isolate. |
| 607 // Call Deoptimizer::New(). | 633 // Call Deoptimizer::New(). |
| 608 __ CallCFunction(ExternalReference::new_deoptimizer_function(isolate), 6); | 634 __ CallCFunction(ExternalReference::new_deoptimizer_function(isolate), 6); |
| 609 | 635 |
| 610 // Preserve "deoptimizer" object in register r0 and get the input | 636 // Preserve "deoptimizer" object in register r0 and get the input |
| 611 // frame descriptor pointer to r1 (deoptimizer->input_); | 637 // frame descriptor pointer to r1 (deoptimizer->input_); |
| 612 __ ldr(r1, MemOperand(r0, Deoptimizer::input_offset())); | 638 __ ldr(r1, MemOperand(r0, Deoptimizer::input_offset())); |
| 613 | 639 |
| 614 // Copy core registers into FrameDescription::registers_[kNumRegisters]. | 640 // Copy core registers into FrameDescription::registers_[kNumRegisters]. |
| 615 ASSERT(Register::kNumRegisters == kNumberOfRegisters); | 641 ASSERT(Register::kNumRegisters == kNumberOfRegisters); |
| 616 ASSERT(kNumberOfRegisters % 2 == 0); | 642 for (int i = 0; i < kNumberOfRegisters; i++) { |
| 617 | 643 int offset = (i * kPointerSize) + FrameDescription::registers_offset(); |
| 618 Label arm_loop; | 644 __ ldr(r2, MemOperand(sp, i * kPointerSize)); |
| 619 __ add(r6, r1, Operand(FrameDescription::registers_offset())); | 645 __ str(r2, MemOperand(r1, offset)); |
| 620 __ mov(r5, Operand(sp)); | 646 } |
| 621 __ mov(r4, Operand(kNumberOfRegisters / 2)); | |
| 622 | |
| 623 __ bind(&arm_loop); | |
| 624 __ Ldrd(r2, r3, MemOperand(r5, kPointerSize * 2, PostIndex)); | |
| 625 __ sub(r4, r4, Operand(1), SetCC); | |
| 626 __ Strd(r2, r3, MemOperand(r6, kPointerSize * 2, PostIndex)); | |
| 627 __ b(gt, &arm_loop); | |
| 628 | 647 |
| 629 // Copy VFP registers to | 648 // Copy VFP registers to |
| 630 // double_registers_[DoubleRegister::kNumAllocatableRegisters] | 649 // double_registers_[DoubleRegister::kNumAllocatableRegisters] |
| 631 Label vfp_loop; | 650 int double_regs_offset = FrameDescription::double_registers_offset(); |
| 632 __ add(r6, r1, Operand(FrameDescription::double_registers_offset())); | 651 for (int i = 0; i < DwVfpRegister::kNumAllocatableRegisters; ++i) { |
| 633 __ mov(r4, Operand(DwVfpRegister::kNumAllocatableRegisters)); | 652 int dst_offset = i * kDoubleSize + double_regs_offset; |
| 634 | 653 int src_offset = i * kDoubleSize + kNumberOfRegisters * kPointerSize; |
| 635 __ bind(&vfp_loop); | 654 __ vldr(d0, sp, src_offset); |
| 636 __ Ldrd(r2, r3, MemOperand(r5, kDoubleSize, PostIndex)); | 655 __ vstr(d0, r1, dst_offset); |
| 637 __ sub(r4, r4, Operand(1), SetCC); | 656 } |
| 638 __ Strd(r2, r3, MemOperand(r6, kDoubleSize, PostIndex)); | |
| 639 __ b(gt, &vfp_loop); | |
| 640 | 657 |
| 641 // Remove the bailout id, eventually return address, and the saved registers | 658 // Remove the bailout id, eventually return address, and the saved registers |
| 642 // from the stack. | 659 // from the stack. |
| 643 if (type() == EAGER || type() == OSR) { | 660 if (type() == EAGER || type() == OSR) { |
| 644 __ add(sp, sp, Operand(kSavedRegistersAreaSize + (1 * kPointerSize))); | 661 __ add(sp, sp, Operand(kSavedRegistersAreaSize + (1 * kPointerSize))); |
| 645 } else { | 662 } else { |
| 646 __ add(sp, sp, Operand(kSavedRegistersAreaSize + (2 * kPointerSize))); | 663 __ add(sp, sp, Operand(kSavedRegistersAreaSize + (2 * kPointerSize))); |
| 647 } | 664 } |
| 648 | 665 |
| 649 // Compute a pointer to the unwinding limit in register r2; that is | 666 // Compute a pointer to the unwinding limit in register r2; that is |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 747 __ push(ip); | 764 __ push(ip); |
| 748 __ b(&done); | 765 __ b(&done); |
| 749 ASSERT(masm()->pc_offset() - start == table_entry_size_); | 766 ASSERT(masm()->pc_offset() - start == table_entry_size_); |
| 750 } | 767 } |
| 751 __ bind(&done); | 768 __ bind(&done); |
| 752 } | 769 } |
| 753 | 770 |
| 754 #undef __ | 771 #undef __ |
| 755 | 772 |
| 756 } } // namespace v8::internal | 773 } } // namespace v8::internal |
| OLD | NEW |