add uncached Function::New
authordcarney@chromium.org <dcarney@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 9 Sep 2013 07:52:52 +0000 (07:52 +0000)
committerdcarney@chromium.org <dcarney@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 9 Sep 2013 07:52:52 +0000 (07:52 +0000)
TBR=mstarzinger@chromium.org
BUG=

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16586 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

include/v8.h
src/api.cc
src/apinatives.js
src/execution.cc
src/macros.py
src/objects-inl.h
src/objects.h
test/cctest/test-api.cc

index be838c2..fef350b 100644 (file)
@@ -2361,11 +2361,129 @@ class V8_EXPORT Array : public Object {
 };
 
 
+template<typename T>
+class ReturnValue {
+ public:
+  template <class S> V8_INLINE(ReturnValue(const ReturnValue<S>& that))
+      : value_(that.value_) {
+    TYPE_CHECK(T, S);
+  }
+  // Handle setters
+  template <typename S> V8_INLINE(void Set(const Persistent<S>& handle));
+  template <typename S> V8_INLINE(void Set(const Handle<S> handle));
+  // Fast primitive setters
+  V8_INLINE(void Set(bool value));
+  V8_INLINE(void Set(double i));
+  V8_INLINE(void Set(int32_t i));
+  V8_INLINE(void Set(uint32_t i));
+  // Fast JS primitive setters
+  V8_INLINE(void SetNull());
+  V8_INLINE(void SetUndefined());
+  V8_INLINE(void SetEmptyString());
+  // Convenience getter for Isolate
+  V8_INLINE(Isolate* GetIsolate());
+
+ private:
+  template<class F> friend class ReturnValue;
+  template<class F> friend class FunctionCallbackInfo;
+  template<class F> friend class PropertyCallbackInfo;
+  V8_INLINE(internal::Object* GetDefaultValue());
+  V8_INLINE(explicit ReturnValue(internal::Object** slot));
+  internal::Object** value_;
+};
+
+
+/**
+ * The argument information given to function call callbacks.  This
+ * class provides access to information about the context of the call,
+ * including the receiver, the number and values of arguments, and
+ * the holder of the function.
+ */
+template<typename T>
+class FunctionCallbackInfo {
+ public:
+  V8_INLINE(int Length() const);
+  V8_INLINE(Local<Value> operator[](int i) const);
+  V8_INLINE(Local<Function> Callee() const);
+  V8_INLINE(Local<Object> This() const);
+  V8_INLINE(Local<Object> Holder() const);
+  V8_INLINE(bool IsConstructCall() const);
+  V8_INLINE(Local<Value> Data() const);
+  V8_INLINE(Isolate* GetIsolate() const);
+  V8_INLINE(ReturnValue<T> GetReturnValue() const);
+  // This shouldn't be public, but the arm compiler needs it.
+  static const int kArgsLength = 6;
+
+ protected:
+  friend class internal::FunctionCallbackArguments;
+  friend class internal::CustomArguments<FunctionCallbackInfo>;
+  static const int kReturnValueIndex = 0;
+  static const int kReturnValueDefaultValueIndex = -1;
+  static const int kIsolateIndex = -2;
+  static const int kDataIndex = -3;
+  static const int kCalleeIndex = -4;
+  static const int kHolderIndex = -5;
+
+  V8_INLINE(FunctionCallbackInfo(internal::Object** implicit_args,
+                   internal::Object** values,
+                   int length,
+                   bool is_construct_call));
+  internal::Object** implicit_args_;
+  internal::Object** values_;
+  int length_;
+  bool is_construct_call_;
+};
+
+
+/**
+ * The information passed to a property callback about the context
+ * of the property access.
+ */
+template<typename T>
+class PropertyCallbackInfo {
+ public:
+  V8_INLINE(Isolate* GetIsolate() const);
+  V8_INLINE(Local<Value> Data() const);
+  V8_INLINE(Local<Object> This() const);
+  V8_INLINE(Local<Object> Holder() const);
+  V8_INLINE(ReturnValue<T> GetReturnValue() const);
+  // This shouldn't be public, but the arm compiler needs it.
+  static const int kArgsLength = 6;
+
+ protected:
+  friend class MacroAssembler;
+  friend class internal::PropertyCallbackArguments;
+  friend class internal::CustomArguments<PropertyCallbackInfo>;
+  static const int kThisIndex = 0;
+  static const int kHolderIndex = -1;
+  static const int kDataIndex = -2;
+  static const int kReturnValueIndex = -3;
+  static const int kReturnValueDefaultValueIndex = -4;
+  static const int kIsolateIndex = -5;
+
+  V8_INLINE(PropertyCallbackInfo(internal::Object** args))
+      : args_(args) { }
+  internal::Object** args_;
+};
+
+
+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[]);
@@ -3034,114 +3152,6 @@ class V8_EXPORT Template : public Data {
 };
 
 
-template<typename T>
-class ReturnValue {
- public:
-  template <class S> V8_INLINE(ReturnValue(const ReturnValue<S>& that))
-      : value_(that.value_) {
-    TYPE_CHECK(T, S);
-  }
-  // Handle setters
-  template <typename S> V8_INLINE(void Set(const Persistent<S>& handle));
-  template <typename S> V8_INLINE(void Set(const Handle<S> handle));
-  // Fast primitive setters
-  V8_INLINE(void Set(bool value));
-  V8_INLINE(void Set(double i));
-  V8_INLINE(void Set(int32_t i));
-  V8_INLINE(void Set(uint32_t i));
-  // Fast JS primitive setters
-  V8_INLINE(void SetNull());
-  V8_INLINE(void SetUndefined());
-  V8_INLINE(void SetEmptyString());
-  // Convenience getter for Isolate
-  V8_INLINE(Isolate* GetIsolate());
-
- private:
-  template<class F> friend class ReturnValue;
-  template<class F> friend class FunctionCallbackInfo;
-  template<class F> friend class PropertyCallbackInfo;
-  V8_INLINE(internal::Object* GetDefaultValue());
-  V8_INLINE(explicit ReturnValue(internal::Object** slot));
-  internal::Object** value_;
-};
-
-
-/**
- * The argument information given to function call callbacks.  This
- * class provides access to information about the context of the call,
- * including the receiver, the number and values of arguments, and
- * the holder of the function.
- */
-template<typename T>
-class FunctionCallbackInfo {
- public:
-  V8_INLINE(int Length() const);
-  V8_INLINE(Local<Value> operator[](int i) const);
-  V8_INLINE(Local<Function> Callee() const);
-  V8_INLINE(Local<Object> This() const);
-  V8_INLINE(Local<Object> Holder() const);
-  V8_INLINE(bool IsConstructCall() const);
-  V8_INLINE(Local<Value> Data() const);
-  V8_INLINE(Isolate* GetIsolate() const);
-  V8_INLINE(ReturnValue<T> GetReturnValue() const);
-  // This shouldn't be public, but the arm compiler needs it.
-  static const int kArgsLength = 6;
-
- protected:
-  friend class internal::FunctionCallbackArguments;
-  friend class internal::CustomArguments<FunctionCallbackInfo>;
-  static const int kReturnValueIndex = 0;
-  static const int kReturnValueDefaultValueIndex = -1;
-  static const int kIsolateIndex = -2;
-  static const int kDataIndex = -3;
-  static const int kCalleeIndex = -4;
-  static const int kHolderIndex = -5;
-
-  V8_INLINE(FunctionCallbackInfo(internal::Object** implicit_args,
-                   internal::Object** values,
-                   int length,
-                   bool is_construct_call));
-  internal::Object** implicit_args_;
-  internal::Object** values_;
-  int length_;
-  bool is_construct_call_;
-};
-
-
-/**
- * The information passed to a property callback about the context
- * of the property access.
- */
-template<typename T>
-class PropertyCallbackInfo {
- public:
-  V8_INLINE(Isolate* GetIsolate() const);
-  V8_INLINE(Local<Value> Data() const);
-  V8_INLINE(Local<Object> This() const);
-  V8_INLINE(Local<Object> Holder() const);
-  V8_INLINE(ReturnValue<T> GetReturnValue() const);
-  // This shouldn't be public, but the arm compiler needs it.
-  static const int kArgsLength = 6;
-
- protected:
-  friend class MacroAssembler;
-  friend class internal::PropertyCallbackArguments;
-  friend class internal::CustomArguments<PropertyCallbackInfo>;
-  static const int kThisIndex = 0;
-  static const int kHolderIndex = -1;
-  static const int kDataIndex = -2;
-  static const int kReturnValueIndex = -3;
-  static const int kReturnValueDefaultValueIndex = -4;
-  static const int kIsolateIndex = -5;
-
-  V8_INLINE(PropertyCallbackInfo(internal::Object** args))
-      : args_(args) { }
-  internal::Object** args_;
-};
-
-
-typedef void (*FunctionCallback)(const FunctionCallbackInfo<Value>& info);
-
 /**
  * NamedProperty[Getter|Setter] are used as interceptors on object.
  * See ObjectTemplate::SetNamedPropertyHandler.
index 22228c4..696f9c2 100644 (file)
@@ -1052,22 +1052,24 @@ void FunctionTemplate::Inherit(v8::Handle<FunctionTemplate> value) {
 }
 
 
-Local<FunctionTemplate> FunctionTemplate::New(
+static Local<FunctionTemplate> FunctionTemplateNew(
+    i::Isolate* isolate,
     FunctionCallback callback,
     v8::Handle<Value> data,
     v8::Handle<Signature> signature,
-    int length) {
-  i::Isolate* isolate = i::Isolate::Current();
-  EnsureInitializedForIsolate(isolate, "v8::FunctionTemplate::New()");
-  LOG_API(isolate, "FunctionTemplate::New");
-  ENTER_V8(isolate);
+    int length,
+    bool do_not_cache) {
   i::Handle<i::Struct> struct_obj =
       isolate->factory()->NewStruct(i::FUNCTION_TEMPLATE_INFO_TYPE);
   i::Handle<i::FunctionTemplateInfo> obj =
       i::Handle<i::FunctionTemplateInfo>::cast(struct_obj);
   InitializeFunctionTemplate(obj);
-  int next_serial_number = isolate->next_serial_number();
-  isolate->set_next_serial_number(next_serial_number + 1);
+  obj->set_do_not_cache(do_not_cache);
+  int next_serial_number = 0;
+  if (!do_not_cache) {
+    next_serial_number = isolate->next_serial_number() + 1;
+    isolate->set_next_serial_number(next_serial_number);
+  }
   obj->set_serial_number(i::Smi::FromInt(next_serial_number));
   if (callback != 0) {
     if (data.IsEmpty()) data = v8::Undefined();
@@ -1076,12 +1078,24 @@ Local<FunctionTemplate> FunctionTemplate::New(
   obj->set_length(length);
   obj->set_undetectable(false);
   obj->set_needs_access_check(false);
-
   if (!signature.IsEmpty())
     obj->set_signature(*Utils::OpenHandle(*signature));
   return Utils::ToLocal(obj);
 }
 
+Local<FunctionTemplate> FunctionTemplate::New(
+    FunctionCallback callback,
+    v8::Handle<Value> data,
+    v8::Handle<Signature> signature,
+    int length) {
+  i::Isolate* isolate = i::Isolate::Current();
+  EnsureInitializedForIsolate(isolate, "v8::FunctionTemplate::New()");
+  LOG_API(isolate, "FunctionTemplate::New");
+  ENTER_V8(isolate);
+  return FunctionTemplateNew(
+      isolate, callback, data, signature, length, false);
+}
+
 
 Local<Signature> Signature::New(Handle<FunctionTemplate> receiver,
       int argc, Handle<FunctionTemplate> argv[]) {
@@ -4189,6 +4203,19 @@ Local<v8::Value> Object::CallAsConstructor(int argc,
 }
 
 
+Local<Function> Function::New(Isolate* v8_isolate,
+                              FunctionCallback callback,
+                              Local<Value> data,
+                              int length) {
+  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
+  LOG_API(isolate, "Function::New");
+  ENTER_V8(isolate);
+  return FunctionTemplateNew(
+      isolate, callback, data, Local<Signature>(), length, true)->
+          GetFunction();
+}
+
+
 Local<v8::Object> Function::NewInstance() const {
   return NewInstance(0, NULL);
 }
@@ -7865,7 +7892,7 @@ void InvokeAccessorGetterCallback(
       getter));
   VMState<EXTERNAL> state(isolate);
   ExternalCallbackScope call_scope(isolate, getter_address);
-  return getter(property, info);
+  getter(property, info);
 }
 
 
@@ -7876,7 +7903,7 @@ void InvokeFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>& info,
       reinterpret_cast<Address>(reinterpret_cast<intptr_t>(callback));
   VMState<EXTERNAL> state(isolate);
   ExternalCallbackScope call_scope(isolate, callback_address);
-  return callback(info);
+  callback(info);
 }
 
 
index 7adeb7e..5fb36c0 100644 (file)
@@ -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 91d340e..c59a737 100644 (file)
@@ -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 38b9a08..d699c14 100644 (file)
@@ -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 cd8426f..8a3cbec 100644 (file)
@@ -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 30b1b85..97d1e5d 100644 (file)
@@ -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 1e572ba..71d1b27 100644 (file)
@@ -20491,4 +20491,34 @@ THREADED_TEST(CrankshaftInterceptorFieldWrite) {
   ExpectInt32("obj.interceptor_age", 103);
 }
 
+
 #endif  // V8_OS_POSIX
+
+
+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());
+}
+