mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-06 23:54:03 +00:00
bugfix for snapshot and change the elements number in jsobject
Signed-off-by: xiongluo <xiongluo@huawei.com>
This commit is contained in:
parent
991c3ea9f9
commit
2fc660ebca
@ -1348,13 +1348,10 @@ static void DumpArrayClass([[maybe_unused]] JSThread *thread, const TaggedArray
|
||||
{
|
||||
DISALLOW_GARBAGE_COLLECTION;
|
||||
array_size_t len = arr->GetLength();
|
||||
|
||||
for (array_size_t i = 0; i < len; i++) {
|
||||
JSTaggedValue val(arr->Get(i));
|
||||
if (!val.IsHole()) {
|
||||
CString str = ToCString(i);
|
||||
vec.push_back(std::make_pair(str, val));
|
||||
}
|
||||
CString str = ToCString(i);
|
||||
vec.push_back(std::make_pair(str, val));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1376,6 +1373,7 @@ static void DumpObject(JSThread *thread, TaggedObject *obj, std::vector<std::pai
|
||||
DumpDynClass(thread, obj, vec);
|
||||
break;
|
||||
case JSType::TAGGED_ARRAY:
|
||||
case JSType::TAGGED_DICTIONARY:
|
||||
DumpArrayClass(thread, TaggedArray::Cast(obj), vec);
|
||||
break;
|
||||
case JSType::STRING:
|
||||
@ -1529,15 +1527,24 @@ static inline void EcmaStringToStd(CString &res, EcmaString *str)
|
||||
res.append(string);
|
||||
}
|
||||
|
||||
static inline void KeyToStd(CString &res, JSTaggedValue key)
|
||||
static void KeyToStd(CString &res, JSTaggedValue key)
|
||||
{
|
||||
if (key.IsString()) {
|
||||
EcmaStringToStd(res, EcmaString::Cast(key.GetTaggedObject()));
|
||||
} else if (key.IsSymbol()) {
|
||||
JSSymbol *sym = JSSymbol::Cast(key.GetTaggedObject());
|
||||
EcmaStringToStd(res, EcmaString::Cast(sym->GetDescription().GetTaggedObject()));
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
if (key.IsInt()) {
|
||||
res = std::to_string(key.GetInt());
|
||||
} else if (key.IsDouble()) {
|
||||
res = std::to_string(key.GetDouble());
|
||||
} else if (key.IsBoolean()) {
|
||||
res = key.IsTrue() ? "true" : "false";
|
||||
} else if (key.IsHeapObject()) {
|
||||
if (key.IsWeak()) {
|
||||
key.RemoveWeakTag();
|
||||
}
|
||||
if (key.IsString()) {
|
||||
EcmaStringToStd(res, EcmaString::Cast(key.GetTaggedObject()));
|
||||
} else if (key.IsSymbol()) {
|
||||
JSSymbol *sym = JSSymbol::Cast(key.GetTaggedObject());
|
||||
EcmaStringToStd(res, EcmaString::Cast(sym->GetDescription().GetTaggedObject()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1557,7 +1564,7 @@ void NumberDictionary::DumpForSnapshot([[maybe_unused]] JSThread *thread,
|
||||
int size = Size();
|
||||
for (int hashIndex = 0; hashIndex < size; hashIndex++) {
|
||||
JSTaggedValue key(GetKey(hashIndex));
|
||||
if (!key.IsUndefined() && !key.IsHole()) {
|
||||
if (!key.IsUndefined() && !key.IsHole() && !key.IsNull()) {
|
||||
JSTaggedValue val(GetValue(hashIndex));
|
||||
CString str = ToCString(static_cast<uint32_t>(JSTaggedNumber(key).GetNumber()));
|
||||
vec.push_back(std::make_pair(str, val));
|
||||
@ -1572,9 +1579,8 @@ void NameDictionary::DumpForSnapshot([[maybe_unused]] JSThread *thread,
|
||||
int size = Size();
|
||||
for (int hashIndex = 0; hashIndex < size; hashIndex++) {
|
||||
JSTaggedValue key(GetKey(hashIndex));
|
||||
if (!key.IsUndefined() && !key.IsHole()) {
|
||||
if (!key.IsUndefined() && !key.IsHole() && !key.IsNull()) {
|
||||
JSTaggedValue val(GetValue(hashIndex));
|
||||
|
||||
CString str;
|
||||
KeyToStd(str, key);
|
||||
vec.push_back(std::make_pair(str, val));
|
||||
@ -1589,12 +1595,10 @@ void GlobalDictionary::DumpForSnapshot([[maybe_unused]] JSThread *thread,
|
||||
int size = Size();
|
||||
for (int hashIndex = 0; hashIndex < size; hashIndex++) {
|
||||
JSTaggedValue key(GetKey(hashIndex));
|
||||
if (!key.IsUndefined() && !key.IsHole()) {
|
||||
PropertyBox *box = PropertyBox::Cast(key.GetTaggedObject());
|
||||
|
||||
if (!key.IsUndefined() && !key.IsHole() && !key.IsNull()) {
|
||||
CString str;
|
||||
KeyToStd(str, key);
|
||||
JSTaggedValue val = box->GetValue();
|
||||
JSTaggedValue val = GetValue(hashIndex);
|
||||
vec.push_back(std::make_pair(str, val));
|
||||
}
|
||||
}
|
||||
@ -1607,7 +1611,7 @@ void LinkedHashSet::DumpForSnapshot([[maybe_unused]] JSThread *thread,
|
||||
int capacity = NumberOfElements() + NumberOfDeletedElements();
|
||||
for (int hashIndex = 0; hashIndex < capacity; hashIndex++) {
|
||||
JSTaggedValue key(GetKey(hashIndex));
|
||||
if (!key.IsUndefined() && !key.IsHole()) {
|
||||
if (!key.IsUndefined() && !key.IsHole() && !key.IsNull()) {
|
||||
CString str;
|
||||
KeyToStd(str, key);
|
||||
vec.push_back(std::make_pair(str, JSTaggedValue::Hole()));
|
||||
@ -1622,8 +1626,8 @@ void LinkedHashMap::DumpForSnapshot([[maybe_unused]] JSThread *thread,
|
||||
int capacity = NumberOfElements() + NumberOfDeletedElements();
|
||||
for (int hashIndex = 0; hashIndex < capacity; hashIndex++) {
|
||||
JSTaggedValue key(GetKey(hashIndex));
|
||||
if (!key.IsUndefined() && !key.IsHole()) {
|
||||
JSTaggedValue val(GetValue(hashIndex));
|
||||
if (!key.IsUndefined() && !key.IsHole() && !key.IsNull()) {
|
||||
JSTaggedValue val = GetValue(hashIndex);
|
||||
CString str;
|
||||
KeyToStd(str, key);
|
||||
vec.push_back(std::make_pair(str, val));
|
||||
|
@ -37,6 +37,10 @@ bool HeapProfiler::DumpHeapSnapShot(JSThread *thread, DumpFormat dumpFormat, con
|
||||
{
|
||||
[[maybe_unused]] bool heapClean = ForceFullGC(thread);
|
||||
ASSERT(heapClean);
|
||||
auto heap = thread->GetEcmaVM()->GetHeap();
|
||||
size_t heapSize = heap->GetNewSpace()->GetHeapObjectSize() + heap->GetOldSpace()->GetHeapObjectSize()
|
||||
+ heap->GetNonMovableSpace()->GetHeapObjectSize();
|
||||
LOG(ERROR, RUNTIME) << "HeapProfiler DumpSnapshot heap size " << heapSize;
|
||||
HeapSnapShot *snapShot = MakeHeapSnapShot(thread, SampleType::ONE_SHOT);
|
||||
ASSERT(snapShot != nullptr);
|
||||
std::pair<bool, CString> realPath = FilePathValid(filePath);
|
||||
@ -148,7 +152,6 @@ bool HeapProfiler::ForceFullGC(JSThread *thread)
|
||||
if (vm->IsInitialized()) {
|
||||
const_cast<Heap *>(vm->GetHeap())->CollectGarbage(TriggerGCType::SEMI_GC);
|
||||
const_cast<Heap *>(vm->GetHeap())->CollectGarbage(TriggerGCType::OLD_GC);
|
||||
const_cast<Heap *>(vm->GetHeap())->CollectGarbage(TriggerGCType::NON_MOVE_GC);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -156,6 +159,7 @@ bool HeapProfiler::ForceFullGC(JSThread *thread)
|
||||
|
||||
HeapSnapShot *HeapProfiler::MakeHeapSnapShot(JSThread *thread, SampleType sampleType)
|
||||
{
|
||||
LOG(ERROR, RUNTIME) << "HeapProfiler::MakeHeapSnapShot";
|
||||
DISALLOW_GARBAGE_COLLECTION;
|
||||
switch (sampleType) {
|
||||
case SampleType::ONE_SHOT: {
|
||||
|
@ -20,6 +20,7 @@
|
||||
namespace panda::ecmascript {
|
||||
void HeapProfilerInterface::DumpHeapSnapShot(JSThread *thread, DumpFormat dumpFormat, const CString &filePath)
|
||||
{
|
||||
LOG(ERROR, RUNTIME) << "HeapProfilerInterface::DumpHeapSnapshot";
|
||||
const Heap *heap = thread->GetEcmaVM()->GetHeap();
|
||||
auto *hprof = const_cast<RegionFactory *>(heap->GetRegionFactory())->New<HeapProfiler>(heap);
|
||||
if (UNLIKELY(hprof == nullptr)) {
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "ecmascript/global_env.h"
|
||||
#include "ecmascript/hprof/heap_root_visitor.h"
|
||||
#include "ecmascript/ic/property_box.h"
|
||||
#include "ecmascript/js_array.h"
|
||||
#include "ecmascript/js_handle.h"
|
||||
#include "ecmascript/js_hclass-inl.h"
|
||||
#include "ecmascript/js_object-inl.h"
|
||||
@ -144,10 +145,17 @@ CString *HeapSnapShot::GenerateNodeName(JSThread *thread, TaggedObject *entry)
|
||||
CString *name = GetString("UnKnownType");
|
||||
auto *hCls = entry->GetClass();
|
||||
if (hCls->IsTaggedArray()) {
|
||||
CString arrayName;
|
||||
TaggedArray *array = TaggedArray::Cast(entry);
|
||||
CString arrayName("Array[");
|
||||
arrayName.append(ToCString(array->GetLength()));
|
||||
arrayName.append("]");
|
||||
if (hCls->IsDictionary()) {
|
||||
arrayName = "TaggedDict[";
|
||||
arrayName.append(ToCString(array->GetLength()));
|
||||
arrayName.append("]");
|
||||
} else {
|
||||
arrayName = "TaggedArray[";
|
||||
arrayName.append(ToCString(array->GetLength()));
|
||||
arrayName.append("]");
|
||||
}
|
||||
name = GetString(arrayName); // String type was handled singly, see#GenerateStringNode
|
||||
} else if (hCls->IsHClass()) {
|
||||
name = GetString("HiddenClass");
|
||||
@ -161,7 +169,11 @@ CString *HeapSnapShot::GenerateNodeName(JSThread *thread, TaggedObject *entry)
|
||||
} else if (hCls->IsJSSymbol()) {
|
||||
name = GetString("JSSymbol");
|
||||
} else if (hCls->IsJSArray()) {
|
||||
name = GetString("JSArray");
|
||||
JSArray *jsArray = JSArray::Cast(entry);
|
||||
CString arrayName("JSArray[");
|
||||
arrayName.append(ToCString(jsArray->GetLength().GetInt()));
|
||||
arrayName.append("]");
|
||||
name = GetString(arrayName);
|
||||
} else if (hCls->IsTypedArray()) {
|
||||
name = GetString("TypedArray");
|
||||
} else if (hCls->IsJSTypedArray()) {
|
||||
@ -352,7 +364,7 @@ CString *HeapSnapShot::GenerateNodeName(JSThread *thread, TaggedObject *entry)
|
||||
|
||||
NodeType HeapSnapShot::GenerateNodeType(TaggedObject *entry)
|
||||
{
|
||||
NodeType nodeType;
|
||||
NodeType nodeType = NodeType::INVALID;
|
||||
auto *hCls = entry->GetClass();
|
||||
if (hCls->IsTaggedArray()) {
|
||||
nodeType = NodeType::JS_ARRAY;
|
||||
@ -381,8 +393,14 @@ Node *HeapSnapShot::GenerateNode(JSThread *thread, JSTaggedValue entry, int sequ
|
||||
sequenceId = sequenceId_ + SEQ_STEP;
|
||||
}
|
||||
if (entry.IsHeapObject()) {
|
||||
if (entry.IsWeak()) {
|
||||
entry.RemoveWeakTag();
|
||||
}
|
||||
if (entry.IsString()) {
|
||||
return GenerateStringNode(entry, sequenceId);
|
||||
node = GenerateStringNode(entry, sequenceId);
|
||||
if (node == nullptr) {
|
||||
LOG(ERROR, RUNTIME) << "string node nullptr";
|
||||
}
|
||||
}
|
||||
TaggedObject *obj = entry.GetTaggedObject();
|
||||
auto *baseClass = obj->GetClass();
|
||||
@ -404,44 +422,36 @@ Node *HeapSnapShot::GenerateNode(JSThread *thread, JSTaggedValue entry, int sequ
|
||||
}
|
||||
}
|
||||
} else {
|
||||
auto *obj = reinterpret_cast<TaggedObject *>(entry.GetRawData());
|
||||
CString primitiveName;
|
||||
JSTaggedValue primitiveObj(obj);
|
||||
if (primitiveObj.IsInt()) {
|
||||
primitiveName.append("Int:");
|
||||
} else if (primitiveObj.IsDouble()) {
|
||||
// A primitive value with tag will be regarded as a pointer
|
||||
auto *obj = reinterpret_cast<TaggedObject *>(entry.GetRawData());
|
||||
if (entry.IsInt()) {
|
||||
primitiveName.append("Int:" + ToCString(entry.GetInt()));
|
||||
} else if (entry.IsDouble()) {
|
||||
primitiveName.append("Double:");
|
||||
} else if (primitiveObj.IsSpecial()) {
|
||||
if (primitiveObj.IsHole()) {
|
||||
primitiveName.append("Hole");
|
||||
} else if (primitiveObj.IsNull()) {
|
||||
primitiveName.append("Null");
|
||||
} else if (primitiveObj.IsTrue()) {
|
||||
primitiveName.append("Boolean:true");
|
||||
} else if (primitiveObj.IsFalse()) {
|
||||
primitiveName.append("Boolean:false");
|
||||
} else if (primitiveObj.IsException()) {
|
||||
primitiveName.append("Exception");
|
||||
} else if (primitiveObj.IsUndefined()) {
|
||||
primitiveName.append("Undefined");
|
||||
}
|
||||
} else if (entry.IsHole()) {
|
||||
primitiveName.append("Hole");
|
||||
} else if (entry.IsNull()) {
|
||||
primitiveName.append("Null");
|
||||
} else if (entry.IsTrue()) {
|
||||
primitiveName.append("Boolean:true");
|
||||
} else if (entry.IsFalse()) {
|
||||
primitiveName.append("Boolean:false");
|
||||
} else if (entry.IsException()) {
|
||||
primitiveName.append("Exception");
|
||||
} else if (entry.IsUndefined()) {
|
||||
primitiveName.append("Undefined");
|
||||
} else {
|
||||
primitiveName.append("Illegal_Primitive");
|
||||
}
|
||||
|
||||
node = Node::NewNode(heap_, sequenceId, nodeCount_, GetString(primitiveName), NodeType::JS_PRIMITIVE_REF, 0,
|
||||
obj);
|
||||
Node *existNode = entryMap_.FindOrInsertNode(node); // Fast Index
|
||||
if (existNode == node) {
|
||||
if (sequenceId == sequenceId_ + SEQ_STEP) {
|
||||
sequenceId_ = sequenceId; // Odd Digit
|
||||
}
|
||||
InsertNodeUnique(node);
|
||||
} else {
|
||||
const_cast<RegionFactory *>(heap_->GetRegionFactory())->Delete(node);
|
||||
node = nullptr;
|
||||
existNode->SetLive(true);
|
||||
entryMap_.InsertEntry(node); // Fast Index
|
||||
if (sequenceId == sequenceId_ + SEQ_STEP) {
|
||||
sequenceId_ = sequenceId; // Odd Digit
|
||||
}
|
||||
InsertNodeUnique(node);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
@ -482,11 +492,16 @@ void HeapSnapShot::FillEdges(JSThread *thread)
|
||||
auto *objFrom = reinterpret_cast<TaggedObject *>((*iter)->GetAddress());
|
||||
std::vector<std::pair<CString, JSTaggedValue>> nameResources;
|
||||
JSTaggedValue(objFrom).DumpForSnapshot(thread, nameResources);
|
||||
JSTaggedValue objValue(objFrom);
|
||||
for (auto const &it : nameResources) {
|
||||
auto *to = reinterpret_cast<TaggedObject *>(it.second.GetRawData());
|
||||
Node *entryTo = entryMap_.FindEntry(Node::NewAddress(to));
|
||||
JSTaggedValue toValue = it.second;
|
||||
Node *entryTo = nullptr;
|
||||
if (toValue.IsHeapObject()) {
|
||||
auto *to = reinterpret_cast<TaggedObject *>(toValue.GetHeapObject());
|
||||
entryTo = entryMap_.FindEntry(Node::NewAddress(to));
|
||||
}
|
||||
if (entryTo == nullptr) {
|
||||
entryTo = GenerateNode(thread, it.second);
|
||||
entryTo = GenerateNode(thread, toValue);
|
||||
}
|
||||
if (entryTo != nullptr) {
|
||||
Edge *edge = Edge::NewEdge(heap_, edgeCount_, EdgeType::DEFAULT, *iter, entryTo, GetString(it.first));
|
||||
@ -565,8 +580,8 @@ Edge *HeapSnapShot::InsertEdgeUnique(Edge *edge)
|
||||
|
||||
void HeapSnapShot::AddSyntheticRoot(JSThread *thread)
|
||||
{
|
||||
Node *syntheticRoot = Node::NewNode(heap_, 1, nodeCount_, GetString("SyntheticRoot"), NodeType::SYNTHETIC, 0,
|
||||
nullptr);
|
||||
Node *syntheticRoot = Node::NewNode(heap_, 1, nodeCount_, GetString("SyntheticRoot"),
|
||||
NodeType::SYNTHETIC, 0, nullptr);
|
||||
InsertNodeAt(0, syntheticRoot);
|
||||
|
||||
int edgeOffset = 0;
|
||||
@ -632,7 +647,7 @@ CString EntryVisitor::ConvertKey(JSTaggedValue key)
|
||||
keyString = EcmaString::Cast(symbol->GetDescription().GetTaggedObject());
|
||||
}
|
||||
// convert, expensive but safe
|
||||
int length;
|
||||
int length = 0;
|
||||
if (keyString->IsUtf8()) {
|
||||
length = keyString->GetUtf8Length();
|
||||
std::vector<uint8_t> buffer(length);
|
||||
@ -687,7 +702,7 @@ void HeapEntryMap::InsertEntry(Node *node)
|
||||
|
||||
FrontType NodeTypeConverter::Convert(NodeType type)
|
||||
{
|
||||
FrontType fType;
|
||||
FrontType fType = FrontType::DEFAULT;
|
||||
if (type == NodeType::PROPERTY_BOX) {
|
||||
fType = FrontType::HIDDEN;
|
||||
} else if (type == NodeType::JS_ARRAY || type == NodeType::JS_TYPED_ARRAY) {
|
||||
|
@ -224,9 +224,9 @@ public:
|
||||
{
|
||||
return nodeEntryCount_;
|
||||
}
|
||||
void InsertEntry(Node *node);
|
||||
|
||||
private:
|
||||
void InsertEntry(Node *node);
|
||||
size_t nodeEntryCount_{0};
|
||||
CUnorderedMap<Address, Node *> nodesMap_{};
|
||||
};
|
||||
|
@ -22,6 +22,7 @@ namespace panda::ecmascript {
|
||||
bool HeapSnapShotJSONSerializer::Serialize(HeapSnapShot *snapShot, const CString &fileName)
|
||||
{
|
||||
// Serialize Node/Edge/String-Table
|
||||
LOG(ERROR, RUNTIME) << "HeapSnapShotJSONSerializer::Serialize begin";
|
||||
snapShot_ = snapShot;
|
||||
ASSERT(snapShot_->GetNodes() != nullptr && snapShot_->GetEdges() != nullptr &&
|
||||
snapShot_->GetEcmaStringTable() != nullptr);
|
||||
@ -38,6 +39,7 @@ bool HeapSnapShotJSONSerializer::Serialize(HeapSnapShot *snapShot, const CString
|
||||
SerializerSnapShotClosure(); // 9.
|
||||
|
||||
WriteJSON(fileName); // 10.
|
||||
LOG(ERROR, RUNTIME) << "HeapSnapShotJSONSerializer::Serialize exit";
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -191,6 +193,7 @@ void HeapSnapShotJSONSerializer::SerializerSnapShotClosure()
|
||||
void HeapSnapShotJSONSerializer::WriteJSON(const CString &fileName)
|
||||
{
|
||||
std::string fName(fileName);
|
||||
LOG(ERROR, RUNTIME) << "HeapSnapShotJSONSerializer::WriteJSON" << fName;
|
||||
outputStream_.open(fName, std::ios::out);
|
||||
if (!outputStream_.good()) {
|
||||
LOG_ECMA(ERROR) << "open file failed";
|
||||
|
@ -359,7 +359,7 @@ public:
|
||||
|
||||
class JSObject : public ECMAObject {
|
||||
public:
|
||||
static constexpr int MIN_ELEMENTS_LENGTH = 16;
|
||||
static constexpr int MIN_ELEMENTS_LENGTH = 3;
|
||||
static constexpr int MIN_PROPERTIES_LENGTH = JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS;
|
||||
static constexpr int PROPERTIES_GROW_SIZE = 4;
|
||||
static constexpr int FAST_ELEMENTS_FACTOR = 3;
|
||||
|
Loading…
Reference in New Issue
Block a user