| OLD | NEW |
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 550 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 561 FunctionGetName, | 561 FunctionGetName, |
| 562 ReadOnlySetAccessor, | 562 ReadOnlySetAccessor, |
| 563 0 | 563 0 |
| 564 }; | 564 }; |
| 565 | 565 |
| 566 | 566 |
| 567 // | 567 // |
| 568 // Accessors::FunctionArguments | 568 // Accessors::FunctionArguments |
| 569 // | 569 // |
| 570 | 570 |
| 571 static Address SlotAddress(JavaScriptFrame* frame, int slot_index) { | |
| 572 if (slot_index >= 0) { | |
| 573 const int offset = JavaScriptFrameConstants::kLocal0Offset; | |
| 574 return frame->fp() + offset - (slot_index * kPointerSize); | |
| 575 } else { | |
| 576 const int offset = JavaScriptFrameConstants::kReceiverOffset; | |
| 577 return frame->caller_sp() + offset + (slot_index * kPointerSize); | |
| 578 } | |
| 579 } | |
| 580 | |
| 581 | |
| 582 // We can't intermix stack decoding and allocations because | |
| 583 // deoptimization infrastracture is not GC safe. | |
| 584 // Thus we build a temporary structure in malloced space. | |
| 585 class SlotRef BASE_EMBEDDED { | |
| 586 public: | |
| 587 enum SlotRepresentation { | |
| 588 UNKNOWN, | |
| 589 TAGGED, | |
| 590 INT32, | |
| 591 DOUBLE, | |
| 592 LITERAL | |
| 593 }; | |
| 594 | |
| 595 SlotRef() | |
| 596 : addr_(NULL), representation_(UNKNOWN) { } | |
| 597 | |
| 598 SlotRef(Address addr, SlotRepresentation representation) | |
| 599 : addr_(addr), representation_(representation) { } | |
| 600 | |
| 601 explicit SlotRef(Object* literal) | |
| 602 : literal_(literal), representation_(LITERAL) { } | |
| 603 | |
| 604 Handle<Object> GetValue() { | |
| 605 switch (representation_) { | |
| 606 case TAGGED: | |
| 607 return Handle<Object>(Memory::Object_at(addr_)); | |
| 608 | |
| 609 case INT32: { | |
| 610 int value = Memory::int32_at(addr_); | |
| 611 if (Smi::IsValid(value)) { | |
| 612 return Handle<Object>(Smi::FromInt(value)); | |
| 613 } else { | |
| 614 return Isolate::Current()->factory()->NewNumberFromInt(value); | |
| 615 } | |
| 616 } | |
| 617 | |
| 618 case DOUBLE: { | |
| 619 double value = Memory::double_at(addr_); | |
| 620 return Isolate::Current()->factory()->NewNumber(value); | |
| 621 } | |
| 622 | |
| 623 case LITERAL: | |
| 624 return literal_; | |
| 625 | |
| 626 default: | |
| 627 UNREACHABLE(); | |
| 628 return Handle<Object>::null(); | |
| 629 } | |
| 630 } | |
| 631 | |
| 632 private: | |
| 633 Address addr_; | |
| 634 Handle<Object> literal_; | |
| 635 SlotRepresentation representation_; | |
| 636 }; | |
| 637 | |
| 638 | |
| 639 static SlotRef ComputeSlotForNextArgument(TranslationIterator* iterator, | |
| 640 DeoptimizationInputData* data, | |
| 641 JavaScriptFrame* frame) { | |
| 642 Translation::Opcode opcode = | |
| 643 static_cast<Translation::Opcode>(iterator->Next()); | |
| 644 | |
| 645 switch (opcode) { | |
| 646 case Translation::BEGIN: | |
| 647 case Translation::FRAME: | |
| 648 // Peeled off before getting here. | |
| 649 break; | |
| 650 | |
| 651 case Translation::ARGUMENTS_OBJECT: | |
| 652 // This can be only emitted for local slots not for argument slots. | |
| 653 break; | |
| 654 | |
| 655 case Translation::REGISTER: | |
| 656 case Translation::INT32_REGISTER: | |
| 657 case Translation::DOUBLE_REGISTER: | |
| 658 case Translation::DUPLICATE: | |
| 659 // We are at safepoint which corresponds to call. All registers are | |
| 660 // saved by caller so there would be no live registers at this | |
| 661 // point. Thus these translation commands should not be used. | |
| 662 break; | |
| 663 | |
| 664 case Translation::STACK_SLOT: { | |
| 665 int slot_index = iterator->Next(); | |
| 666 Address slot_addr = SlotAddress(frame, slot_index); | |
| 667 return SlotRef(slot_addr, SlotRef::TAGGED); | |
| 668 } | |
| 669 | |
| 670 case Translation::INT32_STACK_SLOT: { | |
| 671 int slot_index = iterator->Next(); | |
| 672 Address slot_addr = SlotAddress(frame, slot_index); | |
| 673 return SlotRef(slot_addr, SlotRef::INT32); | |
| 674 } | |
| 675 | |
| 676 case Translation::DOUBLE_STACK_SLOT: { | |
| 677 int slot_index = iterator->Next(); | |
| 678 Address slot_addr = SlotAddress(frame, slot_index); | |
| 679 return SlotRef(slot_addr, SlotRef::DOUBLE); | |
| 680 } | |
| 681 | |
| 682 case Translation::LITERAL: { | |
| 683 int literal_index = iterator->Next(); | |
| 684 return SlotRef(data->LiteralArray()->get(literal_index)); | |
| 685 } | |
| 686 } | |
| 687 | |
| 688 UNREACHABLE(); | |
| 689 return SlotRef(); | |
| 690 } | |
| 691 | |
| 692 | |
| 693 | |
| 694 | |
| 695 | |
| 696 static void ComputeSlotMappingForArguments(JavaScriptFrame* frame, | |
| 697 int inlined_frame_index, | |
| 698 Vector<SlotRef>* args_slots) { | |
| 699 AssertNoAllocation no_gc; | |
| 700 int deopt_index = AstNode::kNoNumber; | |
| 701 DeoptimizationInputData* data = | |
| 702 static_cast<OptimizedFrame*>(frame)->GetDeoptimizationData(&deopt_index); | |
| 703 TranslationIterator it(data->TranslationByteArray(), | |
| 704 data->TranslationIndex(deopt_index)->value()); | |
| 705 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); | |
| 706 ASSERT(opcode == Translation::BEGIN); | |
| 707 int frame_count = it.Next(); | |
| 708 USE(frame_count); | |
| 709 ASSERT(frame_count > inlined_frame_index); | |
| 710 int frames_to_skip = inlined_frame_index; | |
| 711 while (true) { | |
| 712 opcode = static_cast<Translation::Opcode>(it.Next()); | |
| 713 // Skip over operands to advance to the next opcode. | |
| 714 it.Skip(Translation::NumberOfOperandsFor(opcode)); | |
| 715 if (opcode == Translation::FRAME) { | |
| 716 if (frames_to_skip == 0) { | |
| 717 // We reached the frame corresponding to the inlined function | |
| 718 // in question. Process the translation commands for the | |
| 719 // arguments. | |
| 720 // | |
| 721 // Skip the translation command for the receiver. | |
| 722 it.Skip(Translation::NumberOfOperandsFor( | |
| 723 static_cast<Translation::Opcode>(it.Next()))); | |
| 724 // Compute slots for arguments. | |
| 725 for (int i = 0; i < args_slots->length(); ++i) { | |
| 726 (*args_slots)[i] = ComputeSlotForNextArgument(&it, data, frame); | |
| 727 } | |
| 728 return; | |
| 729 } | |
| 730 frames_to_skip--; | |
| 731 } | |
| 732 } | |
| 733 | |
| 734 UNREACHABLE(); | |
| 735 } | |
| 736 | |
| 737 | 571 |
| 738 static MaybeObject* ConstructArgumentsObjectForInlinedFunction( | 572 static MaybeObject* ConstructArgumentsObjectForInlinedFunction( |
| 739 JavaScriptFrame* frame, | 573 JavaScriptFrame* frame, |
| 740 Handle<JSFunction> inlined_function, | 574 Handle<JSFunction> inlined_function, |
| 741 int inlined_frame_index) { | 575 int inlined_frame_index) { |
| 742 Factory* factory = Isolate::Current()->factory(); | 576 Factory* factory = Isolate::Current()->factory(); |
| 743 int args_count = inlined_function->shared()->formal_parameter_count(); | 577 int args_count = inlined_function->shared()->formal_parameter_count(); |
| 744 ScopedVector<SlotRef> args_slots(args_count); | 578 ScopedVector<SlotRef> args_slots(args_count); |
| 745 ComputeSlotMappingForArguments(frame, inlined_frame_index, &args_slots); | 579 SlotRef::ComputeSlotMappingForArguments(frame, |
| 580 inlined_frame_index, |
| 581 &args_slots); |
| 746 Handle<JSObject> arguments = | 582 Handle<JSObject> arguments = |
| 747 factory->NewArgumentsObject(inlined_function, args_count); | 583 factory->NewArgumentsObject(inlined_function, args_count); |
| 748 Handle<FixedArray> array = factory->NewFixedArray(args_count); | 584 Handle<FixedArray> array = factory->NewFixedArray(args_count); |
| 749 for (int i = 0; i < args_count; ++i) { | 585 for (int i = 0; i < args_count; ++i) { |
| 750 Handle<Object> value = args_slots[i].GetValue(); | 586 Handle<Object> value = args_slots[i].GetValue(); |
| 751 array->set(i, *value); | 587 array->set(i, *value); |
| 752 } | 588 } |
| 753 arguments->set_elements(*array); | 589 arguments->set_elements(*array); |
| 754 | 590 |
| 755 // Return the freshly allocated arguments object. | 591 // Return the freshly allocated arguments object. |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 921 } | 757 } |
| 922 | 758 |
| 923 | 759 |
| 924 const AccessorDescriptor Accessors::ObjectPrototype = { | 760 const AccessorDescriptor Accessors::ObjectPrototype = { |
| 925 ObjectGetPrototype, | 761 ObjectGetPrototype, |
| 926 ObjectSetPrototype, | 762 ObjectSetPrototype, |
| 927 0 | 763 0 |
| 928 }; | 764 }; |
| 929 | 765 |
| 930 } } // namespace v8::internal | 766 } } // namespace v8::internal |
| OLD | NEW |