Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(17)

Unified Diff: src/api.cc

Issue 2105943002: Expose TickSample and its APIs in v8-profiler.h (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/api.cc
diff --git a/src/api.cc b/src/api.cc
index 86135fd83d2ab6460a8e96665a651f8a1af42f05..69dd01f6d6bd992988a8c01175006cccad9bc093 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -36,6 +36,7 @@
#include "src/debug/debug.h"
#include "src/deoptimizer.h"
#include "src/execution.h"
+#include "src/frames-inl.h"
#include "src/gdb-jit.h"
#include "src/global-handles.h"
#include "src/icu_util.h"
@@ -50,7 +51,7 @@
#include "src/profiler/heap-profiler.h"
#include "src/profiler/heap-snapshot-generator-inl.h"
#include "src/profiler/profile-generator-inl.h"
-#include "src/profiler/tick-sample.h"
+#include "src/profiler/simulator-helper.h"
#include "src/property-descriptor.h"
#include "src/property-details.h"
#include "src/property.h"
@@ -7564,8 +7565,8 @@ bool Isolate::GetHeapCodeAndMetadataStatistics(
void Isolate::GetStackSample(const RegisterState& state, void** frames,
size_t frames_limit, SampleInfo* sample_info) {
- i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
#if defined(USE_SIMULATOR)
+ i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
RegisterState regs;
regs.pc = state.pc;
regs.sp = state.sp;
@@ -7579,8 +7580,8 @@ void Isolate::GetStackSample(const RegisterState& state, void** frames,
#else
const RegisterState& regs = state;
#endif
- i::TickSample::GetStackSample(isolate, regs, i::TickSample::kSkipCEntryFrame,
- frames, frames_limit, sample_info);
+ TickSample::GetStackSample(this, regs, TickSample::kSkipCEntryFrame, frames,
+ frames_limit, sample_info);
}
size_t Isolate::NumberOfPhantomHandleResetsSinceLastCall() {
@@ -8259,6 +8260,164 @@ MaybeLocal<Array> Debug::GetInternalProperties(Isolate* v8_isolate,
return Utils::ToLocal(result);
}
+namespace {
+
+bool IsSamePage(i::byte* ptr1, i::byte* ptr2) {
+ const uint32_t kPageSize = 4096;
+ uintptr_t mask = ~static_cast<uintptr_t>(kPageSize - 1);
+ return (reinterpret_cast<uintptr_t>(ptr1) & mask) ==
+ (reinterpret_cast<uintptr_t>(ptr2) & mask);
+}
+
+// Check if the code at specified address could potentially be a
+// frame setup code.
+bool IsNoFrameRegion(i::Address address) {
+ struct Pattern {
+ int bytes_count;
+ i::byte bytes[8];
+ int offsets[4];
+ };
+ i::byte* pc = reinterpret_cast<i::byte*>(address);
+ static Pattern patterns[] = {
+#if V8_HOST_ARCH_IA32
+ // push %ebp
+ // mov %esp,%ebp
+ {3, {0x55, 0x89, 0xe5}, {0, 1, -1}},
+ // pop %ebp
+ // ret N
+ {2, {0x5d, 0xc2}, {0, 1, -1}},
+ // pop %ebp
+ // ret
+ {2, {0x5d, 0xc3}, {0, 1, -1}},
+#elif V8_HOST_ARCH_X64
+ // pushq %rbp
+ // movq %rsp,%rbp
+ {4, {0x55, 0x48, 0x89, 0xe5}, {0, 1, -1}},
+ // popq %rbp
+ // ret N
+ {2, {0x5d, 0xc2}, {0, 1, -1}},
+ // popq %rbp
+ // ret
+ {2, {0x5d, 0xc3}, {0, 1, -1}},
+#endif
+ {0, {}, {}}
+ };
+ for (Pattern* pattern = patterns; pattern->bytes_count; ++pattern) {
+ for (int* offset_ptr = pattern->offsets; *offset_ptr != -1; ++offset_ptr) {
+ int offset = *offset_ptr;
+ if (!offset || IsSamePage(pc, pc - offset)) {
+ MSAN_MEMORY_IS_INITIALIZED(pc - offset, pattern->bytes_count);
+ if (!memcmp(pc - offset, pattern->bytes, pattern->bytes_count))
+ return true;
+ } else {
+ // It is not safe to examine bytes on another page as it might not be
+ // allocated thus causing a SEGFAULT.
+ // Check the pattern part that's on the same page and
+ // pessimistically assume it could be the entire pattern match.
+ MSAN_MEMORY_IS_INITIALIZED(pc, pattern->bytes_count - offset);
+ if (!memcmp(pc, pattern->bytes + offset, pattern->bytes_count - offset))
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+} // namespace
+
+//
+// StackTracer implementation
+//
+DISABLE_ASAN void TickSample::Init(Isolate* v8_isolate,
alph 2016/06/28 22:09:01 Don't move that much logic into api.cc Keep it in
lpy 2016/06/28 23:02:53 Done.
+ const RegisterState& regs,
+ RecordCEntryFrame record_c_entry_frame,
+ bool update_stats) {
+ this->update_stats = update_stats;
+
+ SampleInfo info;
+ if (GetStackSample(v8_isolate, const_cast<RegisterState&>(regs),
+ record_c_entry_frame, reinterpret_cast<void**>(&stack[0]),
+ kMaxFramesCount, &info)) {
+ state = info.vm_state;
+ pc = regs.pc;
+ frames_count = static_cast<unsigned>(info.frames_count);
+ has_external_callback = info.external_callback_entry != nullptr;
+ if (has_external_callback) {
+ external_callback_entry = info.external_callback_entry;
+ } else if (frames_count) {
+ // sp register may point at an arbitrary place in memory, make
+ // sure MSAN doesn't complain about it.
+ MSAN_MEMORY_IS_INITIALIZED(regs.sp, sizeof(void*));
+ // Sample potential return address value for frameless invocation of
+ // stubs (we'll figure out later, if this value makes sense).
+ tos = i::Memory::Address_at(reinterpret_cast<i::Address>(regs.sp));
+ } else {
+ tos = nullptr;
+ }
+ } else {
+ // It is executing JS but failed to collect a stack trace.
+ // Mark the sample as spoiled.
+ pc = nullptr;
+ }
+}
+
+bool TickSample::GetStackSample(Isolate* v8_isolate, const RegisterState& regs,
+ RecordCEntryFrame record_c_entry_frame,
+ void** frames, size_t frames_limit,
+ v8::SampleInfo* sample_info) {
+ i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
+ sample_info->frames_count = 0;
+ sample_info->vm_state = isolate->current_vm_state();
+ sample_info->external_callback_entry = nullptr;
+ if (sample_info->vm_state == GC) return true;
+
+ i::Address js_entry_sp = isolate->js_entry_sp();
+ if (js_entry_sp == nullptr) return true; // Not executing JS now.
+ DCHECK(regs.sp);
+
+ if (regs.pc && IsNoFrameRegion(static_cast<i::Address>(regs.pc))) {
+ // Can't collect stack.
+ return false;
+ }
+
+ i::ExternalCallbackScope* scope = isolate->external_callback_scope();
+ i::Address handler = i::Isolate::handler(isolate->thread_local_top());
+ // If there is a handler on top of the external callback scope then
+ // we have already entrered JavaScript again and the external callback
+ // is not the top function.
+ if (scope && scope->scope_address() < handler) {
+ sample_info->external_callback_entry =
+ *scope->callback_entrypoint_address();
+ }
+
+ i::SafeStackFrameIterator it(isolate, reinterpret_cast<i::Address>(regs.fp),
+ reinterpret_cast<i::Address>(regs.sp),
+ js_entry_sp);
+ size_t i = 0;
+ if (record_c_entry_frame == kIncludeCEntryFrame && !it.done() &&
+ it.top_frame_type() == i::StackFrame::EXIT) {
+ frames[i++] = isolate->c_function();
+ }
+ while (!it.done() && i < frames_limit) {
+ 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 dereference it.
+ i::Address bytecode_array =
+ reinterpret_cast<i::Address>(frame->GetBytecodeArray()) -
+ i::kHeapObjectTag;
+ frames[i++] = bytecode_array + i::BytecodeArray::kHeaderSize +
+ frame->GetBytecodeOffset();
+ } else {
+ frames[i++] = it.frame()->pc();
+ }
+ it.Advance();
+ }
+ sample_info->frames_count = i;
+ return true;
+}
Local<String> CpuProfileNode::GetFunctionName() const {
const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
« no previous file with comments | « include/v8-profiler.h ('k') | src/log.h » ('j') | src/profiler/simulator-helper.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698