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
This commit is contained in:
mikhail.naganov@gmail.com 2010-10-20 08:32:24 +00:00
parent 08da2bd6fb
commit 5feede6667
6 changed files with 32 additions and 32 deletions

View File

@ -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);
}

View File

@ -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()) {

View File

@ -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

View File

@ -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);

View File

@ -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.

View File

@ -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));