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:
parent
a933b7044a
commit
a7a9ac37d4
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user