Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(701)

Unified Diff: src/objects.cc

Issue 1500683002: Restructure GetDerivedMap so there's only one place where we read intrinsicDefaultProto (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/objects.cc
diff --git a/src/objects.cc b/src/objects.cc
index a0c68275386bc5c55cd5c890442432870da5d08a..33612a854f346dcb29e73079082e271ef150551c 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -12666,86 +12666,75 @@ MaybeHandle<Map> JSFunction::GetDerivedMap(Isolate* isolate,
Handle<Map> constructor_initial_map(constructor->initial_map(), isolate);
if (*new_target == *constructor) return constructor_initial_map;
+ // Fast case, new.target is a subclass of constructor. The map is cacheable
+ // (and may already have been cached). new.target.prototype is guaranteed to
+ // be a JSReceiver.
+ if (new_target->IsJSFunction()) {
+ Handle<JSFunction> function = Handle<JSFunction>::cast(new_target);
+
+ // Check that |function|'s initial map still in sync with the |constructor|,
+ // otherwise we must create a new initial map for |function|.
+ if (function->has_initial_map() &&
+ function->initial_map()->GetConstructor() == *constructor) {
+ return handle(function->initial_map(), isolate);
+ }
+
+ // Create a new map with the size and number of in-object properties
+ // suggested by |function|.
+
+ // Link initial map and constructor function if the new.target is actually a
+ // subclass constructor.
+ if (IsSubclassConstructor(function->shared()->kind())) {
+ Handle<Object> prototype(function->instance_prototype(), isolate);
+ InstanceType instance_type = constructor_initial_map->instance_type();
+ DCHECK(CanSubclassHaveInobjectProperties(instance_type));
+ int internal_fields =
+ JSObject::GetInternalFieldCount(*constructor_initial_map);
+ int pre_allocated = constructor_initial_map->GetInObjectProperties() -
+ constructor_initial_map->unused_property_fields();
+ int instance_size;
+ int in_object_properties;
+ function->CalculateInstanceSizeForDerivedClass(
+ instance_type, internal_fields, &instance_size,
+ &in_object_properties);
+
+ int unused_property_fields = in_object_properties - pre_allocated;
+ Handle<Map> map =
+ Map::CopyInitialMap(constructor_initial_map, instance_size,
+ in_object_properties, unused_property_fields);
+ map->set_new_target_is_base(false);
+
+ JSFunction::SetInitialMap(function, map, prototype);
+ map->SetConstructor(*constructor);
+ map->StartInobjectSlackTracking();
+ return map;
+ }
+ }
+
+ // Slow path, new.target is either a proxy or can't cache the map.
+ // new.target.prototype is not guaranteed to be a JSReceiver, and may need to
+ // fall back to the intrinsicDefaultProto.
+ Handle<Object> prototype;
if (new_target->IsJSProxy()) {
Handle<JSProxy> new_target_proxy = Handle<JSProxy>::cast(new_target);
- Handle<Object> prototype;
Handle<String> prototype_string = isolate->factory()->prototype_string();
ASSIGN_RETURN_ON_EXCEPTION(
isolate, prototype,
JSReceiver::GetProperty(new_target_proxy, prototype_string), Map);
- Handle<Map> map = Map::CopyInitialMap(constructor_initial_map);
- map->set_new_target_is_base(false);
-
- if (!prototype->IsJSReceiver()) {
- Handle<Context> context;
- ASSIGN_RETURN_ON_EXCEPTION(
- isolate, context, JSProxy::GetFunctionRealm(new_target_proxy), Map);
- DCHECK(context->IsNativeContext());
- // TODO(verwaest): Use the intrinsicDefaultProto instead.
- prototype = handle(context->initial_object_prototype(), isolate);
- }
-
- if (map->prototype() != *prototype) {
- Map::SetPrototype(map, prototype, FAST_PROTOTYPE);
- }
-
- map->SetConstructor(*constructor);
- return map;
- }
-
- Handle<JSFunction> new_target_function = Handle<JSFunction>::cast(new_target);
-
- // Check that |new_target_function|'s initial map still in sync with
- // the |constructor|, otherwise we must create a new initial map for
- // |new_target_function|.
- if (new_target_function->has_initial_map() &&
- new_target_function->initial_map()->GetConstructor() == *constructor) {
- return handle(new_target_function->initial_map(), isolate);
- }
-
- // Create a new map with the size and number of in-object properties suggested
- // by the function.
-
- // Link initial map and constructor function if the original constructor is
- // actually a subclass constructor.
- if (IsSubclassConstructor(new_target_function->shared()->kind())) {
- Handle<Object> prototype(new_target_function->instance_prototype(),
- isolate);
- InstanceType instance_type = constructor_initial_map->instance_type();
- DCHECK(CanSubclassHaveInobjectProperties(instance_type));
- int internal_fields =
- JSObject::GetInternalFieldCount(*constructor_initial_map);
- int pre_allocated = constructor_initial_map->GetInObjectProperties() -
- constructor_initial_map->unused_property_fields();
- int instance_size;
- int in_object_properties;
- new_target_function->CalculateInstanceSizeForDerivedClass(
- instance_type, internal_fields, &instance_size, &in_object_properties);
-
- int unused_property_fields = in_object_properties - pre_allocated;
- Handle<Map> map =
- Map::CopyInitialMap(constructor_initial_map, instance_size,
- in_object_properties, unused_property_fields);
- map->set_new_target_is_base(false);
-
- JSFunction::SetInitialMap(new_target_function, map, prototype);
- map->SetConstructor(*constructor);
- map->StartInobjectSlackTracking();
- return map;
- }
-
- // Fetch the prototype.
- Handle<Object> prototype;
- if (new_target_function->map()->has_non_instance_prototype()) {
- // TODO(verwaest): In case of non-instance prototype, use the
- // intrinsicDefaultProto instead.
- prototype = handle(new_target_function->context()
- ->native_context()
- ->initial_object_prototype());
} else {
- // Make sure the prototype is cached on new_target_function.
- EnsureHasInitialMap(new_target_function);
- prototype = handle(new_target_function->instance_prototype(), isolate);
+ Handle<JSFunction> function = Handle<JSFunction>::cast(new_target);
+ // Make sure the new.target.prototype is cached.
+ EnsureHasInitialMap(function);
+ prototype = handle(function->prototype(), isolate);
+ }
+
+ if (!prototype->IsJSReceiver()) {
+ Handle<Context> context;
+ ASSIGN_RETURN_ON_EXCEPTION(isolate, context,
+ JSReceiver::GetFunctionRealm(new_target), Map);
+ DCHECK(context->IsNativeContext());
+ // TODO(verwaest): Use the intrinsicDefaultProto instead.
+ prototype = handle(context->initial_object_prototype(), isolate);
}
Handle<Map> map = Map::CopyInitialMap(constructor_initial_map);
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698