Chromium Code Reviews| 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 "top.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::JSFunction; | 28 using v8::internal::JSFunction; |
| 29 using v8::internal::SharedFunctionInfo; | |
| 30 using v8::internal::StackTracer; | 29 using v8::internal::StackTracer; |
| 31 using v8::internal::TickSample; | 30 using v8::internal::TickSample; |
| 32 using v8::internal::Top; | 31 using v8::internal::Top; |
| 33 | 32 |
| 34 namespace i = v8::internal; | 33 namespace i = v8::internal; |
| 35 | 34 |
| 36 | 35 |
| 37 static v8::Persistent<v8::Context> env; | 36 static v8::Persistent<v8::Context> env; |
| 38 | 37 |
| 39 | 38 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 71 Address ret_addr, | 70 Address ret_addr, |
| 72 Address func_start_addr, | 71 Address func_start_addr, |
| 73 unsigned int func_len) { | 72 unsigned int func_len) { |
| 74 printf("CheckRetAddrIsInFunction \"%s\": %p %p %p\n", | 73 printf("CheckRetAddrIsInFunction \"%s\": %p %p %p\n", |
| 75 func_name, func_start_addr, ret_addr, func_start_addr + func_len); | 74 func_name, func_start_addr, ret_addr, func_start_addr + func_len); |
| 76 CHECK_GE(ret_addr, func_start_addr); | 75 CHECK_GE(ret_addr, func_start_addr); |
| 77 CHECK_GE(func_start_addr + func_len, ret_addr); | 76 CHECK_GE(func_start_addr + func_len, ret_addr); |
| 78 } | 77 } |
| 79 | 78 |
| 80 | 79 |
| 81 static void CheckRetAddrIsInSharedFunctionInfo( | 80 static void CheckRetAddrIsInJSFunction(const char* func_name, |
| 82 const char* func_name, | 81 Address ret_addr, |
| 83 Address ret_addr, | 82 Handle<JSFunction> func) { |
| 84 Handle<SharedFunctionInfo> func) { | |
| 85 v8::internal::Code* func_code = func->code(); | 83 v8::internal::Code* func_code = func->code(); |
| 86 CheckRetAddrIsInFunction( | 84 CheckRetAddrIsInFunction( |
| 87 func_name, ret_addr, | 85 func_name, ret_addr, |
| 88 func_code->instruction_start(), | 86 func_code->instruction_start(), |
| 89 func_code->ExecutableSize()); | 87 func_code->ExecutableSize()); |
| 90 } | 88 } |
| 91 | 89 |
| 92 | 90 |
| 93 // --- T r a c e E x t e n s i o n --- | 91 // --- T r a c e E x t e n s i o n --- |
| 94 | 92 |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 185 v8::HandleScope scope; | 183 v8::HandleScope scope; |
| 186 const char* extensions[] = { "v8/trace" }; | 184 const char* extensions[] = { "v8/trace" }; |
| 187 v8::ExtensionConfiguration config(1, extensions); | 185 v8::ExtensionConfiguration config(1, extensions); |
| 188 env = v8::Context::New(&config); | 186 env = v8::Context::New(&config); |
| 189 } | 187 } |
| 190 v8::HandleScope scope; | 188 v8::HandleScope scope; |
| 191 env->Enter(); | 189 env->Enter(); |
| 192 } | 190 } |
| 193 | 191 |
| 194 | 192 |
| 195 static Handle<SharedFunctionInfo> CompileFunction(const char* source) { | 193 static Handle<JSFunction> CompileFunction(const char* source) { |
| 196 Handle<v8::internal::Object> obj = | 194 Handle<JSFunction> result(JSFunction::cast( |
| 197 v8::Utils::OpenHandle(*Script::Compile(String::New(source))); | 195 *v8::Utils::OpenHandle(*Script::Compile(String::New(source))))); |
| 198 Handle<SharedFunctionInfo> shared; | 196 return result; |
| 199 if (obj->IsSharedFunctionInfo()) { | |
| 200 shared = Handle<SharedFunctionInfo>(SharedFunctionInfo::cast(*obj)); | |
| 201 } else { | |
| 202 shared = Handle<SharedFunctionInfo>(JSFunction::cast(*obj)->shared()); | |
| 203 } | |
| 204 return shared; | |
| 205 } | 197 } |
| 206 | 198 |
| 207 | 199 |
| 208 static Local<Value> GetGlobalProperty(const char* name) { | 200 static Local<Value> GetGlobalProperty(const char* name) { |
| 209 return env->Global()->Get(String::New(name)); | 201 return env->Global()->Get(String::New(name)); |
| 210 } | 202 } |
| 211 | 203 |
| 212 | 204 |
| 213 static Handle<SharedFunctionInfo> GetGlobalJSFunction(const char* name) { | 205 static Handle<JSFunction> GetGlobalJSFunction(const char* name) { |
| 214 Handle<SharedFunctionInfo> js_func( | 206 Handle<JSFunction> result(JSFunction::cast( |
| 215 SharedFunctionInfo::cast( | 207 *v8::Utils::OpenHandle(*GetGlobalProperty(name)))); |
| 216 *(v8::Utils::OpenHandle(*GetGlobalProperty(name))))); | 208 return result; |
| 217 return js_func; | |
| 218 } | 209 } |
| 219 | 210 |
| 220 | 211 |
| 221 static void CheckRetAddrIsInSharedFunctionInfo(const char* func_name, | 212 static void CheckRetAddrIsInJSFunction(const char* func_name, |
| 222 Address ret_addr) { | 213 Address ret_addr) { |
| 223 CheckRetAddrIsInSharedFunctionInfo(func_name, | 214 CheckRetAddrIsInJSFunction(func_name, |
| 224 ret_addr, | 215 ret_addr, |
|
Kasper Lund
2010/03/23 11:53:28
Indentation.
mnaganov (inactive)
2010/03/23 12:39:18
Done.
| |
| 225 GetGlobalJSFunction(func_name)); | 216 GetGlobalJSFunction(func_name)); |
| 226 } | 217 } |
| 227 | 218 |
| 228 | 219 |
| 229 static void SetGlobalProperty(const char* name, Local<Value> value) { | 220 static void SetGlobalProperty(const char* name, Local<Value> value) { |
| 230 env->Global()->Set(String::New(name), value); | 221 env->Global()->Set(String::New(name), value); |
| 231 } | 222 } |
| 232 | 223 |
| 233 | 224 |
| 234 static Handle<v8::internal::String> NewString(const char* s) { | 225 static Handle<v8::internal::String> NewString(const char* s) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 271 // shifted right to be presented as Smi. | 262 // shifted right to be presented as Smi. |
| 272 static void CreateTraceCallerFunction(const char* func_name, | 263 static void CreateTraceCallerFunction(const char* func_name, |
| 273 const char* trace_func_name) { | 264 const char* trace_func_name) { |
| 274 i::EmbeddedVector<char, 256> trace_call_buf; | 265 i::EmbeddedVector<char, 256> trace_call_buf; |
| 275 i::OS::SNPrintF(trace_call_buf, "%s(%%_GetFramePointer());", trace_func_name); | 266 i::OS::SNPrintF(trace_call_buf, "%s(%%_GetFramePointer());", trace_func_name); |
| 276 | 267 |
| 277 // Compile the script. | 268 // Compile the script. |
| 278 i::CodeGeneratorPatcher patcher; | 269 i::CodeGeneratorPatcher patcher; |
| 279 bool allow_natives_syntax = i::FLAG_allow_natives_syntax; | 270 bool allow_natives_syntax = i::FLAG_allow_natives_syntax; |
| 280 i::FLAG_allow_natives_syntax = true; | 271 i::FLAG_allow_natives_syntax = true; |
| 281 Handle<SharedFunctionInfo> func = CompileFunction(trace_call_buf.start()); | 272 Handle<JSFunction> func = CompileFunction(trace_call_buf.start()); |
| 282 CHECK(!func.is_null()); | 273 CHECK(!func.is_null()); |
| 283 i::FLAG_allow_natives_syntax = allow_natives_syntax; | 274 i::FLAG_allow_natives_syntax = allow_natives_syntax; |
| 284 | 275 |
| 285 #ifdef DEBUG | 276 #ifdef DEBUG |
| 286 v8::internal::Code* func_code = func->code(); | 277 v8::internal::Code* func_code = func->code(); |
| 287 CHECK(func_code->IsCode()); | 278 CHECK(func_code->IsCode()); |
| 288 func_code->Print(); | 279 func_code->Print(); |
| 289 #endif | 280 #endif |
| 290 | 281 |
| 291 SetGlobalProperty(func_name, v8::ToApi<Value>(func)); | 282 SetGlobalProperty(func_name, v8::ToApi<Value>(func)); |
| 283 CHECK_EQ(*func, *GetGlobalJSFunction(func_name)); | |
| 292 } | 284 } |
| 293 | 285 |
| 294 | 286 |
| 295 TEST(CFromJSStackTrace) { | 287 TEST(CFromJSStackTrace) { |
| 296 // TODO(657): Fixup test after FunctionBoilerplate removal. | |
| 297 return; | |
| 298 | |
| 299 TickSample sample; | 288 TickSample sample; |
| 300 InitTraceEnv(&sample); | 289 InitTraceEnv(&sample); |
| 301 | 290 |
| 302 InitializeVM(); | 291 InitializeVM(); |
| 303 v8::HandleScope scope; | 292 v8::HandleScope scope; |
| 304 CreateTraceCallerFunction("JSFuncDoTrace", "trace"); | 293 CreateTraceCallerFunction("JSFuncDoTrace", "trace"); |
| 305 CompileRun( | 294 CHECK(!CompileRun( |
|
Kasper Lund
2010/03/23 11:53:28
I would create a local handle for the result and d
mnaganov (inactive)
2010/03/23 12:39:18
Good point. Done.
| |
| 306 "function JSTrace() {" | 295 "function JSTrace() {" |
| 307 " JSFuncDoTrace();" | 296 " JSFuncDoTrace();" |
| 308 "};\n" | 297 "};\n" |
| 309 "JSTrace();"); | 298 "JSTrace();\n" |
| 299 "true;").IsEmpty()); | |
| 310 CHECK_GT(sample.frames_count, 1); | 300 CHECK_GT(sample.frames_count, 1); |
| 311 // Stack sampling will start from the first JS function, i.e. "JSFuncDoTrace" | 301 // Stack sampling will start from the first JS function, i.e. "JSFuncDoTrace" |
| 312 CheckRetAddrIsInSharedFunctionInfo("JSFuncDoTrace", | 302 CheckRetAddrIsInJSFunction("JSFuncDoTrace", |
| 313 sample.stack[0]); | 303 sample.stack[0]); |
|
Kasper Lund
2010/03/23 11:53:28
Indentation.
mnaganov (inactive)
2010/03/23 12:39:18
Done.
| |
| 314 CheckRetAddrIsInSharedFunctionInfo("JSTrace", | 304 CheckRetAddrIsInJSFunction("JSTrace", |
| 315 sample.stack[1]); | 305 sample.stack[1]); |
|
Kasper Lund
2010/03/23 11:53:28
Indentation.
mnaganov (inactive)
2010/03/23 12:39:18
Done.
| |
| 316 } | 306 } |
| 317 | 307 |
| 318 | 308 |
| 319 TEST(PureJSStackTrace) { | 309 TEST(PureJSStackTrace) { |
| 320 // TODO(657): Fixup test after FunctionBoilerplate removal. | |
| 321 return; | |
| 322 | |
| 323 TickSample sample; | 310 TickSample sample; |
| 324 InitTraceEnv(&sample); | 311 InitTraceEnv(&sample); |
| 325 | 312 |
| 326 InitializeVM(); | 313 InitializeVM(); |
| 327 v8::HandleScope scope; | 314 v8::HandleScope scope; |
| 328 CreateTraceCallerFunction("JSFuncDoTrace", "js_trace"); | 315 CreateTraceCallerFunction("JSFuncDoTrace", "js_trace"); |
| 329 CompileRun( | 316 CHECK(!CompileRun( |
|
Kasper Lund
2010/03/23 11:53:28
I would create a local handle for the result and d
mnaganov (inactive)
2010/03/23 12:39:18
Done.
| |
| 330 "function JSTrace() {" | 317 "function JSTrace() {" |
| 331 " JSFuncDoTrace();" | 318 " JSFuncDoTrace();" |
| 332 "};\n" | 319 "};\n" |
| 333 "function OuterJSTrace() {" | 320 "function OuterJSTrace() {" |
| 334 " JSTrace();" | 321 " JSTrace();" |
| 335 "};\n" | 322 "};\n" |
| 336 "OuterJSTrace();"); | 323 "OuterJSTrace();\n" |
| 324 "true;").IsEmpty()); | |
| 337 // The last JS function called. | 325 // The last JS function called. |
| 338 CHECK_EQ(GetGlobalJSFunction("JSFuncDoTrace")->address(), | 326 CHECK_EQ(GetGlobalJSFunction("JSFuncDoTrace")->address(), |
| 339 sample.function); | 327 sample.function); |
| 340 CHECK_GT(sample.frames_count, 1); | 328 CHECK_GT(sample.frames_count, 1); |
| 341 // Stack sampling will start from the caller of JSFuncDoTrace, i.e. "JSTrace" | 329 // Stack sampling will start from the caller of JSFuncDoTrace, i.e. "JSTrace" |
| 342 CheckRetAddrIsInSharedFunctionInfo("JSTrace", | 330 CheckRetAddrIsInJSFunction("JSTrace", |
| 343 sample.stack[0]); | 331 sample.stack[0]); |
|
Kasper Lund
2010/03/23 11:53:28
Indentation.
mnaganov (inactive)
2010/03/23 12:39:18
Done.
| |
| 344 CheckRetAddrIsInSharedFunctionInfo("OuterJSTrace", | 332 CheckRetAddrIsInJSFunction("OuterJSTrace", |
| 345 sample.stack[1]); | 333 sample.stack[1]); |
|
Kasper Lund
2010/03/23 11:53:28
Indentation.
mnaganov (inactive)
2010/03/23 12:39:18
Done.
| |
| 346 } | 334 } |
| 347 | 335 |
| 348 | 336 |
| 349 static void CFuncDoTrace(byte dummy_parameter) { | 337 static void CFuncDoTrace(byte dummy_parameter) { |
| 350 Address fp; | 338 Address fp; |
| 351 #ifdef __GNUC__ | 339 #ifdef __GNUC__ |
| 352 fp = reinterpret_cast<Address>(__builtin_frame_address(0)); | 340 fp = reinterpret_cast<Address>(__builtin_frame_address(0)); |
| 353 #elif defined _MSC_VER | 341 #elif defined _MSC_VER |
| 354 // Approximate a frame pointer address. We compile without base pointers, | 342 // Approximate a frame pointer address. We compile without base pointers, |
| 355 // so we can't trust ebp/rbp. | 343 // so we can't trust ebp/rbp. |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 385 CHECK_EQ(0, GetJsEntrySp()); | 373 CHECK_EQ(0, GetJsEntrySp()); |
| 386 CompileRun("a = 1; b = a + 1;"); | 374 CompileRun("a = 1; b = a + 1;"); |
| 387 CHECK_EQ(0, GetJsEntrySp()); | 375 CHECK_EQ(0, GetJsEntrySp()); |
| 388 CompileRun("js_entry_sp();"); | 376 CompileRun("js_entry_sp();"); |
| 389 CHECK_EQ(0, GetJsEntrySp()); | 377 CHECK_EQ(0, GetJsEntrySp()); |
| 390 CompileRun("js_entry_sp_level2();"); | 378 CompileRun("js_entry_sp_level2();"); |
| 391 CHECK_EQ(0, GetJsEntrySp()); | 379 CHECK_EQ(0, GetJsEntrySp()); |
| 392 } | 380 } |
| 393 | 381 |
| 394 #endif // ENABLE_LOGGING_AND_PROFILING | 382 #endif // ENABLE_LOGGING_AND_PROFILING |
| OLD | NEW |