Commit 9ae463bc authored by Camillo Bruni's avatar Camillo Bruni Committed by V8 LUCI CQ

[heap-stats] Fix heap-stats with ptr-cage

- Heap-stats was trying to load the map without explicitly passing in
  the PtrComprBase causing failures with Code objects in external code
  space
- Extend the debugPrint.js tests to run with some more debugging and
  testing flags to prevent future regressions

Change-Id: I1f0d03cb31480f316fe533b507ff98fe3befbe8e
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3432386Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Auto-Submit: Camillo Bruni <cbruni@chromium.org>
Reviewed-by: 's avatarDominik Inführ <dinfuehr@chromium.org>
Commit-Queue: Dominik Inführ <dinfuehr@chromium.org>
Cr-Commit-Position: refs/heads/main@{#78919}
parent 18469ec4
...@@ -443,6 +443,11 @@ class ObjectStatsCollectorImpl { ...@@ -443,6 +443,11 @@ class ObjectStatsCollectorImpl {
void RecordVirtualArrayBoilerplateDescription( void RecordVirtualArrayBoilerplateDescription(
ArrayBoilerplateDescription description); ArrayBoilerplateDescription description);
PtrComprCageBase cage_base() const {
return field_stats_collector_.cage_base();
}
Heap* heap_; Heap* heap_;
ObjectStats* stats_; ObjectStats* stats_;
MarkCompactCollector::NonAtomicMarkingState* marking_state_; MarkCompactCollector::NonAtomicMarkingState* marking_state_;
...@@ -488,7 +493,7 @@ void ObjectStatsCollectorImpl::RecordHashTableVirtualObjectStats( ...@@ -488,7 +493,7 @@ void ObjectStatsCollectorImpl::RecordHashTableVirtualObjectStats(
bool ObjectStatsCollectorImpl::RecordSimpleVirtualObjectStats( bool ObjectStatsCollectorImpl::RecordSimpleVirtualObjectStats(
HeapObject parent, HeapObject obj, ObjectStats::VirtualInstanceType type) { HeapObject parent, HeapObject obj, ObjectStats::VirtualInstanceType type) {
return RecordVirtualObjectStats(parent, obj, type, obj.Size(), return RecordVirtualObjectStats(parent, obj, type, obj.Size(cage_base()),
ObjectStats::kNoOverAllocation, kCheckCow); ObjectStats::kNoOverAllocation, kCheckCow);
} }
...@@ -711,7 +716,8 @@ void ObjectStatsCollectorImpl::RecordVirtualFeedbackVectorDetails( ...@@ -711,7 +716,8 @@ void ObjectStatsCollectorImpl::RecordVirtualFeedbackVectorDetails(
MaybeObject raw_object = vector.Get(slot.WithOffset(i)); MaybeObject raw_object = vector.Get(slot.WithOffset(i));
HeapObject object; HeapObject object;
if (raw_object->GetHeapObject(&object)) { if (raw_object->GetHeapObject(&object)) {
if (object.IsCell() || object.IsWeakFixedArray()) { if (object.IsCell(cage_base()) ||
object.IsWeakFixedArray(cage_base())) {
RecordSimpleVirtualObjectStats( RecordSimpleVirtualObjectStats(
vector, object, ObjectStats::FEEDBACK_VECTOR_ENTRY_TYPE); vector, object, ObjectStats::FEEDBACK_VECTOR_ENTRY_TYPE);
} }
...@@ -733,51 +739,55 @@ void ObjectStatsCollectorImpl::RecordVirtualFixedArrayDetails( ...@@ -733,51 +739,55 @@ void ObjectStatsCollectorImpl::RecordVirtualFixedArrayDetails(
void ObjectStatsCollectorImpl::CollectStatistics( void ObjectStatsCollectorImpl::CollectStatistics(
HeapObject obj, Phase phase, CollectFieldStats collect_field_stats) { HeapObject obj, Phase phase, CollectFieldStats collect_field_stats) {
Map map = obj.map(); DisallowGarbageCollection no_gc;
Map map = obj.map(cage_base());
InstanceType instance_type = map.instance_type();
switch (phase) { switch (phase) {
case kPhase1: case kPhase1:
if (obj.IsFeedbackVector()) { if (InstanceTypeChecker::IsFeedbackVector(instance_type)) {
RecordVirtualFeedbackVectorDetails(FeedbackVector::cast(obj)); RecordVirtualFeedbackVectorDetails(FeedbackVector::cast(obj));
} else if (obj.IsMap()) { } else if (InstanceTypeChecker::IsMap(instance_type)) {
RecordVirtualMapDetails(Map::cast(obj)); RecordVirtualMapDetails(Map::cast(obj));
} else if (obj.IsBytecodeArray()) { } else if (InstanceTypeChecker::IsBytecodeArray(instance_type)) {
RecordVirtualBytecodeArrayDetails(BytecodeArray::cast(obj)); RecordVirtualBytecodeArrayDetails(BytecodeArray::cast(obj));
} else if (obj.IsCode()) { } else if (InstanceTypeChecker::IsCode(instance_type)) {
RecordVirtualCodeDetails(Code::cast(obj)); RecordVirtualCodeDetails(Code::cast(obj));
} else if (obj.IsFunctionTemplateInfo()) { } else if (InstanceTypeChecker::IsFunctionTemplateInfo(instance_type)) {
RecordVirtualFunctionTemplateInfoDetails( RecordVirtualFunctionTemplateInfoDetails(
FunctionTemplateInfo::cast(obj)); FunctionTemplateInfo::cast(obj));
} else if (obj.IsJSGlobalObject()) { } else if (InstanceTypeChecker::IsJSGlobalObject(instance_type)) {
RecordVirtualJSGlobalObjectDetails(JSGlobalObject::cast(obj)); RecordVirtualJSGlobalObjectDetails(JSGlobalObject::cast(obj));
} else if (obj.IsJSObject()) { } else if (InstanceTypeChecker::IsJSObject(instance_type)) {
// This phase needs to come after RecordVirtualAllocationSiteDetails // This phase needs to come after RecordVirtualAllocationSiteDetails
// to properly split among boilerplates. // to properly split among boilerplates.
RecordVirtualJSObjectDetails(JSObject::cast(obj)); RecordVirtualJSObjectDetails(JSObject::cast(obj));
} else if (obj.IsSharedFunctionInfo()) { } else if (InstanceTypeChecker::IsSharedFunctionInfo(instance_type)) {
RecordVirtualSharedFunctionInfoDetails(SharedFunctionInfo::cast(obj)); RecordVirtualSharedFunctionInfoDetails(SharedFunctionInfo::cast(obj));
} else if (obj.IsContext()) { } else if (InstanceTypeChecker::IsContext(instance_type)) {
RecordVirtualContext(Context::cast(obj)); RecordVirtualContext(Context::cast(obj));
} else if (obj.IsScript()) { } else if (InstanceTypeChecker::IsScript(instance_type)) {
RecordVirtualScriptDetails(Script::cast(obj)); RecordVirtualScriptDetails(Script::cast(obj));
} else if (obj.IsArrayBoilerplateDescription()) { } else if (InstanceTypeChecker::IsArrayBoilerplateDescription(
instance_type)) {
RecordVirtualArrayBoilerplateDescription( RecordVirtualArrayBoilerplateDescription(
ArrayBoilerplateDescription::cast(obj)); ArrayBoilerplateDescription::cast(obj));
} else if (obj.IsFixedArrayExact()) { } else if (InstanceTypeChecker::IsFixedArrayExact(instance_type)) {
// Has to go last as it triggers too eagerly. // Has to go last as it triggers too eagerly.
RecordVirtualFixedArrayDetails(FixedArray::cast(obj)); RecordVirtualFixedArrayDetails(FixedArray::cast(obj));
} }
break; break;
case kPhase2: case kPhase2:
if (obj.IsExternalString()) { if (InstanceTypeChecker::IsExternalString(instance_type)) {
// This has to be in Phase2 to avoid conflicting with recording Script // This has to be in Phase2 to avoid conflicting with recording Script
// sources. We still want to run RecordObjectStats after though. // sources. We still want to run RecordObjectStats after though.
RecordVirtualExternalStringDetails(ExternalString::cast(obj)); RecordVirtualExternalStringDetails(ExternalString::cast(obj));
} }
size_t over_allocated = ObjectStats::kNoOverAllocation; size_t over_allocated = ObjectStats::kNoOverAllocation;
if (obj.IsJSObject()) { if (InstanceTypeChecker::IsJSObject(instance_type)) {
over_allocated = map.instance_size() - map.UsedInstanceSize(); over_allocated = map.instance_size() - map.UsedInstanceSize();
} }
RecordObjectStats(obj, map.instance_type(), obj.Size(), over_allocated); RecordObjectStats(obj, instance_type, obj.Size(cage_base()),
over_allocated);
if (collect_field_stats == CollectFieldStats::kYes) { if (collect_field_stats == CollectFieldStats::kYes) {
field_stats_collector_.RecordStats(obj); field_stats_collector_.RecordStats(obj);
} }
...@@ -788,7 +798,7 @@ void ObjectStatsCollectorImpl::CollectStatistics( ...@@ -788,7 +798,7 @@ void ObjectStatsCollectorImpl::CollectStatistics(
void ObjectStatsCollectorImpl::CollectGlobalStatistics() { void ObjectStatsCollectorImpl::CollectGlobalStatistics() {
// Iterate boilerplates first to disambiguate them from regular JS objects. // Iterate boilerplates first to disambiguate them from regular JS objects.
Object list = heap_->allocation_sites_list(); Object list = heap_->allocation_sites_list();
while (list.IsAllocationSite()) { while (list.IsAllocationSite(cage_base())) {
AllocationSite site = AllocationSite::cast(list); AllocationSite site = AllocationSite::cast(list);
RecordVirtualAllocationSiteDetails(site); RecordVirtualAllocationSiteDetails(site);
list = site.weak_next(); list = site.weak_next();
...@@ -829,7 +839,7 @@ bool ObjectStatsCollectorImpl::CanRecordFixedArray(FixedArrayBase array) { ...@@ -829,7 +839,7 @@ bool ObjectStatsCollectorImpl::CanRecordFixedArray(FixedArrayBase array) {
} }
bool ObjectStatsCollectorImpl::IsCowArray(FixedArrayBase array) { bool ObjectStatsCollectorImpl::IsCowArray(FixedArrayBase array) {
return array.map() == ReadOnlyRoots(heap_).fixed_cow_array_map(); return array.map(cage_base()) == ReadOnlyRoots(heap_).fixed_cow_array_map();
} }
bool ObjectStatsCollectorImpl::SameLiveness(HeapObject obj1, HeapObject obj2) { bool ObjectStatsCollectorImpl::SameLiveness(HeapObject obj1, HeapObject obj2) {
...@@ -868,7 +878,7 @@ void ObjectStatsCollectorImpl::RecordVirtualMapDetails(Map map) { ...@@ -868,7 +878,7 @@ void ObjectStatsCollectorImpl::RecordVirtualMapDetails(Map map) {
// This will be logged as MAP_TYPE in Phase2. // This will be logged as MAP_TYPE in Phase2.
} }
DescriptorArray array = map.instance_descriptors(isolate()); DescriptorArray array = map.instance_descriptors(cage_base());
if (map.owns_descriptors() && if (map.owns_descriptors() &&
array != ReadOnlyRoots(heap_).empty_descriptor_array()) { array != ReadOnlyRoots(heap_).empty_descriptor_array()) {
// Generally DescriptorArrays have their own instance type already // Generally DescriptorArrays have their own instance type already
...@@ -891,10 +901,10 @@ void ObjectStatsCollectorImpl::RecordVirtualMapDetails(Map map) { ...@@ -891,10 +901,10 @@ void ObjectStatsCollectorImpl::RecordVirtualMapDetails(Map map) {
} }
if (map.is_prototype_map()) { if (map.is_prototype_map()) {
if (map.prototype_info().IsPrototypeInfo()) { if (map.prototype_info().IsPrototypeInfo(cage_base())) {
PrototypeInfo info = PrototypeInfo::cast(map.prototype_info()); PrototypeInfo info = PrototypeInfo::cast(map.prototype_info());
Object users = info.prototype_users(); Object users = info.prototype_users();
if (users.IsWeakFixedArray()) { if (users.IsWeakFixedArray(cage_base())) {
RecordSimpleVirtualObjectStats(map, WeakArrayList::cast(users), RecordSimpleVirtualObjectStats(map, WeakArrayList::cast(users),
ObjectStats::PROTOTYPE_USERS_TYPE); ObjectStats::PROTOTYPE_USERS_TYPE);
} }
...@@ -909,7 +919,7 @@ void ObjectStatsCollectorImpl::RecordVirtualScriptDetails(Script script) { ...@@ -909,7 +919,7 @@ void ObjectStatsCollectorImpl::RecordVirtualScriptDetails(Script script) {
// Log the size of external source code. // Log the size of external source code.
Object raw_source = script.source(); Object raw_source = script.source();
if (raw_source.IsExternalString()) { if (raw_source.IsExternalString(cage_base())) {
// The contents of external strings aren't on the heap, so we have to record // The contents of external strings aren't on the heap, so we have to record
// them manually. The on-heap String object is recorded indepentendely in // them manually. The on-heap String object is recorded indepentendely in
// the normal pass. // the normal pass.
...@@ -922,7 +932,7 @@ void ObjectStatsCollectorImpl::RecordVirtualScriptDetails(Script script) { ...@@ -922,7 +932,7 @@ void ObjectStatsCollectorImpl::RecordVirtualScriptDetails(Script script) {
? ObjectStats::SCRIPT_SOURCE_EXTERNAL_ONE_BYTE_TYPE ? ObjectStats::SCRIPT_SOURCE_EXTERNAL_ONE_BYTE_TYPE
: ObjectStats::SCRIPT_SOURCE_EXTERNAL_TWO_BYTE_TYPE, : ObjectStats::SCRIPT_SOURCE_EXTERNAL_TWO_BYTE_TYPE,
off_heap_size); off_heap_size);
} else if (raw_source.IsString()) { } else if (raw_source.IsString(cage_base())) {
String source = String::cast(raw_source); String source = String::cast(raw_source);
RecordSimpleVirtualObjectStats( RecordSimpleVirtualObjectStats(
script, source, script, source,
...@@ -940,7 +950,7 @@ void ObjectStatsCollectorImpl::RecordVirtualExternalStringDetails( ...@@ -940,7 +950,7 @@ void ObjectStatsCollectorImpl::RecordVirtualExternalStringDetails(
size_t off_heap_size = string.ExternalPayloadSize(); size_t off_heap_size = string.ExternalPayloadSize();
RecordExternalResourceStats( RecordExternalResourceStats(
resource, resource,
string.IsOneByteRepresentation() string.IsOneByteRepresentation(cage_base())
? ObjectStats::STRING_EXTERNAL_RESOURCE_ONE_BYTE_TYPE ? ObjectStats::STRING_EXTERNAL_RESOURCE_ONE_BYTE_TYPE
: ObjectStats::STRING_EXTERNAL_RESOURCE_TWO_BYTE_TYPE, : ObjectStats::STRING_EXTERNAL_RESOURCE_TWO_BYTE_TYPE,
off_heap_size); off_heap_size);
...@@ -967,7 +977,7 @@ void ObjectStatsCollectorImpl:: ...@@ -967,7 +977,7 @@ void ObjectStatsCollectorImpl::
HeapObject parent, HeapObject object, HeapObject parent, HeapObject object,
ObjectStats::VirtualInstanceType type) { ObjectStats::VirtualInstanceType type) {
if (!RecordSimpleVirtualObjectStats(parent, object, type)) return; if (!RecordSimpleVirtualObjectStats(parent, object, type)) return;
if (object.IsFixedArrayExact()) { if (object.IsFixedArrayExact(cage_base())) {
FixedArray array = FixedArray::cast(object); FixedArray array = FixedArray::cast(object);
for (int i = 0; i < array.length(); i++) { for (int i = 0; i < array.length(); i++) {
Object entry = array.get(i); Object entry = array.get(i);
...@@ -988,7 +998,7 @@ void ObjectStatsCollectorImpl::RecordVirtualBytecodeArrayDetails( ...@@ -988,7 +998,7 @@ void ObjectStatsCollectorImpl::RecordVirtualBytecodeArrayDetails(
FixedArray constant_pool = FixedArray::cast(bytecode.constant_pool()); FixedArray constant_pool = FixedArray::cast(bytecode.constant_pool());
for (int i = 0; i < constant_pool.length(); i++) { for (int i = 0; i < constant_pool.length(); i++) {
Object entry = constant_pool.get(i); Object entry = constant_pool.get(i);
if (entry.IsFixedArrayExact()) { if (entry.IsFixedArrayExact(cage_base())) {
RecordVirtualObjectsForConstantPoolOrEmbeddedObjects( RecordVirtualObjectsForConstantPoolOrEmbeddedObjects(
constant_pool, HeapObject::cast(entry), constant_pool, HeapObject::cast(entry),
ObjectStats::EMBEDDED_OBJECT_TYPE); ObjectStats::EMBEDDED_OBJECT_TYPE);
...@@ -1041,11 +1051,10 @@ void ObjectStatsCollectorImpl::RecordVirtualCodeDetails(Code code) { ...@@ -1041,11 +1051,10 @@ void ObjectStatsCollectorImpl::RecordVirtualCodeDetails(Code code) {
} }
} }
int const mode_mask = RelocInfo::EmbeddedObjectModeMask(); int const mode_mask = RelocInfo::EmbeddedObjectModeMask();
PtrComprCageBase cage_base(heap_->isolate());
for (RelocIterator it(code, mode_mask); !it.done(); it.next()) { for (RelocIterator it(code, mode_mask); !it.done(); it.next()) {
DCHECK(RelocInfo::IsEmbeddedObjectMode(it.rinfo()->rmode())); DCHECK(RelocInfo::IsEmbeddedObjectMode(it.rinfo()->rmode()));
Object target = it.rinfo()->target_object(cage_base); Object target = it.rinfo()->target_object(cage_base());
if (target.IsFixedArrayExact()) { if (target.IsFixedArrayExact(cage_base())) {
RecordVirtualObjectsForConstantPoolOrEmbeddedObjects( RecordVirtualObjectsForConstantPoolOrEmbeddedObjects(
code, HeapObject::cast(target), ObjectStats::EMBEDDED_OBJECT_TYPE); code, HeapObject::cast(target), ObjectStats::EMBEDDED_OBJECT_TYPE);
} }
...@@ -1055,7 +1064,7 @@ void ObjectStatsCollectorImpl::RecordVirtualCodeDetails(Code code) { ...@@ -1055,7 +1064,7 @@ void ObjectStatsCollectorImpl::RecordVirtualCodeDetails(Code code) {
void ObjectStatsCollectorImpl::RecordVirtualContext(Context context) { void ObjectStatsCollectorImpl::RecordVirtualContext(Context context) {
if (context.IsNativeContext()) { if (context.IsNativeContext()) {
RecordObjectStats(context, NATIVE_CONTEXT_TYPE, context.Size()); RecordObjectStats(context, NATIVE_CONTEXT_TYPE, context.Size());
if (context.retained_maps().IsWeakArrayList()) { if (context.retained_maps().IsWeakArrayList(cage_base())) {
RecordSimpleVirtualObjectStats( RecordSimpleVirtualObjectStats(
context, WeakArrayList::cast(context.retained_maps()), context, WeakArrayList::cast(context.retained_maps()),
ObjectStats::RETAINED_MAPS_TYPE); ObjectStats::RETAINED_MAPS_TYPE);
......
...@@ -2,7 +2,10 @@ ...@@ -2,7 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// Flags: --allow-natives-syntax // Test various debug flags
// Flags: --allow-natives-syntax --trace-gc-object-stats --gc-global
// Flags: --trace-zone-stats --expose-gc --trace-gc
var largeArray = []; var largeArray = [];
largeArray[0xFFFF00] = 123; largeArray[0xFFFF00] = 123;
...@@ -25,7 +28,22 @@ function slowSloppyArguments2(a, b) { ...@@ -25,7 +28,22 @@ function slowSloppyArguments2(a, b) {
return arguments; return arguments;
} }
let proto_obj = { fn1() { return 1 } }
let obj_with_enum_cache = {
__proto__: proto_obj,
a: 1,
b: 2,
c: "c"
};
for (let k in obj_with_enum_cache) {
// do something
obj_with_enum_cache.a += obj_with_enum_cache.fn1();
}
let string_1 = "aasdfasdfasdfasdf asd fa sdf asdf as dfa sdf asd f"
let string_2 = "aasdfasdfasdfasdf asd fa sdf UC16\u2028asdf as dfa sdf asd f"
var objects = [ var objects = [
this, this,
true, false, null, undefined, true, false, null, undefined,
...@@ -33,8 +51,10 @@ var objects = [ ...@@ -33,8 +51,10 @@ var objects = [
9007199254740991.0, 9007199254740991.0 + 10, 9007199254740991.0, 9007199254740991.0 + 10,
-9007199254740992.0, -9007199254740992.0 - 10, -9007199254740992.0, -9007199254740992.0 - 10,
Infinity, -Infinity, NaN, Infinity, -Infinity, NaN,
"aasdfasdfasdfasdf", "a"+"b", string_1, string_1+"b", string_1.slice(1),
string_2, string_2+"b", string_2.slice(1),
{}, {1:1}, {a:1}, {1:1, 2:2}, Object.create(null), {}, {1:1}, {a:1}, {1:1, 2:2}, Object.create(null),
obj_with_enum_cache,
[], [{}, {}], [1, 1, 1], [1.1, 1.1, 1.1, 1.1, 2], largeArray, [], [{}, {}], [1, 1, 1], [1.1, 1.1, 1.1, 1.1, 2], largeArray,
new Proxy({},{}), new Proxy({},{}),
new Date(), new String(" a"), new Date(), new String(" a"),
...@@ -53,3 +73,6 @@ var objects = [ ...@@ -53,3 +73,6 @@ var objects = [
]; ];
for (var o of objects) %DebugPrint(o); for (var o of objects) %DebugPrint(o);
// Trigger some gcs to trigger heap and zone stats
for (let i = 0; i <= 4; i++) gc();
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