11cb0ef41Sopenharmony_ci// Copyright 2020 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include "tools/v8windbg/src/object-inspection.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#include "src/flags/flags.h" 81cb0ef41Sopenharmony_ci#include "tools/v8windbg/base/utilities.h" 91cb0ef41Sopenharmony_ci#include "tools/v8windbg/src/v8-debug-helper-interop.h" 101cb0ef41Sopenharmony_ci#include "tools/v8windbg/src/v8windbg-extension.h" 111cb0ef41Sopenharmony_ci 121cb0ef41Sopenharmony_ciV8CachedObject::V8CachedObject(Location location, 131cb0ef41Sopenharmony_ci std::string uncompressed_type_name, 141cb0ef41Sopenharmony_ci WRL::ComPtr<IDebugHostContext> context, 151cb0ef41Sopenharmony_ci bool is_compressed) 161cb0ef41Sopenharmony_ci : location_(std::move(location)), 171cb0ef41Sopenharmony_ci uncompressed_type_name_(std::move(uncompressed_type_name)), 181cb0ef41Sopenharmony_ci context_(std::move(context)), 191cb0ef41Sopenharmony_ci is_compressed_(is_compressed) {} 201cb0ef41Sopenharmony_ci 211cb0ef41Sopenharmony_ciHRESULT V8CachedObject::Create(IModelObject* p_v8_object_instance, 221cb0ef41Sopenharmony_ci IV8CachedObject** result) { 231cb0ef41Sopenharmony_ci Location location; 241cb0ef41Sopenharmony_ci RETURN_IF_FAIL(p_v8_object_instance->GetLocation(&location)); 251cb0ef41Sopenharmony_ci 261cb0ef41Sopenharmony_ci WRL::ComPtr<IDebugHostContext> context; 271cb0ef41Sopenharmony_ci RETURN_IF_FAIL(p_v8_object_instance->GetContext(&context)); 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_ci WRL::ComPtr<IDebugHostType> sp_type; 301cb0ef41Sopenharmony_ci _bstr_t type_name; 311cb0ef41Sopenharmony_ci RETURN_IF_FAIL(p_v8_object_instance->GetTypeInfo(&sp_type)); 321cb0ef41Sopenharmony_ci RETURN_IF_FAIL(sp_type->GetName(type_name.GetAddress())); 331cb0ef41Sopenharmony_ci 341cb0ef41Sopenharmony_ci // If the object is of type v8::internal::TaggedValue, and this build uses 351cb0ef41Sopenharmony_ci // compressed pointers, then the value is compressed. Other types such as 361cb0ef41Sopenharmony_ci // v8::internal::Object represent uncompressed tagged values. 371cb0ef41Sopenharmony_ci bool is_compressed = 381cb0ef41Sopenharmony_ci COMPRESS_POINTERS_BOOL && 391cb0ef41Sopenharmony_ci static_cast<const char*>(type_name) == std::string(kTaggedValue); 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_ci const char* uncompressed_type_name = 421cb0ef41Sopenharmony_ci is_compressed ? kObject : static_cast<const char*>(type_name); 431cb0ef41Sopenharmony_ci 441cb0ef41Sopenharmony_ci *result = WRL::Make<V8CachedObject>(location, uncompressed_type_name, context, 451cb0ef41Sopenharmony_ci is_compressed) 461cb0ef41Sopenharmony_ci .Detach(); 471cb0ef41Sopenharmony_ci return S_OK; 481cb0ef41Sopenharmony_ci} 491cb0ef41Sopenharmony_ci 501cb0ef41Sopenharmony_ciV8CachedObject::V8CachedObject(V8HeapObject heap_object) 511cb0ef41Sopenharmony_ci : heap_object_(std::move(heap_object)), heap_object_initialized_(true) {} 521cb0ef41Sopenharmony_ci 531cb0ef41Sopenharmony_ciV8CachedObject::~V8CachedObject() = default; 541cb0ef41Sopenharmony_ci 551cb0ef41Sopenharmony_ciIFACEMETHODIMP V8CachedObject::GetCachedV8HeapObject( 561cb0ef41Sopenharmony_ci V8HeapObject** pp_heap_object) noexcept { 571cb0ef41Sopenharmony_ci if (!heap_object_initialized_) { 581cb0ef41Sopenharmony_ci heap_object_initialized_ = true; 591cb0ef41Sopenharmony_ci uint64_t tagged_ptr = 0; 601cb0ef41Sopenharmony_ci uint64_t bytes_read; 611cb0ef41Sopenharmony_ci HRESULT hr = sp_debug_host_memory->ReadBytes( 621cb0ef41Sopenharmony_ci context_.Get(), location_, reinterpret_cast<void*>(&tagged_ptr), 631cb0ef41Sopenharmony_ci is_compressed_ ? i::kTaggedSize : sizeof(void*), &bytes_read); 641cb0ef41Sopenharmony_ci // S_FALSE can be returned if fewer bytes were read than were requested. We 651cb0ef41Sopenharmony_ci // need all of the bytes, so check for S_OK. 661cb0ef41Sopenharmony_ci if (hr != S_OK) { 671cb0ef41Sopenharmony_ci std::stringstream message; 681cb0ef41Sopenharmony_ci message << "Unable to read memory"; 691cb0ef41Sopenharmony_ci if (location_.IsVirtualAddress()) { 701cb0ef41Sopenharmony_ci message << " at 0x" << std::hex << location_.GetOffset(); 711cb0ef41Sopenharmony_ci } 721cb0ef41Sopenharmony_ci heap_object_.friendly_name = ConvertToU16String(message.str()); 731cb0ef41Sopenharmony_ci } else { 741cb0ef41Sopenharmony_ci if (is_compressed_) 751cb0ef41Sopenharmony_ci tagged_ptr = ExpandCompressedPointer(static_cast<uint32_t>(tagged_ptr)); 761cb0ef41Sopenharmony_ci heap_object_ = 771cb0ef41Sopenharmony_ci ::GetHeapObject(context_, tagged_ptr, location_.GetOffset(), 781cb0ef41Sopenharmony_ci uncompressed_type_name_.c_str(), is_compressed_); 791cb0ef41Sopenharmony_ci } 801cb0ef41Sopenharmony_ci } 811cb0ef41Sopenharmony_ci *pp_heap_object = &this->heap_object_; 821cb0ef41Sopenharmony_ci return S_OK; 831cb0ef41Sopenharmony_ci} 841cb0ef41Sopenharmony_ci 851cb0ef41Sopenharmony_ciIndexedFieldData::IndexedFieldData(Property property) 861cb0ef41Sopenharmony_ci : property_(std::move(property)) {} 871cb0ef41Sopenharmony_ci 881cb0ef41Sopenharmony_ciIndexedFieldData::~IndexedFieldData() = default; 891cb0ef41Sopenharmony_ci 901cb0ef41Sopenharmony_ciIFACEMETHODIMP IndexedFieldData::GetProperty(Property** property) noexcept { 911cb0ef41Sopenharmony_ci if (!property) return E_POINTER; 921cb0ef41Sopenharmony_ci *property = &this->property_; 931cb0ef41Sopenharmony_ci return S_OK; 941cb0ef41Sopenharmony_ci} 951cb0ef41Sopenharmony_ci 961cb0ef41Sopenharmony_ciV8ObjectKeyEnumerator::V8ObjectKeyEnumerator( 971cb0ef41Sopenharmony_ci WRL::ComPtr<IV8CachedObject>& v8_cached_object) 981cb0ef41Sopenharmony_ci : sp_v8_cached_object_{v8_cached_object} {} 991cb0ef41Sopenharmony_ciV8ObjectKeyEnumerator::~V8ObjectKeyEnumerator() = default; 1001cb0ef41Sopenharmony_ci 1011cb0ef41Sopenharmony_ciIFACEMETHODIMP V8ObjectKeyEnumerator::Reset() noexcept { 1021cb0ef41Sopenharmony_ci index_ = 0; 1031cb0ef41Sopenharmony_ci return S_OK; 1041cb0ef41Sopenharmony_ci} 1051cb0ef41Sopenharmony_ci 1061cb0ef41Sopenharmony_ciIFACEMETHODIMP V8ObjectKeyEnumerator::GetNext(BSTR* key, IModelObject** value, 1071cb0ef41Sopenharmony_ci IKeyStore** metadata) noexcept { 1081cb0ef41Sopenharmony_ci V8HeapObject* p_v8_heap_object; 1091cb0ef41Sopenharmony_ci sp_v8_cached_object_->GetCachedV8HeapObject(&p_v8_heap_object); 1101cb0ef41Sopenharmony_ci 1111cb0ef41Sopenharmony_ci if (static_cast<size_t>(index_) >= p_v8_heap_object->properties.size()) 1121cb0ef41Sopenharmony_ci return E_BOUNDS; 1131cb0ef41Sopenharmony_ci 1141cb0ef41Sopenharmony_ci auto* name_ptr = p_v8_heap_object->properties[index_].name.c_str(); 1151cb0ef41Sopenharmony_ci *key = ::SysAllocString(U16ToWChar(name_ptr)); 1161cb0ef41Sopenharmony_ci ++index_; 1171cb0ef41Sopenharmony_ci return S_OK; 1181cb0ef41Sopenharmony_ci} 1191cb0ef41Sopenharmony_ci 1201cb0ef41Sopenharmony_ciIFACEMETHODIMP V8LocalDataModel::InitializeObject( 1211cb0ef41Sopenharmony_ci IModelObject* model_object, 1221cb0ef41Sopenharmony_ci IDebugHostTypeSignature* matching_type_signature, 1231cb0ef41Sopenharmony_ci IDebugHostSymbolEnumerator* wildcard_matches) noexcept { 1241cb0ef41Sopenharmony_ci return S_OK; 1251cb0ef41Sopenharmony_ci} 1261cb0ef41Sopenharmony_ci 1271cb0ef41Sopenharmony_ciIFACEMETHODIMP V8LocalDataModel::GetName(BSTR* model_name) noexcept { 1281cb0ef41Sopenharmony_ci return E_NOTIMPL; 1291cb0ef41Sopenharmony_ci} 1301cb0ef41Sopenharmony_ci 1311cb0ef41Sopenharmony_ciIFACEMETHODIMP V8ObjectDataModel::InitializeObject( 1321cb0ef41Sopenharmony_ci IModelObject* model_object, 1331cb0ef41Sopenharmony_ci IDebugHostTypeSignature* matching_type_signature, 1341cb0ef41Sopenharmony_ci IDebugHostSymbolEnumerator* wildcard_matches) noexcept { 1351cb0ef41Sopenharmony_ci return S_OK; 1361cb0ef41Sopenharmony_ci} 1371cb0ef41Sopenharmony_ci 1381cb0ef41Sopenharmony_ciIFACEMETHODIMP V8ObjectDataModel::GetName(BSTR* model_name) noexcept { 1391cb0ef41Sopenharmony_ci return E_NOTIMPL; 1401cb0ef41Sopenharmony_ci} 1411cb0ef41Sopenharmony_ci 1421cb0ef41Sopenharmony_ciIFACEMETHODIMP V8ObjectDataModel::ToDisplayString( 1431cb0ef41Sopenharmony_ci IModelObject* context_object, IKeyStore* metadata, 1441cb0ef41Sopenharmony_ci BSTR* display_string) noexcept { 1451cb0ef41Sopenharmony_ci WRL::ComPtr<IV8CachedObject> sp_v8_cached_object; 1461cb0ef41Sopenharmony_ci RETURN_IF_FAIL(GetCachedObject(context_object, &sp_v8_cached_object)); 1471cb0ef41Sopenharmony_ci V8HeapObject* p_v8_heap_object; 1481cb0ef41Sopenharmony_ci RETURN_IF_FAIL(sp_v8_cached_object->GetCachedV8HeapObject(&p_v8_heap_object)); 1491cb0ef41Sopenharmony_ci *display_string = ::SysAllocString( 1501cb0ef41Sopenharmony_ci reinterpret_cast<const wchar_t*>(p_v8_heap_object->friendly_name.data())); 1511cb0ef41Sopenharmony_ci return S_OK; 1521cb0ef41Sopenharmony_ci} 1531cb0ef41Sopenharmony_ci 1541cb0ef41Sopenharmony_cinamespace { 1551cb0ef41Sopenharmony_ci 1561cb0ef41Sopenharmony_ci// Creates a synthetic object, attaches a parent model, and sets the context 1571cb0ef41Sopenharmony_ci// object for that parent data model. Caller is responsible for ensuring that 1581cb0ef41Sopenharmony_ci// the parent model's Concepts have been initialized correctly and that the 1591cb0ef41Sopenharmony_ci// data model context is of an appropriate type for the parent model. 1601cb0ef41Sopenharmony_ciHRESULT CreateSyntheticObjectWithParentAndDataContext( 1611cb0ef41Sopenharmony_ci IDebugHostContext* ctx, IModelObject* parent_model, IUnknown* data_context, 1621cb0ef41Sopenharmony_ci IModelObject** result) { 1631cb0ef41Sopenharmony_ci WRL::ComPtr<IModelObject> value; 1641cb0ef41Sopenharmony_ci RETURN_IF_FAIL(sp_data_model_manager->CreateSyntheticObject(ctx, &value)); 1651cb0ef41Sopenharmony_ci RETURN_IF_FAIL( 1661cb0ef41Sopenharmony_ci value->AddParentModel(parent_model, nullptr, true /*override*/)); 1671cb0ef41Sopenharmony_ci RETURN_IF_FAIL(value->SetContextForDataModel(parent_model, data_context)); 1681cb0ef41Sopenharmony_ci *result = value.Detach(); 1691cb0ef41Sopenharmony_ci return S_OK; 1701cb0ef41Sopenharmony_ci} 1711cb0ef41Sopenharmony_ci 1721cb0ef41Sopenharmony_ci// Creates an IModelObject for a V8 object whose value is represented by the 1731cb0ef41Sopenharmony_ci// data in cached_object. This is an alternative to CreateTypedObject for 1741cb0ef41Sopenharmony_ci// particularly complex cases (compressed values and those that don't exist 1751cb0ef41Sopenharmony_ci// anywhere in memory). 1761cb0ef41Sopenharmony_ciHRESULT CreateSyntheticObjectForV8Object(IDebugHostContext* ctx, 1771cb0ef41Sopenharmony_ci V8CachedObject* cached_object, 1781cb0ef41Sopenharmony_ci IModelObject** result) { 1791cb0ef41Sopenharmony_ci // Explicitly add the parent model and data context. On a plain typed object, 1801cb0ef41Sopenharmony_ci // the parent model would be attached automatically because we registered for 1811cb0ef41Sopenharmony_ci // a matching type signature, and the data context would be set during 1821cb0ef41Sopenharmony_ci // V8ObjectDataModel::GetCachedObject. 1831cb0ef41Sopenharmony_ci return CreateSyntheticObjectWithParentAndDataContext( 1841cb0ef41Sopenharmony_ci ctx, Extension::Current()->GetObjectDataModel(), cached_object, result); 1851cb0ef41Sopenharmony_ci} 1861cb0ef41Sopenharmony_ci 1871cb0ef41Sopenharmony_ci// Creates an IModelObject to represent a field that is not a struct or array. 1881cb0ef41Sopenharmony_ciHRESULT GetModelForBasicField(const uint64_t address, 1891cb0ef41Sopenharmony_ci const std::u16string& type_name, 1901cb0ef41Sopenharmony_ci const std::string& uncompressed_type_name, 1911cb0ef41Sopenharmony_ci WRL::ComPtr<IDebugHostContext>& sp_ctx, 1921cb0ef41Sopenharmony_ci IModelObject** result) { 1931cb0ef41Sopenharmony_ci if (type_name == ConvertToU16String(uncompressed_type_name)) { 1941cb0ef41Sopenharmony_ci // For untagged and uncompressed tagged fields, create an IModelObject 1951cb0ef41Sopenharmony_ci // representing a normal native data type. 1961cb0ef41Sopenharmony_ci WRL::ComPtr<IDebugHostType> type = 1971cb0ef41Sopenharmony_ci Extension::Current()->GetTypeFromV8Module(sp_ctx, type_name.c_str()); 1981cb0ef41Sopenharmony_ci if (type == nullptr) return E_FAIL; 1991cb0ef41Sopenharmony_ci return sp_data_model_manager->CreateTypedObject( 2001cb0ef41Sopenharmony_ci sp_ctx.Get(), Location{address}, type.Get(), result); 2011cb0ef41Sopenharmony_ci } 2021cb0ef41Sopenharmony_ci 2031cb0ef41Sopenharmony_ci // For compressed tagged fields, we need to do something a little more 2041cb0ef41Sopenharmony_ci // complicated. We could just use CreateTypedObject with the type 2051cb0ef41Sopenharmony_ci // v8::internal::TaggedValue, but then we'd sacrifice any other data 2061cb0ef41Sopenharmony_ci // that we've learned about the field's specific type. So instead we 2071cb0ef41Sopenharmony_ci // create a synthetic object. 2081cb0ef41Sopenharmony_ci WRL::ComPtr<V8CachedObject> cached_object = WRL::Make<V8CachedObject>( 2091cb0ef41Sopenharmony_ci Location(address), uncompressed_type_name, sp_ctx, 2101cb0ef41Sopenharmony_ci /*is_compressed=*/true); 2111cb0ef41Sopenharmony_ci return CreateSyntheticObjectForV8Object(sp_ctx.Get(), cached_object.Get(), 2121cb0ef41Sopenharmony_ci result); 2131cb0ef41Sopenharmony_ci} 2141cb0ef41Sopenharmony_ci 2151cb0ef41Sopenharmony_ci// Creates an IModelObject representing the value of a bitfield. 2161cb0ef41Sopenharmony_ciHRESULT GetModelForBitField(uint64_t address, const uint8_t num_bits, 2171cb0ef41Sopenharmony_ci uint8_t shift_bits, const std::u16string& type_name, 2181cb0ef41Sopenharmony_ci WRL::ComPtr<IDebugHostContext>& sp_ctx, 2191cb0ef41Sopenharmony_ci IModelObject** result) { 2201cb0ef41Sopenharmony_ci // Look up the type by name. 2211cb0ef41Sopenharmony_ci WRL::ComPtr<IDebugHostType> type = 2221cb0ef41Sopenharmony_ci Extension::Current()->GetTypeFromV8Module(sp_ctx, type_name.c_str()); 2231cb0ef41Sopenharmony_ci if (type == nullptr) return E_FAIL; 2241cb0ef41Sopenharmony_ci 2251cb0ef41Sopenharmony_ci // Figure out exactly which bytes contain the bitfield's data. This depends on 2261cb0ef41Sopenharmony_ci // platform byte order (little-endian for Windows). 2271cb0ef41Sopenharmony_ci constexpr int kBitsPerByte = 8; 2281cb0ef41Sopenharmony_ci uint8_t shift_bytes = shift_bits / kBitsPerByte; 2291cb0ef41Sopenharmony_ci address += shift_bytes; 2301cb0ef41Sopenharmony_ci shift_bits -= shift_bytes * kBitsPerByte; 2311cb0ef41Sopenharmony_ci size_t bits_to_read = shift_bits + num_bits; 2321cb0ef41Sopenharmony_ci size_t bytes_to_read = (bits_to_read + kBitsPerByte - 1) / kBitsPerByte; 2331cb0ef41Sopenharmony_ci 2341cb0ef41Sopenharmony_ci uintptr_t value = 0; 2351cb0ef41Sopenharmony_ci 2361cb0ef41Sopenharmony_ci // V8 guarantees that bitfield structs are no bigger than a single pointer. 2371cb0ef41Sopenharmony_ci if (bytes_to_read > sizeof(value)) { 2381cb0ef41Sopenharmony_ci std::stringstream message; 2391cb0ef41Sopenharmony_ci message << "Fatal v8windbg error: found bitfield struct of " 2401cb0ef41Sopenharmony_ci << bytes_to_read << "bytes, which exceeds the supported size of " 2411cb0ef41Sopenharmony_ci << sizeof(value); 2421cb0ef41Sopenharmony_ci return CreateString(ConvertToU16String(message.str()), result); 2431cb0ef41Sopenharmony_ci } 2441cb0ef41Sopenharmony_ci 2451cb0ef41Sopenharmony_ci uint64_t bytes_read; 2461cb0ef41Sopenharmony_ci HRESULT hr = sp_debug_host_memory->ReadBytes(sp_ctx.Get(), address, 2471cb0ef41Sopenharmony_ci reinterpret_cast<void*>(&value), 2481cb0ef41Sopenharmony_ci bytes_to_read, &bytes_read); 2491cb0ef41Sopenharmony_ci 2501cb0ef41Sopenharmony_ci // S_FALSE can be returned if fewer bytes were read than were requested. We 2511cb0ef41Sopenharmony_ci // need all of the bytes, so check for S_OK. 2521cb0ef41Sopenharmony_ci if (hr != S_OK) { 2531cb0ef41Sopenharmony_ci std::stringstream message; 2541cb0ef41Sopenharmony_ci message << "Unable to read memory at 0x" << std::hex << address; 2551cb0ef41Sopenharmony_ci return CreateString(ConvertToU16String(message.str()), result); 2561cb0ef41Sopenharmony_ci } 2571cb0ef41Sopenharmony_ci 2581cb0ef41Sopenharmony_ci // Decode the bitfield. 2591cb0ef41Sopenharmony_ci value = (value >> shift_bits) & ((1 << num_bits) - 1); 2601cb0ef41Sopenharmony_ci 2611cb0ef41Sopenharmony_ci return CreateTypedIntrinsic(value, type.Get(), result); 2621cb0ef41Sopenharmony_ci} 2631cb0ef41Sopenharmony_ci 2641cb0ef41Sopenharmony_ci// Creates an IModelObject to represent the packed fields in a Torque struct. 2651cb0ef41Sopenharmony_ci// Note that Torque structs are not C++ structs and do not have any type 2661cb0ef41Sopenharmony_ci// definitions in the V8 symbols. 2671cb0ef41Sopenharmony_ciHRESULT GetModelForStruct(const uint64_t address, 2681cb0ef41Sopenharmony_ci const std::vector<StructField>& fields, 2691cb0ef41Sopenharmony_ci WRL::ComPtr<IDebugHostContext>& sp_ctx, 2701cb0ef41Sopenharmony_ci IModelObject** result) { 2711cb0ef41Sopenharmony_ci WRL::ComPtr<IModelObject> sp_value; 2721cb0ef41Sopenharmony_ci RETURN_IF_FAIL( 2731cb0ef41Sopenharmony_ci sp_data_model_manager->CreateSyntheticObject(sp_ctx.Get(), &sp_value)); 2741cb0ef41Sopenharmony_ci 2751cb0ef41Sopenharmony_ci // There's no need for any fancy Concepts here; just add key-value pairs for 2761cb0ef41Sopenharmony_ci // each field. 2771cb0ef41Sopenharmony_ci for (const StructField& field : fields) { 2781cb0ef41Sopenharmony_ci WRL::ComPtr<IModelObject> field_model; 2791cb0ef41Sopenharmony_ci if (field.num_bits == 0) { 2801cb0ef41Sopenharmony_ci RETURN_IF_FAIL(GetModelForBasicField( 2811cb0ef41Sopenharmony_ci address + field.offset, field.type_name, field.uncompressed_type_name, 2821cb0ef41Sopenharmony_ci sp_ctx, &field_model)); 2831cb0ef41Sopenharmony_ci } else { 2841cb0ef41Sopenharmony_ci RETURN_IF_FAIL(GetModelForBitField(address + field.offset, field.num_bits, 2851cb0ef41Sopenharmony_ci field.shift_bits, field.type_name, 2861cb0ef41Sopenharmony_ci sp_ctx, &field_model)); 2871cb0ef41Sopenharmony_ci } 2881cb0ef41Sopenharmony_ci RETURN_IF_FAIL( 2891cb0ef41Sopenharmony_ci sp_value->SetKey(reinterpret_cast<const wchar_t*>(field.name.c_str()), 2901cb0ef41Sopenharmony_ci field_model.Get(), nullptr)); 2911cb0ef41Sopenharmony_ci } 2921cb0ef41Sopenharmony_ci 2931cb0ef41Sopenharmony_ci *result = sp_value.Detach(); 2941cb0ef41Sopenharmony_ci return S_OK; 2951cb0ef41Sopenharmony_ci} 2961cb0ef41Sopenharmony_ci 2971cb0ef41Sopenharmony_ci// Creates an IModelObject representing an array of some type that we expect to 2981cb0ef41Sopenharmony_ci// be defined in the V8 symbols. 2991cb0ef41Sopenharmony_ciHRESULT GetModelForNativeArray(const uint64_t address, 3001cb0ef41Sopenharmony_ci const std::u16string& type_name, size_t count, 3011cb0ef41Sopenharmony_ci WRL::ComPtr<IDebugHostContext>& sp_ctx, 3021cb0ef41Sopenharmony_ci IModelObject** result) { 3031cb0ef41Sopenharmony_ci WRL::ComPtr<IDebugHostType> type = 3041cb0ef41Sopenharmony_ci Extension::Current()->GetTypeFromV8Module(sp_ctx, type_name.c_str()); 3051cb0ef41Sopenharmony_ci if (type == nullptr) return E_FAIL; 3061cb0ef41Sopenharmony_ci 3071cb0ef41Sopenharmony_ci ULONG64 object_size{}; 3081cb0ef41Sopenharmony_ci RETURN_IF_FAIL(type->GetSize(&object_size)); 3091cb0ef41Sopenharmony_ci 3101cb0ef41Sopenharmony_ci ArrayDimension dimensions[] = { 3111cb0ef41Sopenharmony_ci {/*start=*/0, /*length=*/count, /*stride=*/object_size}}; 3121cb0ef41Sopenharmony_ci WRL::ComPtr<IDebugHostType> array_type; 3131cb0ef41Sopenharmony_ci RETURN_IF_FAIL( 3141cb0ef41Sopenharmony_ci type->CreateArrayOf(/*dimensions=*/1, dimensions, &array_type)); 3151cb0ef41Sopenharmony_ci 3161cb0ef41Sopenharmony_ci return sp_data_model_manager->CreateTypedObject( 3171cb0ef41Sopenharmony_ci sp_ctx.Get(), Location{address}, array_type.Get(), result); 3181cb0ef41Sopenharmony_ci} 3191cb0ef41Sopenharmony_ci 3201cb0ef41Sopenharmony_ci// Creates an IModelObject that represents an array of structs or compressed 3211cb0ef41Sopenharmony_ci// tagged values. 3221cb0ef41Sopenharmony_ciHRESULT GetModelForCustomArray(const Property& prop, 3231cb0ef41Sopenharmony_ci WRL::ComPtr<IDebugHostContext>& sp_ctx, 3241cb0ef41Sopenharmony_ci IModelObject** result) { 3251cb0ef41Sopenharmony_ci // Create the context which should be provided to the indexing and iterating 3261cb0ef41Sopenharmony_ci // functionality provided by the parent model. This is instance-specific data, 3271cb0ef41Sopenharmony_ci // whereas the parent model object could be shared among many custom arrays. 3281cb0ef41Sopenharmony_ci WRL::ComPtr<IndexedFieldData> context_data = 3291cb0ef41Sopenharmony_ci WRL::Make<IndexedFieldData>(prop); 3301cb0ef41Sopenharmony_ci 3311cb0ef41Sopenharmony_ci return CreateSyntheticObjectWithParentAndDataContext( 3321cb0ef41Sopenharmony_ci sp_ctx.Get(), Extension::Current()->GetIndexedFieldDataModel(), 3331cb0ef41Sopenharmony_ci context_data.Get(), result); 3341cb0ef41Sopenharmony_ci} 3351cb0ef41Sopenharmony_ci 3361cb0ef41Sopenharmony_ci 3371cb0ef41Sopenharmony_ci// Creates an IModelObject representing the data in an array at the given index. 3381cb0ef41Sopenharmony_ci// context_object is expected to be an object of the form created by 3391cb0ef41Sopenharmony_ci// GetModelForCustomArray, meaning its context for the IndexedFieldParent data 3401cb0ef41Sopenharmony_ci// model is an IIndexedFieldData containing the description of the array. 3411cb0ef41Sopenharmony_ciHRESULT GetModelForCustomArrayElement(IModelObject* context_object, 3421cb0ef41Sopenharmony_ci size_t index, IModelObject** object) { 3431cb0ef41Sopenharmony_ci // Open a few layers of wrapper objects to get to the Property object that 3441cb0ef41Sopenharmony_ci // describes the array. 3451cb0ef41Sopenharmony_ci WRL::ComPtr<IUnknown> data_model_context; 3461cb0ef41Sopenharmony_ci RETURN_IF_FAIL(context_object->GetContextForDataModel( 3471cb0ef41Sopenharmony_ci Extension::Current()->GetIndexedFieldDataModel(), &data_model_context)); 3481cb0ef41Sopenharmony_ci WRL::ComPtr<IIndexedFieldData> indexed_field_data; 3491cb0ef41Sopenharmony_ci RETURN_IF_FAIL(data_model_context.As(&indexed_field_data)); 3501cb0ef41Sopenharmony_ci Property* prop; 3511cb0ef41Sopenharmony_ci RETURN_IF_FAIL(indexed_field_data->GetProperty(&prop)); 3521cb0ef41Sopenharmony_ci 3531cb0ef41Sopenharmony_ci if (index >= prop->length) { 3541cb0ef41Sopenharmony_ci return E_BOUNDS; 3551cb0ef41Sopenharmony_ci } 3561cb0ef41Sopenharmony_ci 3571cb0ef41Sopenharmony_ci WRL::ComPtr<IDebugHostContext> sp_ctx; 3581cb0ef41Sopenharmony_ci RETURN_IF_FAIL(context_object->GetContext(&sp_ctx)); 3591cb0ef41Sopenharmony_ci 3601cb0ef41Sopenharmony_ci ULONG64 address = prop->addr_value + index * prop->item_size; 3611cb0ef41Sopenharmony_ci 3621cb0ef41Sopenharmony_ci switch (prop->type) { 3631cb0ef41Sopenharmony_ci case PropertyType::kArray: 3641cb0ef41Sopenharmony_ci return GetModelForBasicField(address, prop->type_name, 3651cb0ef41Sopenharmony_ci prop->uncompressed_type_name, sp_ctx, 3661cb0ef41Sopenharmony_ci object); 3671cb0ef41Sopenharmony_ci case PropertyType::kStructArray: 3681cb0ef41Sopenharmony_ci return GetModelForStruct(address, prop->fields, sp_ctx, object); 3691cb0ef41Sopenharmony_ci default: 3701cb0ef41Sopenharmony_ci return E_FAIL; // Only array properties should be possible here. 3711cb0ef41Sopenharmony_ci } 3721cb0ef41Sopenharmony_ci} 3731cb0ef41Sopenharmony_ci 3741cb0ef41Sopenharmony_ci} // namespace 3751cb0ef41Sopenharmony_ci 3761cb0ef41Sopenharmony_ciIFACEMETHODIMP IndexedFieldParent::InitializeObject( 3771cb0ef41Sopenharmony_ci IModelObject* model_object, 3781cb0ef41Sopenharmony_ci IDebugHostTypeSignature* matching_type_signature, 3791cb0ef41Sopenharmony_ci IDebugHostSymbolEnumerator* wildcard_matches) noexcept { 3801cb0ef41Sopenharmony_ci return S_OK; 3811cb0ef41Sopenharmony_ci} 3821cb0ef41Sopenharmony_ci 3831cb0ef41Sopenharmony_ciIFACEMETHODIMP IndexedFieldParent::GetName(BSTR* model_name) noexcept { 3841cb0ef41Sopenharmony_ci return E_NOTIMPL; 3851cb0ef41Sopenharmony_ci} 3861cb0ef41Sopenharmony_ci 3871cb0ef41Sopenharmony_ciIFACEMETHODIMP IndexedFieldParent::GetDimensionality( 3881cb0ef41Sopenharmony_ci IModelObject* context_object, ULONG64* dimensionality) noexcept { 3891cb0ef41Sopenharmony_ci *dimensionality = 1; 3901cb0ef41Sopenharmony_ci return S_OK; 3911cb0ef41Sopenharmony_ci} 3921cb0ef41Sopenharmony_ci 3931cb0ef41Sopenharmony_ciIFACEMETHODIMP IndexedFieldParent::GetAt(IModelObject* context_object, 3941cb0ef41Sopenharmony_ci ULONG64 indexer_count, 3951cb0ef41Sopenharmony_ci IModelObject** indexers, 3961cb0ef41Sopenharmony_ci IModelObject** object, 3971cb0ef41Sopenharmony_ci IKeyStore** metadata) noexcept { 3981cb0ef41Sopenharmony_ci if (indexer_count != 1) return E_INVALIDARG; 3991cb0ef41Sopenharmony_ci if (metadata != nullptr) *metadata = nullptr; 4001cb0ef41Sopenharmony_ci 4011cb0ef41Sopenharmony_ci ULONG64 index; 4021cb0ef41Sopenharmony_ci RETURN_IF_FAIL(UnboxULong64(indexers[0], &index, /*convert=*/true)); 4031cb0ef41Sopenharmony_ci 4041cb0ef41Sopenharmony_ci return GetModelForCustomArrayElement(context_object, index, object); 4051cb0ef41Sopenharmony_ci} 4061cb0ef41Sopenharmony_ci 4071cb0ef41Sopenharmony_ciIFACEMETHODIMP IndexedFieldParent::SetAt(IModelObject* context_object, 4081cb0ef41Sopenharmony_ci ULONG64 indexer_count, 4091cb0ef41Sopenharmony_ci IModelObject** indexers, 4101cb0ef41Sopenharmony_ci IModelObject* value) noexcept { 4111cb0ef41Sopenharmony_ci return E_NOTIMPL; 4121cb0ef41Sopenharmony_ci} 4131cb0ef41Sopenharmony_ci 4141cb0ef41Sopenharmony_ciIFACEMETHODIMP IndexedFieldParent::GetDefaultIndexDimensionality( 4151cb0ef41Sopenharmony_ci IModelObject* context_object, ULONG64* dimensionality) noexcept { 4161cb0ef41Sopenharmony_ci *dimensionality = 1; 4171cb0ef41Sopenharmony_ci return S_OK; 4181cb0ef41Sopenharmony_ci} 4191cb0ef41Sopenharmony_ci 4201cb0ef41Sopenharmony_ciIFACEMETHODIMP IndexedFieldParent::GetIterator( 4211cb0ef41Sopenharmony_ci IModelObject* context_object, IModelIterator** iterator) noexcept { 4221cb0ef41Sopenharmony_ci auto indexed_field_iterator{WRL::Make<IndexedFieldIterator>(context_object)}; 4231cb0ef41Sopenharmony_ci *iterator = indexed_field_iterator.Detach(); 4241cb0ef41Sopenharmony_ci return S_OK; 4251cb0ef41Sopenharmony_ci} 4261cb0ef41Sopenharmony_ci 4271cb0ef41Sopenharmony_ciIndexedFieldIterator::IndexedFieldIterator(IModelObject* context_object) 4281cb0ef41Sopenharmony_ci : context_object_(context_object) {} 4291cb0ef41Sopenharmony_ciIndexedFieldIterator::~IndexedFieldIterator() = default; 4301cb0ef41Sopenharmony_ci 4311cb0ef41Sopenharmony_ciIFACEMETHODIMP IndexedFieldIterator::Reset() noexcept { 4321cb0ef41Sopenharmony_ci next_ = 0; 4331cb0ef41Sopenharmony_ci return S_OK; 4341cb0ef41Sopenharmony_ci} 4351cb0ef41Sopenharmony_ci 4361cb0ef41Sopenharmony_ciIFACEMETHODIMP IndexedFieldIterator::GetNext(IModelObject** object, 4371cb0ef41Sopenharmony_ci ULONG64 dimensions, 4381cb0ef41Sopenharmony_ci IModelObject** indexers, 4391cb0ef41Sopenharmony_ci IKeyStore** metadata) noexcept { 4401cb0ef41Sopenharmony_ci if (dimensions > 1) return E_INVALIDARG; 4411cb0ef41Sopenharmony_ci 4421cb0ef41Sopenharmony_ci WRL::ComPtr<IModelObject> sp_index, sp_value; 4431cb0ef41Sopenharmony_ci RETURN_IF_FAIL( 4441cb0ef41Sopenharmony_ci GetModelForCustomArrayElement(context_object_.Get(), next_, &sp_value)); 4451cb0ef41Sopenharmony_ci RETURN_IF_FAIL(CreateULong64(next_, &sp_index)); 4461cb0ef41Sopenharmony_ci 4471cb0ef41Sopenharmony_ci // Everything that could fail (including the bounds check) has succeeded, so 4481cb0ef41Sopenharmony_ci // increment the index. 4491cb0ef41Sopenharmony_ci ++next_; 4501cb0ef41Sopenharmony_ci 4511cb0ef41Sopenharmony_ci // Write results (none of these steps can fail, which is important because we 4521cb0ef41Sopenharmony_ci // transfer ownership of two separate objects). 4531cb0ef41Sopenharmony_ci if (dimensions == 1) { 4541cb0ef41Sopenharmony_ci indexers[0] = sp_index.Detach(); 4551cb0ef41Sopenharmony_ci } 4561cb0ef41Sopenharmony_ci *object = sp_value.Detach(); 4571cb0ef41Sopenharmony_ci if (metadata != nullptr) *metadata = nullptr; 4581cb0ef41Sopenharmony_ci return S_OK; 4591cb0ef41Sopenharmony_ci} 4601cb0ef41Sopenharmony_ci 4611cb0ef41Sopenharmony_ciIFACEMETHODIMP V8ObjectDataModel::GetKey(IModelObject* context_object, 4621cb0ef41Sopenharmony_ci PCWSTR key, IModelObject** key_value, 4631cb0ef41Sopenharmony_ci IKeyStore** metadata, 4641cb0ef41Sopenharmony_ci bool* has_key) noexcept { 4651cb0ef41Sopenharmony_ci if (metadata != nullptr) *metadata = nullptr; 4661cb0ef41Sopenharmony_ci 4671cb0ef41Sopenharmony_ci WRL::ComPtr<IV8CachedObject> sp_v8_cached_object; 4681cb0ef41Sopenharmony_ci RETURN_IF_FAIL(GetCachedObject(context_object, &sp_v8_cached_object)); 4691cb0ef41Sopenharmony_ci V8HeapObject* p_v8_heap_object; 4701cb0ef41Sopenharmony_ci RETURN_IF_FAIL(sp_v8_cached_object->GetCachedV8HeapObject(&p_v8_heap_object)); 4711cb0ef41Sopenharmony_ci 4721cb0ef41Sopenharmony_ci *has_key = false; 4731cb0ef41Sopenharmony_ci for (const auto& prop : p_v8_heap_object->properties) { 4741cb0ef41Sopenharmony_ci const char16_t* p_key = reinterpret_cast<const char16_t*>(key); 4751cb0ef41Sopenharmony_ci if (prop.name.compare(p_key) == 0) { 4761cb0ef41Sopenharmony_ci *has_key = true; 4771cb0ef41Sopenharmony_ci if (key_value != nullptr) { 4781cb0ef41Sopenharmony_ci WRL::ComPtr<IDebugHostContext> sp_ctx; 4791cb0ef41Sopenharmony_ci RETURN_IF_FAIL(context_object->GetContext(&sp_ctx)); 4801cb0ef41Sopenharmony_ci RETURN_IF_FAIL(GetModelForProperty(prop, sp_ctx, key_value)); 4811cb0ef41Sopenharmony_ci } 4821cb0ef41Sopenharmony_ci return S_OK; 4831cb0ef41Sopenharmony_ci } 4841cb0ef41Sopenharmony_ci } 4851cb0ef41Sopenharmony_ci 4861cb0ef41Sopenharmony_ci return S_OK; 4871cb0ef41Sopenharmony_ci} 4881cb0ef41Sopenharmony_ci 4891cb0ef41Sopenharmony_ciIFACEMETHODIMP V8ObjectDataModel::SetKey(IModelObject* context_object, 4901cb0ef41Sopenharmony_ci PCWSTR key, IModelObject* key_value, 4911cb0ef41Sopenharmony_ci IKeyStore* metadata) noexcept { 4921cb0ef41Sopenharmony_ci return E_NOTIMPL; 4931cb0ef41Sopenharmony_ci} 4941cb0ef41Sopenharmony_ci 4951cb0ef41Sopenharmony_ciIFACEMETHODIMP V8ObjectDataModel::EnumerateKeys( 4961cb0ef41Sopenharmony_ci IModelObject* context_object, IKeyEnumerator** pp_enumerator) noexcept { 4971cb0ef41Sopenharmony_ci WRL::ComPtr<IV8CachedObject> sp_v8_cached_object; 4981cb0ef41Sopenharmony_ci RETURN_IF_FAIL(GetCachedObject(context_object, &sp_v8_cached_object)); 4991cb0ef41Sopenharmony_ci 5001cb0ef41Sopenharmony_ci auto enumerator{WRL::Make<V8ObjectKeyEnumerator>(sp_v8_cached_object)}; 5011cb0ef41Sopenharmony_ci *pp_enumerator = enumerator.Detach(); 5021cb0ef41Sopenharmony_ci return S_OK; 5031cb0ef41Sopenharmony_ci} 5041cb0ef41Sopenharmony_ci 5051cb0ef41Sopenharmony_ciIFACEMETHODIMP V8LocalValueProperty::GetValue( 5061cb0ef41Sopenharmony_ci PCWSTR pwsz_key, IModelObject* p_v8_local_instance, 5071cb0ef41Sopenharmony_ci IModelObject** pp_value) noexcept { 5081cb0ef41Sopenharmony_ci // Get the parametric type within v8::Local<*> 5091cb0ef41Sopenharmony_ci // Set value to a pointer to an instance of this type. 5101cb0ef41Sopenharmony_ci 5111cb0ef41Sopenharmony_ci WRL::ComPtr<IDebugHostType> sp_type; 5121cb0ef41Sopenharmony_ci RETURN_IF_FAIL(p_v8_local_instance->GetTypeInfo(&sp_type)); 5131cb0ef41Sopenharmony_ci 5141cb0ef41Sopenharmony_ci bool is_generic; 5151cb0ef41Sopenharmony_ci RETURN_IF_FAIL(sp_type->IsGeneric(&is_generic)); 5161cb0ef41Sopenharmony_ci if (!is_generic) return E_FAIL; 5171cb0ef41Sopenharmony_ci 5181cb0ef41Sopenharmony_ci WRL::ComPtr<IDebugHostSymbol> sp_generic_arg; 5191cb0ef41Sopenharmony_ci RETURN_IF_FAIL(sp_type->GetGenericArgumentAt(0, &sp_generic_arg)); 5201cb0ef41Sopenharmony_ci 5211cb0ef41Sopenharmony_ci _bstr_t generic_name; 5221cb0ef41Sopenharmony_ci RETURN_IF_FAIL(sp_generic_arg->GetName(generic_name.GetAddress())); 5231cb0ef41Sopenharmony_ci 5241cb0ef41Sopenharmony_ci WRL::ComPtr<IDebugHostContext> sp_ctx; 5251cb0ef41Sopenharmony_ci RETURN_IF_FAIL(p_v8_local_instance->GetContext(&sp_ctx)); 5261cb0ef41Sopenharmony_ci 5271cb0ef41Sopenharmony_ci WRL::ComPtr<IDebugHostType> sp_value_type = 5281cb0ef41Sopenharmony_ci Extension::Current()->GetTypeFromV8Module( 5291cb0ef41Sopenharmony_ci sp_ctx, reinterpret_cast<const char16_t*>( 5301cb0ef41Sopenharmony_ci static_cast<const wchar_t*>(generic_name))); 5311cb0ef41Sopenharmony_ci if (sp_value_type == nullptr || 5321cb0ef41Sopenharmony_ci !Extension::Current()->DoesTypeDeriveFromObject(sp_value_type)) { 5331cb0ef41Sopenharmony_ci // The value type doesn't derive from v8::internal::Object (probably a 5341cb0ef41Sopenharmony_ci // public API type), so just use plain v8::internal::Object. We could 5351cb0ef41Sopenharmony_ci // consider mapping some public API types to their corresponding internal 5361cb0ef41Sopenharmony_ci // types here, at the possible cost of increased maintenance. 5371cb0ef41Sopenharmony_ci sp_value_type = Extension::Current()->GetV8ObjectType(sp_ctx); 5381cb0ef41Sopenharmony_ci } 5391cb0ef41Sopenharmony_ci 5401cb0ef41Sopenharmony_ci Location loc; 5411cb0ef41Sopenharmony_ci RETURN_IF_FAIL(p_v8_local_instance->GetLocation(&loc)); 5421cb0ef41Sopenharmony_ci 5431cb0ef41Sopenharmony_ci // Read the pointer at the Object location 5441cb0ef41Sopenharmony_ci ULONG64 obj_address; 5451cb0ef41Sopenharmony_ci RETURN_IF_FAIL( 5461cb0ef41Sopenharmony_ci sp_debug_host_memory->ReadPointers(sp_ctx.Get(), loc, 1, &obj_address)); 5471cb0ef41Sopenharmony_ci 5481cb0ef41Sopenharmony_ci // If the val_ is a nullptr, then there is no value in the Local. 5491cb0ef41Sopenharmony_ci if (obj_address == 0) { 5501cb0ef41Sopenharmony_ci RETURN_IF_FAIL(CreateString(std::u16string{u"<empty>"}, pp_value)); 5511cb0ef41Sopenharmony_ci } else { 5521cb0ef41Sopenharmony_ci // Should be a v8::internal::Object at the address 5531cb0ef41Sopenharmony_ci RETURN_IF_FAIL(sp_data_model_manager->CreateTypedObject( 5541cb0ef41Sopenharmony_ci sp_ctx.Get(), obj_address, sp_value_type.Get(), pp_value)); 5551cb0ef41Sopenharmony_ci } 5561cb0ef41Sopenharmony_ci 5571cb0ef41Sopenharmony_ci return S_OK; 5581cb0ef41Sopenharmony_ci} 5591cb0ef41Sopenharmony_ci 5601cb0ef41Sopenharmony_ciIFACEMETHODIMP V8LocalValueProperty::SetValue( 5611cb0ef41Sopenharmony_ci PCWSTR /*pwsz_key*/, IModelObject* /*p_process_instance*/, 5621cb0ef41Sopenharmony_ci IModelObject* /*p_value*/) noexcept { 5631cb0ef41Sopenharmony_ci return E_NOTIMPL; 5641cb0ef41Sopenharmony_ci} 5651cb0ef41Sopenharmony_ci 5661cb0ef41Sopenharmony_ciIFACEMETHODIMP V8InternalCompilerNodeIdProperty::GetValue( 5671cb0ef41Sopenharmony_ci PCWSTR pwsz_key, IModelObject* p_v8_compiler_node_instance, 5681cb0ef41Sopenharmony_ci IModelObject** pp_value) noexcept { 5691cb0ef41Sopenharmony_ci WRL::ComPtr<IModelObject> sp_bit_field; 5701cb0ef41Sopenharmony_ci RETURN_IF_FAIL(p_v8_compiler_node_instance->GetRawValue( 5711cb0ef41Sopenharmony_ci SymbolKind::SymbolField, L"bit_field_", RawSearchNone, &sp_bit_field)); 5721cb0ef41Sopenharmony_ci 5731cb0ef41Sopenharmony_ci uint64_t bit_field_value; 5741cb0ef41Sopenharmony_ci RETURN_IF_FAIL( 5751cb0ef41Sopenharmony_ci UnboxULong64(sp_bit_field.Get(), &bit_field_value, true /*convert*/)); 5761cb0ef41Sopenharmony_ci 5771cb0ef41Sopenharmony_ci WRL::ComPtr<IDebugHostContext> sp_host_context; 5781cb0ef41Sopenharmony_ci RETURN_IF_FAIL(p_v8_compiler_node_instance->GetContext(&sp_host_context)); 5791cb0ef41Sopenharmony_ci 5801cb0ef41Sopenharmony_ci WRL::ComPtr<IDebugHostType> sp_id_field_type; 5811cb0ef41Sopenharmony_ci RETURN_IF_FAIL(Extension::Current() 5821cb0ef41Sopenharmony_ci ->GetV8Module(sp_host_context) 5831cb0ef41Sopenharmony_ci ->FindTypeByName(L"v8::internal::compiler::Node::IdField", 5841cb0ef41Sopenharmony_ci &sp_id_field_type)); 5851cb0ef41Sopenharmony_ci 5861cb0ef41Sopenharmony_ci // Get 2nd template parameter as 24 in class. 5871cb0ef41Sopenharmony_ci // v8::base::BitField<v8::internal::compiler::NodeId, 0, 24>. 5881cb0ef41Sopenharmony_ci bool is_generic; 5891cb0ef41Sopenharmony_ci RETURN_IF_FAIL(sp_id_field_type->IsGeneric(&is_generic)); 5901cb0ef41Sopenharmony_ci if (!is_generic) return E_FAIL; 5911cb0ef41Sopenharmony_ci 5921cb0ef41Sopenharmony_ci WRL::ComPtr<IDebugHostSymbol> sp_k_size_arg; 5931cb0ef41Sopenharmony_ci RETURN_IF_FAIL(sp_id_field_type->GetGenericArgumentAt(2, &sp_k_size_arg)); 5941cb0ef41Sopenharmony_ci 5951cb0ef41Sopenharmony_ci WRL::ComPtr<IDebugHostConstant> sp_k_size_constant; 5961cb0ef41Sopenharmony_ci RETURN_IF_FAIL(sp_k_size_arg.As(&sp_k_size_constant)); 5971cb0ef41Sopenharmony_ci 5981cb0ef41Sopenharmony_ci int k_size; 5991cb0ef41Sopenharmony_ci RETURN_IF_FAIL(GetInt32(sp_k_size_constant.Get(), &k_size)); 6001cb0ef41Sopenharmony_ci 6011cb0ef41Sopenharmony_ci // Compute node_id. 6021cb0ef41Sopenharmony_ci uint32_t node_id = bit_field_value & (0xFFFFFFFF >> k_size); 6031cb0ef41Sopenharmony_ci RETURN_IF_FAIL(CreateUInt32(node_id, pp_value)); 6041cb0ef41Sopenharmony_ci 6051cb0ef41Sopenharmony_ci return S_OK; 6061cb0ef41Sopenharmony_ci} 6071cb0ef41Sopenharmony_ci 6081cb0ef41Sopenharmony_ciIFACEMETHODIMP V8InternalCompilerNodeIdProperty::SetValue( 6091cb0ef41Sopenharmony_ci PCWSTR /*pwsz_key*/, IModelObject* /*p_process_instance*/, 6101cb0ef41Sopenharmony_ci IModelObject* /*p_value*/) noexcept { 6111cb0ef41Sopenharmony_ci return E_NOTIMPL; 6121cb0ef41Sopenharmony_ci} 6131cb0ef41Sopenharmony_ci 6141cb0ef41Sopenharmony_ciIFACEMETHODIMP V8InternalCompilerBitsetNameProperty::GetValue( 6151cb0ef41Sopenharmony_ci PCWSTR pwsz_key, IModelObject* p_v8_compiler_type_instance, 6161cb0ef41Sopenharmony_ci IModelObject** pp_value) noexcept { 6171cb0ef41Sopenharmony_ci WRL::ComPtr<IModelObject> sp_payload; 6181cb0ef41Sopenharmony_ci RETURN_IF_FAIL(p_v8_compiler_type_instance->GetRawValue( 6191cb0ef41Sopenharmony_ci SymbolKind::SymbolField, L"payload_", RawSearchNone, &sp_payload)); 6201cb0ef41Sopenharmony_ci 6211cb0ef41Sopenharmony_ci uint64_t payload_value; 6221cb0ef41Sopenharmony_ci RETURN_IF_FAIL( 6231cb0ef41Sopenharmony_ci UnboxULong64(sp_payload.Get(), &payload_value, true /*convert*/)); 6241cb0ef41Sopenharmony_ci 6251cb0ef41Sopenharmony_ci const char* bitset_name = ::BitsetName(payload_value); 6261cb0ef41Sopenharmony_ci if (!bitset_name) return E_FAIL; 6271cb0ef41Sopenharmony_ci std::string name(bitset_name); 6281cb0ef41Sopenharmony_ci RETURN_IF_FAIL(CreateString(ConvertToU16String(name), pp_value)); 6291cb0ef41Sopenharmony_ci 6301cb0ef41Sopenharmony_ci return S_OK; 6311cb0ef41Sopenharmony_ci} 6321cb0ef41Sopenharmony_ci 6331cb0ef41Sopenharmony_ciIFACEMETHODIMP V8InternalCompilerBitsetNameProperty::SetValue( 6341cb0ef41Sopenharmony_ci PCWSTR /*pwsz_key*/, IModelObject* /*p_process_instance*/, 6351cb0ef41Sopenharmony_ci IModelObject* /*p_value*/) noexcept { 6361cb0ef41Sopenharmony_ci return E_NOTIMPL; 6371cb0ef41Sopenharmony_ci} 6381cb0ef41Sopenharmony_ci 6391cb0ef41Sopenharmony_ciconstexpr wchar_t usage[] = 6401cb0ef41Sopenharmony_ci LR"(Invalid arguments. 6411cb0ef41Sopenharmony_ciFirst argument should be a uint64 representing the tagged value to investigate. 6421cb0ef41Sopenharmony_ciSecond argument is optional, and may be a fully-qualified type name such as 6431cb0ef41Sopenharmony_civ8::internal::String.)"; 6441cb0ef41Sopenharmony_ci 6451cb0ef41Sopenharmony_ciIFACEMETHODIMP InspectV8ObjectMethod::Call(IModelObject* p_context_object, 6461cb0ef41Sopenharmony_ci ULONG64 arg_count, 6471cb0ef41Sopenharmony_ci _In_reads_(arg_count) 6481cb0ef41Sopenharmony_ci IModelObject** pp_arguments, 6491cb0ef41Sopenharmony_ci IModelObject** pp_result, 6501cb0ef41Sopenharmony_ci IKeyStore** pp_metadata) noexcept { 6511cb0ef41Sopenharmony_ci // Read the arguments. 6521cb0ef41Sopenharmony_ci ULONG64 tagged_value; 6531cb0ef41Sopenharmony_ci _bstr_t type_name; 6541cb0ef41Sopenharmony_ci if (arg_count < 1 || 6551cb0ef41Sopenharmony_ci FAILED(UnboxULong64(pp_arguments[0], &tagged_value, /*convert=*/true)) || 6561cb0ef41Sopenharmony_ci (arg_count >= 2 && 6571cb0ef41Sopenharmony_ci FAILED(UnboxString(pp_arguments[1], type_name.GetAddress())))) { 6581cb0ef41Sopenharmony_ci sp_data_model_manager->CreateErrorObject(E_INVALIDARG, usage, pp_result); 6591cb0ef41Sopenharmony_ci return E_INVALIDARG; 6601cb0ef41Sopenharmony_ci } 6611cb0ef41Sopenharmony_ci 6621cb0ef41Sopenharmony_ci WRL::ComPtr<IDebugHostContext> sp_ctx; 6631cb0ef41Sopenharmony_ci RETURN_IF_FAIL(sp_debug_host->GetCurrentContext(&sp_ctx)); 6641cb0ef41Sopenharmony_ci 6651cb0ef41Sopenharmony_ci // We can't use CreateTypedObject for a value which may not actually reside 6661cb0ef41Sopenharmony_ci // anywhere in memory, so create a synthetic object. 6671cb0ef41Sopenharmony_ci WRL::ComPtr<V8CachedObject> cached_object = 6681cb0ef41Sopenharmony_ci WRL::Make<V8CachedObject>(::GetHeapObject( 6691cb0ef41Sopenharmony_ci sp_ctx, tagged_value, 0, static_cast<const char*>(type_name), 6701cb0ef41Sopenharmony_ci /*is_compressed=*/false)); 6711cb0ef41Sopenharmony_ci return CreateSyntheticObjectForV8Object(sp_ctx.Get(), cached_object.Get(), 6721cb0ef41Sopenharmony_ci pp_result); 6731cb0ef41Sopenharmony_ci} 6741cb0ef41Sopenharmony_ci 6751cb0ef41Sopenharmony_ci// Creates an IModelObject representing the data in the given property. 6761cb0ef41Sopenharmony_ciHRESULT GetModelForProperty(const Property& prop, 6771cb0ef41Sopenharmony_ci WRL::ComPtr<IDebugHostContext>& sp_ctx, 6781cb0ef41Sopenharmony_ci IModelObject** result) { 6791cb0ef41Sopenharmony_ci switch (prop.type) { 6801cb0ef41Sopenharmony_ci case PropertyType::kPointer: 6811cb0ef41Sopenharmony_ci return GetModelForBasicField(prop.addr_value, prop.type_name, 6821cb0ef41Sopenharmony_ci prop.uncompressed_type_name, sp_ctx, result); 6831cb0ef41Sopenharmony_ci case PropertyType::kStruct: 6841cb0ef41Sopenharmony_ci return GetModelForStruct(prop.addr_value, prop.fields, sp_ctx, result); 6851cb0ef41Sopenharmony_ci case PropertyType::kArray: 6861cb0ef41Sopenharmony_ci case PropertyType::kStructArray: 6871cb0ef41Sopenharmony_ci if (prop.type == PropertyType::kArray && 6881cb0ef41Sopenharmony_ci prop.type_name == ConvertToU16String(prop.uncompressed_type_name)) { 6891cb0ef41Sopenharmony_ci // An array of things that are not structs or compressed tagged values 6901cb0ef41Sopenharmony_ci // is most cleanly represented by a native array. 6911cb0ef41Sopenharmony_ci return GetModelForNativeArray(prop.addr_value, prop.type_name, 6921cb0ef41Sopenharmony_ci prop.length, sp_ctx, result); 6931cb0ef41Sopenharmony_ci } 6941cb0ef41Sopenharmony_ci // Otherwise, we must construct a custom iterable object. 6951cb0ef41Sopenharmony_ci return GetModelForCustomArray(prop, sp_ctx, result); 6961cb0ef41Sopenharmony_ci default: 6971cb0ef41Sopenharmony_ci return E_FAIL; 6981cb0ef41Sopenharmony_ci } 6991cb0ef41Sopenharmony_ci} 700