瀏覽代碼

Cache v8::FunctionTemplates created by v8js_named_property_callback

Stefan Siegl 9 年之前
父節點
當前提交
78dd0a9ff0
共有 3 個文件被更改,包括 47 次插入8 次删除
  1. 16 0
      v8js_class.cc
  2. 2 0
      v8js_class.h
  3. 29 8
      v8js_object_export.cc

+ 16 - 0
v8js_class.cc

@@ -109,6 +109,20 @@ static void v8js_free_storage(void *object TSRMLS_DC) /* {{{ */
 	c->global_template.Reset();
 	c->global_template.~Persistent();
 
+	/* Clear persistent call_impl & method_tmpls templates */
+	for (std::map<v8js_tmpl_t *, v8js_tmpl_t>::iterator it = c->call_impls.begin();
+		 it != c->call_impls.end(); ++it) {
+		// No need to free it->first, as it is stored in c->template_cache and freed below
+		it->second.Reset();
+	}
+	c->call_impls.~map();
+
+	for (std::map<zend_function *, v8js_tmpl_t>::iterator it = c->method_tmpls.begin();
+		 it != c->method_tmpls.end(); ++it) {
+		it->second.Reset();
+	}
+	c->method_tmpls.~map();
+
 	/* Clear persistent handles in template cache */
 	for (std::map<const char *,v8js_tmpl_t>::iterator it = c->template_cache.begin();
 		 it != c->template_cache.end(); ++it) {
@@ -217,6 +231,8 @@ static zend_object_value v8js_new(zend_class_entry *ce TSRMLS_DC) /* {{{ */
 
 	new(&c->weak_closures) std::map<v8js_tmpl_t *, v8js_persistent_obj_t>();
 	new(&c->weak_objects) std::map<zval *, v8js_persistent_obj_t>();
+	new(&c->call_impls) std::map<v8js_tmpl_t *, v8js_tmpl_t>();
+	new(&c->method_tmpls) std::map<zend_function *, v8js_tmpl_t>();
 
 	new(&c->v8js_v8objects) std::list<v8js_v8object *>();
 	new(&c->script_objects) std::vector<v8js_script *>();

+ 2 - 0
v8js_class.h

@@ -55,6 +55,8 @@ struct v8js_ctx {
 
   std::map<zval *, v8js_persistent_obj_t> weak_objects;
   std::map<v8js_tmpl_t *, v8js_persistent_obj_t> weak_closures;
+  std::map<v8js_tmpl_t *, v8js_tmpl_t> call_impls;
+  std::map<zend_function *, v8js_tmpl_t> method_tmpls;
 
   std::list<v8js_v8object *> v8js_v8objects;
 

+ 29 - 8
v8js_object_export.cc

@@ -518,6 +518,7 @@ template<typename T>
 inline v8::Local<v8::Value> v8js_named_property_callback(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<T> &info, property_op_t callback_type, v8::Local<v8::Value> set_value) /* {{{ */
 {
 	v8::Isolate *isolate = info.GetIsolate();
+	v8js_ctx *ctx = (v8js_ctx *) isolate->GetData(0);
 	v8::String::Utf8Value cstr(property);
 	const char *name = ToCString(cstr);
 	uint name_len = strlen(name);
@@ -535,9 +536,8 @@ inline v8::Local<v8::Value> v8js_named_property_callback(v8::Local<v8::String> p
 	zval *php_value;
 
 	zval *object = reinterpret_cast<zval *>(v8::External::Cast(*self->GetHiddenValue(V8JS_SYM(PHPJS_OBJECT_KEY)))->Value());
-	v8::Local<v8::FunctionTemplate> tmpl =
-		v8::Local<v8::FunctionTemplate>::New
-		(isolate, *reinterpret_cast<v8js_tmpl_t *>(self->GetAlignedPointerFromInternalField(0)));
+	v8js_tmpl_t *tmpl_ptr = reinterpret_cast<v8js_tmpl_t *>(self->GetAlignedPointerFromInternalField(0));
+	v8::Local<v8::FunctionTemplate> tmpl = v8::Local<v8::FunctionTemplate>::New(isolate, *tmpl_ptr);
 	ce = scope = Z_OBJCE_P(object);
 
 	/* First, check the (case-insensitive) method table */
@@ -568,14 +568,35 @@ inline v8::Local<v8::Value> v8js_named_property_callback(v8::Local<v8::String> p
 					// Fake __call implementation
 					// (only use this if method_ptr==NULL, which means
 					//  there is no actual PHP __call() implementation)
-					v8::Local<v8::Function> cb =
-						v8::FunctionTemplate::New(isolate,
-							v8js_fake_call_impl, V8JS_NULL,
-							v8::Signature::New(isolate, tmpl))->GetFunction();
+					v8::Local<v8::FunctionTemplate> ft;
+					try {
+						ft = v8::Local<v8::FunctionTemplate>::New
+							(isolate, ctx->call_impls.at(tmpl_ptr));
+					}
+					catch (const std::out_of_range &) {
+						ft = v8::FunctionTemplate::New(isolate,
+								v8js_fake_call_impl, V8JS_NULL,
+								v8::Signature::New(isolate, tmpl));
+						v8js_tmpl_t *persistent_ft = &ctx->call_impls[tmpl_ptr];
+						persistent_ft->Reset(isolate, ft);
+					}
+					v8::Local<v8::Function> cb = ft->GetFunction();
 					cb->SetName(property);
 					ret_value = cb;
 				} else {
-					ret_value = PHP_V8JS_CALLBACK(isolate, method_ptr, tmpl);
+					v8::Local<v8::FunctionTemplate> ft;
+					try {
+						ft = v8::Local<v8::FunctionTemplate>::New
+							(isolate, ctx->method_tmpls.at(method_ptr));
+					}
+					catch (const std::out_of_range &) {
+						ft = v8::FunctionTemplate::New(isolate, v8js_php_callback,
+								v8::External::New((isolate), method_ptr),
+								v8::Signature::New((isolate), tmpl));
+						v8js_tmpl_t *persistent_ft = &ctx->method_tmpls[method_ptr];
+						persistent_ft->Reset(isolate, ft);
+					}
+					ret_value = ft->GetFunction();
 				}
 			}
 		} else if (callback_type == V8JS_PROP_QUERY) {