blob: dde8512090ccabea85bbe7d5195077ac581605a0 [file] [log] [blame]
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001// Copyright 2006-2009 the V8 project authors. All rights reserved.
2//
3// Tests of profiler-related functions from log.h
4
5#ifdef ENABLE_LOGGING_AND_PROFILING
6
7#include <stdlib.h>
8
9#include "v8.h"
10
11#include "log.h"
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000012#include "top.h"
kasperl@chromium.org061ef742009-02-27 12:16:20 +000013#include "cctest.h"
14
15using v8::Function;
16using v8::Local;
17using v8::Object;
18using v8::Script;
19using v8::String;
20using v8::Value;
21
22using v8::internal::byte;
23using v8::internal::Handle;
24using v8::internal::JSFunction;
25using v8::internal::StackTracer;
26using v8::internal::TickSample;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000027using v8::internal::Top;
kasperl@chromium.org061ef742009-02-27 12:16:20 +000028
29
30static v8::Persistent<v8::Context> env;
31
32
33static struct {
34 StackTracer* tracer;
35 TickSample* sample;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000036} trace_env = { NULL, NULL };
kasperl@chromium.org061ef742009-02-27 12:16:20 +000037
38
39static void InitTraceEnv(StackTracer* tracer, TickSample* sample) {
40 trace_env.tracer = tracer;
41 trace_env.sample = sample;
42}
43
44
45static void DoTrace(unsigned int fp) {
46 trace_env.sample->fp = fp;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000047 // sp is only used to define stack high bound
48 trace_env.sample->sp =
49 reinterpret_cast<unsigned int>(trace_env.sample) - 10240;
kasperl@chromium.org061ef742009-02-27 12:16:20 +000050 trace_env.tracer->Trace(trace_env.sample);
51}
52
53
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000054// Hide c_entry_fp to emulate situation when sampling is done while
55// pure JS code is being executed
56static void DoTraceHideCEntryFPAddress(unsigned int fp) {
57 v8::internal::Address saved_c_frame_fp = *(Top::c_entry_fp_address());
58 CHECK(saved_c_frame_fp);
59 *(Top::c_entry_fp_address()) = 0;
kasperl@chromium.org061ef742009-02-27 12:16:20 +000060 DoTrace(fp);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000061 *(Top::c_entry_fp_address()) = saved_c_frame_fp;
kasperl@chromium.org061ef742009-02-27 12:16:20 +000062}
63
64
kasperl@chromium.org061ef742009-02-27 12:16:20 +000065// --- T r a c e E x t e n s i o n ---
66
67class TraceExtension : public v8::Extension {
68 public:
69 TraceExtension() : v8::Extension("v8/trace", kSource) { }
70 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000071 v8::Handle<String> name);
kasperl@chromium.org061ef742009-02-27 12:16:20 +000072 static v8::Handle<v8::Value> Trace(const v8::Arguments& args);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000073 static v8::Handle<v8::Value> JSTrace(const v8::Arguments& args);
kasperl@chromium.org061ef742009-02-27 12:16:20 +000074 private:
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000075 static unsigned int GetFP(const v8::Arguments& args);
kasperl@chromium.org061ef742009-02-27 12:16:20 +000076 static const char* kSource;
77};
78
79
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000080const char* TraceExtension::kSource =
81 "native function trace();"
82 "native function js_trace();";
kasperl@chromium.org061ef742009-02-27 12:16:20 +000083
84
85v8::Handle<v8::FunctionTemplate> TraceExtension::GetNativeFunction(
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000086 v8::Handle<String> name) {
87 if (name->Equals(String::New("trace"))) {
88 return v8::FunctionTemplate::New(TraceExtension::Trace);
89 } else if (name->Equals(String::New("js_trace"))) {
90 return v8::FunctionTemplate::New(TraceExtension::JSTrace);
91 } else {
92 CHECK(false);
93 return v8::Handle<v8::FunctionTemplate>();
94 }
95}
96
97
98unsigned int TraceExtension::GetFP(const v8::Arguments& args) {
99 CHECK_EQ(1, args.Length());
100 unsigned int fp = args[0]->Int32Value() << 2;
101 printf("Trace: %08x\n", fp);
102 return fp;
kasperl@chromium.org061ef742009-02-27 12:16:20 +0000103}
104
105
106v8::Handle<v8::Value> TraceExtension::Trace(const v8::Arguments& args) {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000107 DoTrace(GetFP(args));
108 return v8::Undefined();
109}
110
111
112v8::Handle<v8::Value> TraceExtension::JSTrace(const v8::Arguments& args) {
113 DoTraceHideCEntryFPAddress(GetFP(args));
kasperl@chromium.org061ef742009-02-27 12:16:20 +0000114 return v8::Undefined();
115}
116
117
118static TraceExtension kTraceExtension;
119v8::DeclareExtension kTraceExtensionDeclaration(&kTraceExtension);
120
121
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000122static void CFuncDoTrace() {
123 unsigned int fp;
124#ifdef __GNUC__
125 fp = reinterpret_cast<unsigned int>(__builtin_frame_address(0));
126#elif defined _MSC_VER
127 __asm mov [fp], ebp // NOLINT
128#endif
129 DoTrace(fp);
130}
131
132
133static int CFunc(int depth) {
134 if (depth <= 0) {
135 CFuncDoTrace();
136 return 0;
137 } else {
138 return CFunc(depth - 1) + 1;
139 }
140}
141
142
143TEST(PureCStackTrace) {
144 TickSample sample;
145 StackTracer tracer(reinterpret_cast<unsigned int>(&sample));
146 InitTraceEnv(&tracer, &sample);
147 // Check that sampler doesn't crash
148 CHECK_EQ(10, CFunc(10));
149}
150
151
kasperl@chromium.org061ef742009-02-27 12:16:20 +0000152#endif // ENABLE_LOGGING_AND_PROFILING