Pass in the prototype to CreateApiFunction rather than setting it on the result.
authorverwaest@chromium.org <verwaest@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 29 Apr 2014 17:48:07 +0000 (17:48 +0000)
committerverwaest@chromium.org <verwaest@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 29 Apr 2014 17:48:07 +0000 (17:48 +0000)
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

src/apinatives.js
src/bootstrapper.cc
src/factory.cc
src/factory.h
src/runtime.cc
src/runtime.h

index 6068882..0579caf 100644 (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) {
index 0bc0587..3419a6e 100644 (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);
   }
 
index e12d296..272383c 100644 (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 ||
-      type != JS_OBJECT_TYPE ||
-      instance_size != JSObject::kHeaderSize) {
+  Handle<Object> prototype;
+  if (maybe_prototype.ToHandle(&prototype) &&
+      (force_initial_map ||
+       type != JS_OBJECT_TYPE ||
+       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;
index d79a9c9..a87c093 100644 (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);
index f5dc2ac..e28783d 100644 (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,
index 092d323..eb28f83 100644 (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) \