| 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 |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 168 } | 168 } |
| 169 | 169 |
| 170 | 170 |
| 171 static Handle<JSFunction> CompileFunction(const char* source) { | 171 static Handle<JSFunction> CompileFunction(const char* source) { |
| 172 Handle<JSFunction> result(JSFunction::cast( | 172 Handle<JSFunction> result(JSFunction::cast( |
| 173 *v8::Utils::OpenHandle(*Script::Compile(String::New(source))))); | 173 *v8::Utils::OpenHandle(*Script::Compile(String::New(source))))); |
| 174 return result; | 174 return result; |
| 175 } | 175 } |
| 176 | 176 |
| 177 | 177 |
| 178 static Local<Value> GetGlobalProperty(const char* name) { | 178 static void CheckJSFunctionAtAddress(const char* func_name, Address addr) { |
| 179 return env->Global()->Get(String::New(name)); | 179 i::Object* obj = i::HeapObject::FromAddress(addr); |
| 180 } | |
| 181 | |
| 182 | |
| 183 static Handle<JSFunction> GetGlobalJSFunction(const char* name) { | |
| 184 Handle<JSFunction> result(JSFunction::cast( | |
| 185 *v8::Utils::OpenHandle(*GetGlobalProperty(name)))); | |
| 186 return result; | |
| 187 } | |
| 188 | |
| 189 | |
| 190 static void CheckObjectIsJSFunction(const char* func_name, | |
| 191 Address addr) { | |
| 192 i::Object* obj = reinterpret_cast<i::Object*>(addr); | |
| 193 CHECK(obj->IsJSFunction()); | 180 CHECK(obj->IsJSFunction()); |
| 194 CHECK(JSFunction::cast(obj)->shared()->name()->IsString()); | 181 CHECK(JSFunction::cast(obj)->shared()->name()->IsString()); |
| 195 i::SmartPointer<char> found_name = | 182 i::SmartPointer<char> found_name = |
| 196 i::String::cast( | 183 i::String::cast( |
| 197 JSFunction::cast( | 184 JSFunction::cast( |
| 198 obj)->shared()->name())->ToCString(); | 185 obj)->shared()->name())->ToCString(); |
| 199 CHECK_EQ(func_name, *found_name); | 186 CHECK_EQ(func_name, *found_name); |
| 200 } | 187 } |
| 201 | 188 |
| 202 | 189 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 257 i::FLAG_allow_natives_syntax = allow_natives_syntax; | 244 i::FLAG_allow_natives_syntax = allow_natives_syntax; |
| 258 func->shared()->set_name(*NewString(func_name)); | 245 func->shared()->set_name(*NewString(func_name)); |
| 259 | 246 |
| 260 #ifdef DEBUG | 247 #ifdef DEBUG |
| 261 v8::internal::Code* func_code = func->code(); | 248 v8::internal::Code* func_code = func->code(); |
| 262 CHECK(func_code->IsCode()); | 249 CHECK(func_code->IsCode()); |
| 263 func_code->Print(); | 250 func_code->Print(); |
| 264 #endif | 251 #endif |
| 265 | 252 |
| 266 SetGlobalProperty(func_name, v8::ToApi<Value>(func)); | 253 SetGlobalProperty(func_name, v8::ToApi<Value>(func)); |
| 267 CHECK_EQ(*func, *GetGlobalJSFunction(func_name)); | |
| 268 } | 254 } |
| 269 | 255 |
| 270 | 256 |
| 271 // This test verifies that stack tracing works when called during | 257 // This test verifies that stack tracing works when called during |
| 272 // execution of a native function called from JS code. In this case, | 258 // 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 | 259 // StackTracer uses Top::c_entry_fp as a starting point for stack |
| 274 // walking. | 260 // walking. |
| 275 TEST(CFromJSStackTrace) { | 261 TEST(CFromJSStackTrace) { |
| 276 // TODO(711): The hack of replacing the inline runtime function | 262 // TODO(711): The hack of replacing the inline runtime function |
| 277 // RandomHeapNumber with GetFrameNumber does not work with the way | 263 // RandomHeapNumber with GetFrameNumber does not work with the way |
| (...skipping 13 matching lines...) Expand all Loading... |
| 291 "function JSTrace() {" | 277 "function JSTrace() {" |
| 292 " JSFuncDoTrace();" | 278 " JSFuncDoTrace();" |
| 293 "};\n" | 279 "};\n" |
| 294 "JSTrace();\n" | 280 "JSTrace();\n" |
| 295 "true;"); | 281 "true;"); |
| 296 CHECK(!result.IsEmpty()); | 282 CHECK(!result.IsEmpty()); |
| 297 // When stack tracer is invoked, the stack should look as follows: | 283 // When stack tracer is invoked, the stack should look as follows: |
| 298 // script [JS] | 284 // script [JS] |
| 299 // JSTrace() [JS] | 285 // JSTrace() [JS] |
| 300 // JSFuncDoTrace() [JS] [captures EBP value and encodes it as Smi] | 286 // JSFuncDoTrace() [JS] [captures EBP value and encodes it as Smi] |
| 301 // trace(EBP encoded as Smi) [native (extension)] | 287 // trace(EBP) [native (extension)] |
| 302 // DoTrace(EBP) [native] | 288 // DoTrace(EBP) [native] |
| 303 // StackTracer::Trace | 289 // StackTracer::Trace |
| 304 CHECK_GT(sample.frames_count, 1); | 290 CHECK_GT(sample.frames_count, 1); |
| 305 // Stack tracing will start from the first JS function, i.e. "JSFuncDoTrace" | 291 // Stack tracing will start from the first JS function, i.e. "JSFuncDoTrace" |
| 306 CheckObjectIsJSFunction("JSFuncDoTrace", sample.stack[0]); | 292 CheckJSFunctionAtAddress("JSFuncDoTrace", sample.stack[0]); |
| 307 CheckObjectIsJSFunction("JSTrace", sample.stack[1]); | 293 CheckJSFunctionAtAddress("JSTrace", sample.stack[1]); |
| 308 } | 294 } |
| 309 | 295 |
| 310 | 296 |
| 311 // This test verifies that stack tracing works when called during | 297 // This test verifies that stack tracing works when called during |
| 312 // execution of JS code. However, as calling StackTracer requires | 298 // execution of JS code. However, as calling StackTracer requires |
| 313 // entering native code, we can only emulate pure JS by erasing | 299 // entering native code, we can only emulate pure JS by erasing |
| 314 // Top::c_entry_fp value. In this case, StackTracer uses passed frame | 300 // Top::c_entry_fp value. In this case, StackTracer uses passed frame |
| 315 // pointer value as a starting point for stack walking. | 301 // pointer value as a starting point for stack walking. |
| 316 TEST(PureJSStackTrace) { | 302 TEST(PureJSStackTrace) { |
| 317 // TODO(711): The hack of replacing the inline runtime function | 303 // TODO(711): The hack of replacing the inline runtime function |
| (...skipping 17 matching lines...) Expand all Loading... |
| 335 "function OuterJSTrace() {" | 321 "function OuterJSTrace() {" |
| 336 " JSTrace();" | 322 " JSTrace();" |
| 337 "};\n" | 323 "};\n" |
| 338 "OuterJSTrace();\n" | 324 "OuterJSTrace();\n" |
| 339 "true;"); | 325 "true;"); |
| 340 CHECK(!result.IsEmpty()); | 326 CHECK(!result.IsEmpty()); |
| 341 // When stack tracer is invoked, the stack should look as follows: | 327 // When stack tracer is invoked, the stack should look as follows: |
| 342 // script [JS] | 328 // script [JS] |
| 343 // OuterJSTrace() [JS] | 329 // OuterJSTrace() [JS] |
| 344 // JSTrace() [JS] | 330 // JSTrace() [JS] |
| 345 // JSFuncDoTrace() [JS] [captures EBP value and encodes it as Smi] | 331 // JSFuncDoTrace() [JS] |
| 346 // js_trace(EBP encoded as Smi) [native (extension)] | 332 // js_trace(EBP) [native (extension)] |
| 347 // DoTraceHideCEntryFPAddress(EBP) [native] | 333 // DoTraceHideCEntryFPAddress(EBP) [native] |
| 348 // StackTracer::Trace | 334 // StackTracer::Trace |
| 349 // | 335 // |
| 350 // The last JS function called. It is only visible through | 336 // The last JS function called. It is only visible through |
| 351 // sample.function, as its return address is above captured EBP value. | 337 // sample.function, as its return address is above captured EBP value. |
| 352 CHECK_EQ(GetGlobalJSFunction("JSFuncDoTrace")->address(), | 338 CheckJSFunctionAtAddress("JSFuncDoTrace", sample.function); |
| 353 sample.function); | |
| 354 CHECK_GT(sample.frames_count, 1); | 339 CHECK_GT(sample.frames_count, 1); |
| 355 // Stack sampling will start from the caller of JSFuncDoTrace, i.e. "JSTrace" | 340 // Stack sampling will start from the caller of JSFuncDoTrace, i.e. "JSTrace" |
| 356 CheckObjectIsJSFunction("JSTrace", sample.stack[0]); | 341 CheckJSFunctionAtAddress("JSTrace", sample.stack[0]); |
| 357 CheckObjectIsJSFunction("OuterJSTrace", sample.stack[1]); | 342 CheckJSFunctionAtAddress("OuterJSTrace", sample.stack[1]); |
| 358 } | 343 } |
| 359 | 344 |
| 360 | 345 |
| 361 static void CFuncDoTrace(byte dummy_parameter) { | 346 static void CFuncDoTrace(byte dummy_parameter) { |
| 362 Address fp; | 347 Address fp; |
| 363 #ifdef __GNUC__ | 348 #ifdef __GNUC__ |
| 364 fp = reinterpret_cast<Address>(__builtin_frame_address(0)); | 349 fp = reinterpret_cast<Address>(__builtin_frame_address(0)); |
| 365 #elif defined _MSC_VER | 350 #elif defined _MSC_VER |
| 366 // Approximate a frame pointer address. We compile without base pointers, | 351 // Approximate a frame pointer address. We compile without base pointers, |
| 367 // so we can't trust ebp/rbp. | 352 // so we can't trust ebp/rbp. |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 400 CHECK_EQ(0, GetJsEntrySp()); | 385 CHECK_EQ(0, GetJsEntrySp()); |
| 401 CompileRun("a = 1; b = a + 1;"); | 386 CompileRun("a = 1; b = a + 1;"); |
| 402 CHECK_EQ(0, GetJsEntrySp()); | 387 CHECK_EQ(0, GetJsEntrySp()); |
| 403 CompileRun("js_entry_sp();"); | 388 CompileRun("js_entry_sp();"); |
| 404 CHECK_EQ(0, GetJsEntrySp()); | 389 CHECK_EQ(0, GetJsEntrySp()); |
| 405 CompileRun("js_entry_sp_level2();"); | 390 CompileRun("js_entry_sp_level2();"); |
| 406 CHECK_EQ(0, GetJsEntrySp()); | 391 CHECK_EQ(0, GetJsEntrySp()); |
| 407 } | 392 } |
| 408 | 393 |
| 409 #endif // ENABLE_LOGGING_AND_PROFILING | 394 #endif // ENABLE_LOGGING_AND_PROFILING |
| OLD | NEW |