[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/+/2814131 Reviewed-by: Seth Brenith <seth.brenith@microsoft.com> Commit-Queue: Z Nguyen-Huu <duongn@microsoft.com> Cr-Commit-Position: refs/heads/master@{#73888}
This commit is contained in:
parent
5c93a0081e
commit
92973e4bee
@ -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
|
||||
|
@ -1,238 +0,0 @@
|
||||
// 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;
|
||||
}
|
@ -1,100 +0,0 @@
|
||||
// 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_) {
|
||||
|
Loading…
Reference in New Issue
Block a user