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 "src/objects.h" | 5 #include "src/objects.h" |
6 | 6 |
7 #include <cmath> | 7 #include <cmath> |
8 #include <iomanip> | 8 #include <iomanip> |
9 #include <sstream> | 9 #include <sstream> |
10 | 10 |
(...skipping 12648 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
12659 | 12659 |
12660 // static | 12660 // static |
12661 MaybeHandle<Map> JSFunction::GetDerivedMap(Isolate* isolate, | 12661 MaybeHandle<Map> JSFunction::GetDerivedMap(Isolate* isolate, |
12662 Handle<JSFunction> constructor, | 12662 Handle<JSFunction> constructor, |
12663 Handle<JSReceiver> new_target) { | 12663 Handle<JSReceiver> new_target) { |
12664 EnsureHasInitialMap(constructor); | 12664 EnsureHasInitialMap(constructor); |
12665 | 12665 |
12666 Handle<Map> constructor_initial_map(constructor->initial_map(), isolate); | 12666 Handle<Map> constructor_initial_map(constructor->initial_map(), isolate); |
12667 if (*new_target == *constructor) return constructor_initial_map; | 12667 if (*new_target == *constructor) return constructor_initial_map; |
12668 | 12668 |
12669 // Fast case, new.target is a subclass of constructor. The map is cacheable | |
12670 // (and may already have been cached). new.target.prototype is guaranteed to | |
12671 // be a JSReceiver. | |
12672 if (new_target->IsJSFunction()) { | |
12673 Handle<JSFunction> function = Handle<JSFunction>::cast(new_target); | |
12674 | |
12675 // Check that |function|'s initial map still in sync with the |constructor|, | |
12676 // otherwise we must create a new initial map for |function|. | |
12677 if (function->has_initial_map() && | |
12678 function->initial_map()->GetConstructor() == *constructor) { | |
12679 return handle(function->initial_map(), isolate); | |
12680 } | |
12681 | |
12682 // Create a new map with the size and number of in-object properties | |
12683 // suggested | |
Igor Sheludko
2015/12/03 16:40:40
Please reformat.
| |
12684 // by |function|. | |
12685 | |
12686 // Link initial map and constructor function if the new.target is actually a | |
12687 // subclass constructor. | |
12688 if (IsSubclassConstructor(function->shared()->kind())) { | |
12689 Handle<Object> prototype(function->instance_prototype(), isolate); | |
12690 InstanceType instance_type = constructor_initial_map->instance_type(); | |
12691 DCHECK(CanSubclassHaveInobjectProperties(instance_type)); | |
12692 int internal_fields = | |
12693 JSObject::GetInternalFieldCount(*constructor_initial_map); | |
12694 int pre_allocated = constructor_initial_map->GetInObjectProperties() - | |
12695 constructor_initial_map->unused_property_fields(); | |
12696 int instance_size; | |
12697 int in_object_properties; | |
12698 function->CalculateInstanceSizeForDerivedClass( | |
12699 instance_type, internal_fields, &instance_size, | |
12700 &in_object_properties); | |
12701 | |
12702 int unused_property_fields = in_object_properties - pre_allocated; | |
12703 Handle<Map> map = | |
12704 Map::CopyInitialMap(constructor_initial_map, instance_size, | |
12705 in_object_properties, unused_property_fields); | |
12706 map->set_new_target_is_base(false); | |
12707 | |
12708 JSFunction::SetInitialMap(function, map, prototype); | |
12709 map->SetConstructor(*constructor); | |
12710 map->StartInobjectSlackTracking(); | |
12711 return map; | |
12712 } | |
12713 } | |
12714 | |
12715 // Slow path, new.target is either a proxy or can't cache the map. | |
12716 // new.target.prototype is not guaranteed to be a JSReceiver, and may need to | |
12717 // fall back to the intrinsicDefaultProto. | |
12718 Handle<Object> prototype; | |
12669 if (new_target->IsJSProxy()) { | 12719 if (new_target->IsJSProxy()) { |
12670 Handle<JSProxy> new_target_proxy = Handle<JSProxy>::cast(new_target); | 12720 Handle<JSProxy> new_target_proxy = Handle<JSProxy>::cast(new_target); |
12671 Handle<Object> prototype; | |
12672 Handle<String> prototype_string = isolate->factory()->prototype_string(); | 12721 Handle<String> prototype_string = isolate->factory()->prototype_string(); |
12673 ASSIGN_RETURN_ON_EXCEPTION( | 12722 ASSIGN_RETURN_ON_EXCEPTION( |
12674 isolate, prototype, | 12723 isolate, prototype, |
12675 JSReceiver::GetProperty(new_target_proxy, prototype_string), Map); | 12724 JSReceiver::GetProperty(new_target_proxy, prototype_string), Map); |
12676 Handle<Map> map = Map::CopyInitialMap(constructor_initial_map); | 12725 } else { |
12677 map->set_new_target_is_base(false); | 12726 Handle<JSFunction> function = Handle<JSFunction>::cast(new_target); |
12678 | 12727 // Make sure the new.target.prototype is cached. |
12679 if (!prototype->IsJSReceiver()) { | 12728 EnsureHasInitialMap(function); |
12680 Handle<Context> context; | 12729 prototype = handle(function->prototype(), isolate); |
12681 ASSIGN_RETURN_ON_EXCEPTION( | |
12682 isolate, context, JSProxy::GetFunctionRealm(new_target_proxy), Map); | |
12683 DCHECK(context->IsNativeContext()); | |
12684 // TODO(verwaest): Use the intrinsicDefaultProto instead. | |
12685 prototype = handle(context->initial_object_prototype(), isolate); | |
12686 } | |
12687 | |
12688 if (map->prototype() != *prototype) { | |
12689 Map::SetPrototype(map, prototype, FAST_PROTOTYPE); | |
12690 } | |
12691 | |
12692 map->SetConstructor(*constructor); | |
12693 return map; | |
12694 } | 12730 } |
12695 | 12731 |
12696 Handle<JSFunction> new_target_function = Handle<JSFunction>::cast(new_target); | 12732 if (!prototype->IsJSReceiver()) { |
12697 | 12733 Handle<Context> context; |
12698 // Check that |new_target_function|'s initial map still in sync with | 12734 ASSIGN_RETURN_ON_EXCEPTION(isolate, context, |
12699 // the |constructor|, otherwise we must create a new initial map for | 12735 JSReceiver::GetFunctionRealm(new_target), Map); |
12700 // |new_target_function|. | 12736 DCHECK(context->IsNativeContext()); |
12701 if (new_target_function->has_initial_map() && | 12737 // TODO(verwaest): Use the intrinsicDefaultProto instead. |
12702 new_target_function->initial_map()->GetConstructor() == *constructor) { | 12738 prototype = handle(context->initial_object_prototype(), isolate); |
12703 return handle(new_target_function->initial_map(), isolate); | |
12704 } | |
12705 | |
12706 // Create a new map with the size and number of in-object properties suggested | |
12707 // by the function. | |
12708 | |
12709 // Link initial map and constructor function if the original constructor is | |
12710 // actually a subclass constructor. | |
12711 if (IsSubclassConstructor(new_target_function->shared()->kind())) { | |
12712 Handle<Object> prototype(new_target_function->instance_prototype(), | |
12713 isolate); | |
12714 InstanceType instance_type = constructor_initial_map->instance_type(); | |
12715 DCHECK(CanSubclassHaveInobjectProperties(instance_type)); | |
12716 int internal_fields = | |
12717 JSObject::GetInternalFieldCount(*constructor_initial_map); | |
12718 int pre_allocated = constructor_initial_map->GetInObjectProperties() - | |
12719 constructor_initial_map->unused_property_fields(); | |
12720 int instance_size; | |
12721 int in_object_properties; | |
12722 new_target_function->CalculateInstanceSizeForDerivedClass( | |
12723 instance_type, internal_fields, &instance_size, &in_object_properties); | |
12724 | |
12725 int unused_property_fields = in_object_properties - pre_allocated; | |
12726 Handle<Map> map = | |
12727 Map::CopyInitialMap(constructor_initial_map, instance_size, | |
12728 in_object_properties, unused_property_fields); | |
12729 map->set_new_target_is_base(false); | |
12730 | |
12731 JSFunction::SetInitialMap(new_target_function, map, prototype); | |
12732 map->SetConstructor(*constructor); | |
12733 map->StartInobjectSlackTracking(); | |
12734 return map; | |
12735 } | |
12736 | |
12737 // Fetch the prototype. | |
12738 Handle<Object> prototype; | |
12739 if (new_target_function->map()->has_non_instance_prototype()) { | |
12740 // TODO(verwaest): In case of non-instance prototype, use the | |
12741 // intrinsicDefaultProto instead. | |
12742 prototype = handle(new_target_function->context() | |
12743 ->native_context() | |
12744 ->initial_object_prototype()); | |
12745 } else { | |
12746 // Make sure the prototype is cached on new_target_function. | |
12747 EnsureHasInitialMap(new_target_function); | |
12748 prototype = handle(new_target_function->instance_prototype(), isolate); | |
12749 } | 12739 } |
12750 | 12740 |
12751 Handle<Map> map = Map::CopyInitialMap(constructor_initial_map); | 12741 Handle<Map> map = Map::CopyInitialMap(constructor_initial_map); |
12752 map->set_new_target_is_base(false); | 12742 map->set_new_target_is_base(false); |
12753 DCHECK(prototype->IsJSReceiver()); | 12743 DCHECK(prototype->IsJSReceiver()); |
12754 if (map->prototype() != *prototype) { | 12744 if (map->prototype() != *prototype) { |
12755 Map::SetPrototype(map, prototype, FAST_PROTOTYPE); | 12745 Map::SetPrototype(map, prototype, FAST_PROTOTYPE); |
12756 } | 12746 } |
12757 map->SetConstructor(*constructor); | 12747 map->SetConstructor(*constructor); |
12758 return map; | 12748 return map; |
(...skipping 6422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
19181 if (cell->value() != *new_value) { | 19171 if (cell->value() != *new_value) { |
19182 cell->set_value(*new_value); | 19172 cell->set_value(*new_value); |
19183 Isolate* isolate = cell->GetIsolate(); | 19173 Isolate* isolate = cell->GetIsolate(); |
19184 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 19174 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
19185 isolate, DependentCode::kPropertyCellChangedGroup); | 19175 isolate, DependentCode::kPropertyCellChangedGroup); |
19186 } | 19176 } |
19187 } | 19177 } |
19188 | 19178 |
19189 } // namespace internal | 19179 } // namespace internal |
19190 } // namespace v8 | 19180 } // namespace v8 |
OLD | NEW |