Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(17)

Side by Side Diff: test/cctest/test-log-ia32.cc

Issue 28112: Adding unit tests for profiler's stack tracer. (Closed)
Patch Set: Changes according to comments Created 11 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « test/cctest/SConscript ('k') | tools/visual_studio/v8_cctest.vcproj » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2006-2009 the V8 project authors. All rights reserved.
2 //
3 // Tests of profiler-related functions from log.h
4
5 #include <stdlib.h>
6
7 #include "v8.h"
8
9 #include "log.h"
10 #include "cctest.h"
11
12 using v8::Function;
13 using v8::Local;
14 using v8::Object;
15 using v8::Script;
16 using v8::String;
17 using v8::Value;
18
19 using v8::internal::byte;
20 using v8::internal::Handle;
21 using v8::internal::JSFunction;
22 using v8::internal::StackTracer;
23 using v8::internal::TickSample;
24
25
26 static v8::Persistent<v8::Context> env;
27
28
29 static struct {
30 StackTracer* tracer;
31 TickSample* sample;
32 } trace_env;
33
34
35 static void InitTraceEnv(StackTracer* tracer, TickSample* sample) {
36 trace_env.tracer = tracer;
37 trace_env.sample = sample;
38 }
39
40
41 static void DoTrace(unsigned int fp) {
42 trace_env.sample->fp = fp;
43 // something that is less than fp
44 trace_env.sample->sp = trace_env.sample->fp - sizeof(unsigned int);
45 trace_env.tracer->Trace(trace_env.sample);
46 }
47
48
49 static void CFuncDoTrace() {
50 unsigned int fp;
51 #ifdef __GNUC__
52 fp = reinterpret_cast<unsigned int>(__builtin_frame_address(0));
53 #elif defined _MSC_VER
54 __asm mov [fp], ebp
55 #endif
56 DoTrace(fp);
57 }
58
59
60 static void CFunc(int i) {
61 for (int j = i; j >= 0; --j) {
62 CFuncDoTrace();
63 }
64 }
65
66
67 static void CheckRetAddrIsInFunction(unsigned int ret_addr,
68 unsigned int func_start_addr,
69 unsigned int func_len) {
70 printf("CheckRetAddrIsInFunction: %08x %08x %08x\n",
71 func_start_addr, ret_addr, func_start_addr + func_len);
72 CHECK_GE(ret_addr, func_start_addr);
73 CHECK_GE(func_start_addr + func_len, ret_addr);
74 }
75
76
77 #ifdef DEBUG
78 static const int kMaxCFuncLen = 0x40; // seems enough for a small C function
79
80 static void CheckRetAddrIsInCFunction(unsigned int ret_addr,
81 unsigned int func_start_addr) {
82 CheckRetAddrIsInFunction(ret_addr, func_start_addr, kMaxCFuncLen);
83 }
84 #endif
85
86
87 TEST(PureCStackTrace) {
88 TickSample sample;
89 StackTracer tracer(reinterpret_cast<unsigned int>(&sample));
90 InitTraceEnv(&tracer, &sample);
91 CFunc(0);
92 #ifdef DEBUG
93 // C stack trace works only in debug mode, in release mode EBP is
94 // usually treated as a general-purpose register
95 CheckRetAddrIsInCFunction(reinterpret_cast<unsigned int>(sample.stack[0]),
96 reinterpret_cast<unsigned int>(&CFunc));
97 CHECK_EQ(0, sample.stack[1]);
98 #endif
99 }
100
101
102 // --- T r a c e E x t e n s i o n ---
103
104 class TraceExtension : public v8::Extension {
105 public:
106 TraceExtension() : v8::Extension("v8/trace", kSource) { }
107 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
108 v8::Handle<v8::String> name);
109 static v8::Handle<v8::Value> Trace(const v8::Arguments& args);
110 private:
111 static const char* kSource;
112 };
113
114
115 const char* TraceExtension::kSource = "native function trace();";
116
117
118 v8::Handle<v8::FunctionTemplate> TraceExtension::GetNativeFunction(
119 v8::Handle<v8::String> str) {
120 return v8::FunctionTemplate::New(TraceExtension::Trace);
121 }
122
123
124 v8::Handle<v8::Value> TraceExtension::Trace(const v8::Arguments& args) {
125 CHECK_EQ(1, args.Length());
126 unsigned int fp = args[0]->Int32Value() << 2;
127 printf("Trace: %08x\n", fp);
128 DoTrace(fp);
129 return v8::Undefined();
130 }
131
132
133 static TraceExtension kTraceExtension;
134 v8::DeclareExtension kTraceExtensionDeclaration(&kTraceExtension);
135
136
137 static void InitializeVM() {
138 if (env.IsEmpty()) {
139 v8::HandleScope scope;
140 const char* extensions[] = { "v8/trace" };
141 v8::ExtensionConfiguration config(1, extensions);
142 env = v8::Context::New(&config);
143 }
144 v8::HandleScope scope;
145 env->Enter();
146 }
147
148
149 static Handle<JSFunction> CompileFunction(const char* source) {
150 return v8::Utils::OpenHandle(*Script::Compile(String::New(source)));
151 }
152
153
154 static void CompileRun(const char* source) {
155 Script::Compile(String::New(source))->Run();
156 }
157
158
159 static Local<Value> GetGlobalProperty(const char* name) {
160 return env->Global()->Get(String::New(name));
161 }
162
163
164 static void SetGlobalProperty(const char* name, Local<Value> value) {
165 env->Global()->Set(String::New(name), value);
166 }
167
168
169 static bool Patch(byte* from, size_t num, byte* original, byte* patch, size_t pa tch_len) {
170 byte* to = from + num;
171 do {
172 from = (byte*)memchr(from, *original, to - from);
173 CHECK(from != NULL);
174 if (memcmp(original, from, patch_len) == 0) {
175 memcpy(from, patch, patch_len);
176 return true;
177 } else {
178 from++;
179 }
180 } while (to - from > 0);
181 return false;
182 }
183
184
185 TEST(PureJSStackTrace) {
186 TickSample sample;
187 StackTracer tracer(reinterpret_cast<unsigned int>(&sample));
188 InitTraceEnv(&tracer, &sample);
189
190 InitializeVM();
191 v8::HandleScope scope;
192 Handle<JSFunction> call_trace = CompileFunction("trace(0x6666);");
193 CHECK(!call_trace.is_null());
194 v8::internal::Code* call_trace_code = call_trace->code();
195 CHECK(call_trace_code->IsCode());
196
197 byte original[] = { 0x68, 0xcc, 0xcc, 0x00, 0x00 }; // push 0xcccc (= 0x6666 < < 1)
198 byte patch[] = { 0x89, 0xe8, 0xd1, 0xe8, 0x50 }; // mov eax,ebp; shr eax; push eax;
199 // Patch generated code to replace pushing of a constant with
200 // pushing of ebp contents in a Smi
201 CHECK(Patch(call_trace_code->instruction_start(),
202 call_trace_code->instruction_size(),
203 original, patch, sizeof(patch)));
204
205 SetGlobalProperty("JSFuncDoTrace", v8::ToApi<Value>(call_trace));
206
207 CompileRun(
208 "function JSTrace() {"
209 " JSFuncDoTrace();"
210 "};\n"
211 "JSTrace();");
212 Handle<JSFunction> js_trace(JSFunction::cast(*(v8::Utils::OpenHandle(
213 *GetGlobalProperty("JSTrace")))));
214 v8::internal::Code* js_trace_code = js_trace->code();
215 CheckRetAddrIsInFunction(reinterpret_cast<unsigned int>(sample.stack[0]),
216 reinterpret_cast<unsigned int>(js_trace_code->instruc tion_start()),
217 js_trace_code->instruction_size());
218 CHECK_EQ(0, sample.stack[1]);
219 }
OLDNEW
« no previous file with comments | « test/cctest/SConscript ('k') | tools/visual_studio/v8_cctest.vcproj » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698