Commit 92973e4b authored by Z Nguyen-Huu's avatar Z Nguyen-Huu Committed by Commit Bot

[v8windbg] Remove list-chunks command

This command is broken, no testing and no clear demand for it.

Change-Id: Ic86ab346ab29a5d6804f74a3d4458bb3332a7718
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2814131Reviewed-by: 's avatarSeth Brenith <seth.brenith@microsoft.com>
Commit-Queue: Z Nguyen-Huu <duongn@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#73888}
parent 5c93a008
......@@ -42,8 +42,6 @@ v8_shared_library("v8windbg") {
"src/cur-isolate.h",
"src/js-stack.cc",
"src/js-stack.h",
"src/list-chunks.cc",
"src/list-chunks.h",
"src/local-variables.cc",
"src/local-variables.h",
"src/object-inspection.cc",
......
......@@ -41,8 +41,6 @@ functions that can be called from within `dx` commands:
like `dx @$v8object(0x34f49880471, "v8::internal::JSArray")`.
- `@$curisolate()` gets the Isolate pointer for the current thread, if the
current thread has a JavaScript Isolate associated.
- `@$listchunks()` returns a list of the memory chunks in the Heap for the
current Isolate.
- `@$jsstack()` returns a list of the JS stack frames, including information
about script and function.
......@@ -67,8 +65,6 @@ functions declared in `dbgext.h` to create and destroy the extension instance.
`./src` file index:
- `cur-isolate.{cc,h}` implements the `IModelMethod` for `@$curisolate()`.
- `list-chunks.{cc,h}` implements the `IModelMethod` for `@$listchunks()`. Its
result is a custom object that supports iteration and indexing.
- `js-stack.{cc,h}` implements the `IModelMethod` for `@$jsstack()`. Its
result is a custom object that supports iteration and indexing.
- `local-variables.{cc,h}` implements the `IModelPropertyAccessor` that provides
......
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "tools/v8windbg/src/list-chunks.h"
#include "tools/v8windbg/src/cur-isolate.h"
// v8windbg!ListChunksAlias::Call
IFACEMETHODIMP ListChunksAlias::Call(IModelObject* p_context_object,
ULONG64 arg_count,
_In_reads_(arg_count)
IModelObject** pp_arguments,
IModelObject** pp_result,
IKeyStore** pp_metadata) noexcept {
WRL::ComPtr<IDebugHostContext> sp_ctx;
RETURN_IF_FAIL(sp_debug_host->GetCurrentContext(&sp_ctx));
WRL::ComPtr<IModelObject> result;
RETURN_IF_FAIL(
sp_data_model_manager->CreateSyntheticObject(sp_ctx.Get(), &result));
auto sp_iterator{WRL::Make<MemoryChunks>()};
RETURN_IF_FAIL(result->SetConcept(
__uuidof(IIndexableConcept),
static_cast<IIndexableConcept*>(sp_iterator.Get()), nullptr));
RETURN_IF_FAIL(result->SetConcept(
__uuidof(IIterableConcept),
static_cast<IIterableConcept*>(sp_iterator.Get()), nullptr));
*pp_result = result.Detach();
if (pp_metadata) {
*pp_metadata = nullptr;
}
return S_OK;
}
ChunkData::ChunkData() = default;
ChunkData::~ChunkData() = default;
ChunkData::ChunkData(const ChunkData&) = default;
ChunkData::ChunkData(ChunkData&&) = default;
ChunkData& ChunkData::operator=(const ChunkData&) = default;
ChunkData& ChunkData::operator=(ChunkData&&) = default;
MemoryChunkIterator::MemoryChunkIterator(
WRL::ComPtr<IDebugHostContext>& host_context)
: sp_ctx_(host_context) {}
MemoryChunkIterator::~MemoryChunkIterator() = default;
HRESULT MemoryChunkIterator::PopulateChunkData() {
WRL::ComPtr<IModelObject> sp_isolate, sp_heap, sp_space;
chunks_.clear();
RETURN_IF_FAIL(GetCurrentIsolate(sp_isolate));
RETURN_IF_FAIL(
sp_isolate->GetRawValue(SymbolField, L"heap_", RawSearchNone, &sp_heap));
RETURN_IF_FAIL(
sp_heap->GetRawValue(SymbolField, L"space_", RawSearchNone, &sp_space));
WRL::ComPtr<IDebugHostType> sp_space_type;
RETURN_IF_FAIL(sp_space->GetTypeInfo(&sp_space_type));
// Iterate over the array of Space pointers
WRL::ComPtr<IIterableConcept> sp_iterable;
RETURN_IF_FAIL(
sp_space->GetConcept(__uuidof(IIterableConcept), &sp_iterable, nullptr));
WRL::ComPtr<IModelIterator> sp_space_iterator;
RETURN_IF_FAIL(sp_iterable->GetIterator(sp_space.Get(), &sp_space_iterator));
// Loop through all the spaces in the array
WRL::ComPtr<IModelObject> sp_space_ptr;
while (sp_space_iterator->GetNext(&sp_space_ptr, 0, nullptr, nullptr) !=
E_BOUNDS) {
// Should have gotten a "v8::internal::Space *". Dereference, then get field
// "memory_chunk_list_" [Type: v8::base::List<v8::internal::MemoryChunk>]
WRL::ComPtr<IModelObject> sp_space, sp_chunk_list, sp_mem_chunk_ptr,
sp_mem_chunk;
RETURN_IF_FAIL(sp_space_ptr->Dereference(&sp_space));
RETURN_IF_FAIL(sp_space->GetRawValue(SymbolField, L"memory_chunk_list_",
RawSearchNone, &sp_chunk_list));
// Then get field "front_" [Type: v8::internal::MemoryChunk *]
RETURN_IF_FAIL(sp_chunk_list->GetRawValue(
SymbolField, L"front_", RawSearchNone, &sp_mem_chunk_ptr));
// Loop here on the list of MemoryChunks for the space
while (true) {
// See if it is a nullptr (i.e. no chunks in this space)
uint64_t front_val;
RETURN_IF_FAIL(
UnboxULong64(sp_mem_chunk_ptr.Get(), &front_val, true /*convert*/));
if (front_val == 0) {
break;
}
// Dereference and get fields "area_start_" and "area_end_" (both uint64)
RETURN_IF_FAIL(sp_mem_chunk_ptr->Dereference(&sp_mem_chunk));
WRL::ComPtr<IModelObject> sp_start, sp_end;
RETURN_IF_FAIL(sp_mem_chunk->GetRawValue(SymbolField, L"area_start_",
RawSearchNone, &sp_start));
RETURN_IF_FAIL(sp_mem_chunk->GetRawValue(SymbolField, L"area_end_",
RawSearchNone, &sp_end));
ChunkData chunk_entry;
chunk_entry.area_start = sp_start;
chunk_entry.area_end = sp_end;
chunk_entry.space = sp_space;
chunks_.push_back(chunk_entry);
// Follow the list_node_.next_ to the next memory chunk
WRL::ComPtr<IModelObject> sp_list_node;
RETURN_IF_FAIL(sp_mem_chunk->GetRawValue(SymbolField, L"list_node_",
RawSearchNone, &sp_list_node));
sp_mem_chunk_ptr = nullptr;
sp_mem_chunk = nullptr;
RETURN_IF_FAIL(sp_list_node->GetRawValue(
SymbolField, L"next_", RawSearchNone, &sp_mem_chunk_ptr));
// Top of the loop will check if this is a nullptr and exit if so
}
sp_space_ptr = nullptr;
}
return S_OK;
}
IFACEMETHODIMP MemoryChunkIterator::Reset() noexcept {
position_ = 0;
return S_OK;
}
IFACEMETHODIMP MemoryChunkIterator::GetNext(IModelObject** object,
ULONG64 dimensions,
IModelObject** indexers,
IKeyStore** metadata) noexcept {
if (dimensions > 1) return E_INVALIDARG;
if (position_ == 0) {
RETURN_IF_FAIL(PopulateChunkData());
}
if (metadata != nullptr) *metadata = nullptr;
WRL::ComPtr<IModelObject> sp_index, sp_value;
if (dimensions == 1) {
RETURN_IF_FAIL(CreateULong64(position_, &sp_index));
}
RETURN_IF_FAIL(GetAt(position_, &sp_value));
// Now update counter and transfer ownership of results, because nothing can
// fail from this point onward.
++position_;
if (dimensions == 1) {
*indexers = sp_index.Detach();
}
*object = sp_value.Detach();
return S_OK;
}
HRESULT MemoryChunkIterator::GetAt(uint64_t index,
IModelObject** result) const {
if (index >= chunks_.size()) return E_BOUNDS;
// Create the synthetic object representing the chunk here
const ChunkData& curr_chunk = chunks_.at(index);
WRL::ComPtr<IModelObject> sp_value;
RETURN_IF_FAIL(
sp_data_model_manager->CreateSyntheticObject(sp_ctx_.Get(), &sp_value));
RETURN_IF_FAIL(
sp_value->SetKey(L"area_start", curr_chunk.area_start.Get(), nullptr));
RETURN_IF_FAIL(
sp_value->SetKey(L"area_end", curr_chunk.area_end.Get(), nullptr));
RETURN_IF_FAIL(sp_value->SetKey(L"space", curr_chunk.space.Get(), nullptr));
*result = sp_value.Detach();
return S_OK;
}
MemoryChunks::MemoryChunks() = default;
MemoryChunks::~MemoryChunks() = default;
IFACEMETHODIMP MemoryChunks::GetDimensionality(
IModelObject* context_object, ULONG64* dimensionality) noexcept {
*dimensionality = 1;
return S_OK;
}
IFACEMETHODIMP MemoryChunks::GetAt(IModelObject* context_object,
ULONG64 indexer_count,
IModelObject** indexers,
IModelObject** object,
IKeyStore** metadata) noexcept {
if (indexer_count != 1) return E_INVALIDARG;
if (metadata != nullptr) *metadata = nullptr;
WRL::ComPtr<IDebugHostContext> sp_ctx;
RETURN_IF_FAIL(context_object->GetContext(&sp_ctx));
// This should be instantiated once for each synthetic object returned,
// so should be able to cache/reuse an iterator
if (opt_chunks_ == nullptr) {
opt_chunks_ = WRL::Make<MemoryChunkIterator>(sp_ctx);
_ASSERT(opt_chunks_ != nullptr);
RETURN_IF_FAIL(opt_chunks_->PopulateChunkData());
}
uint64_t index;
RETURN_IF_FAIL(UnboxULong64(indexers[0], &index, true /*convert*/));
return opt_chunks_->GetAt(index, object);
}
IFACEMETHODIMP MemoryChunks::SetAt(IModelObject* context_object,
ULONG64 indexer_count,
IModelObject** indexers,
IModelObject* value) noexcept {
return E_NOTIMPL;
}
IFACEMETHODIMP MemoryChunks::GetDefaultIndexDimensionality(
IModelObject* context_object, ULONG64* dimensionality) noexcept {
*dimensionality = 1;
return S_OK;
}
IFACEMETHODIMP MemoryChunks::GetIterator(IModelObject* context_object,
IModelIterator** iterator) noexcept {
WRL::ComPtr<IDebugHostContext> sp_ctx;
RETURN_IF_FAIL(context_object->GetContext(&sp_ctx));
auto sp_memory_iterator{WRL::Make<MemoryChunkIterator>(sp_ctx)};
*iterator = sp_memory_iterator.Detach();
return S_OK;
}
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_TOOLS_V8WINDBG_SRC_LIST_CHUNKS_H_
#define V8_TOOLS_V8WINDBG_SRC_LIST_CHUNKS_H_
#include <crtdbg.h>
#include <wrl/implements.h>
#include <optional>
#include <string>
#include <vector>
#include "src/base/optional.h"
#include "tools/v8windbg/base/utilities.h"
#include "tools/v8windbg/src/v8-debug-helper-interop.h"
#include "tools/v8windbg/src/v8windbg-extension.h"
class ListChunksAlias
: public WRL::RuntimeClass<
WRL::RuntimeClassFlags<WRL::RuntimeClassType::ClassicCom>,
IModelMethod> {
public:
IFACEMETHOD(Call)
(IModelObject* p_context_object, ULONG64 arg_count,
_In_reads_(arg_count) IModelObject** pp_arguments, IModelObject** pp_result,
IKeyStore** pp_metadata);
};
struct ChunkData {
ChunkData();
~ChunkData();
ChunkData(const ChunkData&);
ChunkData(ChunkData&&);
ChunkData& operator=(const ChunkData&);
ChunkData& operator=(ChunkData&&);
WRL::ComPtr<IModelObject> area_start;
WRL::ComPtr<IModelObject> area_end;
WRL::ComPtr<IModelObject> space;
};
class MemoryChunkIterator
: public WRL::RuntimeClass<
WRL::RuntimeClassFlags<WRL::RuntimeClassType::ClassicCom>,
IModelIterator> {
public:
MemoryChunkIterator(WRL::ComPtr<IDebugHostContext>& host_context);
~MemoryChunkIterator() override;
HRESULT PopulateChunkData();
IFACEMETHOD(Reset)();
IFACEMETHOD(GetNext)
(IModelObject** object, ULONG64 dimensions, IModelObject** indexers,
IKeyStore** metadata);
const std::vector<ChunkData>& GetChunks() const { return chunks_; }
HRESULT GetAt(uint64_t index, IModelObject** result) const;
private:
ULONG position_ = 0;
std::vector<ChunkData> chunks_;
WRL::ComPtr<IDebugHostContext> sp_ctx_;
};
class MemoryChunks
: public WRL::RuntimeClass<
WRL::RuntimeClassFlags<WRL::RuntimeClassType::ClassicCom>,
IIndexableConcept, IIterableConcept> {
public:
MemoryChunks();
~MemoryChunks() override;
// IIndexableConcept members
IFACEMETHOD(GetDimensionality)
(IModelObject* context_object, ULONG64* dimensionality);
IFACEMETHOD(GetAt)
(IModelObject* context_object, ULONG64 indexer_count, IModelObject** indexers,
IModelObject** object, IKeyStore** metadata);
IFACEMETHOD(SetAt)
(IModelObject* context_object, ULONG64 indexer_count, IModelObject** indexers,
IModelObject* value);
// IIterableConcept
IFACEMETHOD(GetDefaultIndexDimensionality)
(IModelObject* context_object, ULONG64* dimensionality);
IFACEMETHOD(GetIterator)
(IModelObject* context_object, IModelIterator** iterator);
private:
WRL::ComPtr<MemoryChunkIterator> opt_chunks_;
};
#endif // V8_TOOLS_V8WINDBG_SRC_LIST_CHUNKS_H_
......@@ -9,14 +9,12 @@
#include "tools/v8windbg/base/utilities.h"
#include "tools/v8windbg/src/cur-isolate.h"
#include "tools/v8windbg/src/js-stack.h"
#include "tools/v8windbg/src/list-chunks.h"
#include "tools/v8windbg/src/local-variables.h"
#include "tools/v8windbg/src/object-inspection.h"
std::unique_ptr<Extension> Extension::current_extension_ = nullptr;
const wchar_t* pcur_isolate = L"curisolate";
const wchar_t* pjs_stack = L"jsstack";
const wchar_t* plist_chunks = L"listchunks";
const wchar_t* pv8_object = L"v8object";
HRESULT CreateExtension() {
......@@ -263,7 +261,6 @@ HRESULT Extension::Initialize() {
std::vector<std::pair<const wchar_t*, WRL::ComPtr<IModelMethod>>> functions =
{{pcur_isolate, WRL::Make<CurrIsolateAlias>()},
{pjs_stack, WRL::Make<JSStackAlias>()},
{plist_chunks, WRL::Make<ListChunksAlias>()},
{pv8_object, WRL::Make<InspectV8ObjectMethod>()}};
for (const auto& function : functions) {
WRL::ComPtr<IModelObject> method;
......@@ -375,7 +372,6 @@ Extension::RegistrationType& Extension::RegistrationType::operator=(
Extension::~Extension() {
sp_debug_host_extensibility->DestroyFunctionAlias(pcur_isolate);
sp_debug_host_extensibility->DestroyFunctionAlias(pjs_stack);
sp_debug_host_extensibility->DestroyFunctionAlias(plist_chunks);
sp_debug_host_extensibility->DestroyFunctionAlias(pv8_object);
for (const auto& registered : registered_types_) {
......
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