OLD | NEW |
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 |
11 #include "codegen.h" | 11 #include "codegen.h" |
12 #include "log.h" | 12 #include "log.h" |
13 #include "top.h" | 13 #include "isolate.h" |
14 #include "cctest.h" | 14 #include "cctest.h" |
15 #include "disassembler.h" | 15 #include "disassembler.h" |
16 #include "register-allocator-inl.h" | 16 #include "register-allocator-inl.h" |
17 | 17 |
18 using v8::Function; | 18 using v8::Function; |
19 using v8::Local; | 19 using v8::Local; |
20 using v8::Object; | 20 using v8::Object; |
21 using v8::Script; | 21 using v8::Script; |
22 using v8::String; | 22 using v8::String; |
23 using v8::Value; | 23 using v8::Value; |
24 | 24 |
25 using v8::internal::byte; | 25 using v8::internal::byte; |
26 using v8::internal::Address; | 26 using v8::internal::Address; |
27 using v8::internal::Handle; | 27 using v8::internal::Handle; |
| 28 using v8::internal::Isolate; |
28 using v8::internal::JSFunction; | 29 using v8::internal::JSFunction; |
29 using v8::internal::StackTracer; | 30 using v8::internal::StackTracer; |
30 using v8::internal::TickSample; | 31 using v8::internal::TickSample; |
31 using v8::internal::Top; | |
32 | 32 |
33 namespace i = v8::internal; | 33 namespace i = v8::internal; |
34 | 34 |
35 | 35 |
36 static v8::Persistent<v8::Context> env; | 36 static v8::Persistent<v8::Context> env; |
37 | 37 |
38 | 38 |
39 static struct { | 39 static struct { |
40 TickSample* sample; | 40 TickSample* sample; |
41 } trace_env = { NULL }; | 41 } trace_env = { NULL }; |
42 | 42 |
43 | 43 |
44 static void InitTraceEnv(TickSample* sample) { | 44 static void InitTraceEnv(TickSample* sample) { |
45 trace_env.sample = sample; | 45 trace_env.sample = sample; |
46 } | 46 } |
47 | 47 |
48 | 48 |
49 static void DoTrace(Address fp) { | 49 static void DoTrace(Address fp) { |
50 trace_env.sample->fp = fp; | 50 trace_env.sample->fp = fp; |
51 // sp is only used to define stack high bound | 51 // sp is only used to define stack high bound |
52 trace_env.sample->sp = | 52 trace_env.sample->sp = |
53 reinterpret_cast<Address>(trace_env.sample) - 10240; | 53 reinterpret_cast<Address>(trace_env.sample) - 10240; |
54 StackTracer::Trace(trace_env.sample); | 54 StackTracer::Trace(trace_env.sample); |
55 } | 55 } |
56 | 56 |
57 | 57 |
58 // Hide c_entry_fp to emulate situation when sampling is done while | 58 // Hide c_entry_fp to emulate situation when sampling is done while |
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 = |
| 62 *(Isolate::Current()->c_entry_fp_address()); |
62 CHECK(saved_c_frame_fp); | 63 CHECK(saved_c_frame_fp); |
63 *(Top::c_entry_fp_address()) = 0; | 64 *(Isolate::Current()->c_entry_fp_address()) = 0; |
64 DoTrace(fp); | 65 DoTrace(fp); |
65 *(Top::c_entry_fp_address()) = saved_c_frame_fp; | 66 *(Isolate::Current()->c_entry_fp_address()) = saved_c_frame_fp; |
66 } | 67 } |
67 | 68 |
68 | 69 |
69 // --- T r a c e E x t e n s i o n --- | 70 // --- T r a c e E x t e n s i o n --- |
70 | 71 |
71 class TraceExtension : public v8::Extension { | 72 class TraceExtension : public v8::Extension { |
72 public: | 73 public: |
73 TraceExtension() : v8::Extension("v8/trace", kSource) { } | 74 TraceExtension() : v8::Extension("v8/trace", kSource) { } |
74 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( | 75 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( |
75 v8::Handle<String> name); | 76 v8::Handle<String> name); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
124 | 125 |
125 | 126 |
126 v8::Handle<v8::Value> TraceExtension::JSTrace(const v8::Arguments& args) { | 127 v8::Handle<v8::Value> TraceExtension::JSTrace(const v8::Arguments& args) { |
127 DoTraceHideCEntryFPAddress(GetFP(args)); | 128 DoTraceHideCEntryFPAddress(GetFP(args)); |
128 return v8::Undefined(); | 129 return v8::Undefined(); |
129 } | 130 } |
130 | 131 |
131 | 132 |
132 static Address GetJsEntrySp() { | 133 static Address GetJsEntrySp() { |
133 CHECK_NE(NULL, i::Isolate::Current()->thread_local_top()); | 134 CHECK_NE(NULL, i::Isolate::Current()->thread_local_top()); |
134 return Top::js_entry_sp(i::Isolate::Current()->thread_local_top()); | 135 return Isolate::js_entry_sp(i::Isolate::Current()->thread_local_top()); |
135 } | 136 } |
136 | 137 |
137 | 138 |
138 v8::Handle<v8::Value> TraceExtension::JSEntrySP(const v8::Arguments& args) { | 139 v8::Handle<v8::Value> TraceExtension::JSEntrySP(const v8::Arguments& args) { |
139 CHECK_NE(0, GetJsEntrySp()); | 140 CHECK_NE(0, GetJsEntrySp()); |
140 return v8::Undefined(); | 141 return v8::Undefined(); |
141 } | 142 } |
142 | 143 |
143 | 144 |
144 v8::Handle<v8::Value> TraceExtension::JSEntrySPLevel2( | 145 v8::Handle<v8::Value> TraceExtension::JSEntrySPLevel2( |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
263 func_code->Print(); | 264 func_code->Print(); |
264 #endif | 265 #endif |
265 | 266 |
266 SetGlobalProperty(func_name, v8::ToApi<Value>(func)); | 267 SetGlobalProperty(func_name, v8::ToApi<Value>(func)); |
267 CHECK_EQ(*func, *GetGlobalJSFunction(func_name)); | 268 CHECK_EQ(*func, *GetGlobalJSFunction(func_name)); |
268 } | 269 } |
269 | 270 |
270 | 271 |
271 // This test verifies that stack tracing works when called during | 272 // This test verifies that stack tracing works when called during |
272 // execution of a native function called from JS code. In this case, | 273 // execution of a native function called from JS code. In this case, |
273 // StackTracer uses Top::c_entry_fp as a starting point for stack | 274 // StackTracer uses Isolate::c_entry_fp as a starting point for stack |
274 // walking. | 275 // walking. |
275 TEST(CFromJSStackTrace) { | 276 TEST(CFromJSStackTrace) { |
276 // TODO(711) The hack of replacing the inline runtime function | 277 // TODO(711) The hack of replacing the inline runtime function |
277 // RandomHeapNumber with GetFrameNumber does not work with the way the full | 278 // RandomHeapNumber with GetFrameNumber does not work with the way the full |
278 // compiler generates inline runtime calls. | 279 // compiler generates inline runtime calls. |
279 i::FLAG_always_full_compiler = false; | 280 i::FLAG_always_full_compiler = false; |
280 | 281 |
281 TickSample sample; | 282 TickSample sample; |
282 InitTraceEnv(&sample); | 283 InitTraceEnv(&sample); |
283 | 284 |
(...skipping 19 matching lines...) Expand all Loading... |
303 CHECK_GT(sample.frames_count, 1); | 304 CHECK_GT(sample.frames_count, 1); |
304 // Stack tracing will start from the first JS function, i.e. "JSFuncDoTrace" | 305 // Stack tracing will start from the first JS function, i.e. "JSFuncDoTrace" |
305 CheckObjectIsJSFunction("JSFuncDoTrace", sample.stack[0]); | 306 CheckObjectIsJSFunction("JSFuncDoTrace", sample.stack[0]); |
306 CheckObjectIsJSFunction("JSTrace", sample.stack[1]); | 307 CheckObjectIsJSFunction("JSTrace", sample.stack[1]); |
307 } | 308 } |
308 | 309 |
309 | 310 |
310 // This test verifies that stack tracing works when called during | 311 // This test verifies that stack tracing works when called during |
311 // execution of JS code. However, as calling StackTracer requires | 312 // execution of JS code. However, as calling StackTracer requires |
312 // entering native code, we can only emulate pure JS by erasing | 313 // entering native code, we can only emulate pure JS by erasing |
313 // Top::c_entry_fp value. In this case, StackTracer uses passed frame | 314 // Isolate::c_entry_fp value. In this case, StackTracer uses passed frame |
314 // pointer value as a starting point for stack walking. | 315 // pointer value as a starting point for stack walking. |
315 TEST(PureJSStackTrace) { | 316 TEST(PureJSStackTrace) { |
316 // TODO(711) The hack of replacing the inline runtime function | 317 // TODO(711) The hack of replacing the inline runtime function |
317 // RandomHeapNumber with GetFrameNumber does not work with the way the full | 318 // RandomHeapNumber with GetFrameNumber does not work with the way the full |
318 // compiler generates inline runtime calls. | 319 // compiler generates inline runtime calls. |
319 i::FLAG_always_full_compiler = false; | 320 i::FLAG_always_full_compiler = false; |
320 | 321 |
321 TickSample sample; | 322 TickSample sample; |
322 InitTraceEnv(&sample); | 323 InitTraceEnv(&sample); |
323 | 324 |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
398 CHECK_EQ(0, GetJsEntrySp()); | 399 CHECK_EQ(0, GetJsEntrySp()); |
399 CompileRun("a = 1; b = a + 1;"); | 400 CompileRun("a = 1; b = a + 1;"); |
400 CHECK_EQ(0, GetJsEntrySp()); | 401 CHECK_EQ(0, GetJsEntrySp()); |
401 CompileRun("js_entry_sp();"); | 402 CompileRun("js_entry_sp();"); |
402 CHECK_EQ(0, GetJsEntrySp()); | 403 CHECK_EQ(0, GetJsEntrySp()); |
403 CompileRun("js_entry_sp_level2();"); | 404 CompileRun("js_entry_sp_level2();"); |
404 CHECK_EQ(0, GetJsEntrySp()); | 405 CHECK_EQ(0, GetJsEntrySp()); |
405 } | 406 } |
406 | 407 |
407 #endif // ENABLE_LOGGING_AND_PROFILING | 408 #endif // ENABLE_LOGGING_AND_PROFILING |
OLD | NEW |