[beast: 31/70] V8BSE: cache JS wrappers for RemoteHandles to preserve object identity in JS
- From: Tim Janik <timj src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [beast: 31/70] V8BSE: cache JS wrappers for RemoteHandles to preserve object identity in JS
- Date: Tue, 28 Mar 2017 23:24:19 +0000 (UTC)
commit ca04ec15ed19d4e7d068f9fcca6bd0d0deeebe42
Author: Tim Janik <timj gnu org>
Date: Wed Feb 22 21:14:06 2017 +0100
V8BSE: cache JS wrappers for RemoteHandles to preserve object identity in JS
Signed-off-by: Tim Janik <timj gnu org>
ebeast/v8bse/nodemodule.cc | 69 ++++++++++++++++++++++++++++++++++++++-----
1 files changed, 61 insertions(+), 8 deletions(-)
---
diff --git a/ebeast/v8bse/nodemodule.cc b/ebeast/v8bse/nodemodule.cc
index 5388139..b444150 100644
--- a/ebeast/v8bse/nodemodule.cc
+++ b/ebeast/v8bse/nodemodule.cc
@@ -66,22 +66,72 @@ aida_remote_handle_unwrap_native (v8::Isolate *const isolate, v8::Local<v8::Valu
return nobject;
}
+static v8::Isolate *aida_remote_handle_idmap_isolate = NULL;
+static std::unordered_map<uint64_t, v8pp::persistent<v8::Object>> aida_remote_handle_idmap;
+
+static void
+aida_remote_handle_cache_add (v8::Isolate *const isolate, const Aida::RemoteHandle &rhandle, const
v8::Local<v8::Object> &wrapobj)
+{
+ assert_return (isolate == aida_remote_handle_idmap_isolate);
+ // check handle consistency
+ Aida::RemoteHandle *whandle = aida_remote_handle_unwrap_native<Aida::RemoteHandle> (isolate, wrapobj);
+ assert_return (whandle && whandle->__aida_orbid__() == rhandle.__aida_orbid__());
+ // seal object, since property extensions could not survive GC
+ wrapobj->SetIntegrityLevel (isolate->GetCurrentContext(), v8::IntegrityLevel::kSealed);
+ // use v8::UniquePersistent to keep a unique v8::Object per OrbObject around
+ v8pp::persistent<v8::Object> po (isolate, wrapobj);
+ // get rid of the unique v8::Object once all JS code forgot about its identity
+ auto weak_callback = [] (const v8::WeakCallbackInfo<Aida::RemoteHandle> &data) {
+ // v8::Isolate *const isolate = data.GetIsolate();
+ Aida::RemoteHandle *whandle = data.GetParameter();
+ const uint64_t orbid = whandle->__aida_orbid__();
+ auto it = aida_remote_handle_idmap.find (orbid);
+ if (it != aida_remote_handle_idmap.end())
+ {
+ it->second.Reset();
+ aida_remote_handle_idmap.erase (it);
+ }
+ };
+ po.SetWeak (whandle, weak_callback, v8::WeakCallbackType::kParameter);
+ // enter per-isolate cache
+ aida_remote_handle_idmap.emplace (rhandle.__aida_orbid__(), std::move (po));
+}
+
+static v8::Local<v8::Object>
+aida_remote_handle_cache_find (v8::Isolate *const isolate, const Aida::RemoteHandle &rhandle)
+{
+ v8::Local<v8::Object> result;
+ assert_return (isolate == aida_remote_handle_idmap_isolate, result);
+ auto it = aida_remote_handle_idmap.find (rhandle.__aida_orbid__());
+ if (it != aida_remote_handle_idmap.end())
+ result = v8pp::to_local (isolate, it->second);
+ return result;
+}
+
/// Create (or find) the corresponding down_cast() JS Object for a RemoteHandle.
static v8::Local<v8::Object>
-aida_remote_handle_wrap_native (v8::Isolate *const isolate, Aida::RemoteHandle const &rhandle)
+aida_remote_handle_wrap_native (v8::Isolate *const isolate, const Aida::RemoteHandle &rhandle)
{
v8::EscapableHandleScope scope (isolate);
- if (NULL != rhandle)
+ v8::Local<v8::Object> wrapobj;
+ if (AIDA_LIKELY (NULL != rhandle))
{
- Aida::TypeHashList thl = rhandle.__aida_typelist__();
- for (const auto &th : thl)
+ wrapobj = aida_remote_handle_cache_find (isolate, rhandle);
+ if (AIDA_LIKELY (!wrapobj.IsEmpty()))
+ return scope.Escape (wrapobj);
+ }
+ Aida::TypeHashList thl = rhandle.__aida_typelist__();
+ for (const auto &th : thl)
+ {
+ AidaRemoteHandleWrapper wrapper = aida_remote_handle_wrapper_map (th, AidaRemoteHandleWrapper (NULL));
+ if (wrapper)
{
- AidaRemoteHandleWrapper wrapper = aida_remote_handle_wrapper_map (th, AidaRemoteHandleWrapper
(NULL));
- if (wrapper)
- return scope.Escape (wrapper (isolate, rhandle));
+ wrapobj = wrapper (isolate, rhandle);
+ aida_remote_handle_cache_add (isolate, rhandle, wrapobj);
+ break;
}
}
- return scope.Escape (v8::Local<v8::Object>());
+ return scope.Escape (wrapobj);
}
/// Helper to specialize v8pp::convert<> for all RemoteHandle types.
@@ -159,6 +209,9 @@ v8bse_register_module (v8::Local<v8::Object> exports)
{
assert (bse_v8stub == NULL);
v8::Isolate *const isolate = v8::Isolate::GetCurrent();
+ assert (aida_remote_handle_idmap_isolate == NULL);
+ aida_remote_handle_idmap_isolate = isolate;
+
v8::HandleScope scope (isolate);
// start Bse
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]