Reviewers: Michael Starzinger,

Description:
add uncached Function::New

[email protected]
BUG=

Please review this at https://codereview.chromium.org/23561007/

SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge

Affected files (+68, -9 lines):
  M include/v8.h
  M src/api.cc
  M src/apinatives.js
  M src/execution.cc
  M src/macros.py
  M src/objects-inl.h
  M src/objects.h
  M test/cctest/test-api.cc


Index: include/v8.h
diff --git a/include/v8.h b/include/v8.h
index be838c2b22045f6fcaaf527012118ef645153b61..3c77b93f9d0dc9ec9e1598267caa0dc0509c6971 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -2361,11 +2361,21 @@ class V8_EXPORT Array : public Object {
 };


+typedef void (*FunctionCallback)(const FunctionCallbackInfo<Value>& info);
+
+
 /**
  * A JavaScript function object (ECMA-262, 15.3).
  */
 class V8_EXPORT Function : public Object {
  public:
+  // Create a function in the current execution context
+  // for a given FunctionCallback.
+  static Local<Function> New(Isolate* isolate,
+                             FunctionCallback callback,
+                             Local<Value> data = Local<Value>(),
+                             int length = 0);
+
   Local<Object> NewInstance() const;
   Local<Object> NewInstance(int argc, Handle<Value> argv[]) const;
   Local<Value> Call(Handle<Object> recv, int argc, Handle<Value> argv[]);
@@ -3140,8 +3150,6 @@ class PropertyCallbackInfo {
 };


-typedef void (*FunctionCallback)(const FunctionCallbackInfo<Value>& info);
-
 /**
  * NamedProperty[Getter|Setter] are used as interceptors on object.
  * See ObjectTemplate::SetNamedPropertyHandler.
Index: src/api.cc
diff --git a/src/api.cc b/src/api.cc
index 22228c4e8b175b67db90b04b0089e023280822cc..1c2a2616f294acda876c4ee3f97e9ce407b2910a 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -1076,6 +1076,7 @@ Local<FunctionTemplate> FunctionTemplate::New(
   obj->set_length(length);
   obj->set_undetectable(false);
   obj->set_needs_access_check(false);
+  obj->set_do_not_cache(false);

   if (!signature.IsEmpty())
     obj->set_signature(*Utils::OpenHandle(*signature));
@@ -4189,6 +4190,18 @@ Local<v8::Value> Object::CallAsConstructor(int argc,
 }


+Local<Function> Function::New(Isolate* v8_isolate,
+                              FunctionCallback callback,
+                              Local<Value> data,
+                              int length) {
+  HandleScope scope(reinterpret_cast<Isolate*>(v8_isolate));
+  Local<FunctionTemplate> info =
+      FunctionTemplate::New(callback, data, Local<Signature>(), length);
+  Utils::OpenHandle(*info)->set_do_not_cache(true);
+  return scope.Close(info->GetFunction());
+}
+
+
 Local<v8::Object> Function::NewInstance() const {
   return NewInstance(0, NULL);
 }
Index: src/apinatives.js
diff --git a/src/apinatives.js b/src/apinatives.js
index 7adeb7e7aeb379b14a55fc1c4fb1eaab93c76995..5fb36c09e7242b6289bb9d5f35551893b6e85ed8 100644
--- a/src/apinatives.js
+++ b/src/apinatives.js
@@ -74,8 +74,9 @@ function InstantiateFunction(data, name) {
       cache[serialNumber] = null;
       var fun = %CreateApiFunction(data);
       if (name) %FunctionSetName(fun, name);
-      cache[serialNumber] = fun;
       var flags = %GetTemplateField(data, kApiFlagOffset);
+      var doNotCache = flags & (1 << kDoNotCacheBit);
+      if (!doNotCache) cache[serialNumber] = fun;
       if (flags & (1 << kRemovePrototypeBit)) {
         %FunctionRemovePrototype(fun);
       } else {
@@ -97,6 +98,7 @@ function InstantiateFunction(data, name) {
         }
       }
       ConfigureTemplateInstance(fun, data);
+      if (doNotCache) return fun;
     } catch (e) {
       cache[serialNumber] = kUninitialized;
       throw e;
Index: src/execution.cc
diff --git a/src/execution.cc b/src/execution.cc
index 91d340e5e1064f41b7c27c60ffc68a61a771a2a3..c59a737c32b63158f18b4f1fd41be7525c1f7f05 100644
--- a/src/execution.cc
+++ b/src/execution.cc
@@ -705,12 +705,14 @@ Handle<JSFunction> Execution::InstantiateFunction(
     Handle<FunctionTemplateInfo> data,
     bool* exc) {
   Isolate* isolate = data->GetIsolate();
-  // Fast case: see if the function has already been instantiated
-  int serial_number = Smi::cast(data->serial_number())->value();
-  Object* elm =
-      isolate->native_context()->function_cache()->
-          GetElementNoExceptionThrown(isolate, serial_number);
- if (elm->IsJSFunction()) return Handle<JSFunction>(JSFunction::cast(elm));
+  if (!data->do_not_cache()) {
+    // Fast case: see if the function has already been instantiated
+    int serial_number = Smi::cast(data->serial_number())->value();
+    Object* elm =
+        isolate->native_context()->function_cache()->
+            GetElementNoExceptionThrown(isolate, serial_number);
+ if (elm->IsJSFunction()) return Handle<JSFunction>(JSFunction::cast(elm));
+  }
   // The function has not yet been instantiated in this context; do it.
   Handle<Object> args[] = { data };
   Handle<Object> result = Call(isolate,
Index: src/macros.py
diff --git a/src/macros.py b/src/macros.py
index 38b9a08142d612d74814e4867b951591cfbc06f5..d699c1462119103771da961660018cc94b849a22 100644
--- a/src/macros.py
+++ b/src/macros.py
@@ -69,6 +69,7 @@ const msPerMonth       = 2592000000;
 const kUninitialized = -1;
 const kReadOnlyPrototypeBit = 3;
const kRemovePrototypeBit = 4; # For FunctionTemplateInfo, matches objects.h
+const kDoNotCacheBit = 5;  # For FunctionTemplateInfo, matches objects.h

 # Note: kDayZeroInJulianDay = ToJulianDay(1970, 0, 1).
 const kInvalidDate        = 'Invalid Date';
Index: src/objects-inl.h
diff --git a/src/objects-inl.h b/src/objects-inl.h
index cd8426f08fa5fbe6d79ea99489bf4b3b8d9905ef..8a3cbec19d274bd716ec94cf2916a7b6d43b1f0a 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -4569,6 +4569,8 @@ BOOL_ACCESSORS(FunctionTemplateInfo, flag, read_only_prototype,
                kReadOnlyPrototypeBit)
 BOOL_ACCESSORS(FunctionTemplateInfo, flag, remove_prototype,
                kRemovePrototypeBit)
+BOOL_ACCESSORS(FunctionTemplateInfo, flag, do_not_cache,
+               kDoNotCacheBit)
 BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
                kIsExpressionBit)
 BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
Index: src/objects.h
diff --git a/src/objects.h b/src/objects.h
index 30b1b85668c2ede4e6b2fd1c883ff1cca6190756..97d1e5d0a32da82ac9aff3fe86f283ecf36a7812 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -9878,6 +9878,7 @@ class FunctionTemplateInfo: public TemplateInfo {
   DECL_BOOLEAN_ACCESSORS(needs_access_check)
   DECL_BOOLEAN_ACCESSORS(read_only_prototype)
   DECL_BOOLEAN_ACCESSORS(remove_prototype)
+  DECL_BOOLEAN_ACCESSORS(do_not_cache)

   static inline FunctionTemplateInfo* cast(Object* obj);

@@ -9913,6 +9914,7 @@ class FunctionTemplateInfo: public TemplateInfo {
   static const int kNeedsAccessCheckBit  = 2;
   static const int kReadOnlyPrototypeBit = 3;
   static const int kRemovePrototypeBit   = 4;
+  static const int kDoNotCacheBit        = 5;

   DISALLOW_IMPLICIT_CONSTRUCTORS(FunctionTemplateInfo);
 };
Index: test/cctest/test-api.cc
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index 1e572ba95bbecc7ad9f7269bd1a59b984ac7779c..18be6c0e0dae4cebf2482bf8a6d8624173af33bb 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -20491,4 +20491,33 @@ THREADED_TEST(CrankshaftInterceptorFieldWrite) {
   ExpectInt32("obj.interceptor_age", 103);
 }

+
+static Local<Value> function_new_expected_env;
+static void FunctionNewCallback(const v8::FunctionCallbackInfo<Value>& info) {
+  CHECK_EQ(function_new_expected_env, info.Data());
+  info.GetReturnValue().Set(17);
+}
+
+
+THREADED_TEST(FunctionNew) {
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope scope(isolate);
+  Local<Object> data = v8::Object::New();
+  function_new_expected_env = data;
+  Local<Function> func = Function::New(isolate, FunctionNewCallback, data);
+  env->Global()->Set(v8_str("func"), func);
+  Local<Value> result = CompileRun("func();");
+  CHECK_EQ(v8::Integer::New(17, isolate), result);
+  // Verify function not cached
+  int serial_number =
+      i::Smi::cast(v8::Utils::OpenHandle(*func)
+          ->shared()->get_api_func_data()->serial_number())->value();
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  i::Object* elm = i_isolate->native_context()->function_cache()
+      ->GetElementNoExceptionThrown(i_isolate, serial_number);
+  CHECK(elm->IsNull());
+}
+
+
 #endif  // V8_OS_POSIX


--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to