Share SharedFunctionInfo between all functions created for a FunctionTemplateInfo

BUG=

Review-Url: https://codereview.chromium.org/2095673002
Cr-Commit-Position: refs/heads/master@{#37252}
This commit is contained in:
verwaest 2016-06-24 06:51:24 -07:00 committed by Commit bot
parent a933b7044a
commit a7a9ac37d4
7 changed files with 114 additions and 107 deletions

View File

@ -537,23 +537,37 @@ void ApiNatives::AddNativeDataProperty(Isolate* isolate,
Handle<JSFunction> ApiNatives::CreateApiFunction( Handle<JSFunction> ApiNatives::CreateApiFunction(
Isolate* isolate, Handle<FunctionTemplateInfo> obj, Isolate* isolate, Handle<FunctionTemplateInfo> obj,
Handle<Object> prototype, ApiInstanceType instance_type) { Handle<Object> prototype, ApiInstanceType instance_type) {
Handle<Code> code; Handle<SharedFunctionInfo> shared =
if (obj->call_code()->IsCallHandlerInfo() && FunctionTemplateInfo::GetOrCreateSharedFunctionInfo(isolate, obj);
CallHandlerInfo::cast(obj->call_code())->fast_handler()->IsCode()) { Handle<JSFunction> result =
code = isolate->builtins()->HandleFastApiCall(); isolate->factory()->NewFunctionFromSharedFunctionInfo(
} else { shared, isolate->native_context());
code = isolate->builtins()->HandleApiCall();
}
Handle<Code> construct_stub =
prototype.is_null() ? isolate->builtins()->ConstructedNonConstructable()
: isolate->builtins()->JSConstructStubApi();
obj->set_instantiated(true);
Handle<JSFunction> result;
if (obj->remove_prototype()) { if (obj->remove_prototype()) {
result = isolate->factory()->NewFunctionWithoutPrototype( result->set_map(*isolate->sloppy_function_without_prototype_map());
isolate->factory()->empty_string(), code); DCHECK(prototype.is_null());
DCHECK(result->shared()->IsApiFunction());
DCHECK(!result->has_initial_map());
DCHECK(!result->has_prototype());
DCHECK(!result->IsConstructor());
return result;
}
// Down from here is only valid for API functions that can be used as a
// constructor (don't set the "remove prototype" flag).
if (obj->read_only_prototype()) {
result->set_map(*isolate->sloppy_function_with_readonly_prototype_map());
}
if (prototype->IsTheHole(isolate)) {
prototype = isolate->factory()->NewFunctionPrototype(result);
} else { } else {
JSObject::AddProperty(Handle<JSObject>::cast(prototype),
isolate->factory()->constructor_string(), result,
DONT_ENUM);
}
int internal_field_count = 0; int internal_field_count = 0;
if (!obj->instance_template()->IsUndefined(isolate)) { if (!obj->instance_template()->IsUndefined(isolate)) {
Handle<ObjectTemplateInfo> instance_template = Handle<ObjectTemplateInfo>( Handle<ObjectTemplateInfo> instance_template = Handle<ObjectTemplateInfo>(
@ -591,41 +605,9 @@ Handle<JSFunction> ApiNatives::CreateApiFunction(
break; break;
} }
result = isolate->factory()->NewFunction( Handle<Map> map =
isolate->factory()->empty_string(), code, prototype, type, isolate->factory()->NewMap(type, instance_size, FAST_HOLEY_SMI_ELEMENTS);
instance_size, obj->read_only_prototype(), true); JSFunction::SetInitialMap(result, map, Handle<JSObject>::cast(prototype));
}
result->shared()->set_length(obj->length());
Handle<Object> class_name(obj->class_name(), isolate);
if (class_name->IsString()) {
result->shared()->set_instance_class_name(*class_name);
result->shared()->set_name(*class_name);
}
result->shared()->set_api_func_data(*obj);
result->shared()->set_construct_stub(*construct_stub);
result->shared()->DontAdaptArguments();
if (obj->remove_prototype()) {
DCHECK(result->shared()->IsApiFunction());
DCHECK(!result->has_initial_map());
DCHECK(!result->has_prototype());
return result;
}
#ifdef DEBUG
LookupIterator it(handle(JSObject::cast(result->prototype())),
isolate->factory()->constructor_string(),
LookupIterator::OWN_SKIP_INTERCEPTOR);
MaybeHandle<Object> maybe_prop = Object::GetProperty(&it);
DCHECK(it.IsFound());
DCHECK(maybe_prop.ToHandleChecked().is_identical_to(result));
#endif
// Down from here is only valid for API functions that can be used as a
// constructor (don't set the "remove prototype" flag).
Handle<Map> map(result->initial_map());
// Mark as undetectable if needed. // Mark as undetectable if needed.
if (obj->undetectable()) { if (obj->undetectable()) {
@ -651,7 +633,6 @@ Handle<JSFunction> ApiNatives::CreateApiFunction(
map->set_is_constructor(true); map->set_is_constructor(true);
} }
DCHECK(result->shared()->IsApiFunction());
return result; return result;
} }

View File

@ -399,12 +399,9 @@ Handle<JSFunction> CreateFunction(Isolate* isolate, Handle<String> name,
Factory* factory = isolate->factory(); Factory* factory = isolate->factory();
Handle<Code> call_code(isolate->builtins()->builtin(call)); Handle<Code> call_code(isolate->builtins()->builtin(call));
Handle<JSObject> prototype; Handle<JSObject> prototype;
static const bool kReadOnlyPrototype = false;
static const bool kInstallConstructor = false;
return maybe_prototype.ToHandle(&prototype) return maybe_prototype.ToHandle(&prototype)
? factory->NewFunction(name, call_code, prototype, type, ? factory->NewFunction(name, call_code, prototype, type,
instance_size, kReadOnlyPrototype, instance_size, strict_function_map)
kInstallConstructor, strict_function_map)
: factory->NewFunctionWithoutPrototype(name, call_code, : factory->NewFunctionWithoutPrototype(name, call_code,
strict_function_map); strict_function_map);
} }

View File

@ -1278,15 +1278,8 @@ Handle<JSFunction> Factory::NewFunctionWithoutPrototype(Handle<String> name,
Handle<JSFunction> Factory::NewFunction(Handle<String> name, Handle<Code> code, Handle<JSFunction> Factory::NewFunction(Handle<String> name, Handle<Code> code,
Handle<Object> prototype, Handle<Object> prototype,
bool read_only_prototype,
bool is_strict) { bool is_strict) {
// In strict mode, readonly strict map is only available during bootstrap Handle<Map> map = is_strict ? isolate()->strict_function_map()
DCHECK(!is_strict || !read_only_prototype ||
isolate()->bootstrapper()->IsActive());
Handle<Map> map =
is_strict ? isolate()->strict_function_map()
: read_only_prototype
? isolate()->sloppy_function_with_readonly_prototype_map()
: isolate()->sloppy_function_map(); : isolate()->sloppy_function_map();
Handle<JSFunction> result = NewFunction(map, name, code); Handle<JSFunction> result = NewFunction(map, name, code);
result->set_prototype_or_initial_map(*prototype); result->set_prototype_or_initial_map(*prototype);
@ -1297,12 +1290,9 @@ Handle<JSFunction> Factory::NewFunction(Handle<String> name, Handle<Code> code,
Handle<JSFunction> Factory::NewFunction(Handle<String> name, Handle<Code> code, Handle<JSFunction> Factory::NewFunction(Handle<String> name, Handle<Code> code,
Handle<Object> prototype, Handle<Object> prototype,
InstanceType type, int instance_size, InstanceType type, int instance_size,
bool read_only_prototype,
bool install_constructor,
bool is_strict) { bool is_strict) {
// Allocate the function // Allocate the function
Handle<JSFunction> function = Handle<JSFunction> function = NewFunction(name, code, prototype, is_strict);
NewFunction(name, code, prototype, read_only_prototype, is_strict);
ElementsKind elements_kind = ElementsKind elements_kind =
type == JS_ARRAY_TYPE ? FAST_SMI_ELEMENTS : FAST_HOLEY_SMI_ELEMENTS; type == JS_ARRAY_TYPE ? FAST_SMI_ELEMENTS : FAST_HOLEY_SMI_ELEMENTS;
@ -1313,9 +1303,6 @@ Handle<JSFunction> Factory::NewFunction(Handle<String> name, Handle<Code> code,
if (!function->shared()->is_resumable()) { if (!function->shared()->is_resumable()) {
if (prototype->IsTheHole(isolate())) { if (prototype->IsTheHole(isolate())) {
prototype = NewFunctionPrototype(function); prototype = NewFunctionPrototype(function);
} else if (install_constructor) {
JSObject::AddProperty(Handle<JSObject>::cast(prototype),
constructor_string(), function, DONT_ENUM);
} }
} }

View File

@ -508,7 +508,6 @@ class Factory final {
Handle<JSFunction> NewFunction(Handle<String> name, Handle<Code> code, Handle<JSFunction> NewFunction(Handle<String> name, Handle<Code> code,
Handle<Object> prototype, Handle<Object> prototype,
bool read_only_prototype = false,
bool is_strict = false); bool is_strict = false);
Handle<JSFunction> NewFunction(Handle<String> name); Handle<JSFunction> NewFunction(Handle<String> name);
Handle<JSFunction> NewFunctionWithoutPrototype(Handle<String> name, Handle<JSFunction> NewFunctionWithoutPrototype(Handle<String> name,
@ -526,8 +525,6 @@ class Factory final {
Handle<JSFunction> NewFunction(Handle<String> name, Handle<Code> code, Handle<JSFunction> NewFunction(Handle<String> name, Handle<Code> code,
Handle<Object> prototype, InstanceType type, Handle<Object> prototype, InstanceType type,
int instance_size, int instance_size,
bool read_only_prototype = false,
bool install_constructor = false,
bool is_strict = false); bool is_strict = false);
Handle<JSFunction> NewFunction(Handle<String> name, Handle<JSFunction> NewFunction(Handle<String> name,
Handle<Code> code, Handle<Code> code,

View File

@ -5506,6 +5506,10 @@ bool PrototypeInfo::HasObjectCreateMap() {
return cache->IsWeakCell() && !WeakCell::cast(cache)->cleared(); return cache->IsWeakCell() && !WeakCell::cast(cache)->cleared();
} }
bool FunctionTemplateInfo::instantiated() {
return shared_function_info()->IsSharedFunctionInfo();
}
ACCESSORS(PrototypeInfo, prototype_users, Object, kPrototypeUsersOffset) ACCESSORS(PrototypeInfo, prototype_users, Object, kPrototypeUsersOffset)
ACCESSORS(PrototypeInfo, object_create_map, Object, kObjectCreateMap) ACCESSORS(PrototypeInfo, object_create_map, Object, kObjectCreateMap)
SMI_ACCESSORS(PrototypeInfo, registry_slot, kRegistrySlotOffset) SMI_ACCESSORS(PrototypeInfo, registry_slot, kRegistrySlotOffset)
@ -5562,6 +5566,9 @@ ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
kInstanceCallHandlerOffset) kInstanceCallHandlerOffset)
ACCESSORS(FunctionTemplateInfo, access_check_info, Object, ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
kAccessCheckInfoOffset) kAccessCheckInfoOffset)
ACCESSORS(FunctionTemplateInfo, shared_function_info, Object,
kSharedFunctionInfoOffset)
SMI_ACCESSORS(FunctionTemplateInfo, flag, kFlagOffset) SMI_ACCESSORS(FunctionTemplateInfo, flag, kFlagOffset)
ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset) ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
@ -5667,7 +5674,6 @@ BOOL_ACCESSORS(FunctionTemplateInfo, flag, remove_prototype,
kRemovePrototypeBit) kRemovePrototypeBit)
BOOL_ACCESSORS(FunctionTemplateInfo, flag, do_not_cache, BOOL_ACCESSORS(FunctionTemplateInfo, flag, do_not_cache,
kDoNotCacheBit) kDoNotCacheBit)
BOOL_ACCESSORS(FunctionTemplateInfo, flag, instantiated, kInstantiatedBit)
BOOL_ACCESSORS(FunctionTemplateInfo, flag, accept_any_receiver, BOOL_ACCESSORS(FunctionTemplateInfo, flag, accept_any_receiver,
kAcceptAnyReceiver) kAcceptAnyReceiver)
BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_named_expression, BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_named_expression,

View File

@ -986,6 +986,41 @@ bool Object::ToInt32(int32_t* value) {
return false; return false;
} }
Handle<SharedFunctionInfo> FunctionTemplateInfo::GetOrCreateSharedFunctionInfo(
Isolate* isolate, Handle<FunctionTemplateInfo> info) {
Object* current_info = info->shared_function_info();
if (current_info->IsSharedFunctionInfo()) {
return handle(SharedFunctionInfo::cast(current_info), isolate);
}
Handle<Object> class_name(info->class_name(), isolate);
Handle<String> name = class_name->IsString()
? Handle<String>::cast(class_name)
: isolate->factory()->empty_string();
Handle<Code> code;
if (info->call_code()->IsCallHandlerInfo() &&
CallHandlerInfo::cast(info->call_code())->fast_handler()->IsCode()) {
code = isolate->builtins()->HandleFastApiCall();
} else {
code = isolate->builtins()->HandleApiCall();
}
bool is_constructor = !info->remove_prototype();
Handle<SharedFunctionInfo> result =
isolate->factory()->NewSharedFunctionInfo(name, code, is_constructor);
if (is_constructor) {
result->set_construct_stub(*isolate->builtins()->JSConstructStubApi());
}
result->set_length(info->length());
if (class_name->IsString()) result->set_instance_class_name(*class_name);
result->set_api_func_data(*info);
result->DontAdaptArguments();
DCHECK(result->IsApiFunction());
info->set_shared_function_info(*result);
return result;
}
bool FunctionTemplateInfo::IsTemplateFor(Map* map) { bool FunctionTemplateInfo::IsTemplateFor(Map* map) {
// There is a constraint on the object; check. // There is a constraint on the object; check.
if (!map->IsJSObjectMap()) return false; if (!map->IsJSObjectMap()) return false;

View File

@ -10523,6 +10523,7 @@ class FunctionTemplateInfo: public TemplateInfo {
DECL_ACCESSORS(signature, Object) DECL_ACCESSORS(signature, Object)
DECL_ACCESSORS(instance_call_handler, Object) DECL_ACCESSORS(instance_call_handler, Object)
DECL_ACCESSORS(access_check_info, Object) DECL_ACCESSORS(access_check_info, Object)
DECL_ACCESSORS(shared_function_info, Object)
DECL_INT_ACCESSORS(flag) DECL_INT_ACCESSORS(flag)
inline int length() const; inline int length() const;
@ -10537,7 +10538,6 @@ class FunctionTemplateInfo: public TemplateInfo {
DECL_BOOLEAN_ACCESSORS(read_only_prototype) DECL_BOOLEAN_ACCESSORS(read_only_prototype)
DECL_BOOLEAN_ACCESSORS(remove_prototype) DECL_BOOLEAN_ACCESSORS(remove_prototype)
DECL_BOOLEAN_ACCESSORS(do_not_cache) DECL_BOOLEAN_ACCESSORS(do_not_cache)
DECL_BOOLEAN_ACCESSORS(instantiated)
DECL_BOOLEAN_ACCESSORS(accept_any_receiver) DECL_BOOLEAN_ACCESSORS(accept_any_receiver)
DECLARE_CAST(FunctionTemplateInfo) DECLARE_CAST(FunctionTemplateInfo)
@ -10562,13 +10562,18 @@ class FunctionTemplateInfo: public TemplateInfo {
static const int kInstanceCallHandlerOffset = kSignatureOffset + kPointerSize; static const int kInstanceCallHandlerOffset = kSignatureOffset + kPointerSize;
static const int kAccessCheckInfoOffset = static const int kAccessCheckInfoOffset =
kInstanceCallHandlerOffset + kPointerSize; kInstanceCallHandlerOffset + kPointerSize;
static const int kFlagOffset = kAccessCheckInfoOffset + kPointerSize; static const int kSharedFunctionInfoOffset =
kAccessCheckInfoOffset + kPointerSize;
static const int kFlagOffset = kSharedFunctionInfoOffset + kPointerSize;
static const int kLengthOffset = kFlagOffset + kPointerSize; static const int kLengthOffset = kFlagOffset + kPointerSize;
static const int kSize = kLengthOffset + kPointerSize; static const int kSize = kLengthOffset + kPointerSize;
static Handle<SharedFunctionInfo> GetOrCreateSharedFunctionInfo(
Isolate* isolate, Handle<FunctionTemplateInfo> info);
// Returns true if |object| is an instance of this function template. // Returns true if |object| is an instance of this function template.
inline bool IsTemplateFor(JSObject* object); inline bool IsTemplateFor(JSObject* object);
bool IsTemplateFor(Map* map); bool IsTemplateFor(Map* map);
inline bool instantiated();
private: private:
// Bit position in the flag, from least significant bit position. // Bit position in the flag, from least significant bit position.
@ -10578,8 +10583,7 @@ class FunctionTemplateInfo: public TemplateInfo {
static const int kReadOnlyPrototypeBit = 3; static const int kReadOnlyPrototypeBit = 3;
static const int kRemovePrototypeBit = 4; static const int kRemovePrototypeBit = 4;
static const int kDoNotCacheBit = 5; static const int kDoNotCacheBit = 5;
static const int kInstantiatedBit = 6; static const int kAcceptAnyReceiver = 6;
static const int kAcceptAnyReceiver = 7;
DISALLOW_IMPLICIT_CONSTRUCTORS(FunctionTemplateInfo); DISALLOW_IMPLICIT_CONSTRUCTORS(FunctionTemplateInfo);
}; };