CPU Profiler: postpone moved functions registration until GC completes.

An attempt to retrieve security context for a function may fail if the
destination heap space is in an incomplete state. To fix this, we only
record unknown functions discovered at GC object moves, and then
register them after GC completes.

BUG=crbug/59627

Review URL: http://codereview.chromium.org/3763012

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5667 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 08da2bd6
......@@ -188,6 +188,20 @@ bool ProfilerEventsProcessor::IsKnownFunction(Address start) {
}
void ProfilerEventsProcessor::ProcessMovedFunctions() {
for (int i = 0; i < moved_functions_.length(); ++i) {
JSFunction* function = moved_functions_[i];
CpuProfiler::FunctionCreateEvent(function);
}
moved_functions_.Clear();
}
void ProfilerEventsProcessor::RememberMovedFunction(JSFunction* function) {
moved_functions_.Add(function);
}
void ProfilerEventsProcessor::RegExpCodeCreateEvent(
Logger::LogEventsAndTags tag,
const char* prefix,
......@@ -426,8 +440,12 @@ void CpuProfiler::FunctionCreateEvent(JSFunction* function) {
}
void CpuProfiler::FunctionCreateEventFromMove(JSFunction* function,
HeapObject* source) {
void CpuProfiler::ProcessMovedFunctions() {
singleton_->processor_->ProcessMovedFunctions();
}
void CpuProfiler::FunctionCreateEventFromMove(JSFunction* function) {
// This function is called from GC iterators (during Scavenge,
// MC, and MS), so marking bits can be set on objects. That's
// why unchecked accessors are used here.
......@@ -436,27 +454,7 @@ void CpuProfiler::FunctionCreateEventFromMove(JSFunction* function,
if (function->unchecked_code() == Builtins::builtin(Builtins::LazyCompile)
|| singleton_->processor_->IsKnownFunction(function->address())) return;
int security_token_id = TokenEnumerator::kNoSecurityToken;
// In debug mode, assertions may fail for contexts,
// and we can live without security tokens in debug mode.
#ifndef DEBUG
if (function->unchecked_context()->IsContext()) {
security_token_id = singleton_->token_enumerator_->GetTokenId(
function->context()->global_context()->security_token());
}
// Security token may not be moved yet.
if (security_token_id == TokenEnumerator::kNoSecurityToken) {
JSFunction* old_function = reinterpret_cast<JSFunction*>(source);
if (old_function->unchecked_context()->IsContext()) {
security_token_id = singleton_->token_enumerator_->GetTokenId(
old_function->context()->global_context()->security_token());
}
}
#endif
singleton_->processor_->FunctionCreateEvent(
function->address(),
function->unchecked_code()->address(),
security_token_id);
singleton_->processor_->RememberMovedFunction(function);
}
......
......@@ -165,6 +165,8 @@ class ProfilerEventsProcessor : public Thread {
// Puts current stack into tick sample events buffer.
void AddCurrentStack();
bool IsKnownFunction(Address start);
void ProcessMovedFunctions();
void RememberMovedFunction(JSFunction* function);
// Tick sample events are filled directly in the buffer of the circular
// queue (because the structure is of fixed width, but usually not all
......@@ -202,6 +204,7 @@ class ProfilerEventsProcessor : public Thread {
// Used from the VM thread.
HashMap* known_functions_;
List<JSFunction*> moved_functions_;
};
} } // namespace v8::internal
......@@ -257,12 +260,12 @@ class CpuProfiler {
static void FunctionCreateEvent(JSFunction* function);
// Reports function creation in case we had missed it (e.g.
// if it was created from compiled code).
static void FunctionCreateEventFromMove(JSFunction* function,
HeapObject* source);
static void FunctionCreateEventFromMove(JSFunction* function);
static void FunctionMoveEvent(Address from, Address to);
static void FunctionDeleteEvent(Address from);
static void GetterCallbackEvent(String* name, Address entry_point);
static void RegExpCodeCreateEvent(Code* code, String* source);
static void ProcessMovedFunctions();
static void SetterCallbackEvent(String* name, Address entry_point);
static INLINE(bool is_profiling()) {
......
......@@ -469,6 +469,7 @@ void Heap::CollectGarbage(AllocationSpace space,
#ifdef ENABLE_LOGGING_AND_PROFILING
if (FLAG_log_gc) HeapProfiler::WriteSample();
if (CpuProfiler::is_profiling()) CpuProfiler::ProcessMovedFunctions();
#endif
}
......@@ -1260,7 +1261,7 @@ class ScavengingVisitor : public StaticVisitorBase {
if (Logger::is_logging() || CpuProfiler::is_profiling()) {
if (target->IsJSFunction()) {
PROFILE(FunctionMoveEvent(source->address(), target->address()));
PROFILE(FunctionCreateEventFromMove(JSFunction::cast(target), source));
PROFILE(FunctionCreateEventFromMove(JSFunction::cast(target)));
}
}
#endif
......
......@@ -926,8 +926,7 @@ void Logger::FunctionCreateEvent(JSFunction* function) {
}
void Logger::FunctionCreateEventFromMove(JSFunction* function,
HeapObject*) {
void Logger::FunctionCreateEventFromMove(JSFunction* function) {
#ifdef ENABLE_LOGGING_AND_PROFILING
if (function->unchecked_code() != Builtins::builtin(Builtins::LazyCompile)) {
FunctionCreateEvent(function);
......
......@@ -219,8 +219,7 @@ class Logger {
static void CodeDeleteEvent(Address from);
// Emits a function object create event.
static void FunctionCreateEvent(JSFunction* function);
static void FunctionCreateEventFromMove(JSFunction* function,
HeapObject*);
static void FunctionCreateEventFromMove(JSFunction* function);
// Emits a function move event.
static void FunctionMoveEvent(Address from, Address to);
// Emits a function delete event.
......
......@@ -2553,7 +2553,7 @@ int MarkCompactCollector::RelocateOldNonCodeObject(HeapObject* obj,
HeapObject* copied_to = HeapObject::FromAddress(new_addr);
if (copied_to->IsJSFunction()) {
PROFILE(FunctionMoveEvent(old_addr, new_addr));
PROFILE(FunctionCreateEventFromMove(JSFunction::cast(copied_to), obj));
PROFILE(FunctionCreateEventFromMove(JSFunction::cast(copied_to)));
}
HEAP_PROFILE(ObjectMoveEvent(old_addr, new_addr));
......@@ -2646,7 +2646,7 @@ int MarkCompactCollector::RelocateNewObject(HeapObject* obj) {
HeapObject* copied_to = HeapObject::FromAddress(new_addr);
if (copied_to->IsJSFunction()) {
PROFILE(FunctionMoveEvent(old_addr, new_addr));
PROFILE(FunctionCreateEventFromMove(JSFunction::cast(copied_to), obj));
PROFILE(FunctionCreateEventFromMove(JSFunction::cast(copied_to)));
}
HEAP_PROFILE(ObjectMoveEvent(old_addr, new_addr));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment