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

Unified Diff: src/objects.cc

Issue 1484473002: Fix Reflect.construct wrt proxy, generator, and non-subclass new.target (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 1 month 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 | « src/objects.h ('k') | src/runtime/runtime-array.cc » ('j') | 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 f1dd4d7efe96b236d1536c0611969bf3c1fa3de4..43ed55dc0d073aec3a558b0ff2e51b2607e6d088 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -12206,6 +12206,10 @@ void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) {
if (function->has_initial_map()) return;
Isolate* isolate = function->GetIsolate();
+ // The constructor should be compiled for the optimization hints to be
+ // available.
+ Compiler::Compile(function, CLEAR_EXCEPTION);
+
// First create a new map with the size and number of in-object properties
// suggested by the function.
InstanceType instance_type;
@@ -12245,39 +12249,59 @@ void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) {
}
-Handle<Map> JSFunction::EnsureDerivedHasInitialMap(
- Handle<JSFunction> new_target, Handle<JSFunction> constructor) {
- DCHECK(constructor->has_initial_map());
- Isolate* isolate = constructor->GetIsolate();
+// static
+MaybeHandle<Map> JSFunction::GetDerivedMap(Isolate* isolate,
+ Handle<JSFunction> constructor,
+ Handle<JSReceiver> new_target) {
+ EnsureHasInitialMap(constructor);
+
Handle<Map> constructor_initial_map(constructor->initial_map(), isolate);
if (*new_target == *constructor) return constructor_initial_map;
- if (new_target->has_initial_map()) {
- // Check that |new_target|'s initial map still in sync with
- // the |constructor|, otherwise we must create a new initial map for
- // |new_target|.
- if (new_target->initial_map()->GetConstructor() == *constructor) {
- return handle(new_target->initial_map(), isolate);
+
+ 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);
+
+ 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;
}
- // First create a new map with the size and number of in-object properties
- // suggested by the function.
- DCHECK(!new_target->shared()->is_generator());
- DCHECK(!constructor->shared()->is_generator());
+ Handle<JSFunction> new_target_function = Handle<JSFunction>::cast(new_target);
- // Fetch or allocate prototype.
- // TODO(verwaest): In case of non-instance prototype, use the
- // intrinsicDefaultProto instead.
- Handle<Object> prototype;
- if (new_target->has_instance_prototype()) {
- prototype = handle(new_target->instance_prototype(), isolate);
- } else {
- prototype = isolate->factory()->NewFunctionPrototype(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);
}
- // Finally link initial map and constructor function if the original
- // constructor is actually a subclass constructor.
- if (IsSubclassConstructor(new_target->shared()->kind())) {
+ // 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 =
@@ -12286,7 +12310,7 @@ Handle<Map> JSFunction::EnsureDerivedHasInitialMap(
constructor_initial_map->unused_property_fields();
int instance_size;
int in_object_properties;
- new_target->CalculateInstanceSizeForDerivedClass(
+ new_target_function->CalculateInstanceSizeForDerivedClass(
instance_type, internal_fields, &instance_size, &in_object_properties);
int unused_property_fields = in_object_properties - pre_allocated;
@@ -12294,20 +12318,33 @@ Handle<Map> JSFunction::EnsureDerivedHasInitialMap(
Map::CopyInitialMap(constructor_initial_map, instance_size,
in_object_properties, unused_property_fields);
- JSFunction::SetInitialMap(new_target, map, prototype);
+ JSFunction::SetInitialMap(new_target_function, map, prototype);
map->SetConstructor(*constructor);
- new_target->StartInobjectSlackTracking();
+ new_target_function->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 {
- Handle<Map> map = Map::CopyInitialMap(constructor_initial_map);
- DCHECK(prototype->IsJSReceiver());
- if (map->prototype() != *prototype) {
- Map::SetPrototype(map, prototype, FAST_PROTOTYPE);
- }
- map->SetConstructor(*constructor);
- return map;
+ // Make sure the prototype is cached on new_target_function.
+ EnsureHasInitialMap(new_target_function);
+ prototype = handle(new_target_function->instance_prototype(), isolate);
}
+
+ Handle<Map> map = Map::CopyInitialMap(constructor_initial_map);
+ DCHECK(prototype->IsJSReceiver());
+ if (map->prototype() != *prototype) {
+ Map::SetPrototype(map, prototype, FAST_PROTOTYPE);
+ }
+ map->SetConstructor(*constructor);
+ return map;
}
« no previous file with comments | « src/objects.h ('k') | src/runtime/runtime-array.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698