Upgrade V8 to 5.1.281.57 DO NOT MERGE
FPIIM-449
Change-Id: Id981b686b4d587ac31697662eb98bb34be42ad90
(cherry picked from commit 3b9bc31999c9787eb726ecdbfd5796bfdec32a18)
diff --git a/src/profiler/allocation-tracker.cc b/src/profiler/allocation-tracker.cc
index 942068e..791cdf0 100644
--- a/src/profiler/allocation-tracker.cc
+++ b/src/profiler/allocation-tracker.cc
@@ -149,7 +149,8 @@
void AddressToTraceMap::Print() {
- PrintF("[AddressToTraceMap (%" V8PRIuPTR "): \n", ranges_.size());
+ PrintF("[AddressToTraceMap (%" V8_SIZET_PREFIX V8PRIuPTR "): \n",
+ ranges_.size());
for (RangeMap::iterator it = ranges_.begin(); it != ranges_.end(); ++it) {
PrintF("[%p - %p] => %u\n", it->second.start, it->first,
it->second.trace_node_id);
@@ -226,7 +227,7 @@
// Mark the new block as FreeSpace to make sure the heap is iterable
// while we are capturing stack trace.
- heap->CreateFillerObjectAt(addr, size);
+ heap->CreateFillerObjectAt(addr, size, ClearRecordedSlots::kNo);
Isolate* isolate = heap->isolate();
int length = 0;
diff --git a/src/profiler/cpu-profiler.cc b/src/profiler/cpu-profiler.cc
index b6c7945..47585b7 100644
--- a/src/profiler/cpu-profiler.cc
+++ b/src/profiler/cpu-profiler.cc
@@ -211,10 +211,8 @@
processor_->Enqueue(evt_rec);
}
-
void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
- Code* code,
- const char* name) {
+ AbstractCode* code, const char* name) {
CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
rec->start = code->address();
@@ -222,14 +220,13 @@
tag, profiles_->GetFunctionName(name), CodeEntry::kEmptyNamePrefix,
CodeEntry::kEmptyResourceName, CpuProfileNode::kNoLineNumberInfo,
CpuProfileNode::kNoColumnNumberInfo, NULL, code->instruction_start());
+ RecordInliningInfo(rec->entry, code);
rec->size = code->ExecutableSize();
processor_->Enqueue(evt_rec);
}
-
void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
- Code* code,
- Name* name) {
+ AbstractCode* code, Name* name) {
CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
rec->start = code->address();
@@ -237,12 +234,13 @@
tag, profiles_->GetFunctionName(name), CodeEntry::kEmptyNamePrefix,
CodeEntry::kEmptyResourceName, CpuProfileNode::kNoLineNumberInfo,
CpuProfileNode::kNoColumnNumberInfo, NULL, code->instruction_start());
+ RecordInliningInfo(rec->entry, code);
rec->size = code->ExecutableSize();
processor_->Enqueue(evt_rec);
}
-
-void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag, Code* code,
+void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
+ AbstractCode* code,
SharedFunctionInfo* shared,
CompilationInfo* info, Name* script_name) {
CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
@@ -250,9 +248,11 @@
rec->start = code->address();
rec->entry = profiles_->NewCodeEntry(
tag, profiles_->GetFunctionName(shared->DebugName()),
- CodeEntry::kEmptyNamePrefix, profiles_->GetName(script_name),
+ CodeEntry::kEmptyNamePrefix,
+ profiles_->GetName(InferScriptName(script_name, shared)),
CpuProfileNode::kNoLineNumberInfo, CpuProfileNode::kNoColumnNumberInfo,
NULL, code->instruction_start());
+ RecordInliningInfo(rec->entry, code);
if (info) {
rec->entry->set_inlined_function_infos(info->inlined_function_infos());
}
@@ -261,46 +261,65 @@
processor_->Enqueue(evt_rec);
}
-
-void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag, Code* code,
+void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
+ AbstractCode* abstract_code,
SharedFunctionInfo* shared,
CompilationInfo* info, Name* script_name,
int line, int column) {
CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
- rec->start = code->address();
+ rec->start = abstract_code->address();
Script* script = Script::cast(shared->script());
JITLineInfoTable* line_table = NULL;
if (script) {
- line_table = new JITLineInfoTable();
- for (RelocIterator it(code); !it.done(); it.next()) {
- RelocInfo::Mode mode = it.rinfo()->rmode();
- if (RelocInfo::IsPosition(mode)) {
- int position = static_cast<int>(it.rinfo()->data());
- if (position >= 0) {
- int pc_offset = static_cast<int>(it.rinfo()->pc() - code->address());
- int line_number = script->GetLineNumber(position) + 1;
- line_table->SetPosition(pc_offset, line_number);
- }
+ if (abstract_code->IsCode()) {
+ Code* code = abstract_code->GetCode();
+ int start_position = shared->start_position();
+ int end_position = shared->end_position();
+ line_table = new JITLineInfoTable();
+ for (RelocIterator it(code); !it.done(); it.next()) {
+ RelocInfo* reloc_info = it.rinfo();
+ if (!RelocInfo::IsPosition(reloc_info->rmode())) continue;
+ int position = static_cast<int>(reloc_info->data());
+ // TODO(alph): in case of inlining the position may correspond
+ // to an inlined function source code. Do not collect positions
+ // that fall beyond the function source code. There's however a
+ // chance the inlined function has similar positions but in another
+ // script. So the proper fix is to store script_id in some form
+ // along with the inlined function positions.
+ if (position < start_position || position >= end_position) continue;
+ int pc_offset = static_cast<int>(reloc_info->pc() - code->address());
+ int line_number = script->GetLineNumber(position) + 1;
+ line_table->SetPosition(pc_offset, line_number);
+ }
+ } else {
+ BytecodeArray* bytecode = abstract_code->GetBytecodeArray();
+ line_table = new JITLineInfoTable();
+ interpreter::SourcePositionTableIterator it(
+ bytecode->source_position_table());
+ for (; !it.done(); it.Advance()) {
+ int line_number = script->GetLineNumber(it.source_position()) + 1;
+ int pc_offset = it.bytecode_offset() + BytecodeArray::kHeaderSize;
+ line_table->SetPosition(pc_offset, line_number);
}
}
}
rec->entry = profiles_->NewCodeEntry(
tag, profiles_->GetFunctionName(shared->DebugName()),
- CodeEntry::kEmptyNamePrefix, profiles_->GetName(script_name), line,
- column, line_table, code->instruction_start());
+ CodeEntry::kEmptyNamePrefix,
+ profiles_->GetName(InferScriptName(script_name, shared)), line, column,
+ line_table, abstract_code->instruction_start());
+ RecordInliningInfo(rec->entry, abstract_code);
if (info) {
rec->entry->set_inlined_function_infos(info->inlined_function_infos());
}
rec->entry->FillFunctionInfo(shared);
- rec->size = code->ExecutableSize();
+ rec->size = abstract_code->ExecutableSize();
processor_->Enqueue(evt_rec);
}
-
void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
- Code* code,
- int args_count) {
+ AbstractCode* code, int args_count) {
CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
rec->start = code->address();
@@ -308,21 +327,21 @@
tag, profiles_->GetName(args_count), "args_count: ",
CodeEntry::kEmptyResourceName, CpuProfileNode::kNoLineNumberInfo,
CpuProfileNode::kNoColumnNumberInfo, NULL, code->instruction_start());
+ RecordInliningInfo(rec->entry, code);
rec->size = code->ExecutableSize();
processor_->Enqueue(evt_rec);
}
-
-void CpuProfiler::CodeMoveEvent(Address from, Address to) {
+void CpuProfiler::CodeMoveEvent(AbstractCode* from, Address to) {
CodeEventsContainer evt_rec(CodeEventRecord::CODE_MOVE);
CodeMoveEventRecord* rec = &evt_rec.CodeMoveEventRecord_;
- rec->from = from;
+ rec->from = from->address();
rec->to = to;
processor_->Enqueue(evt_rec);
}
-
-void CpuProfiler::CodeDisableOptEvent(Code* code, SharedFunctionInfo* shared) {
+void CpuProfiler::CodeDisableOptEvent(AbstractCode* code,
+ SharedFunctionInfo* shared) {
CodeEventsContainer evt_rec(CodeEventRecord::CODE_DISABLE_OPT);
CodeDisableOptEventRecord* rec = &evt_rec.CodeDisableOptEventRecord_;
rec->start = code->address();
@@ -330,7 +349,6 @@
processor_->Enqueue(evt_rec);
}
-
void CpuProfiler::CodeDeoptEvent(Code* code, Address pc, int fp_to_sp_delta) {
CodeEventsContainer evt_rec(CodeEventRecord::CODE_DEOPT);
CodeDeoptEventRecord* rec = &evt_rec.CodeDeoptEventRecord_;
@@ -343,11 +361,6 @@
processor_->AddDeoptStack(isolate_, pc, fp_to_sp_delta);
}
-
-void CpuProfiler::CodeDeleteEvent(Address from) {
-}
-
-
void CpuProfiler::GetterCallbackEvent(Name* name, Address entry_point) {
CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
@@ -360,8 +373,7 @@
processor_->Enqueue(evt_rec);
}
-
-void CpuProfiler::RegExpCodeCreateEvent(Code* code, String* source) {
+void CpuProfiler::RegExpCodeCreateEvent(AbstractCode* code, String* source) {
CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
rec->start = code->address();
@@ -386,6 +398,60 @@
processor_->Enqueue(evt_rec);
}
+Name* CpuProfiler::InferScriptName(Name* name, SharedFunctionInfo* info) {
+ if (name->IsString() && String::cast(name)->length()) return name;
+ if (!info->script()->IsScript()) return name;
+ Object* source_url = Script::cast(info->script())->source_url();
+ return source_url->IsName() ? Name::cast(source_url) : name;
+}
+
+void CpuProfiler::RecordInliningInfo(CodeEntry* entry,
+ AbstractCode* abstract_code) {
+ if (!abstract_code->IsCode()) return;
+ Code* code = abstract_code->GetCode();
+ if (code->kind() != Code::OPTIMIZED_FUNCTION) return;
+ DeoptimizationInputData* deopt_input_data =
+ DeoptimizationInputData::cast(code->deoptimization_data());
+ int deopt_count = deopt_input_data->DeoptCount();
+ for (int i = 0; i < deopt_count; i++) {
+ int pc_offset = deopt_input_data->Pc(i)->value();
+ if (pc_offset == -1) continue;
+ int translation_index = deopt_input_data->TranslationIndex(i)->value();
+ TranslationIterator it(deopt_input_data->TranslationByteArray(),
+ translation_index);
+ Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
+ DCHECK_EQ(Translation::BEGIN, opcode);
+ it.Skip(Translation::NumberOfOperandsFor(opcode));
+ int depth = 0;
+ std::vector<CodeEntry*> inline_stack;
+ while (it.HasNext() &&
+ Translation::BEGIN !=
+ (opcode = static_cast<Translation::Opcode>(it.Next()))) {
+ if (opcode != Translation::JS_FRAME &&
+ opcode != Translation::INTERPRETED_FRAME) {
+ it.Skip(Translation::NumberOfOperandsFor(opcode));
+ continue;
+ }
+ it.Next(); // Skip ast_id
+ int shared_info_id = it.Next();
+ it.Next(); // Skip height
+ SharedFunctionInfo* shared_info = SharedFunctionInfo::cast(
+ deopt_input_data->LiteralArray()->get(shared_info_id));
+ if (!depth++) continue; // Skip the current function itself.
+ CodeEntry* inline_entry = new CodeEntry(
+ entry->tag(), profiles_->GetFunctionName(shared_info->DebugName()),
+ CodeEntry::kEmptyNamePrefix, entry->resource_name(),
+ CpuProfileNode::kNoLineNumberInfo,
+ CpuProfileNode::kNoColumnNumberInfo, NULL, code->instruction_start());
+ inline_entry->FillFunctionInfo(shared_info);
+ inline_stack.push_back(inline_entry);
+ }
+ if (!inline_stack.empty()) {
+ entry->AddInlineStack(pc_offset, inline_stack);
+ DCHECK(inline_stack.empty());
+ }
+ }
+}
CpuProfiler::CpuProfiler(Isolate* isolate)
: isolate_(isolate),
diff --git a/src/profiler/cpu-profiler.h b/src/profiler/cpu-profiler.h
index 1a1249c..a04ee3c 100644
--- a/src/profiler/cpu-profiler.h
+++ b/src/profiler/cpu-profiler.h
@@ -201,7 +201,7 @@
ProfileGenerator* test_generator,
ProfilerEventsProcessor* test_processor);
- virtual ~CpuProfiler();
+ ~CpuProfiler() override;
void set_sampling_interval(base::TimeDelta value);
void CollectSample();
@@ -220,29 +220,28 @@
// Must be called via PROFILE macro, otherwise will crash when
// profiling is not enabled.
- virtual void CallbackEvent(Name* name, Address entry_point);
- virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
- Code* code, const char* comment);
- virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
- Code* code, Name* name);
- virtual void CodeCreateEvent(Logger::LogEventsAndTags tag, Code* code,
- SharedFunctionInfo* shared,
- CompilationInfo* info, Name* script_name);
- virtual void CodeCreateEvent(Logger::LogEventsAndTags tag, Code* code,
- SharedFunctionInfo* shared,
- CompilationInfo* info, Name* script_name,
- int line, int column);
- virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
- Code* code, int args_count);
- virtual void CodeMovingGCEvent() {}
- virtual void CodeMoveEvent(Address from, Address to);
- virtual void CodeDisableOptEvent(Code* code, SharedFunctionInfo* shared);
- virtual void CodeDeoptEvent(Code* code, Address pc, int fp_to_sp_delta);
- virtual void CodeDeleteEvent(Address from);
- virtual void GetterCallbackEvent(Name* name, Address entry_point);
- virtual void RegExpCodeCreateEvent(Code* code, String* source);
- virtual void SetterCallbackEvent(Name* name, Address entry_point);
- virtual void SharedFunctionInfoMoveEvent(Address from, Address to) {}
+ void CallbackEvent(Name* name, Address entry_point) override;
+ void CodeCreateEvent(Logger::LogEventsAndTags tag, AbstractCode* code,
+ const char* comment) override;
+ void CodeCreateEvent(Logger::LogEventsAndTags tag, AbstractCode* code,
+ Name* name) override;
+ void CodeCreateEvent(Logger::LogEventsAndTags tag, AbstractCode* code,
+ SharedFunctionInfo* shared, CompilationInfo* info,
+ Name* script_name) override;
+ void CodeCreateEvent(Logger::LogEventsAndTags tag, AbstractCode* code,
+ SharedFunctionInfo* shared, CompilationInfo* info,
+ Name* script_name, int line, int column) override;
+ void CodeCreateEvent(Logger::LogEventsAndTags tag, AbstractCode* code,
+ int args_count) override;
+ void CodeMovingGCEvent() override {}
+ void CodeMoveEvent(AbstractCode* from, Address to) override;
+ void CodeDisableOptEvent(AbstractCode* code,
+ SharedFunctionInfo* shared) override;
+ void CodeDeoptEvent(Code* code, Address pc, int fp_to_sp_delta);
+ void GetterCallbackEvent(Name* name, Address entry_point) override;
+ void RegExpCodeCreateEvent(AbstractCode* code, String* source) override;
+ void SetterCallbackEvent(Name* name, Address entry_point) override;
+ void SharedFunctionInfoMoveEvent(Address from, Address to) override {}
INLINE(bool is_profiling() const) { return is_profiling_; }
bool* is_profiling_address() {
@@ -259,6 +258,8 @@
void StopProcessor();
void ResetProfiles();
void LogBuiltins();
+ void RecordInliningInfo(CodeEntry* entry, AbstractCode* abstract_code);
+ Name* InferScriptName(Name* name, SharedFunctionInfo* info);
Isolate* isolate_;
base::TimeDelta sampling_interval_;
diff --git a/src/profiler/heap-snapshot-generator.cc b/src/profiler/heap-snapshot-generator.cc
index fc43f9f..748f307 100644
--- a/src/profiler/heap-snapshot-generator.cc
+++ b/src/profiler/heap-snapshot-generator.cc
@@ -1383,9 +1383,9 @@
SetInternalReference(obj, entry,
"debug_info", shared->debug_info(),
SharedFunctionInfo::kDebugInfoOffset);
- SetInternalReference(obj, entry,
- "inferred_name", shared->inferred_name(),
- SharedFunctionInfo::kInferredNameOffset);
+ SetInternalReference(obj, entry, "function_identifier",
+ shared->function_identifier(),
+ SharedFunctionInfo::kFunctionIdentifierOffset);
SetInternalReference(obj, entry,
"optimized_code_map", shared->optimized_code_map(),
SharedFunctionInfo::kOptimizedCodeMapOffset);
diff --git a/src/profiler/profile-generator.cc b/src/profiler/profile-generator.cc
index 58d06c9..abcd9e5 100644
--- a/src/profiler/profile-generator.cc
+++ b/src/profiler/profile-generator.cc
@@ -50,6 +50,11 @@
CodeEntry::~CodeEntry() {
delete line_info_;
+ for (auto location : inline_locations_) {
+ for (auto entry : location.second) {
+ delete entry;
+ }
+ }
}
@@ -100,6 +105,18 @@
return v8::CpuProfileNode::kNoLineNumberInfo;
}
+void CodeEntry::AddInlineStack(int pc_offset,
+ std::vector<CodeEntry*>& inline_stack) {
+ // It's better to use std::move to place the vector into the map,
+ // but it's not supported by the current stdlibc++ on MacOS.
+ inline_locations_.insert(std::make_pair(pc_offset, std::vector<CodeEntry*>()))
+ .first->second.swap(inline_stack);
+}
+
+const std::vector<CodeEntry*>* CodeEntry::GetInlineStack(int pc_offset) const {
+ auto it = inline_locations_.find(pc_offset);
+ return it != inline_locations_.end() ? &it->second : NULL;
+}
void CodeEntry::FillFunctionInfo(SharedFunctionInfo* shared) {
if (!shared->script()->IsScript()) return;
@@ -109,7 +126,6 @@
set_bailout_reason(GetBailoutReason(shared->disable_optimization_reason()));
}
-
CpuProfileDeoptInfo CodeEntry::GetDeoptInfo() {
DCHECK(has_deopt_info());
@@ -274,17 +290,14 @@
return static_cast<unsigned>(reinterpret_cast<uintptr_t>(entry->value));
}
-ProfileNode* ProfileTree::AddPathFromEnd(const Vector<CodeEntry*>& path,
+ProfileNode* ProfileTree::AddPathFromEnd(const std::vector<CodeEntry*>& path,
int src_line, bool update_stats) {
ProfileNode* node = root_;
CodeEntry* last_entry = NULL;
- for (CodeEntry** entry = path.start() + path.length() - 1;
- entry != path.start() - 1;
- --entry) {
- if (*entry != NULL) {
- node = node->FindOrAddChild(*entry);
- last_entry = *entry;
- }
+ for (auto it = path.rbegin(); it != path.rend(); ++it) {
+ if (*it == NULL) continue;
+ last_entry = *it;
+ node = node->FindOrAddChild(*it);
}
if (last_entry && last_entry->has_deopt_info()) {
node->CollectDeoptInfo(last_entry);
@@ -356,7 +369,7 @@
top_down_(isolate) {}
void CpuProfile::AddPath(base::TimeTicks timestamp,
- const Vector<CodeEntry*>& path, int src_line,
+ const std::vector<CodeEntry*>& path, int src_line,
bool update_stats) {
ProfileNode* top_frame_node =
top_down_.AddPathFromEnd(path, src_line, update_stats);
@@ -525,8 +538,8 @@
}
void CpuProfilesCollection::AddPathToCurrentProfiles(
- base::TimeTicks timestamp, const Vector<CodeEntry*>& path, int src_line,
- bool update_stats) {
+ base::TimeTicks timestamp, const std::vector<CodeEntry*>& path,
+ int src_line, bool update_stats) {
// As starting / stopping profiles is rare relatively to this
// method, we don't bother minimizing the duration of lock holding,
// e.g. copying contents of the list to a local vector.
@@ -576,12 +589,10 @@
void ProfileGenerator::RecordTickSample(const TickSample& sample) {
- // Allocate space for stack frames + pc + function + vm-state.
- ScopedVector<CodeEntry*> entries(sample.frames_count + 3);
- // As actual number of decoded code entries may vary, initialize
- // entries vector with NULL values.
- CodeEntry** entry = entries.start();
- memset(entry, 0, entries.length() * sizeof(*entry));
+ std::vector<CodeEntry*> entries;
+ // Conservatively reserve space for stack frames + pc + function + vm-state.
+ // There could in fact be more of them because of inlined entries.
+ entries.reserve(sample.frames_count + 3);
// The ProfileNode knows nothing about all versions of generated code for
// the same JS function. The line number information associated with
@@ -597,13 +608,14 @@
// Don't use PC when in external callback code, as it can point
// inside callback's code, and we will erroneously report
// that a callback calls itself.
- *entry++ = code_map_.FindEntry(sample.external_callback_entry);
+ entries.push_back(code_map_.FindEntry(sample.external_callback_entry));
} else {
CodeEntry* pc_entry = code_map_.FindEntry(sample.pc);
// If there is no pc_entry we're likely in native code.
// Find out, if top of stack was pointing inside a JS function
// meaning that we have encountered a frameless invocation.
if (!pc_entry && (sample.top_frame_type == StackFrame::JAVA_SCRIPT ||
+ sample.top_frame_type == StackFrame::INTERPRETED ||
sample.top_frame_type == StackFrame::OPTIMIZED)) {
pc_entry = code_map_.FindEntry(sample.tos);
}
@@ -619,7 +631,7 @@
src_line = pc_entry->line_number();
}
src_line_not_found = false;
- *entry++ = pc_entry;
+ entries.push_back(pc_entry);
if (pc_entry->builtin_id() == Builtins::kFunctionPrototypeApply ||
pc_entry->builtin_id() == Builtins::kFunctionPrototypeCall) {
@@ -630,7 +642,7 @@
// former case we don't so we simply replace the frame with
// 'unresolved' entry.
if (sample.top_frame_type == StackFrame::JAVA_SCRIPT) {
- *entry++ = unresolved_entry_;
+ entries.push_back(unresolved_entry_);
}
}
}
@@ -639,35 +651,43 @@
for (const Address *stack_pos = sample.stack,
*stack_end = stack_pos + sample.frames_count;
stack_pos != stack_end; ++stack_pos) {
- *entry = code_map_.FindEntry(*stack_pos);
+ CodeEntry* entry = code_map_.FindEntry(*stack_pos);
- // Skip unresolved frames (e.g. internal frame) and get source line of
- // the first JS caller.
- if (src_line_not_found && *entry) {
+ if (entry) {
+ // Find out if the entry has an inlining stack associated.
int pc_offset =
- static_cast<int>(*stack_pos - (*entry)->instruction_start());
- src_line = (*entry)->GetSourceLine(pc_offset);
- if (src_line == v8::CpuProfileNode::kNoLineNumberInfo) {
- src_line = (*entry)->line_number();
+ static_cast<int>(*stack_pos - entry->instruction_start());
+ const std::vector<CodeEntry*>* inline_stack =
+ entry->GetInlineStack(pc_offset);
+ if (inline_stack) {
+ entries.insert(entries.end(), inline_stack->rbegin(),
+ inline_stack->rend());
}
- src_line_not_found = false;
+ // Skip unresolved frames (e.g. internal frame) and get source line of
+ // the first JS caller.
+ if (src_line_not_found) {
+ src_line = entry->GetSourceLine(pc_offset);
+ if (src_line == v8::CpuProfileNode::kNoLineNumberInfo) {
+ src_line = entry->line_number();
+ }
+ src_line_not_found = false;
+ }
}
-
- entry++;
+ entries.push_back(entry);
}
}
if (FLAG_prof_browser_mode) {
bool no_symbolized_entries = true;
- for (CodeEntry** e = entries.start(); e != entry; ++e) {
- if (*e != NULL) {
+ for (auto e : entries) {
+ if (e != NULL) {
no_symbolized_entries = false;
break;
}
}
// If no frames were symbolized, put the VM state entry in.
if (no_symbolized_entries) {
- *entry++ = EntryForVMState(sample.state);
+ entries.push_back(EntryForVMState(sample.state));
}
}
diff --git a/src/profiler/profile-generator.h b/src/profiler/profile-generator.h
index 3c976d6..194b490 100644
--- a/src/profiler/profile-generator.h
+++ b/src/profiler/profile-generator.h
@@ -99,7 +99,11 @@
int GetSourceLine(int pc_offset) const;
+ void AddInlineStack(int pc_offset, std::vector<CodeEntry*>& inline_stack);
+ const std::vector<CodeEntry*>* GetInlineStack(int pc_offset) const;
+
Address instruction_start() const { return instruction_start_; }
+ Logger::LogEventsAndTags tag() const { return TagField::decode(bit_field_); }
static const char* const kEmptyNamePrefix;
static const char* const kEmptyResourceName;
@@ -109,7 +113,6 @@
private:
class TagField : public BitField<Logger::LogEventsAndTags, 0, 8> {};
class BuiltinIdField : public BitField<Builtins::Name, 8, 8> {};
- Logger::LogEventsAndTags tag() const { return TagField::decode(bit_field_); }
uint32_t bit_field_;
const char* name_prefix_;
@@ -125,6 +128,8 @@
size_t pc_offset_;
JITLineInfoTable* line_info_;
Address instruction_start_;
+ // Should be an unordered_map, but it doesn't currently work on Win & MacOS.
+ std::map<int, std::vector<CodeEntry*>> inline_locations_;
std::vector<InlinedFunctionInfo> inlined_function_infos_;
@@ -191,7 +196,7 @@
~ProfileTree();
ProfileNode* AddPathFromEnd(
- const Vector<CodeEntry*>& path,
+ const std::vector<CodeEntry*>& path,
int src_line = v8::CpuProfileNode::kNoLineNumberInfo,
bool update_stats = true);
ProfileNode* root() const { return root_; }
@@ -225,7 +230,7 @@
CpuProfile(Isolate* isolate, const char* title, bool record_samples);
// Add pc -> ... -> main() call path to the profile.
- void AddPath(base::TimeTicks timestamp, const Vector<CodeEntry*>& path,
+ void AddPath(base::TimeTicks timestamp, const std::vector<CodeEntry*>& path,
int src_line, bool update_stats);
void CalculateTotalTicksAndSamplingRate();
@@ -334,8 +339,8 @@
// Called from profile generator thread.
void AddPathToCurrentProfiles(base::TimeTicks timestamp,
- const Vector<CodeEntry*>& path, int src_line,
- bool update_stats);
+ const std::vector<CodeEntry*>& path,
+ int src_line, bool update_stats);
// Limits the number of profiles that can be simultaneously collected.
static const int kMaxSimultaneousProfiles = 100;
diff --git a/src/profiler/sampler.cc b/src/profiler/sampler.cc
index e331db9..a340424 100644
--- a/src/profiler/sampler.cc
+++ b/src/profiler/sampler.cc
@@ -336,6 +336,14 @@
reinterpret_cast<Address>(simulator_->get_register(Simulator::sp));
state->fp =
reinterpret_cast<Address>(simulator_->get_register(Simulator::fp));
+#elif V8_TARGET_ARCH_S390
+ if (!simulator_->has_bad_pc()) {
+ state->pc = reinterpret_cast<Address>(simulator_->get_pc());
+ }
+ state->sp =
+ reinterpret_cast<Address>(simulator_->get_register(Simulator::sp));
+ state->fp =
+ reinterpret_cast<Address>(simulator_->get_register(Simulator::fp));
#endif
}
@@ -441,7 +449,7 @@
#else
// Extracting the sample from the context is extremely machine dependent.
ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
-#if !(V8_OS_OPENBSD || (V8_OS_LINUX && V8_HOST_ARCH_PPC))
+#if !(V8_OS_OPENBSD || (V8_OS_LINUX && (V8_HOST_ARCH_PPC || V8_HOST_ARCH_S390)))
mcontext_t& mcontext = ucontext->uc_mcontext;
#endif
#if V8_OS_LINUX
@@ -482,6 +490,17 @@
state.pc = reinterpret_cast<Address>(ucontext->uc_mcontext.regs->nip);
state.sp = reinterpret_cast<Address>(ucontext->uc_mcontext.regs->gpr[PT_R1]);
state.fp = reinterpret_cast<Address>(ucontext->uc_mcontext.regs->gpr[PT_R31]);
+#elif V8_HOST_ARCH_S390
+#if V8_TARGET_ARCH_32_BIT
+ // 31-bit target will have bit 0 (MSB) of the PSW set to denote addressing
+ // mode. This bit needs to be masked out to resolve actual address.
+ state.pc =
+ reinterpret_cast<Address>(ucontext->uc_mcontext.psw.addr & 0x7FFFFFFF);
+#else
+ state.pc = reinterpret_cast<Address>(ucontext->uc_mcontext.psw.addr);
+#endif // V8_TARGET_ARCH_32_BIT
+ state.sp = reinterpret_cast<Address>(ucontext->uc_mcontext.gregs[15]);
+ state.fp = reinterpret_cast<Address>(ucontext->uc_mcontext.gregs[11]);
#endif // V8_HOST_ARCH_*
#elif V8_OS_MACOSX
#if V8_HOST_ARCH_X64
@@ -731,7 +750,18 @@
frames[i++] = isolate->c_function();
}
while (!it.done() && i < frames_limit) {
- frames[i++] = it.frame()->pc();
+ if (it.frame()->is_interpreted()) {
+ // For interpreted frames use the bytecode array pointer as the pc.
+ InterpretedFrame* frame = static_cast<InterpretedFrame*>(it.frame());
+ // Since the sampler can interrupt execution at any point the
+ // bytecode_array might be garbage, so don't dereference it.
+ Address bytecode_array =
+ reinterpret_cast<Address>(frame->GetBytecodeArray()) - kHeapObjectTag;
+ frames[i++] = bytecode_array + BytecodeArray::kHeaderSize +
+ frame->GetBytecodeOffset();
+ } else {
+ frames[i++] = it.frame()->pc();
+ }
it.Advance();
}
sample_info->frames_count = i;
diff --git a/src/profiler/sampler.h b/src/profiler/sampler.h
index 8e8ef1c..dcd1255 100644
--- a/src/profiler/sampler.h
+++ b/src/profiler/sampler.h
@@ -58,7 +58,7 @@
unsigned frames_count : kMaxFramesCountLog2; // Number of captured frames.
bool has_external_callback : 1;
bool update_stats : 1; // Whether the sample should update aggregated stats.
- StackFrame::Type top_frame_type : 4;
+ StackFrame::Type top_frame_type : 5;
};
class Sampler {
diff --git a/src/profiler/sampling-heap-profiler.cc b/src/profiler/sampling-heap-profiler.cc
index c13538c..a32cae3 100644
--- a/src/profiler/sampling-heap-profiler.cc
+++ b/src/profiler/sampling-heap-profiler.cc
@@ -99,7 +99,8 @@
// Mark the new block as FreeSpace to make sure the heap is iterable while we
// are taking the sample.
- heap()->CreateFillerObjectAt(soon_object, static_cast<int>(size));
+ heap()->CreateFillerObjectAt(soon_object, static_cast<int>(size),
+ ClearRecordedSlots::kNo);
Local<v8::Value> loc = v8::Utils::ToLocal(obj);
@@ -199,19 +200,22 @@
int column = v8::AllocationProfile::kNoColumnNumberInfo;
std::vector<v8::AllocationProfile::Allocation> allocations;
allocations.reserve(node->allocations_.size());
- if (node->script_id_ != v8::UnboundScript::kNoScriptId) {
+ if (node->script_id_ != v8::UnboundScript::kNoScriptId &&
+ scripts.find(node->script_id_) != scripts.end()) {
// Cannot use std::map<T>::at because it is not available on android.
auto non_const_scripts = const_cast<std::map<int, Script*>&>(scripts);
Script* script = non_const_scripts[node->script_id_];
- if (script->name()->IsName()) {
- Name* name = Name::cast(script->name());
- script_name = ToApiHandle<v8::String>(
- isolate_->factory()->InternalizeUtf8String(names_->GetName(name)));
+ if (script) {
+ if (script->name()->IsName()) {
+ Name* name = Name::cast(script->name());
+ script_name = ToApiHandle<v8::String>(
+ isolate_->factory()->InternalizeUtf8String(names_->GetName(name)));
+ }
+ Handle<Script> script_handle(script);
+ line = 1 + Script::GetLineNumber(script_handle, node->script_position_);
+ column =
+ 1 + Script::GetColumnNumber(script_handle, node->script_position_);
}
- Handle<Script> script_handle(script);
-
- line = 1 + Script::GetLineNumber(script_handle, node->script_position_);
- column = 1 + Script::GetColumnNumber(script_handle, node->script_position_);
for (auto alloc : node->allocations_) {
allocations.push_back(ScaleSample(alloc.first, alloc.second));
}