OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "v8.h" | 5 #include "v8.h" |
6 | 6 |
7 #include "accessors.h" | 7 #include "accessors.h" |
8 #include "allocation-site-scopes.h" | 8 #include "allocation-site-scopes.h" |
9 #include "api.h" | 9 #include "api.h" |
10 #include "arguments.h" | 10 #include "arguments.h" |
(...skipping 10207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10218 JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value)); | 10218 JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value)); |
10219 } | 10219 } |
10220 | 10220 |
10221 // Now some logic for the maps of the objects that are created by using this | 10221 // Now some logic for the maps of the objects that are created by using this |
10222 // function as a constructor. | 10222 // function as a constructor. |
10223 if (function->has_initial_map()) { | 10223 if (function->has_initial_map()) { |
10224 // If the function has allocated the initial map replace it with a | 10224 // If the function has allocated the initial map replace it with a |
10225 // copy containing the new prototype. Also complete any in-object | 10225 // copy containing the new prototype. Also complete any in-object |
10226 // slack tracking that is in progress at this point because it is | 10226 // slack tracking that is in progress at this point because it is |
10227 // still tracking the old copy. | 10227 // still tracking the old copy. |
10228 if (function->IsInobjectSlackTrackingInProgress()) { | 10228 if (function->shared()->IsInobjectSlackTrackingInProgress()) { |
10229 function->CompleteInobjectSlackTracking(); | 10229 function->shared()->CompleteInobjectSlackTracking(); |
10230 } | 10230 } |
10231 Handle<Map> new_map = Map::Copy(handle(function->initial_map())); | 10231 Handle<Map> new_map = Map::Copy(handle(function->initial_map())); |
10232 new_map->set_prototype(*value); | 10232 new_map->set_prototype(*value); |
10233 | 10233 |
10234 // If the function is used as the global Array function, cache the | 10234 // If the function is used as the global Array function, cache the |
10235 // initial map (and transitioned versions) in the native context. | 10235 // initial map (and transitioned versions) in the native context. |
10236 Context* native_context = function->context()->native_context(); | 10236 Context* native_context = function->context()->native_context(); |
10237 Object* array_function = native_context->get(Context::ARRAY_FUNCTION_INDEX); | 10237 Object* array_function = native_context->get(Context::ARRAY_FUNCTION_INDEX); |
10238 if (array_function->IsJSFunction() && | 10238 if (array_function->IsJSFunction() && |
10239 *function == JSFunction::cast(array_function)) { | 10239 *function == JSFunction::cast(array_function)) { |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10328 if (function->has_instance_prototype()) { | 10328 if (function->has_instance_prototype()) { |
10329 prototype = handle(function->instance_prototype(), isolate); | 10329 prototype = handle(function->instance_prototype(), isolate); |
10330 } else { | 10330 } else { |
10331 prototype = isolate->factory()->NewFunctionPrototype(function); | 10331 prototype = isolate->factory()->NewFunctionPrototype(function); |
10332 } | 10332 } |
10333 map->set_inobject_properties(in_object_properties); | 10333 map->set_inobject_properties(in_object_properties); |
10334 map->set_unused_property_fields(in_object_properties); | 10334 map->set_unused_property_fields(in_object_properties); |
10335 map->set_prototype(*prototype); | 10335 map->set_prototype(*prototype); |
10336 ASSERT(map->has_fast_object_elements()); | 10336 ASSERT(map->has_fast_object_elements()); |
10337 | 10337 |
| 10338 if (!function->shared()->is_generator()) { |
| 10339 function->shared()->StartInobjectSlackTracking(*map); |
| 10340 } |
| 10341 |
10338 // Finally link initial map and constructor function. | 10342 // Finally link initial map and constructor function. |
10339 function->set_initial_map(*map); | 10343 function->set_initial_map(*map); |
10340 map->set_constructor(*function); | 10344 map->set_constructor(*function); |
10341 | |
10342 if (!function->shared()->is_generator()) { | |
10343 function->StartInobjectSlackTracking(); | |
10344 } | |
10345 } | 10345 } |
10346 | 10346 |
10347 | 10347 |
10348 void JSFunction::SetInstanceClassName(String* name) { | 10348 void JSFunction::SetInstanceClassName(String* name) { |
10349 shared()->set_instance_class_name(name); | 10349 shared()->set_instance_class_name(name); |
10350 } | 10350 } |
10351 | 10351 |
10352 | 10352 |
10353 void JSFunction::PrintName(FILE* out) { | 10353 void JSFunction::PrintName(FILE* out) { |
10354 SmartArrayPointer<char> name = shared()->DebugName()->ToCString(); | 10354 SmartArrayPointer<char> name = shared()->DebugName()->ToCString(); |
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10719 ASSERT(!id.IsNone()); | 10719 ASSERT(!id.IsNone()); |
10720 Code* unoptimized = code(); | 10720 Code* unoptimized = code(); |
10721 DeoptimizationOutputData* data = | 10721 DeoptimizationOutputData* data = |
10722 DeoptimizationOutputData::cast(unoptimized->deoptimization_data()); | 10722 DeoptimizationOutputData::cast(unoptimized->deoptimization_data()); |
10723 unsigned ignore = Deoptimizer::GetOutputInfo(data, id, this); | 10723 unsigned ignore = Deoptimizer::GetOutputInfo(data, id, this); |
10724 USE(ignore); | 10724 USE(ignore); |
10725 return true; // Return true if there was no ASSERT. | 10725 return true; // Return true if there was no ASSERT. |
10726 } | 10726 } |
10727 | 10727 |
10728 | 10728 |
10729 void JSFunction::StartInobjectSlackTracking() { | 10729 void SharedFunctionInfo::StartInobjectSlackTracking(Map* map) { |
10730 ASSERT(has_initial_map() && !IsInobjectSlackTrackingInProgress()); | 10730 ASSERT(!IsInobjectSlackTrackingInProgress()); |
10731 | 10731 |
10732 if (!FLAG_clever_optimizations) return; | 10732 if (!FLAG_clever_optimizations) return; |
10733 Map* map = initial_map(); | |
10734 | 10733 |
10735 // Only initiate the tracking the first time. | 10734 // Only initiate the tracking the first time. |
10736 if (map->done_inobject_slack_tracking()) return; | 10735 if (live_objects_may_exist()) return; |
10737 map->set_done_inobject_slack_tracking(true); | 10736 set_live_objects_may_exist(true); |
10738 | 10737 |
10739 // No tracking during the snapshot construction phase. | 10738 // No tracking during the snapshot construction phase. |
10740 Isolate* isolate = GetIsolate(); | 10739 Isolate* isolate = GetIsolate(); |
10741 if (isolate->serializer_enabled()) return; | 10740 if (isolate->serializer_enabled()) return; |
10742 | 10741 |
10743 if (map->unused_property_fields() == 0) return; | 10742 if (map->unused_property_fields() == 0) return; |
10744 | 10743 |
10745 map->set_construction_count(kGenerousAllocationCount); | 10744 // Nonzero counter is a leftover from the previous attempt interrupted |
| 10745 // by GC, keep it. |
| 10746 if (construction_count() == 0) { |
| 10747 set_construction_count(kGenerousAllocationCount); |
| 10748 } |
| 10749 set_initial_map(map); |
| 10750 Builtins* builtins = isolate->builtins(); |
| 10751 ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubGeneric), |
| 10752 construct_stub()); |
| 10753 set_construct_stub(builtins->builtin(Builtins::kJSConstructStubCountdown)); |
10746 } | 10754 } |
10747 | 10755 |
10748 | 10756 |
| 10757 // Called from GC, hence reinterpret_cast and unchecked accessors. |
| 10758 void SharedFunctionInfo::DetachInitialMap() { |
| 10759 Map* map = reinterpret_cast<Map*>(initial_map()); |
| 10760 |
| 10761 // Make the map remember to restore the link if it survives the GC. |
| 10762 map->set_bit_field2( |
| 10763 map->bit_field2() | (1 << Map::kAttachedToSharedFunctionInfo)); |
| 10764 |
| 10765 // Undo state changes made by StartInobjectTracking (except the |
| 10766 // construction_count). This way if the initial map does not survive the GC |
| 10767 // then StartInobjectTracking will be called again the next time the |
| 10768 // constructor is called. The countdown will continue and (possibly after |
| 10769 // several more GCs) CompleteInobjectSlackTracking will eventually be called. |
| 10770 Heap* heap = map->GetHeap(); |
| 10771 set_initial_map(heap->undefined_value()); |
| 10772 Builtins* builtins = heap->isolate()->builtins(); |
| 10773 ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubCountdown), |
| 10774 *RawField(this, kConstructStubOffset)); |
| 10775 set_construct_stub(builtins->builtin(Builtins::kJSConstructStubGeneric)); |
| 10776 // It is safe to clear the flag: it will be set again if the map is live. |
| 10777 set_live_objects_may_exist(false); |
| 10778 } |
| 10779 |
| 10780 |
| 10781 // Called from GC, hence reinterpret_cast and unchecked accessors. |
| 10782 void SharedFunctionInfo::AttachInitialMap(Map* map) { |
| 10783 map->set_bit_field2( |
| 10784 map->bit_field2() & ~(1 << Map::kAttachedToSharedFunctionInfo)); |
| 10785 |
| 10786 // Resume inobject slack tracking. |
| 10787 set_initial_map(map); |
| 10788 Builtins* builtins = map->GetHeap()->isolate()->builtins(); |
| 10789 ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubGeneric), |
| 10790 *RawField(this, kConstructStubOffset)); |
| 10791 set_construct_stub(builtins->builtin(Builtins::kJSConstructStubCountdown)); |
| 10792 // The map survived the gc, so there may be objects referencing it. |
| 10793 set_live_objects_may_exist(true); |
| 10794 } |
| 10795 |
| 10796 |
10749 void SharedFunctionInfo::ResetForNewContext(int new_ic_age) { | 10797 void SharedFunctionInfo::ResetForNewContext(int new_ic_age) { |
10750 code()->ClearInlineCaches(); | 10798 code()->ClearInlineCaches(); |
10751 // If we clear ICs, we need to clear the type feedback vector too, since | 10799 // If we clear ICs, we need to clear the type feedback vector too, since |
10752 // CallICs are synced with a feedback vector slot. | 10800 // CallICs are synced with a feedback vector slot. |
10753 ClearTypeFeedbackInfo(); | 10801 ClearTypeFeedbackInfo(); |
10754 set_ic_age(new_ic_age); | 10802 set_ic_age(new_ic_age); |
10755 if (code()->kind() == Code::FUNCTION) { | 10803 if (code()->kind() == Code::FUNCTION) { |
10756 code()->set_profiler_ticks(0); | 10804 code()->set_profiler_ticks(0); |
10757 if (optimization_disabled() && | 10805 if (optimization_disabled() && |
10758 opt_count() >= FLAG_max_opt_count) { | 10806 opt_count() >= FLAG_max_opt_count) { |
(...skipping 19 matching lines...) Expand all Loading... |
10778 int slack = *reinterpret_cast<int*>(data); | 10826 int slack = *reinterpret_cast<int*>(data); |
10779 map->set_inobject_properties(map->inobject_properties() - slack); | 10827 map->set_inobject_properties(map->inobject_properties() - slack); |
10780 map->set_unused_property_fields(map->unused_property_fields() - slack); | 10828 map->set_unused_property_fields(map->unused_property_fields() - slack); |
10781 map->set_instance_size(map->instance_size() - slack * kPointerSize); | 10829 map->set_instance_size(map->instance_size() - slack * kPointerSize); |
10782 | 10830 |
10783 // Visitor id might depend on the instance size, recalculate it. | 10831 // Visitor id might depend on the instance size, recalculate it. |
10784 map->set_visitor_id(StaticVisitorBase::GetVisitorId(map)); | 10832 map->set_visitor_id(StaticVisitorBase::GetVisitorId(map)); |
10785 } | 10833 } |
10786 | 10834 |
10787 | 10835 |
10788 void JSFunction::CompleteInobjectSlackTracking() { | 10836 void SharedFunctionInfo::CompleteInobjectSlackTracking() { |
10789 ASSERT(has_initial_map()); | 10837 ASSERT(live_objects_may_exist() && IsInobjectSlackTrackingInProgress()); |
10790 Map* map = initial_map(); | 10838 Map* map = Map::cast(initial_map()); |
10791 | 10839 |
10792 ASSERT(map->done_inobject_slack_tracking()); | 10840 Heap* heap = map->GetHeap(); |
10793 map->set_construction_count(kNoSlackTracking); | 10841 set_initial_map(heap->undefined_value()); |
| 10842 Builtins* builtins = heap->isolate()->builtins(); |
| 10843 ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubCountdown), |
| 10844 construct_stub()); |
| 10845 set_construct_stub(builtins->builtin(Builtins::kJSConstructStubGeneric)); |
10794 | 10846 |
10795 int slack = map->unused_property_fields(); | 10847 int slack = map->unused_property_fields(); |
10796 map->TraverseTransitionTree(&GetMinInobjectSlack, &slack); | 10848 map->TraverseTransitionTree(&GetMinInobjectSlack, &slack); |
10797 if (slack != 0) { | 10849 if (slack != 0) { |
10798 // Resize the initial map and all maps in its transition tree. | 10850 // Resize the initial map and all maps in its transition tree. |
10799 map->TraverseTransitionTree(&ShrinkInstanceSize, &slack); | 10851 map->TraverseTransitionTree(&ShrinkInstanceSize, &slack); |
| 10852 |
| 10853 // Give the correct expected_nof_properties to initial maps created later. |
| 10854 ASSERT(expected_nof_properties() >= slack); |
| 10855 set_expected_nof_properties(expected_nof_properties() - slack); |
10800 } | 10856 } |
10801 } | 10857 } |
10802 | 10858 |
10803 | 10859 |
10804 int SharedFunctionInfo::SearchOptimizedCodeMap(Context* native_context, | 10860 int SharedFunctionInfo::SearchOptimizedCodeMap(Context* native_context, |
10805 BailoutId osr_ast_id) { | 10861 BailoutId osr_ast_id) { |
10806 DisallowHeapAllocation no_gc; | 10862 DisallowHeapAllocation no_gc; |
10807 ASSERT(native_context->IsNativeContext()); | 10863 ASSERT(native_context->IsNativeContext()); |
10808 if (!FLAG_cache_optimized_code) return -1; | 10864 if (!FLAG_cache_optimized_code) return -1; |
10809 Object* value = optimized_code_map(); | 10865 Object* value = optimized_code_map(); |
(...skipping 6453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
17263 #define ERROR_MESSAGES_TEXTS(C, T) T, | 17319 #define ERROR_MESSAGES_TEXTS(C, T) T, |
17264 static const char* error_messages_[] = { | 17320 static const char* error_messages_[] = { |
17265 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 17321 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
17266 }; | 17322 }; |
17267 #undef ERROR_MESSAGES_TEXTS | 17323 #undef ERROR_MESSAGES_TEXTS |
17268 return error_messages_[reason]; | 17324 return error_messages_[reason]; |
17269 } | 17325 } |
17270 | 17326 |
17271 | 17327 |
17272 } } // namespace v8::internal | 17328 } } // namespace v8::internal |
OLD | NEW |