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

Side by Side Diff: test/cctest/test-log-stack-tracer.cc

Issue 2084017: Version 2.2.11... (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
Patch Set: Created 10 years, 7 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 | Annotate | Revision Log
« no previous file with comments | « test/cctest/test-disasm-ia32.cc ('k') | test/cctest/test-profile-generator.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 the V8 project authors. All rights reserved.
2 // 2 //
3 // Tests of profiler-related functions from log.h 3 // Tests of profiler-related functions from log.h
4 4
5 #ifdef ENABLE_LOGGING_AND_PROFILING 5 #ifdef ENABLE_LOGGING_AND_PROFILING
6 6
7 #include <stdlib.h> 7 #include <stdlib.h>
8 8
9 #include "v8.h" 9 #include "v8.h"
10 10
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 // pure JS code is being executed 59 // pure JS code is being executed
60 static void DoTraceHideCEntryFPAddress(Address fp) { 60 static void DoTraceHideCEntryFPAddress(Address fp) {
61 v8::internal::Address saved_c_frame_fp = *(Top::c_entry_fp_address()); 61 v8::internal::Address saved_c_frame_fp = *(Top::c_entry_fp_address());
62 CHECK(saved_c_frame_fp); 62 CHECK(saved_c_frame_fp);
63 *(Top::c_entry_fp_address()) = 0; 63 *(Top::c_entry_fp_address()) = 0;
64 DoTrace(fp); 64 DoTrace(fp);
65 *(Top::c_entry_fp_address()) = saved_c_frame_fp; 65 *(Top::c_entry_fp_address()) = saved_c_frame_fp;
66 } 66 }
67 67
68 68
69 static void CheckRetAddrIsInFunction(const char* func_name,
70 Address ret_addr,
71 Address func_start_addr,
72 unsigned int func_len) {
73 printf("CheckRetAddrIsInFunction \"%s\": %p %p %p\n",
74 func_name, func_start_addr, ret_addr, func_start_addr + func_len);
75 CHECK_GE(ret_addr, func_start_addr);
76 CHECK_GE(func_start_addr + func_len, ret_addr);
77 }
78
79
80 static void CheckRetAddrIsInJSFunction(const char* func_name,
81 Address ret_addr,
82 Handle<JSFunction> func) {
83 v8::internal::Code* func_code = func->code();
84 CheckRetAddrIsInFunction(
85 func_name, ret_addr,
86 func_code->instruction_start(),
87 func_code->ExecutableSize());
88 }
89
90
91 // --- T r a c e E x t e n s i o n --- 69 // --- T r a c e E x t e n s i o n ---
92 70
93 class TraceExtension : public v8::Extension { 71 class TraceExtension : public v8::Extension {
94 public: 72 public:
95 TraceExtension() : v8::Extension("v8/trace", kSource) { } 73 TraceExtension() : v8::Extension("v8/trace", kSource) { }
96 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( 74 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
97 v8::Handle<String> name); 75 v8::Handle<String> name);
98 static v8::Handle<v8::Value> Trace(const v8::Arguments& args); 76 static v8::Handle<v8::Value> Trace(const v8::Arguments& args);
99 static v8::Handle<v8::Value> JSTrace(const v8::Arguments& args); 77 static v8::Handle<v8::Value> JSTrace(const v8::Arguments& args);
100 static v8::Handle<v8::Value> JSEntrySP(const v8::Arguments& args); 78 static v8::Handle<v8::Value> JSEntrySP(const v8::Arguments& args);
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
202 } 180 }
203 181
204 182
205 static Handle<JSFunction> GetGlobalJSFunction(const char* name) { 183 static Handle<JSFunction> GetGlobalJSFunction(const char* name) {
206 Handle<JSFunction> result(JSFunction::cast( 184 Handle<JSFunction> result(JSFunction::cast(
207 *v8::Utils::OpenHandle(*GetGlobalProperty(name)))); 185 *v8::Utils::OpenHandle(*GetGlobalProperty(name))));
208 return result; 186 return result;
209 } 187 }
210 188
211 189
212 static void CheckRetAddrIsInJSFunction(const char* func_name, 190 static void CheckObjectIsJSFunction(const char* func_name,
213 Address ret_addr) { 191 Address addr) {
214 CheckRetAddrIsInJSFunction(func_name, 192 i::Object* obj = reinterpret_cast<i::Object*>(addr);
215 ret_addr, 193 CHECK(obj->IsJSFunction());
216 GetGlobalJSFunction(func_name)); 194 CHECK(JSFunction::cast(obj)->shared()->name()->IsString());
195 i::SmartPointer<char> found_name =
196 i::String::cast(
197 JSFunction::cast(
198 obj)->shared()->name())->ToCString();
199 CHECK_EQ(func_name, *found_name);
217 } 200 }
218 201
219 202
220 static void SetGlobalProperty(const char* name, Local<Value> value) { 203 static void SetGlobalProperty(const char* name, Local<Value> value) {
221 env->Global()->Set(String::New(name), value); 204 env->Global()->Set(String::New(name), value);
222 } 205 }
223 206
224 207
225 static Handle<v8::internal::String> NewString(const char* s) { 208 static Handle<v8::internal::String> NewString(const char* s) {
226 return i::Factory::NewStringFromAscii(i::CStrVector(s)); 209 return i::Factory::NewStringFromAscii(i::CStrVector(s));
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
265 i::EmbeddedVector<char, 256> trace_call_buf; 248 i::EmbeddedVector<char, 256> trace_call_buf;
266 i::OS::SNPrintF(trace_call_buf, "%s(%%_GetFramePointer());", trace_func_name); 249 i::OS::SNPrintF(trace_call_buf, "%s(%%_GetFramePointer());", trace_func_name);
267 250
268 // Compile the script. 251 // Compile the script.
269 i::CodeGeneratorPatcher patcher; 252 i::CodeGeneratorPatcher patcher;
270 bool allow_natives_syntax = i::FLAG_allow_natives_syntax; 253 bool allow_natives_syntax = i::FLAG_allow_natives_syntax;
271 i::FLAG_allow_natives_syntax = true; 254 i::FLAG_allow_natives_syntax = true;
272 Handle<JSFunction> func = CompileFunction(trace_call_buf.start()); 255 Handle<JSFunction> func = CompileFunction(trace_call_buf.start());
273 CHECK(!func.is_null()); 256 CHECK(!func.is_null());
274 i::FLAG_allow_natives_syntax = allow_natives_syntax; 257 i::FLAG_allow_natives_syntax = allow_natives_syntax;
258 func->shared()->set_name(*NewString(func_name));
275 259
276 #ifdef DEBUG 260 #ifdef DEBUG
277 v8::internal::Code* func_code = func->code(); 261 v8::internal::Code* func_code = func->code();
278 CHECK(func_code->IsCode()); 262 CHECK(func_code->IsCode());
279 func_code->Print(); 263 func_code->Print();
280 #endif 264 #endif
281 265
282 SetGlobalProperty(func_name, v8::ToApi<Value>(func)); 266 SetGlobalProperty(func_name, v8::ToApi<Value>(func));
283 CHECK_EQ(*func, *GetGlobalJSFunction(func_name)); 267 CHECK_EQ(*func, *GetGlobalJSFunction(func_name));
284 } 268 }
285 269
286 270
287 // This test verifies that stack tracing works when called during 271 // This test verifies that stack tracing works when called during
288 // execution of a native function called from JS code. In this case, 272 // execution of a native function called from JS code. In this case,
289 // StackTracer uses Top::c_entry_fp as a starting point for stack 273 // StackTracer uses Top::c_entry_fp as a starting point for stack
290 // walking. 274 // walking.
291 TEST(CFromJSStackTrace) { 275 TEST(CFromJSStackTrace) {
276 #if defined(V8_HOST_ARCH_IA32) || defined(V8_HOST_ARCH_X64)
277 // TODO(711) The hack of replacing the inline runtime function
278 // RandomHeapNumber with GetFrameNumber does not work with the way the full
279 // compiler generates inline runtime calls.
280 i::FLAG_force_full_compiler = false;
281 #endif
282
292 TickSample sample; 283 TickSample sample;
293 InitTraceEnv(&sample); 284 InitTraceEnv(&sample);
294 285
295 InitializeVM(); 286 InitializeVM();
296 v8::HandleScope scope; 287 v8::HandleScope scope;
297 // Create global function JSFuncDoTrace which calls 288 // Create global function JSFuncDoTrace which calls
298 // extension function trace() with the current frame pointer value. 289 // extension function trace() with the current frame pointer value.
299 CreateTraceCallerFunction("JSFuncDoTrace", "trace"); 290 CreateTraceCallerFunction("JSFuncDoTrace", "trace");
300 Local<Value> result = CompileRun( 291 Local<Value> result = CompileRun(
301 "function JSTrace() {" 292 "function JSTrace() {"
302 " JSFuncDoTrace();" 293 " JSFuncDoTrace();"
303 "};\n" 294 "};\n"
304 "JSTrace();\n" 295 "JSTrace();\n"
305 "true;"); 296 "true;");
306 CHECK(!result.IsEmpty()); 297 CHECK(!result.IsEmpty());
307 // When stack tracer is invoked, the stack should look as follows: 298 // When stack tracer is invoked, the stack should look as follows:
308 // script [JS] 299 // script [JS]
309 // JSTrace() [JS] 300 // JSTrace() [JS]
310 // JSFuncDoTrace() [JS] [captures EBP value and encodes it as Smi] 301 // JSFuncDoTrace() [JS] [captures EBP value and encodes it as Smi]
311 // trace(EBP encoded as Smi) [native (extension)] 302 // trace(EBP encoded as Smi) [native (extension)]
312 // DoTrace(EBP) [native] 303 // DoTrace(EBP) [native]
313 // StackTracer::Trace 304 // StackTracer::Trace
314 CHECK_GT(sample.frames_count, 1); 305 CHECK_GT(sample.frames_count, 1);
315 // Stack tracing will start from the first JS function, i.e. "JSFuncDoTrace" 306 // Stack tracing will start from the first JS function, i.e. "JSFuncDoTrace"
316 CheckRetAddrIsInJSFunction("JSFuncDoTrace", 307 CheckObjectIsJSFunction("JSFuncDoTrace", sample.stack[0]);
317 sample.stack[0]); 308 CheckObjectIsJSFunction("JSTrace", sample.stack[1]);
318 CheckRetAddrIsInJSFunction("JSTrace",
319 sample.stack[1]);
320 } 309 }
321 310
322 311
323 // This test verifies that stack tracing works when called during 312 // This test verifies that stack tracing works when called during
324 // execution of JS code. However, as calling StackTracer requires 313 // execution of JS code. However, as calling StackTracer requires
325 // entering native code, we can only emulate pure JS by erasing 314 // entering native code, we can only emulate pure JS by erasing
326 // Top::c_entry_fp value. In this case, StackTracer uses passed frame 315 // Top::c_entry_fp value. In this case, StackTracer uses passed frame
327 // pointer value as a starting point for stack walking. 316 // pointer value as a starting point for stack walking.
328 TEST(PureJSStackTrace) { 317 TEST(PureJSStackTrace) {
318 #if defined(V8_HOST_ARCH_IA32) || defined(V8_HOST_ARCH_X64)
319 // TODO(711) The hack of replacing the inline runtime function
320 // RandomHeapNumber with GetFrameNumber does not work with the way the full
321 // compiler generates inline runtime calls.
322 i::FLAG_force_full_compiler = false;
323 #endif
324
329 TickSample sample; 325 TickSample sample;
330 InitTraceEnv(&sample); 326 InitTraceEnv(&sample);
331 327
332 InitializeVM(); 328 InitializeVM();
333 v8::HandleScope scope; 329 v8::HandleScope scope;
334 // Create global function JSFuncDoTrace which calls 330 // Create global function JSFuncDoTrace which calls
335 // extension function js_trace() with the current frame pointer value. 331 // extension function js_trace() with the current frame pointer value.
336 CreateTraceCallerFunction("JSFuncDoTrace", "js_trace"); 332 CreateTraceCallerFunction("JSFuncDoTrace", "js_trace");
337 Local<Value> result = CompileRun( 333 Local<Value> result = CompileRun(
338 "function JSTrace() {" 334 "function JSTrace() {"
(...skipping 13 matching lines...) Expand all
352 // js_trace(EBP encoded as Smi) [native (extension)] 348 // js_trace(EBP encoded as Smi) [native (extension)]
353 // DoTraceHideCEntryFPAddress(EBP) [native] 349 // DoTraceHideCEntryFPAddress(EBP) [native]
354 // StackTracer::Trace 350 // StackTracer::Trace
355 // 351 //
356 // The last JS function called. It is only visible through 352 // The last JS function called. It is only visible through
357 // sample.function, as its return address is above captured EBP value. 353 // sample.function, as its return address is above captured EBP value.
358 CHECK_EQ(GetGlobalJSFunction("JSFuncDoTrace")->address(), 354 CHECK_EQ(GetGlobalJSFunction("JSFuncDoTrace")->address(),
359 sample.function); 355 sample.function);
360 CHECK_GT(sample.frames_count, 1); 356 CHECK_GT(sample.frames_count, 1);
361 // Stack sampling will start from the caller of JSFuncDoTrace, i.e. "JSTrace" 357 // Stack sampling will start from the caller of JSFuncDoTrace, i.e. "JSTrace"
362 CheckRetAddrIsInJSFunction("JSTrace", 358 CheckObjectIsJSFunction("JSTrace", sample.stack[0]);
363 sample.stack[0]); 359 CheckObjectIsJSFunction("OuterJSTrace", sample.stack[1]);
364 CheckRetAddrIsInJSFunction("OuterJSTrace",
365 sample.stack[1]);
366 } 360 }
367 361
368 362
369 static void CFuncDoTrace(byte dummy_parameter) { 363 static void CFuncDoTrace(byte dummy_parameter) {
370 Address fp; 364 Address fp;
371 #ifdef __GNUC__ 365 #ifdef __GNUC__
372 fp = reinterpret_cast<Address>(__builtin_frame_address(0)); 366 fp = reinterpret_cast<Address>(__builtin_frame_address(0));
373 #elif defined _MSC_VER 367 #elif defined _MSC_VER
374 // Approximate a frame pointer address. We compile without base pointers, 368 // Approximate a frame pointer address. We compile without base pointers,
375 // so we can't trust ebp/rbp. 369 // so we can't trust ebp/rbp.
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
408 CHECK_EQ(0, GetJsEntrySp()); 402 CHECK_EQ(0, GetJsEntrySp());
409 CompileRun("a = 1; b = a + 1;"); 403 CompileRun("a = 1; b = a + 1;");
410 CHECK_EQ(0, GetJsEntrySp()); 404 CHECK_EQ(0, GetJsEntrySp());
411 CompileRun("js_entry_sp();"); 405 CompileRun("js_entry_sp();");
412 CHECK_EQ(0, GetJsEntrySp()); 406 CHECK_EQ(0, GetJsEntrySp());
413 CompileRun("js_entry_sp_level2();"); 407 CompileRun("js_entry_sp_level2();");
414 CHECK_EQ(0, GetJsEntrySp()); 408 CHECK_EQ(0, GetJsEntrySp());
415 } 409 }
416 410
417 #endif // ENABLE_LOGGING_AND_PROFILING 411 #endif // ENABLE_LOGGING_AND_PROFILING
OLDNEW
« no previous file with comments | « test/cctest/test-disasm-ia32.cc ('k') | test/cctest/test-profile-generator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698