| 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 10188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10199 JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value)); | 10199 JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value)); |
| 10200 } | 10200 } |
| 10201 | 10201 |
| 10202 // Now some logic for the maps of the objects that are created by using this | 10202 // Now some logic for the maps of the objects that are created by using this |
| 10203 // function as a constructor. | 10203 // function as a constructor. |
| 10204 if (function->has_initial_map()) { | 10204 if (function->has_initial_map()) { |
| 10205 // If the function has allocated the initial map replace it with a | 10205 // If the function has allocated the initial map replace it with a |
| 10206 // copy containing the new prototype. Also complete any in-object | 10206 // copy containing the new prototype. Also complete any in-object |
| 10207 // slack tracking that is in progress at this point because it is | 10207 // slack tracking that is in progress at this point because it is |
| 10208 // still tracking the old copy. | 10208 // still tracking the old copy. |
| 10209 if (function->shared()->IsInobjectSlackTrackingInProgress()) { | 10209 if (function->IsInobjectSlackTrackingInProgress()) { |
| 10210 function->shared()->CompleteInobjectSlackTracking(); | 10210 function->CompleteInobjectSlackTracking(); |
| 10211 } | 10211 } |
| 10212 Handle<Map> new_map = Map::Copy(handle(function->initial_map())); | 10212 Handle<Map> new_map = Map::Copy(handle(function->initial_map())); |
| 10213 new_map->set_prototype(*value); | 10213 new_map->set_prototype(*value); |
| 10214 | 10214 |
| 10215 // If the function is used as the global Array function, cache the | 10215 // If the function is used as the global Array function, cache the |
| 10216 // initial map (and transitioned versions) in the native context. | 10216 // initial map (and transitioned versions) in the native context. |
| 10217 Context* native_context = function->context()->native_context(); | 10217 Context* native_context = function->context()->native_context(); |
| 10218 Object* array_function = native_context->get(Context::ARRAY_FUNCTION_INDEX); | 10218 Object* array_function = native_context->get(Context::ARRAY_FUNCTION_INDEX); |
| 10219 if (array_function->IsJSFunction() && | 10219 if (array_function->IsJSFunction() && |
| 10220 *function == JSFunction::cast(array_function)) { | 10220 *function == JSFunction::cast(array_function)) { |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10309 if (function->has_instance_prototype()) { | 10309 if (function->has_instance_prototype()) { |
| 10310 prototype = handle(function->instance_prototype(), isolate); | 10310 prototype = handle(function->instance_prototype(), isolate); |
| 10311 } else { | 10311 } else { |
| 10312 prototype = isolate->factory()->NewFunctionPrototype(function); | 10312 prototype = isolate->factory()->NewFunctionPrototype(function); |
| 10313 } | 10313 } |
| 10314 map->set_inobject_properties(in_object_properties); | 10314 map->set_inobject_properties(in_object_properties); |
| 10315 map->set_unused_property_fields(in_object_properties); | 10315 map->set_unused_property_fields(in_object_properties); |
| 10316 map->set_prototype(*prototype); | 10316 map->set_prototype(*prototype); |
| 10317 ASSERT(map->has_fast_object_elements()); | 10317 ASSERT(map->has_fast_object_elements()); |
| 10318 | 10318 |
| 10319 if (!function->shared()->is_generator()) { | |
| 10320 function->shared()->StartInobjectSlackTracking(*map); | |
| 10321 } | |
| 10322 | |
| 10323 // Finally link initial map and constructor function. | 10319 // Finally link initial map and constructor function. |
| 10324 function->set_initial_map(*map); | 10320 function->set_initial_map(*map); |
| 10325 map->set_constructor(*function); | 10321 map->set_constructor(*function); |
| 10322 |
| 10323 if (!function->shared()->is_generator()) { |
| 10324 function->StartInobjectSlackTracking(); |
| 10325 } |
| 10326 } | 10326 } |
| 10327 | 10327 |
| 10328 | 10328 |
| 10329 void JSFunction::SetInstanceClassName(String* name) { | 10329 void JSFunction::SetInstanceClassName(String* name) { |
| 10330 shared()->set_instance_class_name(name); | 10330 shared()->set_instance_class_name(name); |
| 10331 } | 10331 } |
| 10332 | 10332 |
| 10333 | 10333 |
| 10334 void JSFunction::PrintName(FILE* out) { | 10334 void JSFunction::PrintName(FILE* out) { |
| 10335 SmartArrayPointer<char> name = shared()->DebugName()->ToCString(); | 10335 SmartArrayPointer<char> name = shared()->DebugName()->ToCString(); |
| (...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10702 ASSERT(!id.IsNone()); | 10702 ASSERT(!id.IsNone()); |
| 10703 Code* unoptimized = code(); | 10703 Code* unoptimized = code(); |
| 10704 DeoptimizationOutputData* data = | 10704 DeoptimizationOutputData* data = |
| 10705 DeoptimizationOutputData::cast(unoptimized->deoptimization_data()); | 10705 DeoptimizationOutputData::cast(unoptimized->deoptimization_data()); |
| 10706 unsigned ignore = Deoptimizer::GetOutputInfo(data, id, this); | 10706 unsigned ignore = Deoptimizer::GetOutputInfo(data, id, this); |
| 10707 USE(ignore); | 10707 USE(ignore); |
| 10708 return true; // Return true if there was no ASSERT. | 10708 return true; // Return true if there was no ASSERT. |
| 10709 } | 10709 } |
| 10710 | 10710 |
| 10711 | 10711 |
| 10712 void SharedFunctionInfo::StartInobjectSlackTracking(Map* map) { | 10712 void JSFunction::StartInobjectSlackTracking() { |
| 10713 ASSERT(!IsInobjectSlackTrackingInProgress()); | 10713 ASSERT(has_initial_map() && !IsInobjectSlackTrackingInProgress()); |
| 10714 | 10714 |
| 10715 if (!FLAG_clever_optimizations) return; | 10715 if (!FLAG_clever_optimizations) return; |
| 10716 Map* map = initial_map(); |
| 10716 | 10717 |
| 10717 // Only initiate the tracking the first time. | 10718 // Only initiate the tracking the first time. |
| 10718 if (live_objects_may_exist()) return; | 10719 if (map->done_inobject_slack_tracking()) return; |
| 10719 set_live_objects_may_exist(true); | 10720 map->set_done_inobject_slack_tracking(true); |
| 10720 | 10721 |
| 10721 // No tracking during the snapshot construction phase. | 10722 // No tracking during the snapshot construction phase. |
| 10722 Isolate* isolate = GetIsolate(); | 10723 Isolate* isolate = GetIsolate(); |
| 10723 if (Serializer::enabled(isolate)) return; | 10724 if (Serializer::enabled(isolate)) return; |
| 10724 | 10725 |
| 10725 if (map->unused_property_fields() == 0) return; | 10726 if (map->unused_property_fields() == 0) return; |
| 10726 | 10727 |
| 10727 // Nonzero counter is a leftover from the previous attempt interrupted | 10728 map->set_construction_count(kGenerousAllocationCount); |
| 10728 // by GC, keep it. | |
| 10729 if (construction_count() == 0) { | |
| 10730 set_construction_count(kGenerousAllocationCount); | |
| 10731 } | |
| 10732 set_initial_map(map); | |
| 10733 Builtins* builtins = isolate->builtins(); | |
| 10734 ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubGeneric), | |
| 10735 construct_stub()); | |
| 10736 set_construct_stub(builtins->builtin(Builtins::kJSConstructStubCountdown)); | |
| 10737 } | 10729 } |
| 10738 | 10730 |
| 10739 | 10731 |
| 10740 // Called from GC, hence reinterpret_cast and unchecked accessors. | |
| 10741 void SharedFunctionInfo::DetachInitialMap() { | |
| 10742 Map* map = reinterpret_cast<Map*>(initial_map()); | |
| 10743 | |
| 10744 // Make the map remember to restore the link if it survives the GC. | |
| 10745 map->set_bit_field2( | |
| 10746 map->bit_field2() | (1 << Map::kAttachedToSharedFunctionInfo)); | |
| 10747 | |
| 10748 // Undo state changes made by StartInobjectTracking (except the | |
| 10749 // construction_count). This way if the initial map does not survive the GC | |
| 10750 // then StartInobjectTracking will be called again the next time the | |
| 10751 // constructor is called. The countdown will continue and (possibly after | |
| 10752 // several more GCs) CompleteInobjectSlackTracking will eventually be called. | |
| 10753 Heap* heap = map->GetHeap(); | |
| 10754 set_initial_map(heap->undefined_value()); | |
| 10755 Builtins* builtins = heap->isolate()->builtins(); | |
| 10756 ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubCountdown), | |
| 10757 *RawField(this, kConstructStubOffset)); | |
| 10758 set_construct_stub(builtins->builtin(Builtins::kJSConstructStubGeneric)); | |
| 10759 // It is safe to clear the flag: it will be set again if the map is live. | |
| 10760 set_live_objects_may_exist(false); | |
| 10761 } | |
| 10762 | |
| 10763 | |
| 10764 // Called from GC, hence reinterpret_cast and unchecked accessors. | |
| 10765 void SharedFunctionInfo::AttachInitialMap(Map* map) { | |
| 10766 map->set_bit_field2( | |
| 10767 map->bit_field2() & ~(1 << Map::kAttachedToSharedFunctionInfo)); | |
| 10768 | |
| 10769 // Resume inobject slack tracking. | |
| 10770 set_initial_map(map); | |
| 10771 Builtins* builtins = map->GetHeap()->isolate()->builtins(); | |
| 10772 ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubGeneric), | |
| 10773 *RawField(this, kConstructStubOffset)); | |
| 10774 set_construct_stub(builtins->builtin(Builtins::kJSConstructStubCountdown)); | |
| 10775 // The map survived the gc, so there may be objects referencing it. | |
| 10776 set_live_objects_may_exist(true); | |
| 10777 } | |
| 10778 | |
| 10779 | |
| 10780 void SharedFunctionInfo::ResetForNewContext(int new_ic_age) { | 10732 void SharedFunctionInfo::ResetForNewContext(int new_ic_age) { |
| 10781 code()->ClearInlineCaches(); | 10733 code()->ClearInlineCaches(); |
| 10782 // If we clear ICs, we need to clear the type feedback vector too, since | 10734 // If we clear ICs, we need to clear the type feedback vector too, since |
| 10783 // CallICs are synced with a feedback vector slot. | 10735 // CallICs are synced with a feedback vector slot. |
| 10784 ClearTypeFeedbackInfo(); | 10736 ClearTypeFeedbackInfo(); |
| 10785 set_ic_age(new_ic_age); | 10737 set_ic_age(new_ic_age); |
| 10786 if (code()->kind() == Code::FUNCTION) { | 10738 if (code()->kind() == Code::FUNCTION) { |
| 10787 code()->set_profiler_ticks(0); | 10739 code()->set_profiler_ticks(0); |
| 10788 if (optimization_disabled() && | 10740 if (optimization_disabled() && |
| 10789 opt_count() >= FLAG_max_opt_count) { | 10741 opt_count() >= FLAG_max_opt_count) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 10809 int slack = *reinterpret_cast<int*>(data); | 10761 int slack = *reinterpret_cast<int*>(data); |
| 10810 map->set_inobject_properties(map->inobject_properties() - slack); | 10762 map->set_inobject_properties(map->inobject_properties() - slack); |
| 10811 map->set_unused_property_fields(map->unused_property_fields() - slack); | 10763 map->set_unused_property_fields(map->unused_property_fields() - slack); |
| 10812 map->set_instance_size(map->instance_size() - slack * kPointerSize); | 10764 map->set_instance_size(map->instance_size() - slack * kPointerSize); |
| 10813 | 10765 |
| 10814 // Visitor id might depend on the instance size, recalculate it. | 10766 // Visitor id might depend on the instance size, recalculate it. |
| 10815 map->set_visitor_id(StaticVisitorBase::GetVisitorId(map)); | 10767 map->set_visitor_id(StaticVisitorBase::GetVisitorId(map)); |
| 10816 } | 10768 } |
| 10817 | 10769 |
| 10818 | 10770 |
| 10819 void SharedFunctionInfo::CompleteInobjectSlackTracking() { | 10771 void JSFunction::CompleteInobjectSlackTracking() { |
| 10820 ASSERT(live_objects_may_exist() && IsInobjectSlackTrackingInProgress()); | 10772 ASSERT(has_initial_map()); |
| 10821 Map* map = Map::cast(initial_map()); | 10773 Map* map = initial_map(); |
| 10822 | 10774 |
| 10823 Heap* heap = map->GetHeap(); | 10775 ASSERT(map->done_inobject_slack_tracking()); |
| 10824 set_initial_map(heap->undefined_value()); | 10776 map->set_construction_count(kNoSlackTracking); |
| 10825 Builtins* builtins = heap->isolate()->builtins(); | |
| 10826 ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubCountdown), | |
| 10827 construct_stub()); | |
| 10828 set_construct_stub(builtins->builtin(Builtins::kJSConstructStubGeneric)); | |
| 10829 | 10777 |
| 10830 int slack = map->unused_property_fields(); | 10778 int slack = map->unused_property_fields(); |
| 10831 map->TraverseTransitionTree(&GetMinInobjectSlack, &slack); | 10779 map->TraverseTransitionTree(&GetMinInobjectSlack, &slack); |
| 10832 if (slack != 0) { | 10780 if (slack != 0) { |
| 10833 // Resize the initial map and all maps in its transition tree. | 10781 // Resize the initial map and all maps in its transition tree. |
| 10834 map->TraverseTransitionTree(&ShrinkInstanceSize, &slack); | 10782 map->TraverseTransitionTree(&ShrinkInstanceSize, &slack); |
| 10835 | |
| 10836 // Give the correct expected_nof_properties to initial maps created later. | |
| 10837 ASSERT(expected_nof_properties() >= slack); | |
| 10838 set_expected_nof_properties(expected_nof_properties() - slack); | |
| 10839 } | 10783 } |
| 10840 } | 10784 } |
| 10841 | 10785 |
| 10842 | 10786 |
| 10843 int SharedFunctionInfo::SearchOptimizedCodeMap(Context* native_context, | 10787 int SharedFunctionInfo::SearchOptimizedCodeMap(Context* native_context, |
| 10844 BailoutId osr_ast_id) { | 10788 BailoutId osr_ast_id) { |
| 10845 DisallowHeapAllocation no_gc; | 10789 DisallowHeapAllocation no_gc; |
| 10846 ASSERT(native_context->IsNativeContext()); | 10790 ASSERT(native_context->IsNativeContext()); |
| 10847 if (!FLAG_cache_optimized_code) return -1; | 10791 if (!FLAG_cache_optimized_code) return -1; |
| 10848 Object* value = optimized_code_map(); | 10792 Object* value = optimized_code_map(); |
| (...skipping 6425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 17274 #define ERROR_MESSAGES_TEXTS(C, T) T, | 17218 #define ERROR_MESSAGES_TEXTS(C, T) T, |
| 17275 static const char* error_messages_[] = { | 17219 static const char* error_messages_[] = { |
| 17276 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 17220 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
| 17277 }; | 17221 }; |
| 17278 #undef ERROR_MESSAGES_TEXTS | 17222 #undef ERROR_MESSAGES_TEXTS |
| 17279 return error_messages_[reason]; | 17223 return error_messages_[reason]; |
| 17280 } | 17224 } |
| 17281 | 17225 |
| 17282 | 17226 |
| 17283 } } // namespace v8::internal | 17227 } } // namespace v8::internal |
| OLD | NEW |