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