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

Unified Diff: src/api-natives.cc

Issue 2170743003: [api] Introduce fast instantiations cache (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: fixing uint issue under windows Created 4 years, 5 months 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 | src/bootstrapper.cc » ('j') | src/objects.h » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/api-natives.cc
diff --git a/src/api-natives.cc b/src/api-natives.cc
index cd9f0ddd5d239887c9f5f94b6059d4e86dcbe2dd..ecbe4dc1bf5e8ccf60a1fd9923bc1bd3eb9c4093 100644
--- a/src/api-natives.cc
+++ b/src/api-natives.cc
@@ -15,6 +15,24 @@ namespace internal {
namespace {
+class InvokeScope {
+ public:
+ explicit InvokeScope(Isolate* isolate)
+ : isolate_(isolate), save_context_(isolate) {}
+ ~InvokeScope() {
+ bool has_exception = isolate_->has_pending_exception();
+ if (has_exception) {
+ isolate_->ReportPendingMessages();
+ } else {
+ isolate_->clear_pending_message();
+ }
+ }
+
+ private:
+ Isolate* isolate_;
+ SaveContext save_context_;
+};
+
MaybeHandle<JSObject> InstantiateObject(Isolate* isolate,
Handle<ObjectTemplateInfo> data,
Handle<JSReceiver> new_target,
@@ -153,30 +171,6 @@ Object* GetIntrinsic(Isolate* isolate, v8::Intrinsic intrinsic) {
return nullptr;
}
-// Returns parent function template or null.
-FunctionTemplateInfo* GetParent(FunctionTemplateInfo* data) {
- Object* parent = data->parent_template();
- return parent->IsUndefined(data->GetIsolate())
- ? 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();
- Isolate* isolate = data->GetIsolate();
- if (maybe_ctor->IsUndefined(isolate)) 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(isolate)) {
- return ObjectTemplateInfo::cast(maybe_obj);
- }
- }
-}
template <typename TemplateInfoT>
MaybeHandle<JSObject> ConfigureInstance(Isolate* isolate, Handle<JSObject> obj,
@@ -198,7 +192,7 @@ MaybeHandle<JSObject> ConfigureInstance(Isolate* isolate, Handle<JSObject> obj,
max_number_of_properties += props_array.length();
}
}
- info = GetParent(info);
+ info = info->GetParent(isolate);
}
if (max_number_of_properties > 0) {
@@ -215,7 +209,7 @@ MaybeHandle<JSObject> ConfigureInstance(Isolate* isolate, Handle<JSObject> obj,
valid_descriptors =
AccessorInfo::AppendUnique(props, array, valid_descriptors);
}
- info = GetParent(info);
+ info = info->GetParent(isolate);
}
// Install accumulated accessors.
@@ -234,9 +228,9 @@ MaybeHandle<JSObject> ConfigureInstance(Isolate* isolate, Handle<JSObject> obj,
int i = 0;
for (int c = 0; c < data->number_of_properties(); c++) {
auto name = handle(Name::cast(properties.get(i++)), isolate);
- auto bit = handle(properties.get(i++), isolate);
+ Object* bit = properties.get(i++);
if (bit->IsSmi()) {
- PropertyDetails details(Smi::cast(*bit));
+ PropertyDetails details(Smi::cast(bit));
PropertyAttributes attributes = details.attributes();
PropertyKind kind = details.kind();
@@ -272,24 +266,80 @@ MaybeHandle<JSObject> ConfigureInstance(Isolate* isolate, Handle<JSObject> obj,
return obj;
}
-void CacheTemplateInstantiation(Isolate* isolate, uint32_t serial_number,
+MaybeHandle<JSObject> ProbeInstantiationsCache(Isolate* isolate,
+ int serial_number) {
+ DCHECK_LE(1, serial_number);
+ if (serial_number <= TemplateInfo::kFastTemplateInstantiationsCacheSize) {
+ Handle<FixedArray> fast_cache =
+ isolate->fast_template_instantiations_cache();
+ return fast_cache->GetValue<JSObject>(isolate, serial_number - 1);
+ } else {
+ Handle<UnseededNumberDictionary> slow_cache =
+ isolate->slow_template_instantiations_cache();
+ int entry = slow_cache->FindEntry(serial_number);
+ if (entry == UnseededNumberDictionary::kNotFound) {
+ return MaybeHandle<JSObject>();
+ }
+ return handle(JSObject::cast(slow_cache->ValueAt(entry)), isolate);
+ }
+}
+
+void CacheTemplateInstantiation(Isolate* isolate, int serial_number,
Handle<JSObject> object) {
- auto cache = isolate->template_instantiations_cache();
- auto new_cache =
- UnseededNumberDictionary::AtNumberPut(cache, serial_number, object);
- isolate->native_context()->set_template_instantiations_cache(*new_cache);
+ DCHECK_LE(1, serial_number);
+ if (serial_number <= TemplateInfo::kFastTemplateInstantiationsCacheSize) {
+ Handle<FixedArray> fast_cache =
+ isolate->fast_template_instantiations_cache();
+ Handle<FixedArray> new_cache =
+ FixedArray::SetAndGrow(fast_cache, serial_number - 1, object);
+ if (*new_cache != *fast_cache) {
+ isolate->native_context()->set_fast_template_instantiations_cache(
+ *new_cache);
+ }
+ } else {
+ Handle<UnseededNumberDictionary> cache =
+ isolate->slow_template_instantiations_cache();
+ auto new_cache =
+ UnseededNumberDictionary::AtNumberPut(cache, serial_number, object);
+ if (*new_cache != *cache) {
+ isolate->native_context()->set_slow_template_instantiations_cache(
+ *new_cache);
+ }
+ }
+}
+
+void UncacheTemplateInstantiation(Isolate* isolate, int serial_number) {
+ DCHECK_LE(1, serial_number);
+ if (serial_number <= TemplateInfo::kFastTemplateInstantiationsCacheSize) {
+ Handle<FixedArray> fast_cache =
+ isolate->fast_template_instantiations_cache();
+ DCHECK(!fast_cache->get(serial_number - 1)->IsUndefined(isolate));
+ fast_cache->set_undefined(serial_number - 1);
+ } else {
+ Handle<UnseededNumberDictionary> cache =
+ isolate->slow_template_instantiations_cache();
+ int entry = cache->FindEntry(serial_number);
+ DCHECK(entry != UnseededNumberDictionary::kNotFound);
+ Handle<Object> result =
+ UnseededNumberDictionary::DeleteProperty(cache, entry);
+ USE(result);
+ DCHECK(result->IsTrue(isolate));
+ auto new_cache = UnseededNumberDictionary::Shrink(cache, entry);
+ isolate->native_context()->set_slow_template_instantiations_cache(
+ *new_cache);
+ }
}
-void UncacheTemplateInstantiation(Isolate* isolate, uint32_t serial_number) {
- auto cache = isolate->template_instantiations_cache();
- int entry = cache->FindEntry(serial_number);
- DCHECK(entry != UnseededNumberDictionary::kNotFound);
- Handle<Object> result =
- UnseededNumberDictionary::DeleteProperty(cache, entry);
- USE(result);
- DCHECK(result->IsTrue(isolate));
- auto new_cache = UnseededNumberDictionary::Shrink(cache, entry);
- isolate->native_context()->set_template_instantiations_cache(*new_cache);
+bool IsSimpleInstantiation(Isolate* isolate, ObjectTemplateInfo* info,
+ JSReceiver* new_target) {
+ DisallowHeapAllocation no_gc;
+
+ if (!new_target->IsJSFunction()) return false;
+ JSFunction* fun = JSFunction::cast(new_target);
+ if (fun->shared()->function_data() != info->constructor()) return false;
+ if (info->immutable_proto()) return false;
+ return fun->context()->native_context() !=
+ isolate->context()->native_context();
}
MaybeHandle<JSObject> InstantiateObject(Isolate* isolate,
@@ -297,15 +347,9 @@ MaybeHandle<JSObject> InstantiateObject(Isolate* isolate,
Handle<JSReceiver> new_target,
bool is_hidden_prototype) {
Handle<JSFunction> constructor;
- uint32_t serial_number =
- static_cast<uint32_t>(Smi::cast(info->serial_number())->value());
+ int serial_number = 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() &&
- !info->immutable_proto()) {
+ if (IsSimpleInstantiation(isolate, *info, *new_target)) {
constructor = Handle<JSFunction>::cast(new_target);
} else {
// Disable caching for subclass instantiation.
@@ -315,27 +359,25 @@ MaybeHandle<JSObject> InstantiateObject(Isolate* isolate,
// Fast path.
Handle<JSObject> result;
if (serial_number) {
- // Probe cache.
- auto cache = isolate->template_instantiations_cache();
- int entry = cache->FindEntry(serial_number);
- if (entry != UnseededNumberDictionary::kNotFound) {
- Object* boilerplate = cache->ValueAt(entry);
- result = handle(JSObject::cast(boilerplate), isolate);
+ if (ProbeInstantiationsCache(isolate, serial_number).ToHandle(&result)) {
return isolate->factory()->CopyJSObject(result);
}
}
- // Enter a new scope. Recursion could otherwise create a lot of handles.
- HandleScope scope(isolate);
if (constructor.is_null()) {
- Handle<Object> cons(info->constructor(), isolate);
- if (cons->IsUndefined(isolate)) {
+ Object* maybe_constructor_info = info->constructor();
+ if (maybe_constructor_info->IsUndefined(isolate)) {
constructor = isolate->object_function();
} else {
- auto cons_templ = Handle<FunctionTemplateInfo>::cast(cons);
- ASSIGN_RETURN_ON_EXCEPTION(isolate, constructor,
+ // Enter a new scope. Recursion could otherwise create a lot of handles.
+ HandleScope scope(isolate);
+ Handle<FunctionTemplateInfo> cons_templ(
+ FunctionTemplateInfo::cast(maybe_constructor_info), isolate);
+ Handle<JSFunction> tmp_constructor;
+ ASSIGN_RETURN_ON_EXCEPTION(isolate, tmp_constructor,
InstantiateFunction(isolate, cons_templ),
JSObject);
+ constructor = scope.CloseAndEscape(tmp_constructor);
}
if (new_target.is_null()) new_target = constructor;
@@ -357,46 +399,43 @@ MaybeHandle<JSObject> InstantiateObject(Isolate* isolate,
CacheTemplateInstantiation(isolate, serial_number, result);
result = isolate->factory()->CopyJSObject(result);
}
- return scope.CloseAndEscape(result);
+ return result;
}
MaybeHandle<JSFunction> InstantiateFunction(Isolate* isolate,
Handle<FunctionTemplateInfo> data,
Handle<Name> name) {
- uint32_t serial_number =
- static_cast<uint32_t>(Smi::cast(data->serial_number())->value());
+ int serial_number = Smi::cast(data->serial_number())->value();
if (serial_number) {
- // Probe cache.
- auto cache = isolate->template_instantiations_cache();
- int entry = cache->FindEntry(serial_number);
- if (entry != UnseededNumberDictionary::kNotFound) {
- Object* element = cache->ValueAt(entry);
- return handle(JSFunction::cast(element), isolate);
+ Handle<JSObject> result;
+ if (ProbeInstantiationsCache(isolate, serial_number).ToHandle(&result)) {
+ return Handle<JSFunction>::cast(result);
}
}
- // Enter a new scope. Recursion could otherwise create a lot of handles.
- HandleScope scope(isolate);
Handle<JSObject> prototype;
if (!data->remove_prototype()) {
- auto prototype_templ = handle(data->prototype_template(), isolate);
+ Object* prototype_templ = data->prototype_template();
if (prototype_templ->IsUndefined(isolate)) {
prototype = isolate->factory()->NewJSObject(isolate->object_function());
} else {
ASSIGN_RETURN_ON_EXCEPTION(
isolate, prototype,
- InstantiateObject(isolate,
- Handle<ObjectTemplateInfo>::cast(prototype_templ),
- Handle<JSReceiver>(), data->hidden_prototype()),
+ InstantiateObject(
+ isolate,
+ handle(ObjectTemplateInfo::cast(prototype_templ), isolate),
+ Handle<JSReceiver>(), data->hidden_prototype()),
JSFunction);
}
- auto parent = handle(data->parent_template(), isolate);
+ Object* parent = data->parent_template();
if (!parent->IsUndefined(isolate)) {
+ // Enter a new scope. Recursion could otherwise create a lot of handles.
+ HandleScope scope(isolate);
Handle<JSFunction> parent_instance;
ASSIGN_RETURN_ON_EXCEPTION(
isolate, parent_instance,
- InstantiateFunction(isolate,
- Handle<FunctionTemplateInfo>::cast(parent)),
+ InstantiateFunction(
+ isolate, handle(FunctionTemplateInfo::cast(parent), isolate)),
JSFunction);
// TODO(dcarney): decide what to do here.
Handle<Object> parent_prototype;
@@ -410,7 +449,7 @@ MaybeHandle<JSFunction> InstantiateFunction(Isolate* isolate,
MaybeHandle<JSFunction>());
}
}
- auto function = ApiNatives::CreateApiFunction(
+ Handle<JSFunction> function = ApiNatives::CreateApiFunction(
isolate, data, prototype, ApiNatives::JavaScriptObjectType);
if (!name.is_null() && name->IsString()) {
function->shared()->set_name(*name);
@@ -419,7 +458,7 @@ MaybeHandle<JSFunction> InstantiateFunction(Isolate* isolate,
// Cache the function.
CacheTemplateInstantiation(isolate, serial_number, function);
}
- auto result =
+ MaybeHandle<JSObject> result =
ConfigureInstance(isolate, function, data, data->hidden_prototype());
if (result.is_null()) {
// Uncache on error.
@@ -428,29 +467,10 @@ MaybeHandle<JSFunction> InstantiateFunction(Isolate* isolate,
}
return MaybeHandle<JSFunction>();
}
- return scope.CloseAndEscape(function);
+ return function;
}
-class InvokeScope {
- public:
- explicit InvokeScope(Isolate* isolate)
- : isolate_(isolate), save_context_(isolate) {}
- ~InvokeScope() {
- bool has_exception = isolate_->has_pending_exception();
- if (has_exception) {
- isolate_->ReportPendingMessages();
- } else {
- isolate_->clear_pending_message();
- }
- }
-
- private:
- Isolate* isolate_;
- SaveContext save_context_;
-};
-
-
void AddPropertyToPropertyList(Isolate* isolate, Handle<TemplateInfo> templ,
int length, Handle<Object>* data) {
auto list = handle(templ->property_list(), isolate);
« no previous file with comments | « no previous file | src/bootstrapper.cc » ('j') | src/objects.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698