Pass in the prototype to CreateApiFunction rather than setting it on the result.

BUG=
R=ishell@chromium.org

Review URL: https://codereview.chromium.org/253603003

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@21066 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
verwaest@chromium.org 2014-04-29 17:48:07 +00:00
parent 8452271f1b
commit 22cdf0c0fd
6 changed files with 78 additions and 39 deletions

View File

@ -48,31 +48,29 @@ function InstantiateFunction(data, name) {
(serialNumber in cache) && (cache[serialNumber] != kUninitialized);
if (!isFunctionCached) {
try {
var fun = %CreateApiFunction(data);
if (name) %FunctionSetName(fun, name);
var flags = %GetTemplateField(data, kApiFlagOffset);
var doNotCache = flags & (1 << kDoNotCacheBit);
if (!doNotCache) cache[serialNumber] = fun;
if (flags & (1 << kRemovePrototypeBit)) {
%FunctionRemovePrototype(fun);
} else {
var prototype = %GetTemplateField(data, kApiPrototypeTemplateOffset);
// Note: Do not directly use an object template as a condition, our
// internal ToBoolean doesn't handle that!
fun.prototype = typeof prototype === 'undefined' ?
{} : Instantiate(prototype);
if (flags & (1 << kReadOnlyPrototypeBit)) {
%FunctionSetReadOnlyPrototype(fun);
}
%SetProperty(fun.prototype, "constructor", fun, DONT_ENUM);
var has_proto = !(flags & (1 << kRemovePrototypeBit));
var prototype;
if (has_proto) {
var template = %GetTemplateField(data, kApiPrototypeTemplateOffset);
prototype = typeof template === 'undefined'
? {} : Instantiate(template);
var parent = %GetTemplateField(data, kApiParentTemplateOffset);
// Note: Do not directly use a function template as a condition, our
// internal ToBoolean doesn't handle that!
if (!(typeof parent === 'undefined')) {
if (typeof parent !== 'undefined') {
var parent_fun = Instantiate(parent);
%SetPrototype(fun.prototype, parent_fun.prototype);
%SetPrototype(prototype, parent_fun.prototype);
}
}
var fun = %CreateApiFunction(data, prototype);
if (name) %FunctionSetName(fun, name);
var doNotCache = flags & (1 << kDoNotCacheBit);
if (!doNotCache) cache[serialNumber] = fun;
if (has_proto && flags & (1 << kReadOnlyPrototypeBit)) {
%FunctionSetReadOnlyPrototype(fun);
}
ConfigureTemplateInstance(fun, data);
if (doNotCache) return fun;
} catch (e) {

View File

@ -729,6 +729,7 @@ Handle<JSGlobalProxy> Genesis::CreateNewGlobals(
FunctionTemplateInfo::cast(js_global_template->constructor()));
js_global_function =
factory()->CreateApiFunction(js_global_constructor,
factory()->the_hole_value(),
factory()->InnerGlobalObject);
}
@ -756,6 +757,7 @@ Handle<JSGlobalProxy> Genesis::CreateNewGlobals(
FunctionTemplateInfo::cast(data->constructor()));
global_proxy_function =
factory()->CreateApiFunction(global_constructor,
factory()->the_hole_value(),
factory()->OuterGlobalObject);
}

View File

@ -1255,19 +1255,30 @@ Handle<Object> Factory::NewError(const char* constructor,
}
Handle<JSFunction> Factory::NewFunction(Handle<String> name,
Handle<JSFunction> Factory::NewFunction(MaybeHandle<Object> maybe_prototype,
Handle<String> name,
InstanceType type,
int instance_size,
Handle<Code> code,
bool force_initial_map) {
// Allocate the function
Handle<JSFunction> function = NewFunction(name, code, the_hole_value());
Handle<JSFunction> function = NewFunction(name, code, maybe_prototype);
if (force_initial_map ||
Handle<Object> prototype;
if (maybe_prototype.ToHandle(&prototype) &&
(force_initial_map ||
type != JS_OBJECT_TYPE ||
instance_size != JSObject::kHeaderSize) {
instance_size != JSObject::kHeaderSize)) {
Handle<Map> initial_map = NewMap(type, instance_size);
Handle<JSObject> prototype = NewFunctionPrototype(function);
if (prototype->IsJSObject()) {
JSObject::SetLocalPropertyIgnoreAttributes(
Handle<JSObject>::cast(prototype),
constructor_string(),
function,
DONT_ENUM).Assert();
} else if (!function->shared()->is_generator()) {
prototype = NewFunctionPrototype(function);
}
initial_map->set_prototype(*prototype);
function->set_initial_map(*initial_map);
initial_map->set_constructor(*function);
@ -1280,6 +1291,16 @@ Handle<JSFunction> Factory::NewFunction(Handle<String> name,
}
Handle<JSFunction> Factory::NewFunction(Handle<String> name,
InstanceType type,
int instance_size,
Handle<Code> code,
bool force_initial_map) {
return NewFunction(
the_hole_value(), name, type, instance_size, code, force_initial_map);
}
Handle<JSFunction> Factory::NewFunctionWithPrototype(Handle<String> name,
InstanceType type,
int instance_size,
@ -2057,7 +2078,9 @@ Handle<JSObject> Factory::NewArgumentsObject(Handle<Object> callee,
Handle<JSFunction> Factory::CreateApiFunction(
Handle<FunctionTemplateInfo> obj, ApiInstanceType instance_type) {
Handle<FunctionTemplateInfo> obj,
Handle<Object> prototype,
ApiInstanceType instance_type) {
Handle<Code> code = isolate()->builtins()->HandleApiCall();
Handle<Code> construct_stub = isolate()->builtins()->JSConstructStubApi();
@ -2093,20 +2116,31 @@ Handle<JSFunction> Factory::CreateApiFunction(
break;
}
MaybeHandle<Object> maybe_prototype = prototype;
if (obj->remove_prototype()) maybe_prototype = MaybeHandle<Object>();
Handle<JSFunction> result = NewFunction(
Factory::empty_string(), type, instance_size, code, true);
maybe_prototype, Factory::empty_string(), type,
instance_size, code, true);
// Set length.
result->shared()->set_length(obj->length());
// Set class name.
Handle<Object> class_name = Handle<Object>(obj->class_name(), isolate());
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_function_data(*obj);
result->shared()->set_construct_stub(*construct_stub);
result->shared()->DontAdaptArguments();
Handle<Map> map = Handle<Map>(result->initial_map());
if (obj->remove_prototype()) {
ASSERT(result->shared()->IsApiFunction());
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).
Handle<Map> map(result->initial_map());
// Mark as undetectable if needed.
if (obj->undetectable()) {
@ -2136,10 +2170,6 @@ Handle<JSFunction> Factory::CreateApiFunction(
map->set_has_instance_call_handler();
}
result->shared()->set_function_data(*obj);
result->shared()->set_construct_stub(*construct_stub);
result->shared()->DontAdaptArguments();
// Recursively copy parent instance templates' accessors,
// 'data' may be modified.
int max_number_of_additional_properties = 0;

View File

@ -464,6 +464,12 @@ class Factory V8_FINAL {
Handle<Context> context,
PretenureFlag pretenure = TENURED);
Handle<JSFunction> NewFunction(MaybeHandle<Object> maybe_prototype,
Handle<String> name,
InstanceType type,
int instance_size,
Handle<Code> code,
bool force_initial_map);
Handle<JSFunction> NewFunction(Handle<String> name,
InstanceType type,
int instance_size,
@ -551,6 +557,7 @@ class Factory V8_FINAL {
Handle<JSFunction> CreateApiFunction(
Handle<FunctionTemplateInfo> data,
Handle<Object> prototype,
ApiInstanceType type = JavaScriptObject);
Handle<JSFunction> InstallMembers(Handle<JSFunction> function);

View File

@ -2112,9 +2112,10 @@ RUNTIME_FUNCTION(Runtime_RegExpCompile) {
RUNTIME_FUNCTION(Runtime_CreateApiFunction) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(FunctionTemplateInfo, data, 0);
return *isolate->factory()->CreateApiFunction(data);
CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
return *isolate->factory()->CreateApiFunction(data, prototype);
}
@ -2786,7 +2787,8 @@ static Handle<JSFunction> InstallBuiltin(Isolate* isolate,
Handle<String> key = isolate->factory()->InternalizeUtf8String(name);
Handle<Code> code(isolate->builtins()->builtin(builtin_name));
Handle<JSFunction> optimized =
isolate->factory()->NewFunction(key,
isolate->factory()->NewFunction(MaybeHandle<Object>(),
key,
JS_OBJECT_TYPE,
JSObject::kHeaderSize,
code,

View File

@ -202,7 +202,7 @@ namespace internal {
F(SetCode, 2, 1) \
F(SetExpectedNumberOfProperties, 2, 1) \
\
F(CreateApiFunction, 1, 1) \
F(CreateApiFunction, 2, 1) \
F(IsTemplate, 1, 1) \
F(GetTemplateField, 2, 1) \
F(DisableAccessChecks, 1, 1) \