Skip to content

Commit 415b64c

Browse files
committed
Merge pull request #161 from stesie/method-tmpl-cache
Cache v8::FunctionTemplates created by v8js_named_property_callback
2 parents 53995ac + 78dd0a9 commit 415b64c

File tree

3 files changed

+47
-8
lines changed

3 files changed

+47
-8
lines changed

v8js_class.cc

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,20 @@ static void v8js_free_storage(void *object TSRMLS_DC) /* {{{ */
109109
c->global_template.Reset();
110110
c->global_template.~Persistent();
111111

112+
/* Clear persistent call_impl & method_tmpls templates */
113+
for (std::map<v8js_tmpl_t *, v8js_tmpl_t>::iterator it = c->call_impls.begin();
114+
it != c->call_impls.end(); ++it) {
115+
// No need to free it->first, as it is stored in c->template_cache and freed below
116+
it->second.Reset();
117+
}
118+
c->call_impls.~map();
119+
120+
for (std::map<zend_function *, v8js_tmpl_t>::iterator it = c->method_tmpls.begin();
121+
it != c->method_tmpls.end(); ++it) {
122+
it->second.Reset();
123+
}
124+
c->method_tmpls.~map();
125+
112126
/* Clear persistent handles in template cache */
113127
for (std::map<const char *,v8js_tmpl_t>::iterator it = c->template_cache.begin();
114128
it != c->template_cache.end(); ++it) {
@@ -217,6 +231,8 @@ static zend_object_value v8js_new(zend_class_entry *ce TSRMLS_DC) /* {{{ */
217231

218232
new(&c->weak_closures) std::map<v8js_tmpl_t *, v8js_persistent_obj_t>();
219233
new(&c->weak_objects) std::map<zval *, v8js_persistent_obj_t>();
234+
new(&c->call_impls) std::map<v8js_tmpl_t *, v8js_tmpl_t>();
235+
new(&c->method_tmpls) std::map<zend_function *, v8js_tmpl_t>();
220236

221237
new(&c->v8js_v8objects) std::list<v8js_v8object *>();
222238
new(&c->script_objects) std::vector<v8js_script *>();

v8js_class.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ struct v8js_ctx {
5555

5656
std::map<zval *, v8js_persistent_obj_t> weak_objects;
5757
std::map<v8js_tmpl_t *, v8js_persistent_obj_t> weak_closures;
58+
std::map<v8js_tmpl_t *, v8js_tmpl_t> call_impls;
59+
std::map<zend_function *, v8js_tmpl_t> method_tmpls;
5860

5961
std::list<v8js_v8object *> v8js_v8objects;
6062

v8js_object_export.cc

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,7 @@ template<typename T>
518518
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) /* {{{ */
519519
{
520520
v8::Isolate *isolate = info.GetIsolate();
521+
v8js_ctx *ctx = (v8js_ctx *) isolate->GetData(0);
521522
v8::String::Utf8Value cstr(property);
522523
const char *name = ToCString(cstr);
523524
uint name_len = strlen(name);
@@ -535,9 +536,8 @@ inline v8::Local<v8::Value> v8js_named_property_callback(v8::Local<v8::String> p
535536
zval *php_value;
536537

537538
zval *object = reinterpret_cast<zval *>(v8::External::Cast(*self->GetHiddenValue(V8JS_SYM(PHPJS_OBJECT_KEY)))->Value());
538-
v8::Local<v8::FunctionTemplate> tmpl =
539-
v8::Local<v8::FunctionTemplate>::New
540-
(isolate, *reinterpret_cast<v8js_tmpl_t *>(self->GetAlignedPointerFromInternalField(0)));
539+
v8js_tmpl_t *tmpl_ptr = reinterpret_cast<v8js_tmpl_t *>(self->GetAlignedPointerFromInternalField(0));
540+
v8::Local<v8::FunctionTemplate> tmpl = v8::Local<v8::FunctionTemplate>::New(isolate, *tmpl_ptr);
541541
ce = scope = Z_OBJCE_P(object);
542542

543543
/* 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
568568
// Fake __call implementation
569569
// (only use this if method_ptr==NULL, which means
570570
// there is no actual PHP __call() implementation)
571-
v8::Local<v8::Function> cb =
572-
v8::FunctionTemplate::New(isolate,
573-
v8js_fake_call_impl, V8JS_NULL,
574-
v8::Signature::New(isolate, tmpl))->GetFunction();
571+
v8::Local<v8::FunctionTemplate> ft;
572+
try {
573+
ft = v8::Local<v8::FunctionTemplate>::New
574+
(isolate, ctx->call_impls.at(tmpl_ptr));
575+
}
576+
catch (const std::out_of_range &) {
577+
ft = v8::FunctionTemplate::New(isolate,
578+
v8js_fake_call_impl, V8JS_NULL,
579+
v8::Signature::New(isolate, tmpl));
580+
v8js_tmpl_t *persistent_ft = &ctx->call_impls[tmpl_ptr];
581+
persistent_ft->Reset(isolate, ft);
582+
}
583+
v8::Local<v8::Function> cb = ft->GetFunction();
575584
cb->SetName(property);
576585
ret_value = cb;
577586
} else {
578-
ret_value = PHP_V8JS_CALLBACK(isolate, method_ptr, tmpl);
587+
v8::Local<v8::FunctionTemplate> ft;
588+
try {
589+
ft = v8::Local<v8::FunctionTemplate>::New
590+
(isolate, ctx->method_tmpls.at(method_ptr));
591+
}
592+
catch (const std::out_of_range &) {
593+
ft = v8::FunctionTemplate::New(isolate, v8js_php_callback,
594+
v8::External::New((isolate), method_ptr),
595+
v8::Signature::New((isolate), tmpl));
596+
v8js_tmpl_t *persistent_ft = &ctx->method_tmpls[method_ptr];
597+
persistent_ft->Reset(isolate, ft);
598+
}
599+
ret_value = ft->GetFunction();
579600
}
580601
}
581602
} else if (callback_type == V8JS_PROP_QUERY) {

0 commit comments

Comments
 (0)