Commit 9d0438ba authored by Alexei Filippov's avatar Alexei Filippov Committed by Commit Bot

[heap-profiler] Instrument JSPromise

Change-Id: I0c46b8b86a6ea33e4f48d498e1521fac54e3305e
Reviewed-on: https://chromium-review.googlesource.com/578728
Commit-Queue: Alexei Filippov <alph@chromium.org>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#46802}
parent 69c8f16d
......@@ -1013,6 +1013,8 @@ bool V8HeapExplorer::ExtractReferencesPass1(int entry, HeapObject* obj) {
ExtractJSCollectionReferences(entry, JSSet::cast(obj));
} else if (obj->IsJSMap()) {
ExtractJSCollectionReferences(entry, JSMap::cast(obj));
} else if (obj->IsJSPromise()) {
ExtractJSPromiseReferences(entry, JSPromise::cast(obj));
}
ExtractJSObjectReferences(entry, JSObject::cast(obj));
} else if (obj->IsString()) {
......@@ -1405,7 +1407,6 @@ void V8HeapExplorer::ExtractAccessorInfoReferences(
}
}
void V8HeapExplorer::ExtractAccessorPairReferences(
int entry, AccessorPair* accessors) {
SetInternalReference(accessors, entry, "getter", accessors->getter(),
......@@ -1414,12 +1415,10 @@ void V8HeapExplorer::ExtractAccessorPairReferences(
AccessorPair::kSetterOffset);
}
void V8HeapExplorer::TagBuiltinCodeObject(Code* code, const char* name) {
TagObject(code, names_->GetFormatted("(%s builtin)", name));
}
void V8HeapExplorer::TagCodeObject(Code* code) {
if (code->kind() == Code::STUB) {
TagObject(code, names_->GetFormatted(
......@@ -1428,7 +1427,6 @@ void V8HeapExplorer::TagCodeObject(Code* code) {
}
}
void V8HeapExplorer::ExtractCodeReferences(int entry, Code* code) {
TagCodeObject(code);
TagObject(code->relocation_info(), "(code relocation info)");
......@@ -1472,7 +1470,6 @@ void V8HeapExplorer::ExtractPropertyCellReferences(int entry,
PropertyCell::kDependentCodeOffset);
}
void V8HeapExplorer::ExtractAllocationSiteReferences(int entry,
AllocationSite* site) {
SetInternalReference(site, entry, "transition_info",
......@@ -1489,7 +1486,6 @@ void V8HeapExplorer::ExtractAllocationSiteReferences(int entry,
AllocationSite::kPointerFieldsEndOffset);
}
class JSArrayBufferDataEntryAllocator : public HeapEntriesAllocator {
public:
JSArrayBufferDataEntryAllocator(size_t size, V8HeapExplorer* explorer)
......@@ -1506,7 +1502,6 @@ class JSArrayBufferDataEntryAllocator : public HeapEntriesAllocator {
V8HeapExplorer* explorer_;
};
void V8HeapExplorer::ExtractJSArrayBufferReferences(
int entry, JSArrayBuffer* buffer) {
// Setup a reference to a native memory backing_store object.
......@@ -1520,6 +1515,26 @@ void V8HeapExplorer::ExtractJSArrayBufferReferences(
entry, "backing_store", data_entry);
}
void V8HeapExplorer::ExtractJSPromiseReferences(int entry, JSPromise* promise) {
SetInternalReference(promise, entry, "result", promise->result(),
JSPromise::kResultOffset);
SetInternalReference(promise, entry, "deferred_promise",
promise->deferred_promise(),
JSPromise::kDeferredPromiseOffset);
SetInternalReference(promise, entry, "deferred_on_resolve",
promise->deferred_on_resolve(),
JSPromise::kDeferredOnResolveOffset);
SetInternalReference(promise, entry, "deferred_on_reject",
promise->deferred_on_reject(),
JSPromise::kDeferredOnRejectOffset);
SetInternalReference(promise, entry, "fulfill_reactions",
promise->fulfill_reactions(),
JSPromise::kFulfillReactionsOffset);
SetInternalReference(promise, entry, "reject_reactions",
promise->reject_reactions(),
JSPromise::kRejectReactionsOffset);
}
void V8HeapExplorer::ExtractFixedArrayReferences(int entry, FixedArray* array) {
auto it = array_types_.find(array);
if (it == array_types_.end()) {
......
......@@ -391,6 +391,7 @@ class V8HeapExplorer : public HeapEntriesAllocator {
void ExtractPropertyCellReferences(int entry, PropertyCell* cell);
void ExtractAllocationSiteReferences(int entry, AllocationSite* site);
void ExtractJSArrayBufferReferences(int entry, JSArrayBuffer* buffer);
void ExtractJSPromiseReferences(int entry, JSPromise* promise);
void ExtractFixedArrayReferences(int entry, FixedArray* array);
void ExtractPropertyReferences(JSObject* js_obj, int entry);
void ExtractAccessorPairProperty(JSObject* js_obj, int entry, Name* key,
......
......@@ -132,6 +132,14 @@ static bool HasString(const v8::HeapGraphNode* node, const char* contents) {
return false;
}
static void EnsureNoUninstrumentedInternals(const v8::HeapGraphNode* node) {
for (int i = 0; i < 20; ++i) {
i::ScopedVector<char> buffer(10);
const v8::HeapGraphNode* internal = GetProperty(
node, v8::HeapGraphEdge::kInternal, i::IntToCString(i, buffer));
CHECK(!internal);
}
}
// Check that snapshot has no unretained entries except root.
static bool ValidateSnapshot(const v8::HeapSnapshot* snapshot, int depth = 3) {
......@@ -2705,6 +2713,43 @@ TEST(WeakContainers) {
}
}
TEST(JSPromise) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
CompileRun(
"function A() {}\n"
"function B() {}\n"
"resolved = Promise.resolve(new A());\n"
"rejected = Promise.reject(new B());\n"
"pending = new Promise(() => 0);\n"
"chained = pending.then(A, B);\n");
const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
const v8::HeapGraphNode* resolved =
GetProperty(global, v8::HeapGraphEdge::kProperty, "resolved");
CHECK(GetProperty(resolved, v8::HeapGraphEdge::kInternal, "result"));
const v8::HeapGraphNode* rejected =
GetProperty(global, v8::HeapGraphEdge::kProperty, "rejected");
CHECK(GetProperty(rejected, v8::HeapGraphEdge::kInternal, "result"));
const v8::HeapGraphNode* pending =
GetProperty(global, v8::HeapGraphEdge::kProperty, "pending");
CHECK(GetProperty(pending, v8::HeapGraphEdge::kInternal, "deferred_promise"));
CHECK(
GetProperty(pending, v8::HeapGraphEdge::kInternal, "fulfill_reactions"));
CHECK(GetProperty(pending, v8::HeapGraphEdge::kInternal, "reject_reactions"));
const char* objectNames[] = {"resolved", "rejected", "pending", "chained"};
for (auto objectName : objectNames) {
const v8::HeapGraphNode* promise =
GetProperty(global, v8::HeapGraphEdge::kProperty, objectName);
EnsureNoUninstrumentedInternals(promise);
}
}
static inline i::Address ToAddress(int n) {
return reinterpret_cast<i::Address>(n);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment