Index: src/api-natives.cc |
diff --git a/src/api-natives.cc b/src/api-natives.cc |
index 4d3dc4d5401d9ddf75b687456887dcec111b7d02..fcd19ccadad7b364599d830ac72f90c0a40c5ace 100644 |
--- a/src/api-natives.cc |
+++ b/src/api-natives.cc |
@@ -17,6 +17,7 @@ namespace { |
MaybeHandle<JSObject> InstantiateObject(Isolate* isolate, |
Handle<ObjectTemplateInfo> data, |
+ Handle<JSReceiver> new_target, |
bool is_hidden_prototype); |
MaybeHandle<JSFunction> InstantiateFunction(Isolate* isolate, |
@@ -31,7 +32,7 @@ MaybeHandle<Object> Instantiate(Isolate* isolate, Handle<Object> data, |
Handle<FunctionTemplateInfo>::cast(data), name); |
} else if (data->IsObjectTemplateInfo()) { |
return InstantiateObject(isolate, Handle<ObjectTemplateInfo>::cast(data), |
- false); |
+ Handle<JSReceiver>(), false); |
} else { |
return data; |
} |
@@ -288,11 +289,25 @@ void UncacheTemplateInstantiation(Isolate* isolate, uint32_t serial_number) { |
MaybeHandle<JSObject> InstantiateObject(Isolate* isolate, |
Handle<ObjectTemplateInfo> info, |
+ Handle<JSReceiver> new_target, |
bool is_hidden_prototype) { |
- // Fast path. |
- Handle<JSObject> result; |
+ Handle<JSFunction> constructor; |
uint32_t serial_number = |
static_cast<uint32_t>(Smi::cast(info->serial_number())->value()); |
+ if (!new_target.is_null()) { |
+ if (new_target->IsJSFunction() && |
+ JSFunction::cast(*new_target)->shared()->function_data() == |
+ info->constructor() && |
+ JSFunction::cast(*new_target)->context()->native_context() == |
+ isolate->context()->native_context()) { |
+ constructor = Handle<JSFunction>::cast(new_target); |
+ } else { |
+ // Disable caching for subclass instantiation. |
+ serial_number = 0; |
+ } |
+ } |
+ // Fast path. |
+ Handle<JSObject> result; |
if (serial_number) { |
// Probe cache. |
auto cache = isolate->template_instantiations_cache(); |
@@ -305,20 +320,27 @@ MaybeHandle<JSObject> InstantiateObject(Isolate* isolate, |
} |
// Enter a new scope. Recursion could otherwise create a lot of handles. |
HandleScope scope(isolate); |
- auto constructor = handle(info->constructor(), isolate); |
- Handle<JSFunction> cons; |
- if (constructor->IsUndefined()) { |
- cons = isolate->object_function(); |
- } else { |
- auto cons_templ = Handle<FunctionTemplateInfo>::cast(constructor); |
- ASSIGN_RETURN_ON_EXCEPTION( |
- isolate, cons, InstantiateFunction(isolate, cons_templ), JSFunction); |
+ |
+ if (constructor.is_null()) { |
+ Handle<Object> cons(info->constructor(), isolate); |
+ if (cons->IsUndefined()) { |
+ constructor = isolate->object_function(); |
+ } else { |
+ auto cons_templ = Handle<FunctionTemplateInfo>::cast(cons); |
+ ASSIGN_RETURN_ON_EXCEPTION(isolate, constructor, |
+ InstantiateFunction(isolate, cons_templ), |
+ JSObject); |
+ } |
+ |
+ if (new_target.is_null()) new_target = constructor; |
} |
- auto object = isolate->factory()->NewJSObject(cons); |
+ |
+ Handle<JSObject> object; |
+ ASSIGN_RETURN_ON_EXCEPTION(isolate, object, |
+ JSObject::New(constructor, new_target), JSObject); |
ASSIGN_RETURN_ON_EXCEPTION( |
isolate, result, |
- ConfigureInstance(isolate, object, info, is_hidden_prototype), |
- JSFunction); |
+ ConfigureInstance(isolate, object, info, is_hidden_prototype), JSObject); |
// TODO(dcarney): is this necessary? |
JSObject::MigrateSlowToFast(result, 0, "ApiNatives::InstantiateObject"); |
@@ -356,7 +378,7 @@ MaybeHandle<JSFunction> InstantiateFunction(Isolate* isolate, |
isolate, prototype, |
InstantiateObject(isolate, |
Handle<ObjectTemplateInfo>::cast(prototype_templ), |
- data->hidden_prototype()), |
+ Handle<JSReceiver>(), data->hidden_prototype()), |
JSFunction); |
} |
auto parent = handle(data->parent_template(), isolate); |
@@ -448,12 +470,11 @@ MaybeHandle<JSFunction> ApiNatives::InstantiateFunction( |
return ::v8::internal::InstantiateFunction(isolate, data); |
} |
- |
MaybeHandle<JSObject> ApiNatives::InstantiateObject( |
- Handle<ObjectTemplateInfo> data) { |
+ Handle<ObjectTemplateInfo> data, Handle<JSReceiver> new_target) { |
Isolate* isolate = data->GetIsolate(); |
InvokeScope invoke_scope(isolate); |
- return ::v8::internal::InstantiateObject(isolate, data, false); |
+ return ::v8::internal::InstantiateObject(isolate, data, new_target, false); |
} |