OLD | NEW |
---|---|
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 755 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
766 // descriptions. | 766 // descriptions. |
767 int count = iterator.Next(); | 767 int count = iterator.Next(); |
768 iterator.Next(); // Drop JS frames count. | 768 iterator.Next(); // Drop JS frames count. |
769 ASSERT(output_ == NULL); | 769 ASSERT(output_ == NULL); |
770 output_ = new FrameDescription*[count]; | 770 output_ = new FrameDescription*[count]; |
771 for (int i = 0; i < count; ++i) { | 771 for (int i = 0; i < count; ++i) { |
772 output_[i] = NULL; | 772 output_[i] = NULL; |
773 } | 773 } |
774 output_count_ = count; | 774 output_count_ = count; |
775 | 775 |
776 Register fp_reg = JavaScriptFrame::fp_register(); | |
777 stack_fp_ = reinterpret_cast<Address>( | |
778 input_->GetRegister(fp_reg.code()) + | |
779 has_alignment_padding_ * kPointerSize); | |
780 | |
776 // Translate each output frame. | 781 // Translate each output frame. |
777 for (int i = 0; i < count; ++i) { | 782 for (int i = 0; i < count; ++i) { |
778 // Read the ast node id, function, and frame height for this output frame. | 783 // Read the ast node id, function, and frame height for this output frame. |
779 Translation::Opcode opcode = | 784 Translation::Opcode opcode = |
780 static_cast<Translation::Opcode>(iterator.Next()); | 785 static_cast<Translation::Opcode>(iterator.Next()); |
781 switch (opcode) { | 786 switch (opcode) { |
782 case Translation::JS_FRAME: | 787 case Translation::JS_FRAME: |
783 DoComputeJSFrame(&iterator, i); | 788 DoComputeJSFrame(&iterator, i); |
784 jsframe_count_++; | 789 jsframe_count_++; |
785 break; | 790 break; |
(...skipping 984 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1770 // Dispatch on the instance type of the object to be materialized. | 1775 // Dispatch on the instance type of the object to be materialized. |
1771 // We also need to make sure that the representation of all fields | 1776 // We also need to make sure that the representation of all fields |
1772 // in the given object are general enough to hold a tagged value. | 1777 // in the given object are general enough to hold a tagged value. |
1773 Handle<Map> map = Map::GeneralizeAllFieldRepresentations( | 1778 Handle<Map> map = Map::GeneralizeAllFieldRepresentations( |
1774 Handle<Map>::cast(MaterializeNextValue()), Representation::Tagged()); | 1779 Handle<Map>::cast(MaterializeNextValue()), Representation::Tagged()); |
1775 switch (map->instance_type()) { | 1780 switch (map->instance_type()) { |
1776 case HEAP_NUMBER_TYPE: { | 1781 case HEAP_NUMBER_TYPE: { |
1777 // Reuse the HeapNumber value directly as it is already properly | 1782 // Reuse the HeapNumber value directly as it is already properly |
1778 // tagged and skip materializing the HeapNumber explicitly. | 1783 // tagged and skip materializing the HeapNumber explicitly. |
1779 Handle<Object> object = MaterializeNextValue(); | 1784 Handle<Object> object = MaterializeNextValue(); |
1780 materialized_objects_->Add(object); | 1785 if (object_index < prev_materialized_count_) { |
1786 materialized_objects_->Add(Handle<Object>( | |
1787 previously_materialized_objects_->get(object_index), isolate_)); | |
1788 } else { | |
1789 materialized_objects_->Add(object); | |
1790 } | |
1781 materialization_value_index_ += kDoubleSize / kPointerSize - 1; | 1791 materialization_value_index_ += kDoubleSize / kPointerSize - 1; |
1782 break; | 1792 break; |
1783 } | 1793 } |
1784 case JS_OBJECT_TYPE: { | 1794 case JS_OBJECT_TYPE: { |
1785 Handle<JSObject> object = | 1795 Handle<JSObject> object = |
1786 isolate_->factory()->NewJSObjectFromMap(map, NOT_TENURED, false); | 1796 isolate_->factory()->NewJSObjectFromMap(map, NOT_TENURED, false); |
1787 materialized_objects_->Add(object); | 1797 if (object_index < prev_materialized_count_) { |
1798 materialized_objects_->Add(Handle<Object>( | |
1799 previously_materialized_objects_->get(object_index), isolate_)); | |
1800 } else { | |
1801 materialized_objects_->Add(object); | |
1802 } | |
1788 Handle<Object> properties = MaterializeNextValue(); | 1803 Handle<Object> properties = MaterializeNextValue(); |
1789 Handle<Object> elements = MaterializeNextValue(); | 1804 Handle<Object> elements = MaterializeNextValue(); |
1790 object->set_properties(FixedArray::cast(*properties)); | 1805 object->set_properties(FixedArray::cast(*properties)); |
1791 object->set_elements(FixedArrayBase::cast(*elements)); | 1806 object->set_elements(FixedArrayBase::cast(*elements)); |
1792 for (int i = 0; i < length - 3; ++i) { | 1807 for (int i = 0; i < length - 3; ++i) { |
1793 Handle<Object> value = MaterializeNextValue(); | 1808 Handle<Object> value = MaterializeNextValue(); |
1794 object->FastPropertyAtPut(i, *value); | 1809 object->FastPropertyAtPut(i, *value); |
1795 } | 1810 } |
1796 break; | 1811 break; |
1797 } | 1812 } |
1798 case JS_ARRAY_TYPE: { | 1813 case JS_ARRAY_TYPE: { |
1799 Handle<JSArray> object = | 1814 Handle<JSArray> object = |
1800 isolate_->factory()->NewJSArray(0, map->elements_kind()); | 1815 isolate_->factory()->NewJSArray(0, map->elements_kind()); |
1801 materialized_objects_->Add(object); | 1816 if (object_index < prev_materialized_count_) { |
1817 materialized_objects_->Add(Handle<Object>( | |
1818 previously_materialized_objects_->get(object_index), isolate_)); | |
1819 } else { | |
1820 materialized_objects_->Add(object); | |
1821 } | |
1802 Handle<Object> properties = MaterializeNextValue(); | 1822 Handle<Object> properties = MaterializeNextValue(); |
1803 Handle<Object> elements = MaterializeNextValue(); | 1823 Handle<Object> elements = MaterializeNextValue(); |
1804 Handle<Object> length = MaterializeNextValue(); | 1824 Handle<Object> length = MaterializeNextValue(); |
1805 object->set_properties(FixedArray::cast(*properties)); | 1825 object->set_properties(FixedArray::cast(*properties)); |
1806 object->set_elements(FixedArrayBase::cast(*elements)); | 1826 object->set_elements(FixedArrayBase::cast(*elements)); |
1807 object->set_length(*length); | 1827 object->set_length(*length); |
1808 break; | 1828 break; |
1809 } | 1829 } |
1810 default: | 1830 default: |
1811 PrintF(stderr, | 1831 PrintF(stderr, |
(...skipping 12 matching lines...) Expand all Loading... | |
1824 if (*value == isolate_->heap()->arguments_marker()) { | 1844 if (*value == isolate_->heap()->arguments_marker()) { |
1825 value = MaterializeNextHeapObject(); | 1845 value = MaterializeNextHeapObject(); |
1826 } | 1846 } |
1827 return value; | 1847 return value; |
1828 } | 1848 } |
1829 | 1849 |
1830 | 1850 |
1831 void Deoptimizer::MaterializeHeapObjects(JavaScriptFrameIterator* it) { | 1851 void Deoptimizer::MaterializeHeapObjects(JavaScriptFrameIterator* it) { |
1832 ASSERT_NE(DEBUGGER, bailout_type_); | 1852 ASSERT_NE(DEBUGGER, bailout_type_); |
1833 | 1853 |
1854 MaterializedObjectStore* materialized_store = | |
1855 isolate_->materialized_object_store(); | |
1856 previously_materialized_objects_ = materialized_store->Get(stack_fp_); | |
1857 prev_materialized_count_ = previously_materialized_objects_.is_null() ? | |
1858 0 : previously_materialized_objects_->length(); | |
1859 | |
1834 // Walk all JavaScript output frames with the given frame iterator. | 1860 // Walk all JavaScript output frames with the given frame iterator. |
1835 for (int frame_index = 0; frame_index < jsframe_count(); ++frame_index) { | 1861 for (int frame_index = 0; frame_index < jsframe_count(); ++frame_index) { |
1836 if (frame_index != 0) it->Advance(); | 1862 if (frame_index != 0) it->Advance(); |
1837 JavaScriptFrame* frame = it->frame(); | 1863 JavaScriptFrame* frame = it->frame(); |
1838 jsframe_functions_.Add(handle(frame->function(), isolate_)); | 1864 jsframe_functions_.Add(handle(frame->function(), isolate_)); |
1839 jsframe_has_adapted_arguments_.Add(frame->has_adapted_arguments()); | 1865 jsframe_has_adapted_arguments_.Add(frame->has_adapted_arguments()); |
1840 } | 1866 } |
1841 | 1867 |
1842 // Handlify all tagged object values before triggering any allocation. | 1868 // Handlify all tagged object values before triggering any allocation. |
1843 List<Handle<Object> > values(deferred_objects_tagged_values_.length()); | 1869 List<Handle<Object> > values(deferred_objects_tagged_values_.length()); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1913 reinterpret_cast<void*>(descriptor.slot_address())); | 1939 reinterpret_cast<void*>(descriptor.slot_address())); |
1914 } | 1940 } |
1915 object->ShortPrint(trace_scope_->file()); | 1941 object->ShortPrint(trace_scope_->file()); |
1916 PrintF(trace_scope_->file(), "\n"); | 1942 PrintF(trace_scope_->file(), "\n"); |
1917 } | 1943 } |
1918 } | 1944 } |
1919 | 1945 |
1920 ASSERT(materialization_object_index_ == materialized_objects_->length()); | 1946 ASSERT(materialization_object_index_ == materialized_objects_->length()); |
1921 ASSERT(materialization_value_index_ == materialized_values_->length()); | 1947 ASSERT(materialization_value_index_ == materialized_values_->length()); |
1922 } | 1948 } |
1949 | |
1950 if (prev_materialized_count_ > 0) { | |
1951 materialized_store->Remove(stack_fp_); | |
1952 } | |
1923 } | 1953 } |
1924 | 1954 |
1925 | 1955 |
1926 #ifdef ENABLE_DEBUGGER_SUPPORT | 1956 #ifdef ENABLE_DEBUGGER_SUPPORT |
1927 void Deoptimizer::MaterializeHeapNumbersForDebuggerInspectableFrame( | 1957 void Deoptimizer::MaterializeHeapNumbersForDebuggerInspectableFrame( |
1928 Address parameters_top, | 1958 Address parameters_top, |
1929 uint32_t parameters_size, | 1959 uint32_t parameters_size, |
1930 Address expressions_top, | 1960 Address expressions_top, |
1931 uint32_t expressions_size, | 1961 uint32_t expressions_size, |
1932 DeoptimizedFrameInfo* info) { | 1962 DeoptimizedFrameInfo* info) { |
(...skipping 1008 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2941 UNREACHABLE(); | 2971 UNREACHABLE(); |
2942 return ""; | 2972 return ""; |
2943 } | 2973 } |
2944 | 2974 |
2945 #endif | 2975 #endif |
2946 | 2976 |
2947 | 2977 |
2948 // We can't intermix stack decoding and allocations because | 2978 // We can't intermix stack decoding and allocations because |
2949 // deoptimization infrastracture is not GC safe. | 2979 // deoptimization infrastracture is not GC safe. |
2950 // Thus we build a temporary structure in malloced space. | 2980 // Thus we build a temporary structure in malloced space. |
2951 SlotRef SlotRef::ComputeSlotForNextArgument(TranslationIterator* iterator, | 2981 SlotRef SlotRefValueBuilder::ComputeSlotForNextArgument( |
2952 DeoptimizationInputData* data, | 2982 Translation::Opcode opcode, |
2953 JavaScriptFrame* frame) { | 2983 TranslationIterator* iterator, |
2954 Translation::Opcode opcode = | 2984 DeoptimizationInputData* data, |
2955 static_cast<Translation::Opcode>(iterator->Next()); | 2985 JavaScriptFrame* frame) { |
2956 | |
2957 switch (opcode) { | 2986 switch (opcode) { |
2958 case Translation::BEGIN: | 2987 case Translation::BEGIN: |
2959 case Translation::JS_FRAME: | 2988 case Translation::JS_FRAME: |
2960 case Translation::ARGUMENTS_ADAPTOR_FRAME: | 2989 case Translation::ARGUMENTS_ADAPTOR_FRAME: |
2961 case Translation::CONSTRUCT_STUB_FRAME: | 2990 case Translation::CONSTRUCT_STUB_FRAME: |
2962 case Translation::GETTER_STUB_FRAME: | 2991 case Translation::GETTER_STUB_FRAME: |
2963 case Translation::SETTER_STUB_FRAME: | 2992 case Translation::SETTER_STUB_FRAME: |
2964 // Peeled off before getting here. | 2993 // Peeled off before getting here. |
2965 break; | 2994 break; |
2966 | 2995 |
2967 case Translation::DUPLICATED_OBJECT: | 2996 case Translation::DUPLICATED_OBJECT: { |
2997 return SlotRef::NewDuplicateObject(iterator->Next()); | |
2998 } | |
2999 | |
2968 case Translation::ARGUMENTS_OBJECT: | 3000 case Translation::ARGUMENTS_OBJECT: |
2969 case Translation::CAPTURED_OBJECT: | |
2970 // This can be only emitted for local slots not for argument slots. | 3001 // This can be only emitted for local slots not for argument slots. |
2971 break; | 3002 break; |
2972 | 3003 |
3004 case Translation::CAPTURED_OBJECT: { | |
3005 return SlotRef::NewDeferredObject(iterator->Next()); | |
3006 } | |
3007 | |
2973 case Translation::REGISTER: | 3008 case Translation::REGISTER: |
2974 case Translation::INT32_REGISTER: | 3009 case Translation::INT32_REGISTER: |
2975 case Translation::UINT32_REGISTER: | 3010 case Translation::UINT32_REGISTER: |
2976 case Translation::DOUBLE_REGISTER: | 3011 case Translation::DOUBLE_REGISTER: |
2977 // We are at safepoint which corresponds to call. All registers are | 3012 // We are at safepoint which corresponds to call. All registers are |
2978 // saved by caller so there would be no live registers at this | 3013 // saved by caller so there would be no live registers at this |
2979 // point. Thus these translation commands should not be used. | 3014 // point. Thus these translation commands should not be used. |
2980 break; | 3015 break; |
2981 | 3016 |
2982 case Translation::STACK_SLOT: { | 3017 case Translation::STACK_SLOT: { |
(...skipping 29 matching lines...) Expand all Loading... | |
3012 case Translation::COMPILED_STUB_FRAME: | 3047 case Translation::COMPILED_STUB_FRAME: |
3013 UNREACHABLE(); | 3048 UNREACHABLE(); |
3014 break; | 3049 break; |
3015 } | 3050 } |
3016 | 3051 |
3017 UNREACHABLE(); | 3052 UNREACHABLE(); |
3018 return SlotRef(); | 3053 return SlotRef(); |
3019 } | 3054 } |
3020 | 3055 |
3021 | 3056 |
3022 void SlotRef::ComputeSlotsForArguments(Vector<SlotRef>* args_slots, | 3057 SlotRefValueBuilder::SlotRefValueBuilder(JavaScriptFrame* frame, |
3023 TranslationIterator* it, | 3058 int inlined_jsframe_index, |
3024 DeoptimizationInputData* data, | 3059 int formal_parameter_count) |
3025 JavaScriptFrame* frame) { | 3060 : current_slot_(0), args_length_(-1), first_slot_index_(-1) { |
3026 // Process the translation commands for the arguments. | 3061 DisallowHeapAllocation no_gc; |
3027 | 3062 |
3028 // Skip the translation command for the receiver. | |
3029 it->Skip(Translation::NumberOfOperandsFor( | |
3030 static_cast<Translation::Opcode>(it->Next()))); | |
3031 | |
3032 // Compute slots for arguments. | |
3033 for (int i = 0; i < args_slots->length(); ++i) { | |
3034 (*args_slots)[i] = ComputeSlotForNextArgument(it, data, frame); | |
3035 } | |
3036 } | |
3037 | |
3038 | |
3039 Vector<SlotRef> SlotRef::ComputeSlotMappingForArguments( | |
3040 JavaScriptFrame* frame, | |
3041 int inlined_jsframe_index, | |
3042 int formal_parameter_count) { | |
3043 DisallowHeapAllocation no_gc; | |
3044 int deopt_index = Safepoint::kNoDeoptimizationIndex; | 3063 int deopt_index = Safepoint::kNoDeoptimizationIndex; |
3045 DeoptimizationInputData* data = | 3064 DeoptimizationInputData* data = |
3046 static_cast<OptimizedFrame*>(frame)->GetDeoptimizationData(&deopt_index); | 3065 static_cast<OptimizedFrame*>(frame)->GetDeoptimizationData(&deopt_index); |
3047 TranslationIterator it(data->TranslationByteArray(), | 3066 TranslationIterator it(data->TranslationByteArray(), |
3048 data->TranslationIndex(deopt_index)->value()); | 3067 data->TranslationIndex(deopt_index)->value()); |
3049 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); | 3068 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); |
3050 ASSERT(opcode == Translation::BEGIN); | 3069 ASSERT(opcode == Translation::BEGIN); |
3051 it.Next(); // Drop frame count. | 3070 it.Next(); // Drop frame count. |
3071 | |
3072 stack_frame_id_ = frame->fp(); | |
3073 | |
3052 int jsframe_count = it.Next(); | 3074 int jsframe_count = it.Next(); |
3053 USE(jsframe_count); | 3075 USE(jsframe_count); |
3054 ASSERT(jsframe_count > inlined_jsframe_index); | 3076 ASSERT(jsframe_count > inlined_jsframe_index); |
3055 int jsframes_to_skip = inlined_jsframe_index; | 3077 int jsframes_to_skip = inlined_jsframe_index; |
3056 while (true) { | 3078 int number_of_slots = -1; // Number of slots inside our frame (yet unknown) |
3079 bool should_deopt = false; | |
3080 while (number_of_slots != 0) { | |
3057 opcode = static_cast<Translation::Opcode>(it.Next()); | 3081 opcode = static_cast<Translation::Opcode>(it.Next()); |
3082 bool processed = false; | |
3058 if (opcode == Translation::ARGUMENTS_ADAPTOR_FRAME) { | 3083 if (opcode == Translation::ARGUMENTS_ADAPTOR_FRAME) { |
3059 if (jsframes_to_skip == 0) { | 3084 if (jsframes_to_skip == 0) { |
3060 ASSERT(Translation::NumberOfOperandsFor(opcode) == 2); | 3085 ASSERT(Translation::NumberOfOperandsFor(opcode) == 2); |
3061 | 3086 |
3062 it.Skip(1); // literal id | 3087 it.Skip(1); // literal id |
3063 int height = it.Next(); | 3088 int height = it.Next(); |
3064 | 3089 |
3090 // Skip the translation command for the receiver. | |
3091 it.Skip(Translation::NumberOfOperandsFor( | |
3092 static_cast<Translation::Opcode>(it.Next()))); | |
3093 | |
3065 // We reached the arguments adaptor frame corresponding to the | 3094 // We reached the arguments adaptor frame corresponding to the |
3066 // inlined function in question. Number of arguments is height - 1. | 3095 // inlined function in question. Number of arguments is height - 1. |
3067 Vector<SlotRef> args_slots = | 3096 first_slot_index_ = slot_refs_.length(); |
3068 Vector<SlotRef>::New(height - 1); // Minus receiver. | 3097 args_length_ = height - 1; |
3069 ComputeSlotsForArguments(&args_slots, &it, data, frame); | 3098 number_of_slots = height - 1; |
3070 return args_slots; | 3099 processed = true; |
3071 } | 3100 } |
3072 } else if (opcode == Translation::JS_FRAME) { | 3101 } else if (opcode == Translation::JS_FRAME) { |
3073 if (jsframes_to_skip == 0) { | 3102 if (jsframes_to_skip == 0) { |
3074 // Skip over operands to advance to the next opcode. | 3103 // Skip over operands to advance to the next opcode. |
3075 it.Skip(Translation::NumberOfOperandsFor(opcode)); | 3104 it.Skip(Translation::NumberOfOperandsFor(opcode)); |
3076 | 3105 |
3106 // Skip the translation command for the receiver. | |
3107 it.Skip(Translation::NumberOfOperandsFor( | |
3108 static_cast<Translation::Opcode>(it.Next()))); | |
3109 | |
3077 // We reached the frame corresponding to the inlined function | 3110 // We reached the frame corresponding to the inlined function |
3078 // in question. Process the translation commands for the | 3111 // in question. Process the translation commands for the |
3079 // arguments. Number of arguments is equal to the number of | 3112 // arguments. Number of arguments is equal to the number of |
3080 // format parameter count. | 3113 // format parameter count. |
3081 Vector<SlotRef> args_slots = | 3114 first_slot_index_ = slot_refs_.length(); |
3082 Vector<SlotRef>::New(formal_parameter_count); | 3115 args_length_ = formal_parameter_count; |
3083 ComputeSlotsForArguments(&args_slots, &it, data, frame); | 3116 number_of_slots = formal_parameter_count; |
3084 return args_slots; | 3117 processed = true; |
3085 } | 3118 } |
3086 jsframes_to_skip--; | 3119 jsframes_to_skip--; |
3087 } | 3120 } else if (opcode != Translation::BEGIN && |
3088 | 3121 opcode != Translation::CONSTRUCT_STUB_FRAME) { |
3089 // Skip over operands to advance to the next opcode. | 3122 slot_refs_.Add(ComputeSlotForNextArgument(opcode, &it, data, frame)); |
3090 it.Skip(Translation::NumberOfOperandsFor(opcode)); | 3123 |
3124 if (first_slot_index_ >= 0) { | |
3125 // We have found the beginning of our frame -> make sure we count | |
3126 // the nested slots of captured objects | |
3127 number_of_slots--; | |
3128 SlotRef& slot = slot_refs_.last(); | |
3129 if (slot.Representation() == SlotRef::DEFERRED_OBJECT) { | |
3130 number_of_slots += slot.DeferredObjectLength(); | |
3131 } | |
3132 if (slot.Representation() == SlotRef::DEFERRED_OBJECT || | |
3133 slot.Representation() == SlotRef::DUPLICATE_OBJECT) { | |
3134 should_deopt = true; | |
3135 } | |
3136 } | |
3137 | |
3138 processed = true; | |
3139 } | |
3140 if (!processed) { | |
3141 // Skip over operands to advance to the next opcode. | |
3142 it.Skip(Translation::NumberOfOperandsFor(opcode)); | |
3143 } | |
3144 } | |
3145 if (should_deopt) { | |
3146 List<JSFunction*> functions(2); | |
3147 frame->GetFunctions(&functions); | |
3148 Deoptimizer::DeoptimizeFunction(functions[0]); | |
3149 } | |
3150 } | |
3151 | |
3152 | |
3153 Handle<Object> SlotRef::GetValue(Isolate* isolate) { | |
3154 switch (representation_) { | |
3155 case TAGGED: | |
3156 return Handle<Object>(Memory::Object_at(addr_), isolate); | |
3157 | |
3158 case INT32: { | |
3159 int value = Memory::int32_at(addr_); | |
3160 if (Smi::IsValid(value)) { | |
3161 return Handle<Object>(Smi::FromInt(value), isolate); | |
3162 } else { | |
3163 return isolate->factory()->NewNumberFromInt(value); | |
3164 } | |
3165 } | |
3166 | |
3167 case UINT32: { | |
3168 uint32_t value = Memory::uint32_at(addr_); | |
3169 if (value <= static_cast<uint32_t>(Smi::kMaxValue)) { | |
3170 return Handle<Object>(Smi::FromInt(static_cast<int>(value)), isolate); | |
3171 } else { | |
3172 return isolate->factory()->NewNumber(static_cast<double>(value)); | |
3173 } | |
3174 } | |
3175 | |
3176 case DOUBLE: { | |
3177 double value = read_double_value(addr_); | |
3178 return isolate->factory()->NewNumber(value); | |
3179 } | |
3180 | |
3181 case LITERAL: | |
3182 return literal_; | |
3183 | |
3184 default: | |
3185 UNREACHABLE(); | |
3186 return Handle<Object>::null(); | |
3187 } | |
3188 } | |
3189 | |
3190 | |
3191 void SlotRefValueBuilder::Prepare(Isolate* isolate) { | |
3192 MaterializedObjectStore* materialized_store = | |
3193 isolate->materialized_object_store(); | |
3194 previously_materialized_objects_ = materialized_store->Get(stack_frame_id_); | |
3195 prev_materialized_count_ = previously_materialized_objects_.is_null() ? | |
danno
2014/01/28 15:44:34
nit: funky formatting. Put the ? on the next line
Jarin
2014/01/28 19:52:30
Done.
| |
3196 0 : previously_materialized_objects_->length(); | |
3197 | |
3198 // Now skip the initial segment (we need to get over the segment | |
danno
2014/01/28 15:44:34
What do you mean by "first segment"?
Jarin
2014/01/28 19:52:30
I mean materialized objects of the callers inlined
| |
3199 // to recover the captured objects in case we have duplicate | |
3200 // objects) | |
3201 while (current_slot_ < first_slot_index_) { | |
3202 GetNext(isolate, 0); | |
3203 } | |
3204 ASSERT(current_slot_ == first_slot_index_); | |
3205 } | |
3206 | |
3207 | |
3208 Handle<Object> SlotRefValueBuilder::GetPreviouslyMaterialized( | |
3209 Isolate* isolate, int length) { | |
3210 int object_index = materialized_objects_.length(); | |
danno
2014/01/28 15:44:34
nit: indent should be 2, not 4
Jarin
2014/01/28 19:52:30
Done.
| |
3211 Handle<Object> return_value = Handle<Object>( | |
3212 previously_materialized_objects_->get(object_index), isolate); | |
3213 materialized_objects_.Add(return_value); | |
3214 | |
3215 // Now need to skip all nested objects (and possibly read them from | |
3216 // the materialization store, too) | |
3217 for (int i = 0; i < length; i++) { | |
3218 SlotRef& slot = slot_refs_[current_slot_]; | |
3219 current_slot_++; | |
3220 | |
3221 // For nested deferred objects, we need to read its properties | |
3222 if (slot.Representation() == SlotRef::DEFERRED_OBJECT) { | |
3223 length += slot.DeferredObjectLength(); | |
3224 } | |
3225 | |
3226 // For nested deferred and duplicate objects, we need to put them into | |
3227 // our materialization array | |
3228 if (slot.Representation() == SlotRef::DEFERRED_OBJECT || | |
3229 slot.Representation() == SlotRef::DUPLICATE_OBJECT) { | |
3230 int nested_object_index = materialized_objects_.length(); | |
3231 Handle<Object> nested_object = Handle<Object>( | |
3232 previously_materialized_objects_->get(nested_object_index), | |
3233 isolate); | |
3234 materialized_objects_.Add(nested_object); | |
3235 } | |
3236 } | |
3237 | |
3238 return return_value; | |
3239 } | |
3240 | |
3241 | |
3242 Handle<Object> SlotRefValueBuilder::GetNext(Isolate* isolate, int lvl) { | |
3243 SlotRef& slot = slot_refs_[current_slot_]; | |
3244 current_slot_++; | |
3245 switch (slot.Representation()) { | |
3246 case SlotRef::TAGGED: | |
3247 case SlotRef::INT32: | |
3248 case SlotRef::UINT32: | |
3249 case SlotRef::DOUBLE: | |
3250 case SlotRef::LITERAL: { | |
3251 return slot.GetValue(isolate); | |
3252 } | |
3253 case SlotRef::DEFERRED_OBJECT: { | |
3254 int length = slot.DeferredObjectLength(); | |
3255 ASSERT(slot_refs_[current_slot_].Representation() == SlotRef::LITERAL || | |
3256 slot_refs_[current_slot_].Representation() == SlotRef::TAGGED); | |
3257 | |
3258 int object_index = materialized_objects_.length(); | |
3259 if (object_index < prev_materialized_count_) { | |
danno
2014/01/28 15:44:34
This confuses me a bit. Isn't it the case that whe
Jarin
2014/01/28 19:52:30
At the moment, it would not be correct as the code
| |
3260 return GetPreviouslyMaterialized(isolate, length); | |
3261 } | |
3262 | |
3263 Handle<Object> map_object = slot_refs_[current_slot_].GetValue(isolate); | |
3264 Handle<Map> map = Map::GeneralizeAllFieldRepresentations( | |
3265 Handle<Map>::cast(map_object), Representation::Tagged()); | |
3266 current_slot_++; | |
3267 // TODO(jarin) this should be unified with the code in | |
3268 // Deoptimizer::MaterializeNextHeapObject() | |
3269 switch (map->instance_type()) { | |
3270 case HEAP_NUMBER_TYPE: { | |
3271 // Reuse the HeapNumber value directly as it is already properly | |
3272 // tagged and skip materializing the HeapNumber explicitly. | |
3273 Handle<Object> object = GetNext(isolate, lvl + 1); | |
3274 materialized_objects_.Add(object); | |
3275 return object; | |
3276 } | |
3277 case JS_OBJECT_TYPE: { | |
3278 Handle<JSObject> object = | |
3279 isolate->factory()->NewJSObjectFromMap(map, NOT_TENURED, false); | |
3280 materialized_objects_.Add(object); | |
3281 Handle<Object> properties = GetNext(isolate, lvl + 1); | |
3282 Handle<Object> elements = GetNext(isolate, lvl + 1); | |
3283 object->set_properties(FixedArray::cast(*properties)); | |
3284 object->set_elements(FixedArrayBase::cast(*elements)); | |
3285 for (int i = 0; i < length - 3; ++i) { | |
3286 Handle<Object> value = GetNext(isolate, lvl + 1); | |
3287 object->FastPropertyAtPut(i, *value); | |
3288 } | |
3289 return object; | |
3290 } | |
3291 case JS_ARRAY_TYPE: { | |
3292 Handle<JSArray> object = | |
3293 isolate->factory()->NewJSArray(0, map->elements_kind()); | |
3294 materialized_objects_.Add(object); | |
3295 Handle<Object> properties = GetNext(isolate, lvl + 1); | |
3296 Handle<Object> elements = GetNext(isolate, lvl + 1); | |
3297 Handle<Object> length = GetNext(isolate, lvl + 1); | |
3298 object->set_properties(FixedArray::cast(*properties)); | |
3299 object->set_elements(FixedArrayBase::cast(*elements)); | |
3300 object->set_length(*length); | |
3301 return object; | |
3302 } | |
3303 default: | |
3304 PrintF(stderr, | |
3305 "[couldn't handle instance type %d]\n", map->instance_type()); | |
3306 UNREACHABLE(); | |
3307 break; | |
3308 } | |
3309 UNREACHABLE(); | |
3310 } | |
3311 | |
3312 case SlotRef::DUPLICATE_OBJECT: { | |
3313 int object_index = slot.DuplicateObjectId(); | |
3314 Handle<Object> object = materialized_objects_[object_index]; | |
3315 materialized_objects_.Add(object); | |
3316 return object; | |
3317 } | |
3318 default: | |
3319 UNREACHABLE(); | |
3320 break; | |
3091 } | 3321 } |
3092 | 3322 |
3093 UNREACHABLE(); | 3323 UNREACHABLE(); |
3094 return Vector<SlotRef>(); | 3324 return Handle<Object>::null(); |
3325 } | |
3326 | |
3327 | |
3328 void SlotRefValueBuilder::Finish(Isolate* isolate) { | |
3329 // We should have processed all slot | |
3330 ASSERT(slot_refs_.length() == current_slot_); | |
3331 | |
3332 if (materialized_objects_.length() > prev_materialized_count_) { | |
3333 // We have materialized some new objects, so we have to store them | |
3334 // to prevent duplicate materialization | |
3335 Handle<FixedArray> array = isolate->factory()->NewFixedArray( | |
3336 materialized_objects_.length()); | |
3337 for (int i = 0; i < materialized_objects_.length(); i++) { | |
3338 array->set(i, *(materialized_objects_.at(i))); | |
3339 } | |
3340 isolate->materialized_object_store()->Set(stack_frame_id_, array); | |
3341 } | |
3342 } | |
3343 | |
3344 | |
3345 Handle<FixedArray> MaterializedObjectStore::Get(Address fp) { | |
3346 int index = StackIdToIndex(fp); | |
3347 if (index == -1) { | |
3348 return Handle<FixedArray>::null(); | |
3349 } | |
3350 Handle<FixedArray> array = GetStackEntries(); | |
3351 ASSERT(array->length() > index); | |
3352 return Handle<FixedArray>::cast(Handle<Object>(array->get(index), | |
3353 isolate())); | |
3354 } | |
3355 | |
3356 | |
3357 void MaterializedObjectStore::Set(Address fp, | |
3358 Handle<FixedArray> materialized_objects) { | |
3359 int index = StackIdToIndex(fp); | |
3360 if (index == -1) { | |
3361 index = frame_fps_.length(); | |
3362 frame_fps_.Add(fp); | |
3363 } | |
3364 EnsureStackEntries(index + 1); | |
3365 Handle<FixedArray> array = GetStackEntries(); | |
3366 array->set(index, *materialized_objects); | |
3367 } | |
3368 | |
3369 | |
3370 void MaterializedObjectStore::Remove(Address fp) { | |
3371 int index = StackIdToIndex(fp); | |
3372 ASSERT(index >= 0); | |
3373 | |
3374 frame_fps_.Remove(index); | |
3375 Handle<FixedArray> array = GetStackEntries(); | |
3376 ASSERT(array->length() > index); | |
3377 for (int i = index; i < frame_fps_.length(); i++) { | |
3378 array->set(i, array->get(i + 1)); | |
3379 } | |
3380 array->set(frame_fps_.length(), isolate()->heap()->undefined_value()); | |
3381 } | |
3382 | |
3383 | |
3384 int MaterializedObjectStore::StackIdToIndex(Address fp) { | |
3385 for (int i = 0; i < frame_fps_.length(); i++) { | |
3386 if (frame_fps_[i] == fp) { | |
3387 return i; | |
3388 } | |
3389 } | |
3390 return -1; | |
3391 } | |
3392 | |
3393 | |
3394 Handle<FixedArray> MaterializedObjectStore::GetStackEntries() { | |
3395 return Handle<FixedArray>::cast( | |
3396 Handle<Object>(isolate()->heap()->materialized_objects()->get(0), | |
3397 isolate())); | |
3398 } | |
3399 | |
3400 | |
3401 Handle<FixedArray> MaterializedObjectStore::EnsureStackEntries(int length) { | |
3402 Handle<FixedArray> array = GetStackEntries(); | |
3403 if (array->length() >= length) { | |
3404 return array; | |
3405 } | |
3406 | |
3407 int new_length = length > 10 ? length : 10; | |
3408 if (new_length < 2 * array->length()) { | |
3409 new_length = 2 * array->length(); | |
3410 } | |
3411 | |
3412 Handle<FixedArray> new_array = | |
3413 isolate()->factory()->NewFixedArray(new_length, TENURED); | |
3414 for (int i = 0; i < array->length(); i++) { | |
3415 new_array->set(i, array->get(i)); | |
3416 } | |
3417 for (int i = array->length(); i < length; i++) { | |
3418 new_array->set(i, isolate()->heap()->undefined_value()); | |
3419 } | |
3420 isolate()->heap()->materialized_objects()->set(0, *new_array); | |
3421 return new_array; | |
3095 } | 3422 } |
3096 | 3423 |
3097 #ifdef ENABLE_DEBUGGER_SUPPORT | 3424 #ifdef ENABLE_DEBUGGER_SUPPORT |
3098 | 3425 |
3099 DeoptimizedFrameInfo::DeoptimizedFrameInfo(Deoptimizer* deoptimizer, | 3426 DeoptimizedFrameInfo::DeoptimizedFrameInfo(Deoptimizer* deoptimizer, |
3100 int frame_index, | 3427 int frame_index, |
3101 bool has_arguments_adaptor, | 3428 bool has_arguments_adaptor, |
3102 bool has_construct_stub) { | 3429 bool has_construct_stub) { |
3103 FrameDescription* output_frame = deoptimizer->output_[frame_index]; | 3430 FrameDescription* output_frame = deoptimizer->output_[frame_index]; |
3104 function_ = output_frame->GetFunction(); | 3431 function_ = output_frame->GetFunction(); |
(...skipping 30 matching lines...) Expand all Loading... | |
3135 | 3462 |
3136 void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) { | 3463 void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) { |
3137 v->VisitPointer(BitCast<Object**>(&function_)); | 3464 v->VisitPointer(BitCast<Object**>(&function_)); |
3138 v->VisitPointers(parameters_, parameters_ + parameters_count_); | 3465 v->VisitPointers(parameters_, parameters_ + parameters_count_); |
3139 v->VisitPointers(expression_stack_, expression_stack_ + expression_count_); | 3466 v->VisitPointers(expression_stack_, expression_stack_ + expression_count_); |
3140 } | 3467 } |
3141 | 3468 |
3142 #endif // ENABLE_DEBUGGER_SUPPORT | 3469 #endif // ENABLE_DEBUGGER_SUPPORT |
3143 | 3470 |
3144 } } // namespace v8::internal | 3471 } } // namespace v8::internal |
OLD | NEW |