Reduce some ref-churn when using CPDF_References.
Also avoid virtual function call to GetMutableDirect(), which
make sense when the subclass isn't known, but when already
in CPDF_Reference code, just go obtain the referred-to object
from the indirect object holder.
Change-Id: Ieadbf0e03143684c5c8123c98ea920014fd0ef1a
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/97974
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fpdfapi/parser/cpdf_indirect_object_holder.cpp b/core/fpdfapi/parser/cpdf_indirect_object_holder.cpp
index 539aae5..59d54b9 100644
--- a/core/fpdfapi/parser/cpdf_indirect_object_holder.cpp
+++ b/core/fpdfapi/parser/cpdf_indirect_object_holder.cpp
@@ -16,7 +16,7 @@
namespace {
-RetainPtr<CPDF_Object> FilterInvalidObjNum(RetainPtr<CPDF_Object> obj) {
+const CPDF_Object* FilterInvalidObjNum(const CPDF_Object* obj) {
return obj && obj->GetObjNum() != CPDF_Object::kInvalidObjNum ? obj : nullptr;
}
@@ -31,29 +31,40 @@
RetainPtr<const CPDF_Object> CPDF_IndirectObjectHolder::GetIndirectObject(
uint32_t objnum) const {
- return const_cast<CPDF_IndirectObjectHolder*>(this)->GetMutableIndirectObject(
- objnum);
+ return pdfium::WrapRetain(GetIndirectObjectInternal(objnum));
}
RetainPtr<CPDF_Object> CPDF_IndirectObjectHolder::GetMutableIndirectObject(
uint32_t objnum) {
+ return pdfium::WrapRetain(
+ const_cast<CPDF_Object*>(GetIndirectObjectInternal(objnum)));
+}
+
+const CPDF_Object* CPDF_IndirectObjectHolder::GetIndirectObjectInternal(
+ uint32_t objnum) const {
auto it = m_IndirectObjs.find(objnum);
if (it == m_IndirectObjs.end())
return nullptr;
- return FilterInvalidObjNum(it->second);
+ return FilterInvalidObjNum(it->second.Get());
}
RetainPtr<CPDF_Object> CPDF_IndirectObjectHolder::GetOrParseIndirectObject(
uint32_t objnum) {
+ return pdfium::WrapRetain(GetOrParseIndirectObjectInternal(objnum));
+}
+
+CPDF_Object* CPDF_IndirectObjectHolder::GetOrParseIndirectObjectInternal(
+ uint32_t objnum) {
if (objnum == 0 || objnum == CPDF_Object::kInvalidObjNum)
return nullptr;
// Add item anyway to prevent recursively parsing of same object.
auto insert_result = m_IndirectObjs.insert(std::make_pair(objnum, nullptr));
- if (!insert_result.second)
- return FilterInvalidObjNum(insert_result.first->second);
-
+ if (!insert_result.second) {
+ return const_cast<CPDF_Object*>(
+ FilterInvalidObjNum(insert_result.first->second.Get()));
+ }
RetainPtr<CPDF_Object> pNewObj = ParseIndirectObject(objnum);
if (!pNewObj) {
m_IndirectObjs.erase(insert_result.first);
@@ -62,8 +73,10 @@
pNewObj->SetObjNum(objnum);
m_LastObjNum = std::max(m_LastObjNum, objnum);
- insert_result.first->second = pNewObj;
- return pNewObj;
+
+ CPDF_Object* result = pNewObj.Get();
+ insert_result.first->second = std::move(pNewObj);
+ return result;
}
RetainPtr<CPDF_Object> CPDF_IndirectObjectHolder::ParseIndirectObject(
@@ -89,7 +102,7 @@
return false;
auto& obj_holder = m_IndirectObjs[objnum];
- RetainPtr<const CPDF_Object> old_object = FilterInvalidObjNum(obj_holder);
+ const CPDF_Object* old_object = FilterInvalidObjNum(obj_holder.Get());
if (old_object && pObj->GetGenNum() <= old_object->GetGenNum())
return false;
@@ -101,7 +114,7 @@
void CPDF_IndirectObjectHolder::DeleteIndirectObject(uint32_t objnum) {
auto it = m_IndirectObjs.find(objnum);
- if (it == m_IndirectObjs.end() || !FilterInvalidObjNum(it->second))
+ if (it == m_IndirectObjs.end() || !FilterInvalidObjNum(it->second.Get()))
return;
m_IndirectObjs.erase(it);
diff --git a/core/fpdfapi/parser/cpdf_indirect_object_holder.h b/core/fpdfapi/parser/cpdf_indirect_object_holder.h
index 3906754..544e012 100644
--- a/core/fpdfapi/parser/cpdf_indirect_object_holder.h
+++ b/core/fpdfapi/parser/cpdf_indirect_object_holder.h
@@ -77,6 +77,11 @@
virtual RetainPtr<CPDF_Object> ParseIndirectObject(uint32_t objnum);
private:
+ friend class CPDF_Reference;
+
+ const CPDF_Object* GetIndirectObjectInternal(uint32_t objnum) const;
+ CPDF_Object* GetOrParseIndirectObjectInternal(uint32_t objnum);
+
uint32_t m_LastObjNum = 0;
std::map<uint32_t, RetainPtr<CPDF_Object>> m_IndirectObjs;
WeakPtr<ByteStringPool> m_pByteStringPool;
diff --git a/core/fpdfapi/parser/cpdf_reference.cpp b/core/fpdfapi/parser/cpdf_reference.cpp
index e784524..9e22174 100644
--- a/core/fpdfapi/parser/cpdf_reference.cpp
+++ b/core/fpdfapi/parser/cpdf_reference.cpp
@@ -22,22 +22,22 @@
}
ByteString CPDF_Reference::GetString() const {
- RetainPtr<const CPDF_Object> obj = SafeGetDirect();
+ const CPDF_Object* obj = FastGetDirect();
return obj ? obj->GetString() : ByteString();
}
float CPDF_Reference::GetNumber() const {
- RetainPtr<const CPDF_Object> obj = SafeGetDirect();
+ const CPDF_Object* obj = FastGetDirect();
return obj ? obj->GetNumber() : 0;
}
int CPDF_Reference::GetInteger() const {
- RetainPtr<const CPDF_Object> obj = SafeGetDirect();
+ const CPDF_Object* obj = FastGetDirect();
return obj ? obj->GetInteger() : 0;
}
RetainPtr<const CPDF_Dictionary> CPDF_Reference::GetDict() const {
- RetainPtr<const CPDF_Object> obj = SafeGetDirect();
+ const CPDF_Object* obj = FastGetDirect();
return obj ? obj->GetDict() : nullptr;
}
@@ -62,8 +62,11 @@
: nullptr;
}
-RetainPtr<const CPDF_Object> CPDF_Reference::SafeGetDirect() const {
- RetainPtr<const CPDF_Object> obj = GetDirect();
+const CPDF_Object* CPDF_Reference::FastGetDirect() const {
+ if (!m_pObjList)
+ return nullptr;
+ const CPDF_Object* obj =
+ m_pObjList->GetOrParseIndirectObjectInternal(m_RefObjNum);
return (obj && !obj->IsReference()) ? obj : nullptr;
}
diff --git a/core/fpdfapi/parser/cpdf_reference.h b/core/fpdfapi/parser/cpdf_reference.h
index 68eca1d..efa4a72 100644
--- a/core/fpdfapi/parser/cpdf_reference.h
+++ b/core/fpdfapi/parser/cpdf_reference.h
@@ -43,7 +43,8 @@
RetainPtr<CPDF_Object> CloneNonCyclic(
bool bDirect,
std::set<const CPDF_Object*>* pVisited) const override;
- RetainPtr<const CPDF_Object> SafeGetDirect() const;
+
+ const CPDF_Object* FastGetDirect() const;
UnownedPtr<CPDF_IndirectObjectHolder> m_pObjList;
uint32_t m_RefObjNum;