diff --git a/test/cctest/test-debug-helper.cc b/test/cctest/test-debug-helper.cc index c374303713..6e3033d993 100644 --- a/test/cctest/test-debug-helper.cc +++ b/test/cctest/test-debug-helper.cc @@ -422,9 +422,29 @@ static void FrameIterationCheck( d::StackFrameResultPtr props = d::GetStackFrame(frame->fp(), &ReadMemory); if (frame->is_java_script()) { JavaScriptFrame* js_frame = JavaScriptFrame::cast(frame); - CHECK_EQ(props->num_properties, 1); + CHECK_EQ(props->num_properties, 5); + auto js_function = js_frame->function(); CheckProp(*props->properties[0], "v8::internal::JSFunction", - "currently_executing_jsfunction", js_frame->function().ptr()); + "currently_executing_jsfunction", js_function.ptr()); + auto shared_function_info = js_function.shared(); + auto script = i::Script::cast(shared_function_info.script()); + CheckProp(*props->properties[1], "v8::internal::Object", "script_name", + static_cast(script.name().ptr())); + CheckProp(*props->properties[2], "v8::internal::Object", "script_source", + static_cast(script.source().ptr())); + + auto scope_info = shared_function_info.scope_info(); + CheckProp(*props->properties[3], "v8::internal::Object", "function_name", + static_cast(scope_info.FunctionName().ptr())); + + CheckProp(*props->properties[4], "", "function_character_offset"); + const d::ObjectProperty& function_character_offset = + *props->properties[4]; + CHECK_EQ(function_character_offset.num_struct_fields, 2); + CheckStructProp(*function_character_offset.struct_fields[0], + "v8::internal::Object", "start", 0); + CheckStructProp(*function_character_offset.struct_fields[1], + "v8::internal::Object", "end", 4); } else { CHECK_EQ(props->num_properties, 0); } diff --git a/tools/debug_helper/get-object-properties.cc b/tools/debug_helper/get-object-properties.cc index a6ebcc0761..a7cc1414df 100644 --- a/tools/debug_helper/get-object-properties.cc +++ b/tools/debug_helper/get-object-properties.cc @@ -14,6 +14,7 @@ #include "src/objects/string-inl.h" #include "src/strings/unicode-inl.h" #include "torque-generated/class-debug-readers.h" +#include "torque-generated/debug-macros.h" namespace i = v8::internal; @@ -133,6 +134,23 @@ TypedObject GetTypedObjectByInstanceType(uintptr_t address, } } +bool IsTypedHeapObjectInstanceTypeOf(uintptr_t address, + d::MemoryAccessor accessor, + i::InstanceType instance_type) { + auto heap_object = std::make_unique(address); + Value map_ptr = heap_object->GetMapValue(accessor); + + if (map_ptr.validity == d::MemoryAccessResult::kOk) { + Value type = + TqMap(map_ptr.value).GetInstanceTypeValue(accessor); + if (type.validity == d::MemoryAccessResult::kOk) { + return instance_type == type.value; + } + } + + return false; +} + TypedObject GetTypedHeapObject(uintptr_t address, d::MemoryAccessor accessor, const char* type_hint, const d::HeapAddresses& heap_addresses) { @@ -654,6 +672,90 @@ std::unique_ptr GetStackFrame( sizeof(v8::internal::JSFunction), std::vector>(), d::PropertyKind::kSingle)); + // Add more items in the Locals pane representing the JS function name, + // source file name, and line & column numbers within the source file, so + // that the user doesn’t need to dig through the shared_function_info to + // find them. + intptr_t js_function_ptr = 0; + validity = memory_accessor( + frame_pointer + StandardFrameConstants::kFunctionOffset, + reinterpret_cast(&js_function_ptr), sizeof(intptr_t)); + if (validity == d::MemoryAccessResult::kOk) { + TqJSFunction js_function(js_function_ptr); + auto shared_function_info_ptr = + js_function.GetSharedFunctionInfoValue(memory_accessor); + if (shared_function_info_ptr.validity == d::MemoryAccessResult::kOk) { + TqSharedFunctionInfo shared_function_info( + shared_function_info_ptr.value); + auto script_or_debug_info_ptr = + shared_function_info.GetScriptOrDebugInfoValue(memory_accessor); + if (script_or_debug_info_ptr.validity == d::MemoryAccessResult::kOk) { + // Make sure script_or_debug_info_ptr is script. + auto address = script_or_debug_info_ptr.value; + if (IsTypedHeapObjectInstanceTypeOf(address, memory_accessor, + i::InstanceType::SCRIPT_TYPE)) { + TqScript script(script_or_debug_info_ptr.value); + props.push_back(std::make_unique( + "script_name", kObjectAsStoredInHeap, kObject, + script.GetNameAddress(), 1, i::kTaggedSize, + std::vector>(), + d::PropertyKind::kSingle)); + props.push_back(std::make_unique( + "script_source", kObjectAsStoredInHeap, kObject, + script.GetSourceAddress(), 1, i::kTaggedSize, + std::vector>(), + d::PropertyKind::kSingle)); + } + } + auto name_or_scope_info_ptr = + shared_function_info.GetNameOrScopeInfoValue(memory_accessor); + if (name_or_scope_info_ptr.validity == d::MemoryAccessResult::kOk) { + auto scope_info_address = name_or_scope_info_ptr.value; + // Make sure name_or_scope_info_ptr is scope info. + if (IsTypedHeapObjectInstanceTypeOf( + scope_info_address, memory_accessor, + i::InstanceType::SCOPE_INFO_TYPE)) { + auto indexed_field_slice_function_variable_info = + TqDebugFieldSliceScopeInfoFunctionVariableInfo( + memory_accessor, scope_info_address); + if (indexed_field_slice_function_variable_info.validity == + d::MemoryAccessResult::kOk) { + props.push_back(std::make_unique( + "function_name", kObjectAsStoredInHeap, kObject, + scope_info_address - i::kHeapObjectTag + + std::get<1>( + indexed_field_slice_function_variable_info.value), + std::get<2>( + indexed_field_slice_function_variable_info.value), + i::kTaggedSize, + std::vector>(), + d::PropertyKind::kSingle)); + } + std::vector> + position_info_struct_field_list; + position_info_struct_field_list.push_back( + std::make_unique( + "start", kObjectAsStoredInHeap, kObject, 0, 0, 0)); + position_info_struct_field_list.push_back( + std::make_unique("end", kObjectAsStoredInHeap, + kObject, 4, 0, 0)); + auto indexed_field_slice_position_info = + TqDebugFieldSliceScopeInfoPositionInfo(memory_accessor, + scope_info_address); + if (indexed_field_slice_position_info.validity == + d::MemoryAccessResult::kOk) { + props.push_back(std::make_unique( + "function_character_offset", "", "", + scope_info_address - i::kHeapObjectTag + + std::get<1>(indexed_field_slice_position_info.value), + std::get<2>(indexed_field_slice_position_info.value), + i::kTaggedSize, std::move(position_info_struct_field_list), + d::PropertyKind::kSingle)); + } + } + } + } + } } }