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 657 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
668 } | 668 } |
669 | 669 |
670 | 670 |
671 | 671 |
672 | 672 |
673 | 673 |
674 static void ComputeSlotMappingForArguments(JavaScriptFrame* frame, | 674 static void ComputeSlotMappingForArguments(JavaScriptFrame* frame, |
675 int inlined_frame_index, | 675 int inlined_frame_index, |
676 Vector<SlotRef>* args_slots) { | 676 Vector<SlotRef>* args_slots) { |
677 AssertNoAllocation no_gc; | 677 AssertNoAllocation no_gc; |
678 | |
679 int deopt_index = AstNode::kNoNumber; | 678 int deopt_index = AstNode::kNoNumber; |
680 | |
681 DeoptimizationInputData* data = | 679 DeoptimizationInputData* data = |
682 static_cast<OptimizedFrame*>(frame)->GetDeoptimizationData(&deopt_index); | 680 static_cast<OptimizedFrame*>(frame)->GetDeoptimizationData(&deopt_index); |
683 | |
684 TranslationIterator it(data->TranslationByteArray(), | 681 TranslationIterator it(data->TranslationByteArray(), |
685 data->TranslationIndex(deopt_index)->value()); | 682 data->TranslationIndex(deopt_index)->value()); |
686 | |
687 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); | 683 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); |
688 ASSERT(opcode == Translation::BEGIN); | 684 ASSERT(opcode == Translation::BEGIN); |
689 int frame_count = it.Next(); | 685 int frame_count = it.Next(); |
690 | |
691 USE(frame_count); | 686 USE(frame_count); |
692 ASSERT(frame_count > inlined_frame_index); | 687 ASSERT(frame_count > inlined_frame_index); |
693 | |
694 int frames_to_skip = inlined_frame_index; | 688 int frames_to_skip = inlined_frame_index; |
695 while (true) { | 689 while (true) { |
696 opcode = static_cast<Translation::Opcode>(it.Next()); | 690 opcode = static_cast<Translation::Opcode>(it.Next()); |
697 | |
698 // Skip over operands to advance to the next opcode. | 691 // Skip over operands to advance to the next opcode. |
699 it.Skip(Translation::NumberOfOperandsFor(opcode)); | 692 it.Skip(Translation::NumberOfOperandsFor(opcode)); |
700 | |
701 if (opcode == Translation::FRAME) { | 693 if (opcode == Translation::FRAME) { |
702 if (frames_to_skip == 0) { | 694 if (frames_to_skip == 0) { |
703 // We reached frame corresponding to inlined function in question. | 695 // We reached the frame corresponding to the inlined function |
704 // Process translation commands for arguments. | 696 // in question. Process the translation commands for the |
705 | 697 // arguments. |
706 // Skip translation command for receiver. | 698 // |
| 699 // Skip the translation command for the receiver. |
707 it.Skip(Translation::NumberOfOperandsFor( | 700 it.Skip(Translation::NumberOfOperandsFor( |
708 static_cast<Translation::Opcode>(it.Next()))); | 701 static_cast<Translation::Opcode>(it.Next()))); |
709 | |
710 // Compute slots for arguments. | 702 // Compute slots for arguments. |
711 for (int i = 0; i < args_slots->length(); ++i) { | 703 for (int i = 0; i < args_slots->length(); ++i) { |
712 (*args_slots)[i] = ComputeSlotForNextArgument(&it, data, frame); | 704 (*args_slots)[i] = ComputeSlotForNextArgument(&it, data, frame); |
713 } | 705 } |
714 | |
715 return; | 706 return; |
716 } | 707 } |
717 | |
718 frames_to_skip--; | 708 frames_to_skip--; |
719 } | 709 } |
720 } | 710 } |
721 | 711 |
722 UNREACHABLE(); | 712 UNREACHABLE(); |
723 } | 713 } |
724 | 714 |
725 | 715 |
726 static MaybeObject* ConstructArgumentsObjectForInlinedFunction( | 716 static MaybeObject* ConstructArgumentsObjectForInlinedFunction( |
727 JavaScriptFrame* frame, | 717 JavaScriptFrame* frame, |
728 Handle<JSFunction> inlined_function, | 718 Handle<JSFunction> inlined_function, |
729 int inlined_frame_index) { | 719 int inlined_frame_index) { |
730 | |
731 int args_count = inlined_function->shared()->formal_parameter_count(); | 720 int args_count = inlined_function->shared()->formal_parameter_count(); |
732 | |
733 ScopedVector<SlotRef> args_slots(args_count); | 721 ScopedVector<SlotRef> args_slots(args_count); |
734 | |
735 ComputeSlotMappingForArguments(frame, inlined_frame_index, &args_slots); | 722 ComputeSlotMappingForArguments(frame, inlined_frame_index, &args_slots); |
736 | |
737 Handle<JSObject> arguments = | 723 Handle<JSObject> arguments = |
738 Factory::NewArgumentsObject(inlined_function, args_count); | 724 Factory::NewArgumentsObject(inlined_function, args_count); |
739 | |
740 Handle<FixedArray> array = Factory::NewFixedArray(args_count); | 725 Handle<FixedArray> array = Factory::NewFixedArray(args_count); |
741 for (int i = 0; i < args_count; ++i) { | 726 for (int i = 0; i < args_count; ++i) { |
742 Handle<Object> value = args_slots[i].GetValue(); | 727 Handle<Object> value = args_slots[i].GetValue(); |
743 array->set(i, *value); | 728 array->set(i, *value); |
744 } | 729 } |
745 arguments->set_elements(*array); | 730 arguments->set_elements(*array); |
746 | 731 |
747 // Return the freshly allocated arguments object. | 732 // Return the freshly allocated arguments object. |
748 return *arguments; | 733 return *arguments; |
749 } | 734 } |
750 | 735 |
751 | 736 |
752 MaybeObject* Accessors::FunctionGetArguments(Object* object, void*) { | 737 MaybeObject* Accessors::FunctionGetArguments(Object* object, void*) { |
753 HandleScope scope; | 738 HandleScope scope; |
754 bool found_it = false; | 739 bool found_it = false; |
755 JSFunction* holder = FindInPrototypeChain<JSFunction>(object, &found_it); | 740 JSFunction* holder = FindInPrototypeChain<JSFunction>(object, &found_it); |
756 if (!found_it) return Heap::undefined_value(); | 741 if (!found_it) return Heap::undefined_value(); |
757 Handle<JSFunction> function(holder); | 742 Handle<JSFunction> function(holder); |
758 | 743 |
759 // Find the top invocation of the function by traversing frames. | 744 // Find the top invocation of the function by traversing frames. |
760 List<JSFunction*> functions(2); | 745 List<JSFunction*> functions(2); |
761 for (JavaScriptFrameIterator it; !it.done(); it.Advance()) { | 746 for (JavaScriptFrameIterator it; !it.done(); it.Advance()) { |
762 JavaScriptFrame* frame = it.frame(); | 747 JavaScriptFrame* frame = it.frame(); |
763 frame->GetFunctions(&functions); | 748 frame->GetFunctions(&functions); |
764 for (int i = functions.length() - 1; i >= 0; i--) { | 749 for (int i = functions.length() - 1; i >= 0; i--) { |
765 // Skip all frames that aren't invocations of the given function. | 750 // Skip all frames that aren't invocations of the given function. |
766 if (functions[i] != *function) continue; | 751 if (functions[i] != *function) continue; |
767 | 752 |
768 if (i > 0) { | 753 if (i > 0) { |
769 // Function in question was inlined. | 754 // The function in question was inlined. Inlined functions have the |
| 755 // correct number of arguments and no allocated arguments object, so |
| 756 // we can construct a fresh one by interpreting the function's |
| 757 // deoptimization input data. |
770 return ConstructArgumentsObjectForInlinedFunction(frame, function, i); | 758 return ConstructArgumentsObjectForInlinedFunction(frame, function, i); |
771 } else { | 759 } |
| 760 |
| 761 if (!frame->is_optimized()) { |
772 // If there is an arguments variable in the stack, we return that. | 762 // If there is an arguments variable in the stack, we return that. |
773 int index = function->shared()->scope_info()-> | 763 Handle<SerializedScopeInfo> info(function->shared()->scope_info()); |
774 StackSlotIndex(Heap::arguments_symbol()); | 764 int index = info->StackSlotIndex(Heap::arguments_symbol()); |
775 if (index >= 0) { | 765 if (index >= 0) { |
776 Handle<Object> arguments = | 766 Handle<Object> arguments(frame->GetExpression(index)); |
777 Handle<Object>(frame->GetExpression(index)); | |
778 if (!arguments->IsArgumentsMarker()) return *arguments; | 767 if (!arguments->IsArgumentsMarker()) return *arguments; |
779 } | 768 } |
| 769 } |
780 | 770 |
781 // If there isn't an arguments variable in the stack, we need to | 771 // If there is no arguments variable in the stack or we have an |
782 // find the frame that holds the actual arguments passed to the | 772 // optimized frame, we find the frame that holds the actual arguments |
783 // function on the stack. | 773 // passed to the function. |
784 it.AdvanceToArgumentsFrame(); | 774 it.AdvanceToArgumentsFrame(); |
785 frame = it.frame(); | 775 frame = it.frame(); |
786 | 776 |
787 // Get the number of arguments and construct an arguments object | 777 // Get the number of arguments and construct an arguments object |
788 // mirror for the right frame. | 778 // mirror for the right frame. |
789 const int length = frame->GetProvidedParametersCount(); | 779 const int length = frame->GetProvidedParametersCount(); |
790 Handle<JSObject> arguments = Factory::NewArgumentsObject(function, | 780 Handle<JSObject> arguments = Factory::NewArgumentsObject(function, |
791 length); | 781 length); |
792 Handle<FixedArray> array = Factory::NewFixedArray(length); | 782 Handle<FixedArray> array = Factory::NewFixedArray(length); |
793 | 783 |
794 // Copy the parameters to the arguments object. | 784 // Copy the parameters to the arguments object. |
795 ASSERT(array->length() == length); | 785 ASSERT(array->length() == length); |
796 for (int i = 0; i < length; i++) array->set(i, frame->GetParameter(i)); | 786 for (int i = 0; i < length; i++) array->set(i, frame->GetParameter(i)); |
797 arguments->set_elements(*array); | 787 arguments->set_elements(*array); |
798 | 788 |
799 // Return the freshly allocated arguments object. | 789 // Return the freshly allocated arguments object. |
800 return *arguments; | 790 return *arguments; |
801 } | |
802 } | 791 } |
803 functions.Rewind(0); | 792 functions.Rewind(0); |
804 } | 793 } |
805 | 794 |
806 // No frame corresponding to the given function found. Return null. | 795 // No frame corresponding to the given function found. Return null. |
807 return Heap::null_value(); | 796 return Heap::null_value(); |
808 } | 797 } |
809 | 798 |
810 | 799 |
811 const AccessorDescriptor Accessors::FunctionArguments = { | 800 const AccessorDescriptor Accessors::FunctionArguments = { |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
894 } | 883 } |
895 | 884 |
896 | 885 |
897 const AccessorDescriptor Accessors::ObjectPrototype = { | 886 const AccessorDescriptor Accessors::ObjectPrototype = { |
898 ObjectGetPrototype, | 887 ObjectGetPrototype, |
899 ObjectSetPrototype, | 888 ObjectSetPrototype, |
900 0 | 889 0 |
901 }; | 890 }; |
902 | 891 |
903 } } // namespace v8::internal | 892 } } // namespace v8::internal |
OLD | NEW |