[profiler] Don't cast bytecode array to avoid heap DCHECKs

When iterating over stack frames in the cpu profiler, don't perform any
object casts that have heap-testing DCHECKs. Instead, access values on
the frame by offsets directly, and only check their tags for validity.

Cq-Include-Trybots: master.tryserver.chromium.linux:linux_chromium_rel_ng
Change-Id: Ia54b18f8ab947c1827f17483806104f0d1d34136
Reviewed-on: https://chromium-review.googlesource.com/536973
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#45985}
This commit is contained in:
Leszek Swirski 2017-06-16 15:58:23 +01:00 committed by Commit Bot
parent 8bc4fe57a4
commit 86b3b92230
2 changed files with 26 additions and 13 deletions

View File

@ -743,7 +743,11 @@ struct AccessorDescriptor {
// Testers for test.
#define HAS_SMI_TAG(value) \
((reinterpret_cast<intptr_t>(value) & kSmiTagMask) == kSmiTag)
((reinterpret_cast<intptr_t>(value) & ::i::kSmiTagMask) == ::i::kSmiTag)
#define HAS_HEAP_OBJECT_TAG(value) \
(((reinterpret_cast<intptr_t>(value) & ::i::kHeapObjectTagMask) == \
::i::kHeapObjectTag))
// OBJECT_POINTER_ALIGN returns the value aligned as a HeapObject pointer
#define OBJECT_POINTER_ALIGN(value) \

View File

@ -242,19 +242,28 @@ bool TickSample::GetStackSample(Isolate* v8_isolate, RegisterState* regs,
timer = timer->parent();
}
if (i == frames_limit) break;
if (!it.frame()->is_interpreted()) {
frames[i++] = it.frame()->pc();
continue;
if (it.frame()->is_interpreted()) {
// For interpreted frames use the bytecode array pointer as the pc.
i::InterpretedFrame* frame =
static_cast<i::InterpretedFrame*>(it.frame());
// Since the sampler can interrupt execution at any point the
// bytecode_array might be garbage, so don't actually dereference it. We
// avoid the frame->GetXXX functions since they call BytecodeArray::cast,
// which has a heap access in its DCHECK.
i::Object* bytecode_array = i::Memory::Object_at(
frame->fp() + i::InterpreterFrameConstants::kBytecodeArrayFromFp);
i::Object* bytecode_offset = i::Memory::Object_at(
frame->fp() + i::InterpreterFrameConstants::kBytecodeOffsetFromFp);
// If the bytecode array is a heap object and the bytecode offset is a
// Smi, use those, otherwise fall back to using the frame's pc.
if (HAS_HEAP_OBJECT_TAG(bytecode_array) && HAS_SMI_TAG(bytecode_offset)) {
frames[i++] = reinterpret_cast<i::Address>(bytecode_array) +
i::Internals::SmiValue(bytecode_offset);
continue;
}
}
// For interpreted frames use the bytecode array pointer as the pc.
i::InterpretedFrame* frame = static_cast<i::InterpretedFrame*>(it.frame());
// Since the sampler can interrupt execution at any point the
// bytecode_array might be garbage, so don't dereference it.
i::Address bytecode_array =
reinterpret_cast<i::Address>(frame->GetBytecodeArray()) -
i::kHeapObjectTag;
frames[i++] = bytecode_array + i::BytecodeArray::kHeaderSize +
frame->GetBytecodeOffset();
frames[i++] = it.frame()->pc();
}
sample_info->frames_count = i;
return true;