Revert "Revert "Upgrade to 5.0.71.48"" DO NOT MERGE
This reverts commit f2e3994fa5148cc3d9946666f0b0596290192b0e,
and updates the x64 makefile properly so it doesn't break that
build.
FPIIM-449
Change-Id: Ib83e35bfbae6af627451c926a9650ec57c045605
(cherry picked from commit 109988c7ccb6f3fd1a58574fa3dfb88beaef6632)
diff --git a/src/api-natives.cc b/src/api-natives.cc
index bc71e3e..3be2df0 100644
--- a/src/api-natives.cc
+++ b/src/api-natives.cc
@@ -16,8 +16,8 @@
namespace {
MaybeHandle<JSObject> InstantiateObject(Isolate* isolate,
- Handle<ObjectTemplateInfo> data);
-
+ Handle<ObjectTemplateInfo> data,
+ bool is_hidden_prototype);
MaybeHandle<JSFunction> InstantiateFunction(Isolate* isolate,
Handle<FunctionTemplateInfo> data,
@@ -30,32 +30,36 @@
return InstantiateFunction(isolate,
Handle<FunctionTemplateInfo>::cast(data), name);
} else if (data->IsObjectTemplateInfo()) {
- return InstantiateObject(isolate, Handle<ObjectTemplateInfo>::cast(data));
+ return InstantiateObject(isolate, Handle<ObjectTemplateInfo>::cast(data),
+ false);
} else {
return data;
}
}
-
-MaybeHandle<Object> DefineAccessorProperty(Isolate* isolate,
- Handle<JSObject> object,
- Handle<Name> name,
- Handle<Object> getter,
- Handle<Object> setter,
- PropertyAttributes attributes) {
- if (!getter->IsUndefined()) {
- ASSIGN_RETURN_ON_EXCEPTION(
- isolate, getter,
- InstantiateFunction(isolate,
- Handle<FunctionTemplateInfo>::cast(getter)),
- Object);
- }
- if (!setter->IsUndefined()) {
- ASSIGN_RETURN_ON_EXCEPTION(
- isolate, setter,
- InstantiateFunction(isolate,
- Handle<FunctionTemplateInfo>::cast(setter)),
- Object);
+MaybeHandle<Object> DefineAccessorProperty(
+ Isolate* isolate, Handle<JSObject> object, Handle<Name> name,
+ Handle<Object> getter, Handle<Object> setter, PropertyAttributes attributes,
+ bool force_instantiate) {
+ DCHECK(!getter->IsFunctionTemplateInfo() ||
+ !FunctionTemplateInfo::cast(*getter)->do_not_cache());
+ DCHECK(!setter->IsFunctionTemplateInfo() ||
+ !FunctionTemplateInfo::cast(*setter)->do_not_cache());
+ if (force_instantiate) {
+ if (getter->IsFunctionTemplateInfo()) {
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, getter,
+ InstantiateFunction(isolate,
+ Handle<FunctionTemplateInfo>::cast(getter)),
+ Object);
+ }
+ if (setter->IsFunctionTemplateInfo()) {
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, setter,
+ InstantiateFunction(isolate,
+ Handle<FunctionTemplateInfo>::cast(setter)),
+ Object);
+ }
}
RETURN_ON_EXCEPTION(isolate, JSObject::DefineAccessor(object, name, getter,
setter, attributes),
@@ -148,17 +152,78 @@
return nullptr;
}
+// Returns parent function template or null.
+FunctionTemplateInfo* GetParent(FunctionTemplateInfo* data) {
+ Object* parent = data->parent_template();
+ return parent->IsUndefined() ? nullptr : FunctionTemplateInfo::cast(parent);
+}
+// Starting from given object template's constructor walk up the inheritance
+// chain till a function template that has an instance template is found.
+ObjectTemplateInfo* GetParent(ObjectTemplateInfo* data) {
+ Object* maybe_ctor = data->constructor();
+ if (maybe_ctor->IsUndefined()) return nullptr;
+ FunctionTemplateInfo* ctor = FunctionTemplateInfo::cast(maybe_ctor);
+ while (true) {
+ ctor = GetParent(ctor);
+ if (ctor == nullptr) return nullptr;
+ Object* maybe_obj = ctor->instance_template();
+ if (!maybe_obj->IsUndefined()) return ObjectTemplateInfo::cast(maybe_obj);
+ }
+}
+
+template <typename TemplateInfoT>
MaybeHandle<JSObject> ConfigureInstance(Isolate* isolate, Handle<JSObject> obj,
- Handle<TemplateInfo> data) {
+ Handle<TemplateInfoT> data,
+ bool is_hidden_prototype) {
+ HandleScope scope(isolate);
+ // Disable access checks while instantiating the object.
+ AccessCheckDisableScope access_check_scope(isolate, obj);
+
+ // Walk the inheritance chain and copy all accessors to current object.
+ int max_number_of_properties = 0;
+ TemplateInfoT* info = *data;
+ while (info != nullptr) {
+ if (!info->property_accessors()->IsUndefined()) {
+ Object* props = info->property_accessors();
+ if (!props->IsUndefined()) {
+ Handle<Object> props_handle(props, isolate);
+ NeanderArray props_array(props_handle);
+ max_number_of_properties += props_array.length();
+ }
+ }
+ info = GetParent(info);
+ }
+
+ if (max_number_of_properties > 0) {
+ int valid_descriptors = 0;
+ // Use a temporary FixedArray to accumulate unique accessors.
+ Handle<FixedArray> array =
+ isolate->factory()->NewFixedArray(max_number_of_properties);
+
+ info = *data;
+ while (info != nullptr) {
+ // Accumulate accessors.
+ if (!info->property_accessors()->IsUndefined()) {
+ Handle<Object> props(info->property_accessors(), isolate);
+ valid_descriptors =
+ AccessorInfo::AppendUnique(props, array, valid_descriptors);
+ }
+ info = GetParent(info);
+ }
+
+ // Install accumulated accessors.
+ for (int i = 0; i < valid_descriptors; i++) {
+ Handle<AccessorInfo> accessor(AccessorInfo::cast(array->get(i)));
+ JSObject::SetAccessor(obj, accessor).Assert();
+ }
+ }
+
auto property_list = handle(data->property_list(), isolate);
if (property_list->IsUndefined()) return obj;
// TODO(dcarney): just use a FixedArray here.
NeanderArray properties(property_list);
if (properties.length() == 0) return obj;
- HandleScope scope(isolate);
- // Disable access checks while instantiating the object.
- AccessCheckDisableScope access_check_scope(isolate, obj);
int i = 0;
for (int c = 0; c < data->number_of_properties(); c++) {
@@ -171,17 +236,16 @@
if (kind == kData) {
auto prop_data = handle(properties.get(i++), isolate);
-
RETURN_ON_EXCEPTION(isolate, DefineDataProperty(isolate, obj, name,
prop_data, attributes),
JSObject);
} else {
auto getter = handle(properties.get(i++), isolate);
auto setter = handle(properties.get(i++), isolate);
- RETURN_ON_EXCEPTION(isolate,
- DefineAccessorProperty(isolate, obj, name, getter,
- setter, attributes),
- JSObject);
+ RETURN_ON_EXCEPTION(
+ isolate, DefineAccessorProperty(isolate, obj, name, getter, setter,
+ attributes, is_hidden_prototype),
+ JSObject);
}
} else {
// Intrinsic data property --- Get appropriate value from the current
@@ -202,14 +266,28 @@
return obj;
}
+void CacheTemplateInstantiation(Isolate* isolate, Handle<Smi> serial_number,
+ Handle<JSObject> object) {
+ auto cache = isolate->template_instantiations_cache();
+ auto new_cache = ObjectHashTable::Put(cache, serial_number, object);
+ isolate->native_context()->set_template_instantiations_cache(*new_cache);
+}
+
+void UncacheTemplateInstantiation(Isolate* isolate, Handle<Smi> serial_number) {
+ auto cache = isolate->template_instantiations_cache();
+ bool was_present = false;
+ auto new_cache = ObjectHashTable::Remove(cache, serial_number, &was_present);
+ DCHECK(was_present);
+ isolate->native_context()->set_template_instantiations_cache(*new_cache);
+}
MaybeHandle<JSObject> InstantiateObject(Isolate* isolate,
- Handle<ObjectTemplateInfo> data) {
+ Handle<ObjectTemplateInfo> info,
+ bool is_hidden_prototype) {
// Enter a new scope. Recursion could otherwise create a lot of handles.
HandleScope scope(isolate);
// Fast path.
Handle<JSObject> result;
- auto info = Handle<ObjectTemplateInfo>::cast(data);
auto constructor = handle(info->constructor(), isolate);
Handle<JSFunction> cons;
if (constructor->IsUndefined()) {
@@ -219,39 +297,42 @@
ASSIGN_RETURN_ON_EXCEPTION(
isolate, cons, InstantiateFunction(isolate, cons_templ), JSFunction);
}
+ auto serial_number = handle(Smi::cast(info->serial_number()), isolate);
+ if (serial_number->value()) {
+ // Probe cache.
+ auto cache = isolate->template_instantiations_cache();
+ Object* boilerplate = cache->Lookup(serial_number);
+ if (boilerplate->IsJSObject()) {
+ result = handle(JSObject::cast(boilerplate), isolate);
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, result, JSObject::DeepCopyApiBoilerplate(result), JSObject);
+ return scope.CloseAndEscape(result);
+ }
+ }
auto object = isolate->factory()->NewJSObject(cons);
ASSIGN_RETURN_ON_EXCEPTION(
- isolate, result, ConfigureInstance(isolate, object, info), JSFunction);
+ isolate, result,
+ ConfigureInstance(isolate, object, info, is_hidden_prototype),
+ JSFunction);
// TODO(dcarney): is this necessary?
JSObject::MigrateSlowToFast(result, 0, "ApiNatives::InstantiateObject");
+
+ if (serial_number->value()) {
+ CacheTemplateInstantiation(isolate, serial_number, result);
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, result, JSObject::DeepCopyApiBoilerplate(result), JSObject);
+ }
return scope.CloseAndEscape(result);
}
-void CacheFunction(Isolate* isolate, Handle<Smi> serial_number,
- Handle<JSFunction> function) {
- auto cache = isolate->function_cache();
- auto new_cache = ObjectHashTable::Put(cache, serial_number, function);
- isolate->native_context()->set_function_cache(*new_cache);
-}
-
-
-void UncacheFunction(Isolate* isolate, Handle<Smi> serial_number) {
- auto cache = isolate->function_cache();
- bool was_present = false;
- auto new_cache = ObjectHashTable::Remove(cache, serial_number, &was_present);
- DCHECK(was_present);
- isolate->native_context()->set_function_cache(*new_cache);
-}
-
-
MaybeHandle<JSFunction> InstantiateFunction(Isolate* isolate,
Handle<FunctionTemplateInfo> data,
Handle<Name> name) {
auto serial_number = handle(Smi::cast(data->serial_number()), isolate);
- // Probe cache.
- if (!data->do_not_cache()) {
- auto cache = isolate->function_cache();
+ if (serial_number->value()) {
+ // Probe cache.
+ auto cache = isolate->template_instantiations_cache();
Object* element = cache->Lookup(serial_number);
if (element->IsJSFunction()) {
return handle(JSFunction::cast(element), isolate);
@@ -268,7 +349,8 @@
ASSIGN_RETURN_ON_EXCEPTION(
isolate, prototype,
InstantiateObject(isolate,
- Handle<ObjectTemplateInfo>::cast(prototype_templ)),
+ Handle<ObjectTemplateInfo>::cast(prototype_templ),
+ data->hidden_prototype()),
JSFunction);
}
auto parent = handle(data->parent_template(), isolate);
@@ -296,15 +378,16 @@
if (!name.is_null() && name->IsString()) {
function->shared()->set_name(*name);
}
- if (!data->do_not_cache()) {
+ if (serial_number->value()) {
// Cache the function.
- CacheFunction(isolate, serial_number, function);
+ CacheTemplateInstantiation(isolate, serial_number, function);
}
- auto result = ConfigureInstance(isolate, function, data);
+ auto result =
+ ConfigureInstance(isolate, function, data, data->hidden_prototype());
if (result.is_null()) {
// Uncache on error.
- if (!data->do_not_cache()) {
- UncacheFunction(isolate, serial_number);
+ if (serial_number->value()) {
+ UncacheTemplateInstantiation(isolate, serial_number);
}
return MaybeHandle<JSFunction>();
}
@@ -364,23 +447,7 @@
Handle<ObjectTemplateInfo> data) {
Isolate* isolate = data->GetIsolate();
InvokeScope invoke_scope(isolate);
- return ::v8::internal::InstantiateObject(isolate, data);
-}
-
-
-MaybeHandle<FunctionTemplateInfo> ApiNatives::ConfigureInstance(
- Isolate* isolate, Handle<FunctionTemplateInfo> desc,
- Handle<JSObject> instance) {
- // Configure the instance by adding the properties specified by the
- // instance template.
- if (desc->instance_template()->IsUndefined()) return desc;
- InvokeScope invoke_scope(isolate);
- Handle<ObjectTemplateInfo> instance_template(
- ObjectTemplateInfo::cast(desc->instance_template()), isolate);
- RETURN_ON_EXCEPTION(isolate, ::v8::internal::ConfigureInstance(
- isolate, instance, instance_template),
- FunctionTemplateInfo);
- return desc;
+ return ::v8::internal::InstantiateObject(isolate, data, false);
}
@@ -527,11 +594,6 @@
map->set_is_undetectable();
}
- // Mark as hidden for the __proto__ accessor if needed.
- if (obj->hidden_prototype()) {
- map->set_is_hidden_prototype();
- }
-
// Mark as needs_access_check if needed.
if (obj->needs_access_check()) {
map->set_is_access_check_needed(true);
@@ -548,73 +610,7 @@
// Mark instance as callable in the map.
if (!obj->instance_call_handler()->IsUndefined()) {
map->set_is_callable();
- map->set_is_constructor();
- }
-
- // Recursively copy parent instance templates' accessors,
- // 'data' may be modified.
- int max_number_of_additional_properties = 0;
- int max_number_of_static_properties = 0;
- FunctionTemplateInfo* info = *obj;
- while (true) {
- if (!info->instance_template()->IsUndefined()) {
- Object* props = ObjectTemplateInfo::cast(info->instance_template())
- ->property_accessors();
- if (!props->IsUndefined()) {
- Handle<Object> props_handle(props, isolate);
- NeanderArray props_array(props_handle);
- max_number_of_additional_properties += props_array.length();
- }
- }
- if (!info->property_accessors()->IsUndefined()) {
- Object* props = info->property_accessors();
- if (!props->IsUndefined()) {
- Handle<Object> props_handle(props, isolate);
- NeanderArray props_array(props_handle);
- max_number_of_static_properties += props_array.length();
- }
- }
- Object* parent = info->parent_template();
- if (parent->IsUndefined()) break;
- info = FunctionTemplateInfo::cast(parent);
- }
-
- Map::EnsureDescriptorSlack(map, max_number_of_additional_properties);
-
- // Use a temporary FixedArray to acculumate static accessors
- int valid_descriptors = 0;
- Handle<FixedArray> array;
- if (max_number_of_static_properties > 0) {
- array = isolate->factory()->NewFixedArray(max_number_of_static_properties);
- }
-
- while (true) {
- // Install instance descriptors
- if (!obj->instance_template()->IsUndefined()) {
- Handle<ObjectTemplateInfo> instance = Handle<ObjectTemplateInfo>(
- ObjectTemplateInfo::cast(obj->instance_template()), isolate);
- Handle<Object> props =
- Handle<Object>(instance->property_accessors(), isolate);
- if (!props->IsUndefined()) {
- Map::AppendCallbackDescriptors(map, props);
- }
- }
- // Accumulate static accessors
- if (!obj->property_accessors()->IsUndefined()) {
- Handle<Object> props = Handle<Object>(obj->property_accessors(), isolate);
- valid_descriptors =
- AccessorInfo::AppendUnique(props, array, valid_descriptors);
- }
- // Climb parent chain
- Handle<Object> parent = Handle<Object>(obj->parent_template(), isolate);
- if (parent->IsUndefined()) break;
- obj = Handle<FunctionTemplateInfo>::cast(parent);
- }
-
- // Install accumulated static accessors
- for (int i = 0; i < valid_descriptors; i++) {
- Handle<AccessorInfo> accessor(AccessorInfo::cast(array->get(i)));
- JSObject::SetAccessor(result, accessor).Assert();
+ map->set_is_constructor(true);
}
DCHECK(result->shared()->IsApiFunction());