[heap] Fix --code-stats with code cache

During deserialization all allocated objects are preinitialized with
Smi 0. During code cache deserialization GCs may happen. When
--code-stats is enabled as well, code stats are collected during GC.
In such situations crashes may happen because of fields in
BytecodeArray objects not being deserialized at the time of GC.

This CL introduces new raw_* getters for --code-stats which allows
accessing these fields while they still contain 0.

Bug: v8:13704
Change-Id: I767714ca1c936a031d71f3eb53d6401030ccce7e
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4212406
Reviewed-by: Jakob Linke <jgruber@chromium.org>
Commit-Queue: Dominik Inführ <dinfuehr@chromium.org>
Cr-Commit-Position: refs/heads/main@{#85632}
This commit is contained in:
Dominik Inführ 2023-02-02 14:24:36 +01:00 committed by V8 LUCI CQ
parent de4e49260f
commit 31654be902
2 changed files with 45 additions and 5 deletions

View File

@ -1416,15 +1416,50 @@ DEF_GETTER(BytecodeArray, SourcePositionTable, ByteArray) {
return roots.empty_byte_array();
}
DEF_GETTER(BytecodeArray, raw_constant_pool, Object) {
Object value =
TaggedField<Object>::load(cage_base, *this, kConstantPoolOffset);
// This field might be 0 during deserialization.
DCHECK(value == Smi::zero() || value.IsFixedArray());
return value;
}
DEF_GETTER(BytecodeArray, raw_handler_table, Object) {
Object value =
TaggedField<Object>::load(cage_base, *this, kHandlerTableOffset);
// This field might be 0 during deserialization.
DCHECK(value == Smi::zero() || value.IsByteArray());
return value;
}
DEF_GETTER(BytecodeArray, raw_source_position_table, Object) {
Object value =
TaggedField<Object>::load(cage_base, *this, kSourcePositionTableOffset);
// This field might be 0 during deserialization.
DCHECK(value == Smi::zero() || value.IsByteArray() || value.IsUndefined() ||
value.IsException());
return value;
}
int BytecodeArray::BytecodeArraySize() const { return SizeFor(this->length()); }
DEF_GETTER(BytecodeArray, SizeIncludingMetadata, int) {
int size = BytecodeArraySize();
size += constant_pool(cage_base).Size(cage_base);
size += handler_table(cage_base).Size();
ByteArray table = SourcePositionTable(cage_base);
if (table.length() != 0) {
size += table.Size();
Object maybe_constant_pool = raw_constant_pool(cage_base);
if (maybe_constant_pool.IsFixedArray()) {
size += FixedArray::cast(maybe_constant_pool).Size(cage_base);
} else {
DCHECK_EQ(maybe_constant_pool, Smi::zero());
}
Object maybe_handler_table = raw_handler_table(cage_base);
if (maybe_handler_table.IsByteArray()) {
size += ByteArray::cast(maybe_handler_table).Size();
} else {
DCHECK_EQ(maybe_handler_table, Smi::zero());
}
Object maybe_table = raw_source_position_table(cage_base);
if (maybe_table.IsByteArray()) {
size += ByteArray::cast(maybe_table).Size();
}
return size;
}

View File

@ -1068,6 +1068,11 @@ class BytecodeArray
// this will return empty_byte_array.
DECL_GETTER(SourcePositionTable, ByteArray)
// Raw accessors to access these fields during code cache deserialization.
DECL_GETTER(raw_constant_pool, Object)
DECL_GETTER(raw_handler_table, Object)
DECL_GETTER(raw_source_position_table, Object)
// Indicates that an attempt was made to collect source positions, but that it
// failed most likely due to stack exhaustion. When in this state
// |SourcePositionTable| will return an empty byte array rather than crashing