summaryrefslogtreecommitdiff
path: root/deps/v8/src/log.cc
diff options
context:
space:
mode:
authorRyan Dahl <ry@tinyclouds.org>2010-12-07 13:56:11 -0800
committerRyan Dahl <ry@tinyclouds.org>2010-12-07 13:56:11 -0800
commitc30f1137121315b0d3641af6dc61e3b047f940e1 (patch)
treef118eaf670505e6a63f28bc8df845520f67adc55 /deps/v8/src/log.cc
parent5b8c62f7d12c1c5a553e765ba05bbd8a7e17ee47 (diff)
downloadnode-c30f1137121315b0d3641af6dc61e3b047f940e1.tar.gz
Upgrade V8 to 3.0.0
Diffstat (limited to 'deps/v8/src/log.cc')
-rw-r--r--deps/v8/src/log.cc145
1 files changed, 114 insertions, 31 deletions
diff --git a/deps/v8/src/log.cc b/deps/v8/src/log.cc
index 55f15debd..672334792 100644
--- a/deps/v8/src/log.cc
+++ b/deps/v8/src/log.cc
@@ -31,11 +31,14 @@
#include "bootstrapper.h"
#include "code-stubs.h"
+#include "deoptimizer.h"
#include "global-handles.h"
#include "log.h"
#include "macro-assembler.h"
+#include "runtime-profiler.h"
#include "serialize.h"
#include "string-stream.h"
+#include "vm-state-inl.h"
namespace v8 {
namespace internal {
@@ -147,6 +150,7 @@ void StackTracer::Trace(TickSample* sample) {
sample->function = NULL;
sample->frames_count = 0;
+ // Avoid collecting traces while doing GC.
if (sample->state == GC) return;
const Address js_entry_sp = Top::js_entry_sp(Top::GetCurrentThread());
@@ -155,15 +159,18 @@ void StackTracer::Trace(TickSample* sample) {
return;
}
- const Address functionAddr =
+ const Address function_address =
sample->fp + JavaScriptFrameConstants::kFunctionOffset;
if (SafeStackFrameIterator::IsWithinBounds(sample->sp, js_entry_sp,
- functionAddr)) {
- sample->function = Memory::Address_at(functionAddr) - kHeapObjectTag;
+ function_address)) {
+ Object* object = Memory::Object_at(function_address);
+ if (object->IsHeapObject()) {
+ sample->function = HeapObject::cast(object)->address();
+ }
}
int i = 0;
- const Address callback = VMState::external_callback();
+ const Address callback = Top::external_callback();
// Surprisingly, PC can point _exactly_ to callback start, with good
// probability, and this will result in reporting fake nested
// callback call.
@@ -174,9 +181,10 @@ void StackTracer::Trace(TickSample* sample) {
SafeStackTraceFrameIterator it(sample->fp, sample->sp,
sample->sp, js_entry_sp);
while (!it.done() && i < TickSample::kMaxFramesCount) {
- sample->stack[i++] =
- reinterpret_cast<Address>(it.frame()->function_slot_object()) -
- kHeapObjectTag;
+ Object* object = it.frame()->function_slot_object();
+ if (object->IsHeapObject()) {
+ sample->stack[i++] = HeapObject::cast(object)->address();
+ }
it.Advance();
}
sample->frames_count = i;
@@ -189,8 +197,10 @@ void StackTracer::Trace(TickSample* sample) {
//
class Ticker: public Sampler {
public:
- explicit Ticker(int interval):
- Sampler(interval, FLAG_prof), window_(NULL), profiler_(NULL) {}
+ explicit Ticker(int interval) :
+ Sampler(interval),
+ window_(NULL),
+ profiler_(NULL) {}
~Ticker() { if (IsActive()) Stop(); }
@@ -206,22 +216,24 @@ class Ticker: public Sampler {
void ClearWindow() {
window_ = NULL;
- if (!profiler_ && IsActive()) Stop();
+ if (!profiler_ && IsActive() && !RuntimeProfiler::IsEnabled()) Stop();
}
void SetProfiler(Profiler* profiler) {
+ ASSERT(profiler_ == NULL);
profiler_ = profiler;
+ IncreaseProfilingDepth();
if (!FLAG_prof_lazy && !IsActive()) Start();
}
void ClearProfiler() {
+ DecreaseProfilingDepth();
profiler_ = NULL;
- if (!window_ && IsActive()) Stop();
+ if (!window_ && IsActive() && !RuntimeProfiler::IsEnabled()) Stop();
}
protected:
virtual void DoSampleStack(TickSample* sample) {
- ASSERT(IsSynchronous());
StackTracer::Trace(sample);
}
@@ -759,6 +771,15 @@ void Logger::SetterCallbackEvent(String* name, Address entry_point) {
}
+static const char* ComputeMarker(Code* code) {
+ switch (code->kind()) {
+ case Code::FUNCTION: return code->optimizable() ? "~" : "";
+ case Code::OPTIMIZED_FUNCTION: return "*";
+ default: return "";
+ }
+}
+
+
void Logger::CodeCreateEvent(LogEventsAndTags tag,
Code* code,
const char* comment) {
@@ -767,7 +788,7 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag,
LogMessageBuilder msg;
msg.Append("%s,%s,", log_events_[CODE_CREATION_EVENT], log_events_[tag]);
msg.AppendAddress(code->address());
- msg.Append(",%d,\"", code->ExecutableSize());
+ msg.Append(",%d,\"%s", code->ExecutableSize(), ComputeMarker(code));
for (const char* p = comment; *p != '\0'; p++) {
if (*p == '"') {
msg.Append('\\');
@@ -794,7 +815,7 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag, Code* code, String* name) {
name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
msg.Append("%s,%s,", log_events_[CODE_CREATION_EVENT], log_events_[tag]);
msg.AppendAddress(code->address());
- msg.Append(",%d,\"%s\"", code->ExecutableSize(), *str);
+ msg.Append(",%d,\"%s%s\"", code->ExecutableSize(), ComputeMarker(code), *str);
LowLevelCodeCreateEvent(code, &msg);
if (FLAG_compress_log) {
ASSERT(compression_helper_ != NULL);
@@ -818,8 +839,12 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag,
source->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
msg.Append("%s,%s,", log_events_[CODE_CREATION_EVENT], log_events_[tag]);
msg.AppendAddress(code->address());
- msg.Append(",%d,\"%s %s:%d\"",
- code->ExecutableSize(), *str, *sourcestr, line);
+ msg.Append(",%d,\"%s%s %s:%d\"",
+ code->ExecutableSize(),
+ ComputeMarker(code),
+ *str,
+ *sourcestr,
+ line);
LowLevelCodeCreateEvent(code, &msg);
if (FLAG_compress_log) {
ASSERT(compression_helper_ != NULL);
@@ -1226,7 +1251,9 @@ void Logger::PauseProfiler(int flags, int tag) {
if (--cpu_profiler_nesting_ == 0) {
profiler_->pause();
if (FLAG_prof_lazy) {
- if (!FLAG_sliding_state_window) ticker_->Stop();
+ if (!FLAG_sliding_state_window && !RuntimeProfiler::IsEnabled()) {
+ ticker_->Stop();
+ }
FLAG_log_code = false;
// Must be the same message as Log::kDynamicBufferSeal.
LOG(UncheckedStringEvent("profiler", "pause"));
@@ -1262,7 +1289,9 @@ void Logger::ResumeProfiler(int flags, int tag) {
LogCompiledFunctions();
LogFunctionObjects();
LogAccessorCallbacks();
- if (!FLAG_sliding_state_window) ticker_->Start();
+ if (!FLAG_sliding_state_window && !ticker_->IsActive()) {
+ ticker_->Start();
+ }
}
profiler_->resume();
}
@@ -1295,9 +1324,41 @@ int Logger::GetLogLines(int from_pos, char* dest_buf, int max_size) {
}
-static int EnumerateCompiledFunctions(Handle<SharedFunctionInfo>* sfis) {
+class EnumerateOptimizedFunctionsVisitor: public OptimizedFunctionVisitor {
+ public:
+ EnumerateOptimizedFunctionsVisitor(Handle<SharedFunctionInfo>* sfis,
+ Handle<Code>* code_objects,
+ int* count)
+ : sfis_(sfis), code_objects_(code_objects), count_(count) { }
+
+ virtual void EnterContext(Context* context) {}
+ virtual void LeaveContext(Context* context) {}
+
+ virtual void VisitFunction(JSFunction* function) {
+ if (sfis_ != NULL) {
+ sfis_[*count_] = Handle<SharedFunctionInfo>(function->shared());
+ }
+ if (code_objects_ != NULL) {
+ ASSERT(function->code()->kind() == Code::OPTIMIZED_FUNCTION);
+ code_objects_[*count_] = Handle<Code>(function->code());
+ }
+ *count_ = *count_ + 1;
+ }
+
+ private:
+ Handle<SharedFunctionInfo>* sfis_;
+ Handle<Code>* code_objects_;
+ int* count_;
+};
+
+
+static int EnumerateCompiledFunctions(Handle<SharedFunctionInfo>* sfis,
+ Handle<Code>* code_objects) {
AssertNoAllocation no_alloc;
int compiled_funcs_count = 0;
+
+ // Iterate the heap to find shared function info objects and record
+ // the unoptimized code for them.
HeapIterator iterator;
for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
if (!obj->IsSharedFunctionInfo()) continue;
@@ -1305,11 +1366,22 @@ static int EnumerateCompiledFunctions(Handle<SharedFunctionInfo>* sfis) {
if (sfi->is_compiled()
&& (!sfi->script()->IsScript()
|| Script::cast(sfi->script())->HasValidSource())) {
- if (sfis != NULL)
+ if (sfis != NULL) {
sfis[compiled_funcs_count] = Handle<SharedFunctionInfo>(sfi);
+ }
+ if (code_objects != NULL) {
+ code_objects[compiled_funcs_count] = Handle<Code>(sfi->code());
+ }
++compiled_funcs_count;
}
}
+
+ // Iterate all optimized functions in all contexts.
+ EnumerateOptimizedFunctionsVisitor visitor(sfis,
+ code_objects,
+ &compiled_funcs_count);
+ Deoptimizer::VisitAllOptimizedFunctions(&visitor);
+
return compiled_funcs_count;
}
@@ -1321,9 +1393,11 @@ void Logger::LogCodeObject(Object* object) {
const char* description = "Unknown code from the snapshot";
switch (code_object->kind()) {
case Code::FUNCTION:
+ case Code::OPTIMIZED_FUNCTION:
return; // We log this later using LogCompiledFunctions.
- case Code::BINARY_OP_IC:
- // fall through
+ case Code::BINARY_OP_IC: // fall through
+ case Code::TYPE_RECORDING_BINARY_OP_IC: // fall through
+ case Code::COMPARE_IC: // fall through
case Code::STUB:
description =
CodeStub::MajorName(CodeStub::GetMajorKey(code_object), true);
@@ -1406,9 +1480,10 @@ void Logger::LogCodeObjects() {
void Logger::LogCompiledFunctions() {
HandleScope scope;
- const int compiled_funcs_count = EnumerateCompiledFunctions(NULL);
+ const int compiled_funcs_count = EnumerateCompiledFunctions(NULL, NULL);
ScopedVector< Handle<SharedFunctionInfo> > sfis(compiled_funcs_count);
- EnumerateCompiledFunctions(sfis.start());
+ ScopedVector< Handle<Code> > code_objects(compiled_funcs_count);
+ EnumerateCompiledFunctions(sfis.start(), code_objects.start());
// During iteration, there can be heap allocation due to
// GetScriptLineNumber call.
@@ -1425,18 +1500,18 @@ void Logger::LogCompiledFunctions() {
if (line_num > 0) {
PROFILE(CodeCreateEvent(
Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script),
- shared->code(), *func_name,
+ *code_objects[i], *func_name,
*script_name, line_num + 1));
} else {
// Can't distinguish eval and script here, so always use Script.
PROFILE(CodeCreateEvent(
Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
- shared->code(), *script_name));
+ *code_objects[i], *script_name));
}
} else {
PROFILE(CodeCreateEvent(
Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script),
- shared->code(), *func_name));
+ *code_objects[i], *func_name));
}
} else if (shared->IsApiFunction()) {
// API function.
@@ -1450,7 +1525,7 @@ void Logger::LogCompiledFunctions() {
}
} else {
PROFILE(CodeCreateEvent(
- Logger::LAZY_COMPILE_TAG, shared->code(), *func_name));
+ Logger::LAZY_COMPILE_TAG, *code_objects[i], *func_name));
}
}
}
@@ -1571,8 +1646,6 @@ bool Logger::Setup() {
}
}
- ASSERT(VMState::is_outermost_external());
-
if (FLAG_ll_prof) LogCodeInfo();
ticker_ = new Ticker(kSamplingIntervalMs);
@@ -1604,7 +1677,6 @@ bool Logger::Setup() {
}
LogMessageBuilder::set_write_failure_handler(StopLoggingAndProfiling);
-
return true;
#else
@@ -1613,6 +1685,17 @@ bool Logger::Setup() {
}
+void Logger::EnsureTickerStarted() {
+ ASSERT(ticker_ != NULL);
+ if (!ticker_->IsActive()) ticker_->Start();
+}
+
+
+void Logger::EnsureTickerStopped() {
+ if (ticker_ != NULL && ticker_->IsActive()) ticker_->Stop();
+}
+
+
void Logger::TearDown() {
#ifdef ENABLE_LOGGING_AND_PROFILING
LogMessageBuilder::set_write_failure_handler(NULL);