| Index: runtime/vm/profiler_service.cc
|
| diff --git a/runtime/vm/profiler_service.cc b/runtime/vm/profiler_service.cc
|
| index d59108ba3d42efafbd79e80c9c0d15c7abaa3d7f..40b7bdc249a9739c82fe1ff4cfcd2369be4aa534 100644
|
| --- a/runtime/vm/profiler_service.cc
|
| +++ b/runtime/vm/profiler_service.cc
|
| @@ -1075,6 +1075,27 @@ class ProfileBuilder : public ValueObject {
|
|
|
| void BuildCodeTable() {
|
| ScopeTimer sw("ProfileBuilder::BuildCodeTable", FLAG_trace_profiler);
|
| +
|
| + Isolate* isolate = thread_->isolate();
|
| + ASSERT(isolate != NULL);
|
| +
|
| + // Build the live code table eagerly by populating it with code objects
|
| + // from the processed sample buffer.
|
| + const CodeLookupTable& code_lookup_table = samples_->code_lookup_table();
|
| + for (intptr_t i = 0; i < code_lookup_table.length(); i++) {
|
| + const CodeDescriptor* descriptor = code_lookup_table.At(i);
|
| + ASSERT(descriptor != NULL);
|
| + const Code& code = Code::Handle(descriptor->code());
|
| + ASSERT(!code.IsNull());
|
| + RegisterLiveProfileCode(
|
| + new ProfileCode(ProfileCode::kDartCode,
|
| + code.EntryPoint(),
|
| + code.EntryPoint() + code.Size(),
|
| + code.compile_timestamp(),
|
| + code));
|
| + }
|
| +
|
| + // Iterate over samples.
|
| for (intptr_t sample_index = 0;
|
| sample_index < samples_->length();
|
| sample_index++) {
|
| @@ -1102,7 +1123,7 @@ class ProfileBuilder : public ValueObject {
|
| frame_index++) {
|
| const uword pc = sample->At(frame_index);
|
| ASSERT(pc != 0);
|
| - ProfileCode* code = RegisterProfileCode(pc, timestamp);
|
| + ProfileCode* code = FindOrRegisterProfileCode(pc, timestamp);
|
| ASSERT(code != NULL);
|
| code->Tick(pc, IsExecutingFrame(sample, frame_index), sample_index);
|
| }
|
| @@ -1837,67 +1858,30 @@ class ProfileBuilder : public ValueObject {
|
| return code;
|
| }
|
|
|
| - ProfileCode* CreateProfileCode(uword pc) {
|
| - const intptr_t kDartCodeAlignment = OS::PreferredCodeAlignment();
|
| - const intptr_t kDartCodeAlignmentMask = ~(kDartCodeAlignment - 1);
|
| - Code& code = Code::Handle(thread_->zone());
|
| + bool IsPCInDartHeap(uword pc) {
|
| + return vm_isolate_->heap()->CodeContains(pc) ||
|
| + thread_->isolate()->heap()->CodeContains(pc);
|
| + }
|
|
|
| - // Check current isolate for pc.
|
| - if (thread_->isolate()->heap()->CodeContains(pc)) {
|
| - code ^= Code::LookupCode(pc);
|
| - if (!code.IsNull()) {
|
| - deoptimized_code_->Add(code);
|
| - return new ProfileCode(ProfileCode::kDartCode,
|
| - code.EntryPoint(),
|
| - code.EntryPoint() + code.Size(),
|
| - code.compile_timestamp(),
|
| - code);
|
| - }
|
| - return new ProfileCode(ProfileCode::kCollectedCode,
|
| - pc,
|
| - (pc & kDartCodeAlignmentMask) + kDartCodeAlignment,
|
| - 0,
|
| - code);
|
| - }
|
| -
|
| - // Check VM isolate for pc.
|
| - if (vm_isolate_->heap()->CodeContains(pc)) {
|
| - code ^= Code::LookupCodeInVmIsolate(pc);
|
| - if (!code.IsNull()) {
|
| - return new ProfileCode(ProfileCode::kDartCode,
|
| - code.EntryPoint(),
|
| - code.EntryPoint() + code.Size(),
|
| - code.compile_timestamp(),
|
| - code);
|
| - }
|
| - // Precompiled instructions are in the VM isolate, but the code (except
|
| - // stubs) is in the current isolate.
|
| - code ^= Code::LookupCode(pc);
|
| - if (!code.IsNull()) {
|
| - return new ProfileCode(ProfileCode::kDartCode,
|
| - code.EntryPoint(),
|
| - code.EntryPoint() + code.Size(),
|
| - code.compile_timestamp(),
|
| - code);
|
| - }
|
| - return new ProfileCode(ProfileCode::kCollectedCode,
|
| - pc,
|
| - (pc & kDartCodeAlignmentMask) + kDartCodeAlignment,
|
| - 0,
|
| - code);
|
| +
|
| + ProfileCode* FindOrRegisterNativeProfileCode(uword pc) {
|
| + // Check if |pc| is already known in the live code table.
|
| + ProfileCodeTable* live_table = profile_->live_code_;
|
| + ProfileCode* profile_code = live_table->FindCodeForPC(pc);
|
| + if (profile_code != NULL) {
|
| + return profile_code;
|
| }
|
|
|
| + // We haven't seen this pc yet.
|
| + Code& code = Code::Handle(thread_->zone());
|
| +
|
| // Check NativeSymbolResolver for pc.
|
| uintptr_t native_start = 0;
|
| char* native_name = NativeSymbolResolver::LookupSymbolName(pc,
|
| &native_start);
|
| if (native_name == NULL) {
|
| - // No native name found.
|
| - return new ProfileCode(ProfileCode::kNativeCode,
|
| - pc,
|
| - pc + 1,
|
| - 0,
|
| - code);
|
| + // Failed to find a native symbol for pc.
|
| + native_start = pc;
|
| }
|
|
|
| #if defined(HOST_ARCH_ARM)
|
| @@ -1907,54 +1891,55 @@ class ProfileBuilder : public ValueObject {
|
| #endif
|
|
|
| ASSERT(pc >= native_start);
|
| - ProfileCode* profile_code =
|
| - new ProfileCode(ProfileCode::kNativeCode,
|
| - native_start,
|
| - pc + 1,
|
| - 0,
|
| - code);
|
| - profile_code->SetName(native_name);
|
| - NativeSymbolResolver::FreeSymbolName(native_name);
|
| + profile_code = new ProfileCode(ProfileCode::kNativeCode,
|
| + native_start,
|
| + pc + 1,
|
| + 0,
|
| + code);
|
| + if (native_name != NULL) {
|
| + profile_code->SetName(native_name);
|
| + NativeSymbolResolver::FreeSymbolName(native_name);
|
| + }
|
| +
|
| + RegisterLiveProfileCode(profile_code);
|
| return profile_code;
|
| }
|
|
|
| - ProfileCode* RegisterProfileCode(uword pc, int64_t timestamp) {
|
| + void RegisterLiveProfileCode(ProfileCode* code) {
|
| ProfileCodeTable* live_table = profile_->live_code_;
|
| + intptr_t index = live_table->InsertCode(code);
|
| + ASSERT(index >= 0);
|
| + }
|
| +
|
| + ProfileCode* FindOrRegisterDeadProfileCode(uword pc) {
|
| ProfileCodeTable* dead_table = profile_->dead_code_;
|
|
|
| - ProfileCode* code = live_table->FindCodeForPC(pc);
|
| - if (code == NULL) {
|
| - // Code not found.
|
| - intptr_t index = live_table->InsertCode(CreateProfileCode(pc));
|
| - ASSERT(index >= 0);
|
| - code = live_table->At(index);
|
| - if (code->compile_timestamp() <= timestamp) {
|
| - // Code was compiled before sample was taken.
|
| - return code;
|
| - }
|
| - // Code was compiled after the sample was taken. Insert code object into
|
| - // the dead code table.
|
| - index = dead_table->InsertCode(CreateProfileCodeReused(pc));
|
| - ASSERT(index >= 0);
|
| - return dead_table->At(index);
|
| - }
|
| - // Existing code found.
|
| - if (code->compile_timestamp() <= timestamp) {
|
| - // Code was compiled before sample was taken.
|
| - return code;
|
| - }
|
| - // Code was compiled after the sample was taken. Check if we have an entry
|
| - // in the dead code table.
|
| - code = dead_table->FindCodeForPC(pc);
|
| + ProfileCode* code = dead_table->FindCodeForPC(pc);
|
| if (code != NULL) {
|
| return code;
|
| }
|
| +
|
| // Create a new dead code entry.
|
| intptr_t index = dead_table->InsertCode(CreateProfileCodeReused(pc));
|
| ASSERT(index >= 0);
|
| return dead_table->At(index);
|
| }
|
|
|
| + ProfileCode* FindOrRegisterProfileCode(uword pc, int64_t timestamp) {
|
| + ProfileCodeTable* live_table = profile_->live_code_;
|
| + ProfileCode* code = live_table->FindCodeForPC(pc);
|
| + if ((code != NULL) && (code->compile_timestamp() <= timestamp)) {
|
| + // Code was compiled before sample was taken.
|
| + return code;
|
| + }
|
| + if ((code == NULL) && !IsPCInDartHeap(pc)) {
|
| + // Not a PC from Dart code. Check with native code.
|
| + return FindOrRegisterNativeProfileCode(pc);
|
| + }
|
| + // We either didn't find the code or it was compiled after the sample.
|
| + return FindOrRegisterDeadProfileCode(pc);
|
| + }
|
| +
|
| Profile::TagOrder tag_order() const {
|
| return tag_order_;
|
| }
|
|
|