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->shared()->IsInobjectSlackTrackingInProgress()) { | 10228 if (function->IsInobjectSlackTrackingInProgress()) { |
10229 function->shared()->CompleteInobjectSlackTracking(); | 10229 function->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 | |
10342 // Finally link initial map and constructor function. | 10338 // Finally link initial map and constructor function. |
10343 function->set_initial_map(*map); | 10339 function->set_initial_map(*map); |
10344 map->set_constructor(*function); | 10340 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 SharedFunctionInfo::StartInobjectSlackTracking(Map* map) { | 10729 void JSFunction::StartInobjectSlackTracking() { |
10730 ASSERT(!IsInobjectSlackTrackingInProgress()); | 10730 ASSERT(has_initial_map() && !IsInobjectSlackTrackingInProgress()); |
10731 | 10731 |
10732 if (!FLAG_clever_optimizations) return; | 10732 if (!FLAG_clever_optimizations) return; |
| 10733 Map* map = initial_map(); |
10733 | 10734 |
10734 // Only initiate the tracking the first time. | 10735 // Only initiate the tracking the first time. |
10735 if (live_objects_may_exist()) return; | 10736 if (map->done_inobject_slack_tracking()) return; |
10736 set_live_objects_may_exist(true); | 10737 map->set_done_inobject_slack_tracking(true); |
10737 | 10738 |
10738 // No tracking during the snapshot construction phase. | 10739 // No tracking during the snapshot construction phase. |
10739 Isolate* isolate = GetIsolate(); | 10740 Isolate* isolate = GetIsolate(); |
10740 if (isolate->serializer_enabled()) return; | 10741 if (isolate->serializer_enabled()) return; |
10741 | 10742 |
10742 if (map->unused_property_fields() == 0) return; | 10743 if (map->unused_property_fields() == 0) return; |
10743 | 10744 |
10744 // Nonzero counter is a leftover from the previous attempt interrupted | 10745 map->set_construction_count(kGenerousAllocationCount); |
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)); | |
10754 } | 10746 } |
10755 | 10747 |
10756 | 10748 |
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 | |
10797 void SharedFunctionInfo::ResetForNewContext(int new_ic_age) { | 10749 void SharedFunctionInfo::ResetForNewContext(int new_ic_age) { |
10798 code()->ClearInlineCaches(); | 10750 code()->ClearInlineCaches(); |
10799 // If we clear ICs, we need to clear the type feedback vector too, since | 10751 // If we clear ICs, we need to clear the type feedback vector too, since |
10800 // CallICs are synced with a feedback vector slot. | 10752 // CallICs are synced with a feedback vector slot. |
10801 ClearTypeFeedbackInfo(); | 10753 ClearTypeFeedbackInfo(); |
10802 set_ic_age(new_ic_age); | 10754 set_ic_age(new_ic_age); |
10803 if (code()->kind() == Code::FUNCTION) { | 10755 if (code()->kind() == Code::FUNCTION) { |
10804 code()->set_profiler_ticks(0); | 10756 code()->set_profiler_ticks(0); |
10805 if (optimization_disabled() && | 10757 if (optimization_disabled() && |
10806 opt_count() >= FLAG_max_opt_count) { | 10758 opt_count() >= FLAG_max_opt_count) { |
(...skipping 19 matching lines...) Expand all Loading... |
10826 int slack = *reinterpret_cast<int*>(data); | 10778 int slack = *reinterpret_cast<int*>(data); |
10827 map->set_inobject_properties(map->inobject_properties() - slack); | 10779 map->set_inobject_properties(map->inobject_properties() - slack); |
10828 map->set_unused_property_fields(map->unused_property_fields() - slack); | 10780 map->set_unused_property_fields(map->unused_property_fields() - slack); |
10829 map->set_instance_size(map->instance_size() - slack * kPointerSize); | 10781 map->set_instance_size(map->instance_size() - slack * kPointerSize); |
10830 | 10782 |
10831 // Visitor id might depend on the instance size, recalculate it. | 10783 // Visitor id might depend on the instance size, recalculate it. |
10832 map->set_visitor_id(StaticVisitorBase::GetVisitorId(map)); | 10784 map->set_visitor_id(StaticVisitorBase::GetVisitorId(map)); |
10833 } | 10785 } |
10834 | 10786 |
10835 | 10787 |
10836 void SharedFunctionInfo::CompleteInobjectSlackTracking() { | 10788 void JSFunction::CompleteInobjectSlackTracking() { |
10837 ASSERT(live_objects_may_exist() && IsInobjectSlackTrackingInProgress()); | 10789 ASSERT(has_initial_map()); |
10838 Map* map = Map::cast(initial_map()); | 10790 Map* map = initial_map(); |
10839 | 10791 |
10840 Heap* heap = map->GetHeap(); | 10792 ASSERT(map->done_inobject_slack_tracking()); |
10841 set_initial_map(heap->undefined_value()); | 10793 map->set_construction_count(kNoSlackTracking); |
10842 Builtins* builtins = heap->isolate()->builtins(); | |
10843 ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubCountdown), | |
10844 construct_stub()); | |
10845 set_construct_stub(builtins->builtin(Builtins::kJSConstructStubGeneric)); | |
10846 | 10794 |
10847 int slack = map->unused_property_fields(); | 10795 int slack = map->unused_property_fields(); |
10848 map->TraverseTransitionTree(&GetMinInobjectSlack, &slack); | 10796 map->TraverseTransitionTree(&GetMinInobjectSlack, &slack); |
10849 if (slack != 0) { | 10797 if (slack != 0) { |
10850 // Resize the initial map and all maps in its transition tree. | 10798 // Resize the initial map and all maps in its transition tree. |
10851 map->TraverseTransitionTree(&ShrinkInstanceSize, &slack); | 10799 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); | |
10856 } | 10800 } |
10857 } | 10801 } |
10858 | 10802 |
10859 | 10803 |
10860 int SharedFunctionInfo::SearchOptimizedCodeMap(Context* native_context, | 10804 int SharedFunctionInfo::SearchOptimizedCodeMap(Context* native_context, |
10861 BailoutId osr_ast_id) { | 10805 BailoutId osr_ast_id) { |
10862 DisallowHeapAllocation no_gc; | 10806 DisallowHeapAllocation no_gc; |
10863 ASSERT(native_context->IsNativeContext()); | 10807 ASSERT(native_context->IsNativeContext()); |
10864 if (!FLAG_cache_optimized_code) return -1; | 10808 if (!FLAG_cache_optimized_code) return -1; |
10865 Object* value = optimized_code_map(); | 10809 Object* value = optimized_code_map(); |
(...skipping 6444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
17310 #define ERROR_MESSAGES_TEXTS(C, T) T, | 17254 #define ERROR_MESSAGES_TEXTS(C, T) T, |
17311 static const char* error_messages_[] = { | 17255 static const char* error_messages_[] = { |
17312 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 17256 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
17313 }; | 17257 }; |
17314 #undef ERROR_MESSAGES_TEXTS | 17258 #undef ERROR_MESSAGES_TEXTS |
17315 return error_messages_[reason]; | 17259 return error_messages_[reason]; |
17316 } | 17260 } |
17317 | 17261 |
17318 | 17262 |
17319 } } // namespace v8::internal | 17263 } } // namespace v8::internal |
OLD | NEW |