From 7d4c74d1b96d82681d49519c129262a1568e87d4 Mon Sep 17 00:00:00 2001 From: Tom Sepez Date: Tue, 10 Nov 2015 15:07:08 -0800 Subject: Keep "static" objects per-context rather than per isolate. Every time we initialize a new v8::Context, we make a new set of pre-existing native objects, and overwrite the v8::Global handles to those in the previous set. Thus, we may be theoretically releasing some v8::Globals early. R=jochen@chromium.org Review URL: https://codereview.chromium.org/1424933013 . --- fpdfsdk/include/jsapi/fxjs_v8.h | 12 +++++---- fpdfsdk/src/javascript/JS_Runtime.cpp | 4 +-- fpdfsdk/src/javascript/JS_Runtime.h | 2 ++ fpdfsdk/src/jsapi/fxjs_v8.cpp | 43 +++++++++++++++++------------- fpdfsdk/src/jsapi/fxjs_v8_embeddertest.cpp | 6 +++-- 5 files changed, 39 insertions(+), 28 deletions(-) diff --git a/fpdfsdk/include/jsapi/fxjs_v8.h b/fpdfsdk/include/jsapi/fxjs_v8.h index c5a864026b..b8a63c6c7b 100644 --- a/fpdfsdk/include/jsapi/fxjs_v8.h +++ b/fpdfsdk/include/jsapi/fxjs_v8.h @@ -59,7 +59,6 @@ extern const wchar_t kFXJSValueNameFxobj[]; extern const wchar_t kFXJSValueNameNull[]; extern const wchar_t kFXJSValueNameUndefined[]; - class FXJS_ArrayBufferAllocator : public v8::ArrayBuffer::Allocator { void* Allocate(size_t length) override; void* AllocateUninitialized(size_t length) override; @@ -123,11 +122,14 @@ void FXJS_DefineGlobalConst(v8::Isolate* pIsolate, v8::Local pDefault); // Called after FXJS_Define* calls made. -void FXJS_InitializeRuntime(v8::Isolate* pIsolate, - IJS_Runtime* pIRuntime, - v8::Global& v8PersistentContext); +void FXJS_InitializeRuntime( + v8::Isolate* pIsolate, + IJS_Runtime* pIRuntime, + v8::Global* pV8PersistentContext, + std::vector*>* pStaticObjects); void FXJS_ReleaseRuntime(v8::Isolate* pIsolate, - v8::Global& v8PersistentContext); + v8::Global* pV8PersistentContext, + std::vector*>* pStaticObjects); IJS_Runtime* FXJS_GetRuntimeFromIsolate(v8::Isolate* pIsolate); // Called after FXJS_InitializeRuntime call made. diff --git a/fpdfsdk/src/javascript/JS_Runtime.cpp b/fpdfsdk/src/javascript/JS_Runtime.cpp index 34a18dc385..74d9a44a1c 100644 --- a/fpdfsdk/src/javascript/JS_Runtime.cpp +++ b/fpdfsdk/src/javascript/JS_Runtime.cpp @@ -64,7 +64,7 @@ CJS_Runtime::CJS_Runtime(CPDFDoc_Environment* pApp) DefineJSObjects(); CJS_Context* pContext = (CJS_Context*)NewContext(); - FXJS_InitializeRuntime(GetIsolate(), this, m_context); + FXJS_InitializeRuntime(GetIsolate(), this, &m_context, &m_StaticObjects); ReleaseContext(pContext); } @@ -76,7 +76,7 @@ CJS_Runtime::~CJS_Runtime() { delete m_ContextArray.GetAt(i); m_ContextArray.RemoveAll(); - FXJS_ReleaseRuntime(GetIsolate(), m_context); + FXJS_ReleaseRuntime(GetIsolate(), &m_context, &m_StaticObjects); m_pApp = NULL; m_pDocument = NULL; diff --git a/fpdfsdk/src/javascript/JS_Runtime.h b/fpdfsdk/src/javascript/JS_Runtime.h index 4a55c2e9e6..1bdd8e6fdd 100644 --- a/fpdfsdk/src/javascript/JS_Runtime.h +++ b/fpdfsdk/src/javascript/JS_Runtime.h @@ -9,6 +9,7 @@ #include #include +#include #include "../../include/javascript/IJavaScript.h" #include "../../include/jsapi/fxjs_v8.h" @@ -71,6 +72,7 @@ class CJS_Runtime : public IJS_Runtime { v8::Isolate* m_isolate; bool m_isolateManaged; v8::Global m_context; + std::vector*> m_StaticObjects; std::set m_observers; }; diff --git a/fpdfsdk/src/jsapi/fxjs_v8.cpp b/fpdfsdk/src/jsapi/fxjs_v8.cpp index 0c58a1b01f..d21970e595 100644 --- a/fpdfsdk/src/jsapi/fxjs_v8.cpp +++ b/fpdfsdk/src/jsapi/fxjs_v8.cpp @@ -95,7 +95,6 @@ class CFXJS_ObjDefinition { v8::Isolate* m_pIsolate; v8::Global m_FunctionTemplate; v8::Global m_Signature; - v8::Global m_StaticObj; }; static v8::Local GetGlobalObjectTemplate( @@ -273,9 +272,11 @@ void FXJS_DefineGlobalConst(v8::Isolate* pIsolate, pDefault, v8::ReadOnly); } -void FXJS_InitializeRuntime(v8::Isolate* pIsolate, - IJS_Runtime* pIRuntime, - v8::Global& v8PersistentContext) { +void FXJS_InitializeRuntime( + v8::Isolate* pIsolate, + IJS_Runtime* pIRuntime, + v8::Global* pV8PersistentContext, + std::vector*>* pStaticObjects) { if (pIsolate == g_isolate) ++g_isolate_ref_count; @@ -289,14 +290,9 @@ void FXJS_InitializeRuntime(v8::Isolate* pIsolate, v8Context->SetAlignedPointerInEmbedderData(kPerContextDataIndex, pIRuntime); int maxID = CFXJS_ObjDefinition::MaxID(pIsolate); + pStaticObjects->resize(maxID + 1); for (int i = 0; i < maxID; ++i) { CFXJS_ObjDefinition* pObjDef = CFXJS_ObjDefinition::ForID(pIsolate, i); - CFX_ByteString bs = CFX_WideString(pObjDef->m_ObjName).UTF8Encode(); - v8::Local m_ObjName = - v8::String::NewFromUtf8(pIsolate, bs.c_str(), - v8::NewStringType::kNormal, - bs.GetLength()).ToLocalChecked(); - if (pObjDef->m_ObjType == FXJSOBJTYPE_GLOBAL) { v8Context->Global() ->GetPrototype() @@ -310,23 +306,27 @@ void FXJS_InitializeRuntime(v8::Isolate* pIsolate, ->ToObject(v8Context) .ToLocalChecked()); } else if (pObjDef->m_ObjType == FXJSOBJTYPE_STATIC) { + CFX_ByteString bs = CFX_WideString(pObjDef->m_ObjName).UTF8Encode(); + v8::Local m_ObjName = + v8::String::NewFromUtf8(pIsolate, bs.c_str(), + v8::NewStringType::kNormal, + bs.GetLength()).ToLocalChecked(); + v8::Local obj = FXJS_NewFxDynamicObj(pIsolate, pIRuntime, i); v8Context->Global()->Set(v8Context, m_ObjName, obj).FromJust(); - pObjDef->m_StaticObj.Reset(pIsolate, obj); + pStaticObjects->at(i) = new v8::Global(pIsolate, obj); } } - v8PersistentContext.Reset(pIsolate, v8Context); + pV8PersistentContext->Reset(pIsolate, v8Context); } void FXJS_ReleaseRuntime(v8::Isolate* pIsolate, - v8::Global& v8PersistentContext) { - if (pIsolate == g_isolate && --g_isolate_ref_count > 0) - return; - + v8::Global* pV8PersistentContext, + std::vector*>* pStaticObjects) { v8::Isolate::Scope isolate_scope(pIsolate); v8::HandleScope handle_scope(pIsolate); v8::Local context = - v8::Local::New(pIsolate, v8PersistentContext); + v8::Local::New(pIsolate, *pV8PersistentContext); v8::Context::Scope context_scope(context); FXJS_PerIsolateData* pData = FXJS_PerIsolateData::Get(pIsolate); @@ -340,8 +340,10 @@ void FXJS_ReleaseRuntime(v8::Isolate* pIsolate, if (pObjDef->m_ObjType == FXJSOBJTYPE_GLOBAL) { pObj = context->Global()->GetPrototype()->ToObject(context).ToLocalChecked(); - } else if (!pObjDef->m_StaticObj.IsEmpty()) { - pObj = v8::Local::New(pIsolate, pObjDef->m_StaticObj); + } else if (pStaticObjects->at(i) && !pStaticObjects->at(i)->IsEmpty()) { + pObj = v8::Local::New(pIsolate, *pStaticObjects->at(i)); + delete pStaticObjects->at(i); + pStaticObjects->at(i) = nullptr; } if (!pObj.IsEmpty()) { @@ -352,6 +354,9 @@ void FXJS_ReleaseRuntime(v8::Isolate* pIsolate, delete pObjDef; } + if (pIsolate == g_isolate && --g_isolate_ref_count > 0) + return; + pIsolate->SetData(g_embedderDataSlot, nullptr); delete pData; } diff --git a/fpdfsdk/src/jsapi/fxjs_v8_embeddertest.cpp b/fpdfsdk/src/jsapi/fxjs_v8_embeddertest.cpp index b965ced32e..eaaee86d67 100644 --- a/fpdfsdk/src/jsapi/fxjs_v8_embeddertest.cpp +++ b/fpdfsdk/src/jsapi/fxjs_v8_embeddertest.cpp @@ -32,11 +32,12 @@ class FXJSV8Embeddertest : public EmbedderTest { v8::Isolate::Scope isolate_scope(m_pIsolate); v8::HandleScope handle_scope(m_pIsolate); FXJS_PerIsolateData::SetUp(m_pIsolate); - FXJS_InitializeRuntime(m_pIsolate, nullptr, m_pPersistentContext); + FXJS_InitializeRuntime(m_pIsolate, nullptr, &m_pPersistentContext, + &m_StaticObjects); } void TearDown() override { - FXJS_ReleaseRuntime(m_pIsolate, m_pPersistentContext); + FXJS_ReleaseRuntime(m_pIsolate, &m_pPersistentContext, &m_StaticObjects); m_pPersistentContext.Reset(); FXJS_Release(); EmbedderTest::TearDown(); @@ -51,6 +52,7 @@ class FXJSV8Embeddertest : public EmbedderTest { nonstd::unique_ptr m_pArrayBufferAllocator; v8::Isolate* m_pIsolate; v8::Global m_pPersistentContext; + std::vector*> m_StaticObjects; }; TEST_F(FXJSV8Embeddertest, Getters) { -- cgit v1.2.3