summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjinming_wang <jinming_wang@foxitsoftware.com>2016-01-28 14:39:56 +0800
committerjinming_wang <jinming_wang@foxitsoftware.com>2016-01-28 14:39:56 +0800
commit61dc96f9aa2512807b62cfaec35b1cd012459a6f (patch)
tree5a42c470141d8d6b82c6d2ff1b1feb25468950ab
parent5fe3cb645c4ca8fe60600cbb13246457d70ab75d (diff)
downloadpdfium-61dc96f9aa2512807b62cfaec35b1cd012459a6f.tar.xz
Fix memory leakage on Linux - part3
BUG=pdfium:348 R=jochen@chromium.org, tsepez@chromium.org Review URL: https://codereview.chromium.org/1633083002 .
-rw-r--r--fpdfsdk/include/jsapi/fxjs_v8.h63
-rw-r--r--fpdfsdk/src/jsapi/fxjs_v8.cpp43
2 files changed, 100 insertions, 6 deletions
diff --git a/fpdfsdk/include/jsapi/fxjs_v8.h b/fpdfsdk/include/jsapi/fxjs_v8.h
index b0845a396f..50b2656e91 100644
--- a/fpdfsdk/include/jsapi/fxjs_v8.h
+++ b/fpdfsdk/include/jsapi/fxjs_v8.h
@@ -15,6 +15,7 @@
#define FPDFSDK_INCLUDE_JSAPI_FXJS_V8_H_
#include <v8.h>
+#include <v8-util.h>
#include <vector>
@@ -45,21 +46,76 @@ struct FXJSErr {
unsigned linnum;
};
+// Global weak map to save dynamic objects.
+class V8TemplateMapTraits : public v8::StdMapTraits<void*, v8::Object> {
+ public:
+ typedef v8::GlobalValueMap<void*, v8::Object, V8TemplateMapTraits> MapType;
+ typedef void WeakCallbackDataType;
+
+ static WeakCallbackDataType* WeakCallbackParameter(
+ MapType* map,
+ void* key,
+ const v8::Local<v8::Object>& value) {
+ return key;
+ }
+ static MapType* MapFromWeakCallbackInfo(
+ const v8::WeakCallbackInfo<WeakCallbackDataType>&);
+
+ static void* KeyFromWeakCallbackInfo(
+ const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
+ return data.GetParameter();
+ }
+ static const v8::PersistentContainerCallbackType kCallbackType =
+ v8::kWeakWithInternalFields;
+ static void DisposeWeak(
+ const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {}
+ static void OnWeakCallback(
+ const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {}
+ static void Dispose(v8::Isolate* isolate,
+ v8::Global<v8::Object> value,
+ void* key);
+ static void DisposeCallbackData(WeakCallbackDataType* callbackData) {}
+};
+
+class V8TemplateMap {
+ public:
+ typedef v8::GlobalValueMap<void*, v8::Object, V8TemplateMapTraits> MapType;
+
+ void set(void* key, v8::Local<v8::Object> handle) {
+ ASSERT(!m_map.Contains(key));
+ m_map.Set(key, handle);
+ }
+ explicit V8TemplateMap(v8::Isolate* isolate) : m_map(isolate) {}
+ friend class V8TemplateMapTraits;
+
+ private:
+ MapType m_map;
+};
+
class FXJS_PerIsolateData {
public:
static void SetUp(v8::Isolate* pIsolate);
static FXJS_PerIsolateData* Get(v8::Isolate* pIsolate);
+ void CreateDynamicObjsMap(v8::Isolate* pIsolate) {
+ m_pDynamicObjsMap = new V8TemplateMap(pIsolate);
+ }
+ void ReleaseDynamicObjsMap() {
+ delete m_pDynamicObjsMap;
+ m_pDynamicObjsMap = nullptr;
+ }
std::vector<CFXJS_ObjDefinition*> m_ObjectDefnArray;
#ifdef PDF_ENABLE_XFA
CFXJSE_RuntimeData* m_pFXJSERuntimeData;
#endif // PDF_ENABLE_XFA
+ V8TemplateMap* m_pDynamicObjsMap;
protected:
#ifndef PDF_ENABLE_XFA
- FXJS_PerIsolateData() {}
+ FXJS_PerIsolateData() : m_pDynamicObjsMap(nullptr) {}
#else // PDF_ENABLE_XFA
- FXJS_PerIsolateData() : m_pFXJSERuntimeData(nullptr) {}
+ FXJS_PerIsolateData()
+ : m_pFXJSERuntimeData(nullptr), m_pDynamicObjsMap(nullptr) {}
#endif // PDF_ENABLE_XFA
};
@@ -160,7 +216,8 @@ int FXJS_Execute(v8::Isolate* pIsolate,
v8::Local<v8::Object> FXJS_NewFxDynamicObj(v8::Isolate* pIsolate,
IJS_Runtime* pJSContext,
- int nObjDefnID);
+ int nObjDefnID,
+ bool bStatic = false);
v8::Local<v8::Object> FXJS_GetThisObj(v8::Isolate* pIsolate);
int FXJS_GetObjDefnID(v8::Local<v8::Object> pObj);
const wchar_t* FXJS_GetTypeof(v8::Local<v8::Value> pObj);
diff --git a/fpdfsdk/src/jsapi/fxjs_v8.cpp b/fpdfsdk/src/jsapi/fxjs_v8.cpp
index b06f747edb..9b6b5fa445 100644
--- a/fpdfsdk/src/jsapi/fxjs_v8.cpp
+++ b/fpdfsdk/src/jsapi/fxjs_v8.cpp
@@ -125,6 +125,31 @@ void FXJS_ArrayBufferAllocator::Free(void* data, size_t length) {
free(data);
}
+void V8TemplateMapTraits::Dispose(v8::Isolate* isolate,
+ v8::Global<v8::Object> value,
+ void* key) {
+ v8::Local<v8::Object> obj = value.Get(isolate);
+ if (obj.IsEmpty())
+ return;
+ int id = FXJS_GetObjDefnID(obj);
+ if (id == -1)
+ return;
+
+ CFXJS_ObjDefinition* pObjDef = CFXJS_ObjDefinition::ForID(isolate, id);
+ if (!pObjDef)
+ return;
+ if (pObjDef->m_pDestructor)
+ pObjDef->m_pDestructor(obj);
+ FXJS_FreePrivate(obj);
+}
+
+V8TemplateMapTraits::MapType* V8TemplateMapTraits::MapFromWeakCallbackInfo(
+ const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
+ V8TemplateMap* pMap =
+ (FXJS_PerIsolateData::Get(data.GetIsolate()))->m_pDynamicObjsMap;
+ return pMap ? &pMap->m_map : nullptr;
+}
+
void FXJS_Initialize(unsigned int embedderDataSlot, v8::Isolate* pIsolate) {
if (g_isolate) {
ASSERT(g_embedderDataSlot == embedderDataSlot);
@@ -290,6 +315,10 @@ void FXJS_InitializeRuntime(
v8::Context::Scope context_scope(v8Context);
FXJS_PerIsolateData::SetUp(pIsolate);
+ FXJS_PerIsolateData* pData = FXJS_PerIsolateData::Get(pIsolate);
+ if (!pData)
+ return;
+ pData->CreateDynamicObjsMap(pIsolate);
v8Context->SetAlignedPointerInEmbedderData(kPerContextDataIndex, pIRuntime);
int maxID = CFXJS_ObjDefinition::MaxID(pIsolate);
@@ -315,7 +344,8 @@ void FXJS_InitializeRuntime(
v8::NewStringType::kNormal,
bs.GetLength()).ToLocalChecked();
- v8::Local<v8::Object> obj = FXJS_NewFxDynamicObj(pIsolate, pIRuntime, i);
+ v8::Local<v8::Object> obj =
+ FXJS_NewFxDynamicObj(pIsolate, pIRuntime, i, true);
v8Context->Global()->Set(v8Context, m_ObjName, obj).FromJust();
pStaticObjects->at(i) = new v8::Global<v8::Object>(pIsolate, obj);
}
@@ -338,6 +368,7 @@ void FXJS_ReleaseRuntime(v8::Isolate* pIsolate,
FXJS_PerIsolateData* pData = FXJS_PerIsolateData::Get(pIsolate);
if (!pData)
return;
+ pData->ReleaseDynamicObjsMap();
#ifdef PDF_ENABLE_XFA
// XFA, if present, should have already cleaned itself up.
@@ -417,7 +448,8 @@ int FXJS_Execute(v8::Isolate* pIsolate,
v8::Local<v8::Object> FXJS_NewFxDynamicObj(v8::Isolate* pIsolate,
IJS_Runtime* pIRuntime,
- int nObjDefnID) {
+ int nObjDefnID,
+ bool bStatic) {
v8::Isolate::Scope isolate_scope(pIsolate);
v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
if (nObjDefnID == -1) {
@@ -441,10 +473,15 @@ v8::Local<v8::Object> FXJS_NewFxDynamicObj(v8::Isolate* pIsolate,
if (!pObjDef->GetInstanceTemplate()->NewInstance(context).ToLocal(&obj))
return v8::Local<v8::Object>();
- obj->SetAlignedPointerInInternalField(0, new CFXJS_PerObjectData(nObjDefnID));
+ CFXJS_PerObjectData* pPerObjData = new CFXJS_PerObjectData(nObjDefnID);
+ obj->SetAlignedPointerInInternalField(0, pPerObjData);
if (pObjDef->m_pConstructor)
pObjDef->m_pConstructor(pIRuntime, obj);
+ if (!bStatic && FXJS_PerIsolateData::Get(pIsolate)->m_pDynamicObjsMap) {
+ FXJS_PerIsolateData::Get(pIsolate)
+ ->m_pDynamicObjsMap->set(pPerObjData, obj);
+ }
return obj;
}