OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 18 matching lines...) Expand all Loading... |
29 | 29 |
30 #ifdef ENABLE_LOGGING_AND_PROFILING | 30 #ifdef ENABLE_LOGGING_AND_PROFILING |
31 | 31 |
32 #include <stdlib.h> | 32 #include <stdlib.h> |
33 | 33 |
34 #include "v8.h" | 34 #include "v8.h" |
35 | 35 |
36 #include "api.h" | 36 #include "api.h" |
37 #include "codegen.h" | 37 #include "codegen.h" |
38 #include "log.h" | 38 #include "log.h" |
39 #include "top.h" | 39 #include "isolate.h" |
40 #include "cctest.h" | 40 #include "cctest.h" |
41 #include "disassembler.h" | 41 #include "disassembler.h" |
42 #include "register-allocator-inl.h" | 42 #include "register-allocator-inl.h" |
43 #include "vm-state-inl.h" | 43 #include "vm-state-inl.h" |
44 | 44 |
45 using v8::Function; | 45 using v8::Function; |
46 using v8::Local; | 46 using v8::Local; |
47 using v8::Object; | 47 using v8::Object; |
48 using v8::Script; | 48 using v8::Script; |
49 using v8::String; | 49 using v8::String; |
50 using v8::Value; | 50 using v8::Value; |
51 | 51 |
52 using v8::internal::byte; | 52 using v8::internal::byte; |
53 using v8::internal::Address; | 53 using v8::internal::Address; |
54 using v8::internal::Handle; | 54 using v8::internal::Handle; |
| 55 using v8::internal::Isolate; |
55 using v8::internal::JSFunction; | 56 using v8::internal::JSFunction; |
56 using v8::internal::StackTracer; | 57 using v8::internal::StackTracer; |
57 using v8::internal::TickSample; | 58 using v8::internal::TickSample; |
58 using v8::internal::Top; | |
59 | 59 |
60 namespace i = v8::internal; | 60 namespace i = v8::internal; |
61 | 61 |
62 | 62 |
63 static v8::Persistent<v8::Context> env; | 63 static v8::Persistent<v8::Context> env; |
64 | 64 |
65 | 65 |
66 static struct { | 66 static struct { |
67 TickSample* sample; | 67 TickSample* sample; |
68 } trace_env = { NULL }; | 68 } trace_env = { NULL }; |
69 | 69 |
70 | 70 |
71 static void InitTraceEnv(TickSample* sample) { | 71 static void InitTraceEnv(TickSample* sample) { |
72 trace_env.sample = sample; | 72 trace_env.sample = sample; |
73 } | 73 } |
74 | 74 |
75 | 75 |
76 static void DoTrace(Address fp) { | 76 static void DoTrace(Address fp) { |
77 trace_env.sample->fp = fp; | 77 trace_env.sample->fp = fp; |
78 // sp is only used to define stack high bound | 78 // sp is only used to define stack high bound |
79 trace_env.sample->sp = | 79 trace_env.sample->sp = |
80 reinterpret_cast<Address>(trace_env.sample) - 10240; | 80 reinterpret_cast<Address>(trace_env.sample) - 10240; |
81 StackTracer::Trace(trace_env.sample); | 81 StackTracer::Trace(Isolate::Current(), trace_env.sample); |
82 } | 82 } |
83 | 83 |
84 | 84 |
85 // Hide c_entry_fp to emulate situation when sampling is done while | 85 // Hide c_entry_fp to emulate situation when sampling is done while |
86 // pure JS code is being executed | 86 // pure JS code is being executed |
87 static void DoTraceHideCEntryFPAddress(Address fp) { | 87 static void DoTraceHideCEntryFPAddress(Address fp) { |
88 v8::internal::Address saved_c_frame_fp = *(Top::c_entry_fp_address()); | 88 v8::internal::Address saved_c_frame_fp = |
| 89 *(Isolate::Current()->c_entry_fp_address()); |
89 CHECK(saved_c_frame_fp); | 90 CHECK(saved_c_frame_fp); |
90 *(Top::c_entry_fp_address()) = 0; | 91 *(Isolate::Current()->c_entry_fp_address()) = 0; |
91 DoTrace(fp); | 92 DoTrace(fp); |
92 *(Top::c_entry_fp_address()) = saved_c_frame_fp; | 93 *(Isolate::Current()->c_entry_fp_address()) = saved_c_frame_fp; |
93 } | 94 } |
94 | 95 |
95 | 96 |
96 // --- T r a c e E x t e n s i o n --- | 97 // --- T r a c e E x t e n s i o n --- |
97 | 98 |
98 class TraceExtension : public v8::Extension { | 99 class TraceExtension : public v8::Extension { |
99 public: | 100 public: |
100 TraceExtension() : v8::Extension("v8/trace", kSource) { } | 101 TraceExtension() : v8::Extension("v8/trace", kSource) { } |
101 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( | 102 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( |
102 v8::Handle<String> name); | 103 v8::Handle<String> name); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
156 } | 157 } |
157 | 158 |
158 | 159 |
159 v8::Handle<v8::Value> TraceExtension::JSTrace(const v8::Arguments& args) { | 160 v8::Handle<v8::Value> TraceExtension::JSTrace(const v8::Arguments& args) { |
160 DoTraceHideCEntryFPAddress(GetFP(args)); | 161 DoTraceHideCEntryFPAddress(GetFP(args)); |
161 return v8::Undefined(); | 162 return v8::Undefined(); |
162 } | 163 } |
163 | 164 |
164 | 165 |
165 static Address GetJsEntrySp() { | 166 static Address GetJsEntrySp() { |
166 CHECK_NE(NULL, Top::GetCurrentThread()); | 167 CHECK_NE(NULL, i::Isolate::Current()->thread_local_top()); |
167 return Top::js_entry_sp(Top::GetCurrentThread()); | 168 return Isolate::js_entry_sp(i::Isolate::Current()->thread_local_top()); |
168 } | 169 } |
169 | 170 |
170 | 171 |
171 v8::Handle<v8::Value> TraceExtension::JSEntrySP(const v8::Arguments& args) { | 172 v8::Handle<v8::Value> TraceExtension::JSEntrySP(const v8::Arguments& args) { |
172 CHECK_NE(0, GetJsEntrySp()); | 173 CHECK_NE(0, GetJsEntrySp()); |
173 return v8::Undefined(); | 174 return v8::Undefined(); |
174 } | 175 } |
175 | 176 |
176 | 177 |
177 v8::Handle<v8::Value> TraceExtension::JSEntrySPLevel2( | 178 v8::Handle<v8::Value> TraceExtension::JSEntrySPLevel2( |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
269 // when called as a constructor. | 270 // when called as a constructor. |
270 CreateFramePointerGrabberConstructor("FPGrabber"); | 271 CreateFramePointerGrabberConstructor("FPGrabber"); |
271 | 272 |
272 // Compile the script. | 273 // Compile the script. |
273 CompileRun(trace_call_buf.start()); | 274 CompileRun(trace_call_buf.start()); |
274 } | 275 } |
275 | 276 |
276 | 277 |
277 // This test verifies that stack tracing works when called during | 278 // This test verifies that stack tracing works when called during |
278 // execution of a native function called from JS code. In this case, | 279 // execution of a native function called from JS code. In this case, |
279 // StackTracer uses Top::c_entry_fp as a starting point for stack | 280 // StackTracer uses Isolate::c_entry_fp as a starting point for stack |
280 // walking. | 281 // walking. |
281 TEST(CFromJSStackTrace) { | 282 TEST(CFromJSStackTrace) { |
282 TickSample sample; | 283 TickSample sample; |
283 InitTraceEnv(&sample); | 284 InitTraceEnv(&sample); |
284 | 285 |
285 InitializeVM(); | 286 InitializeVM(); |
286 v8::HandleScope scope; | 287 v8::HandleScope scope; |
287 // Create global function JSFuncDoTrace which calls | 288 // Create global function JSFuncDoTrace which calls |
288 // extension function trace() with the current frame pointer value. | 289 // extension function trace() with the current frame pointer value. |
289 CreateTraceCallerFunction("JSFuncDoTrace", "trace"); | 290 CreateTraceCallerFunction("JSFuncDoTrace", "trace"); |
(...skipping 21 matching lines...) Expand all Loading... |
311 // Stack tracing will start from the first JS function, i.e. "JSFuncDoTrace" | 312 // Stack tracing will start from the first JS function, i.e. "JSFuncDoTrace" |
312 CHECK_GT(sample.frames_count, base + 1); | 313 CHECK_GT(sample.frames_count, base + 1); |
313 CHECK(IsAddressWithinFuncCode("JSFuncDoTrace", sample.stack[base + 0])); | 314 CHECK(IsAddressWithinFuncCode("JSFuncDoTrace", sample.stack[base + 0])); |
314 CHECK(IsAddressWithinFuncCode("JSTrace", sample.stack[base + 1])); | 315 CHECK(IsAddressWithinFuncCode("JSTrace", sample.stack[base + 1])); |
315 } | 316 } |
316 | 317 |
317 | 318 |
318 // This test verifies that stack tracing works when called during | 319 // This test verifies that stack tracing works when called during |
319 // execution of JS code. However, as calling StackTracer requires | 320 // execution of JS code. However, as calling StackTracer requires |
320 // entering native code, we can only emulate pure JS by erasing | 321 // entering native code, we can only emulate pure JS by erasing |
321 // Top::c_entry_fp value. In this case, StackTracer uses passed frame | 322 // Isolate::c_entry_fp value. In this case, StackTracer uses passed frame |
322 // pointer value as a starting point for stack walking. | 323 // pointer value as a starting point for stack walking. |
323 TEST(PureJSStackTrace) { | 324 TEST(PureJSStackTrace) { |
324 // This test does not pass with inlining enabled since inlined functions | 325 // This test does not pass with inlining enabled since inlined functions |
325 // don't appear in the stack trace. | 326 // don't appear in the stack trace. |
326 i::FLAG_use_inlining = false; | 327 i::FLAG_use_inlining = false; |
327 | 328 |
328 TickSample sample; | 329 TickSample sample; |
329 InitTraceEnv(&sample); | 330 InitTraceEnv(&sample); |
330 | 331 |
331 InitializeVM(); | 332 InitializeVM(); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
390 } | 391 } |
391 } | 392 } |
392 | 393 |
393 | 394 |
394 // This test verifies that stack tracing doesn't crash when called on | 395 // This test verifies that stack tracing doesn't crash when called on |
395 // pure native code. StackTracer only unrolls JS code, so we can't | 396 // pure native code. StackTracer only unrolls JS code, so we can't |
396 // get any meaningful info here. | 397 // get any meaningful info here. |
397 TEST(PureCStackTrace) { | 398 TEST(PureCStackTrace) { |
398 TickSample sample; | 399 TickSample sample; |
399 InitTraceEnv(&sample); | 400 InitTraceEnv(&sample); |
| 401 InitializeVM(); |
400 // Check that sampler doesn't crash | 402 // Check that sampler doesn't crash |
401 CHECK_EQ(10, CFunc(10)); | 403 CHECK_EQ(10, CFunc(10)); |
402 } | 404 } |
403 | 405 |
404 | 406 |
405 TEST(JsEntrySp) { | 407 TEST(JsEntrySp) { |
406 InitializeVM(); | 408 InitializeVM(); |
407 v8::HandleScope scope; | 409 v8::HandleScope scope; |
408 CHECK_EQ(0, GetJsEntrySp()); | 410 CHECK_EQ(0, GetJsEntrySp()); |
409 CompileRun("a = 1; b = a + 1;"); | 411 CompileRun("a = 1; b = a + 1;"); |
410 CHECK_EQ(0, GetJsEntrySp()); | 412 CHECK_EQ(0, GetJsEntrySp()); |
411 CompileRun("js_entry_sp();"); | 413 CompileRun("js_entry_sp();"); |
412 CHECK_EQ(0, GetJsEntrySp()); | 414 CHECK_EQ(0, GetJsEntrySp()); |
413 CompileRun("js_entry_sp_level2();"); | 415 CompileRun("js_entry_sp_level2();"); |
414 CHECK_EQ(0, GetJsEntrySp()); | 416 CHECK_EQ(0, GetJsEntrySp()); |
415 } | 417 } |
416 | 418 |
417 #endif // ENABLE_LOGGING_AND_PROFILING | 419 #endif // ENABLE_LOGGING_AND_PROFILING |
OLD | NEW |