📄 test-debug.cc.svn-base
字号:
Handle<v8::internal::JSFunction> fun = v8::Utils::OpenHandle( *CompileFunction(env, source, name)); int bp = SetBreakPoint(fun, position); // Check that the debug break function is as expected. Handle<v8::internal::SharedFunctionInfo> shared(fun->shared()); CHECK(Debug::HasDebugInfo(shared)); TestBreakLocationIterator it1(Debug::GetDebugInfo(shared)); it1.FindBreakLocationFromPosition(position); CHECK_EQ(mode, it1.it()->rinfo()->rmode()); if (mode != v8::internal::RelocInfo::JS_RETURN) { CHECK_EQ(debug_break, Debug::GetCodeTarget(it1.it()->rinfo()->target_address())); } else { // TODO(1240753): Make the test architecture independent or split // parts of the debugger into architecture dependent files. CHECK_EQ(0xE8, *(it1.rinfo()->pc())); } // Clear the break point and check that the debug break function is no longer // there ClearBreakPoint(bp); CHECK(!Debug::HasDebugInfo(shared)); CHECK(Debug::EnsureDebugInfo(shared)); TestBreakLocationIterator it2(Debug::GetDebugInfo(shared)); it2.FindBreakLocationFromPosition(position); CHECK_EQ(mode, it2.it()->rinfo()->rmode()); if (mode == v8::internal::RelocInfo::JS_RETURN) { // TODO(1240753): Make the test architecture independent or split // parts of the debugger into architecture dependent files. CHECK_NE(0xE8, *(it2.rinfo()->pc())); }}// --- D e b u g E v e n t H a n d l e r s// ---// --- The different tests uses a number of debug event handlers.// ---// Source for The JavaScript function which picks out the function name on the// top frame.const char* frame_function_name_source = "function frame_function_name(exec_state) {" " return exec_state.frame(0).func().name();" "}";v8::Local<v8::Function> frame_function_name;// Global variable to store the last function hit - used by some tests.char last_function_hit[80];// Debug event handler which counts the break points which have been hit.int break_point_hit_count = 0;static void DebugEventBreakPointHitCount(v8::DebugEvent event, v8::Handle<v8::Object> exec_state, v8::Handle<v8::Object> event_data, v8::Handle<v8::Value> data) { // Count the number of breaks. if (event == v8::Break) { break_point_hit_count++; if (!frame_function_name.IsEmpty()) { // Get the name of the function. const int argc = 1; v8::Handle<v8::Value> argv[argc] = { exec_state }; v8::Handle<v8::Value> result = frame_function_name->Call(exec_state, argc, argv); if (result->IsUndefined()) { last_function_hit[0] = '\0'; } else { CHECK(result->IsString()); v8::Handle<v8::String> function_name(result->ToString()); function_name->WriteAscii(last_function_hit); } } }}// Debug event handler which counts a number of events.int exception_hit_count = 0;int uncaught_exception_hit_count = 0;static void DebugEventCounterClear() { break_point_hit_count = 0; exception_hit_count = 0; uncaught_exception_hit_count = 0;}static void DebugEventCounter(v8::DebugEvent event, v8::Handle<v8::Object> exec_state, v8::Handle<v8::Object> event_data, v8::Handle<v8::Value> data) { // Count the number of breaks. if (event == v8::Break) { break_point_hit_count++; } else if (event == v8::Exception) { exception_hit_count++; // Check whether the exception was uncaught. v8::Local<v8::String> fun_name = v8::String::New("uncaught"); v8::Local<v8::Function> fun = v8::Function::Cast(*event_data->Get(fun_name)); v8::Local<v8::Value> result = *fun->Call(event_data, 0, NULL); if (result->IsTrue()) { uncaught_exception_hit_count++; } }}// Debug event handler which evaluates a number of expressions when a break// point is hit. Each evaluated expression is compared with an expected value.// For this debug event handler to work the following two global varaibles// must be initialized.// checks: An array of expressions and expected results// evaluate_check_function: A JavaScript function (see below)// Structure for holding checks to do.struct EvaluateCheck { const char* expr; // An expression to evaluate when a break point is hit. v8::Handle<v8::Value> expected; // The expected result.};// Array of checks to do.struct EvaluateCheck* checks = NULL;// Source for The JavaScript function which can do the evaluation when a break// point is hit.const char* evaluate_check_source = "function evaluate_check(exec_state, expr, expected) {" " return exec_state.frame(0).evaluate(expr).value() === expected;" "}";v8::Local<v8::Function> evaluate_check_function;// The actual debug event described by the longer comment above.static void DebugEventEvaluate(v8::DebugEvent event, v8::Handle<v8::Object> exec_state, v8::Handle<v8::Object> event_data, v8::Handle<v8::Value> data) { if (event == v8::Break) { for (int i = 0; checks[i].expr != NULL; i++) { const int argc = 3; v8::Handle<v8::Value> argv[argc] = { exec_state, v8::String::New(checks[i].expr), checks[i].expected }; v8::Handle<v8::Value> result = evaluate_check_function->Call(exec_state, argc, argv); if (!result->IsTrue()) { v8::String::AsciiValue ascii(checks[i].expected->ToString()); V8_Fatal(__FILE__, __LINE__, "%s != %s", checks[i].expr, *ascii); } } }}// This debug event listener removes a breakpoint in a functionint debug_event_remove_break_point = 0;static void DebugEventRemoveBreakPoint(v8::DebugEvent event, v8::Handle<v8::Object> exec_state, v8::Handle<v8::Object> event_data, v8::Handle<v8::Value> data) { if (event == v8::Break) { break_point_hit_count++; v8::Handle<v8::Function> fun = v8::Handle<v8::Function>::Cast(data); ClearBreakPoint(debug_event_remove_break_point); }}// Debug event handler which counts break points hit and performs a step// afterwards.StepAction step_action = StepIn; // Step action to perform when stepping.static void DebugEventStep(v8::DebugEvent event, v8::Handle<v8::Object> exec_state, v8::Handle<v8::Object> event_data, v8::Handle<v8::Value> data) { if (event == v8::Break) { break_point_hit_count++; PrepareStep(step_action); }}// Debug event handler which counts break points hit and performs a step// afterwards. For each call the expected function is checked.// For this debug event handler to work the following two global varaibles// must be initialized.// expected_step_sequence: An array of the expected function call sequence.// frame_function_name: A JavaScript function (see below).// String containing the expected function call sequence. Note: this only works// if functions have name length of one.const char* expected_step_sequence = NULL;// The actual debug event described by the longer comment above.static void DebugEventStepSequence(v8::DebugEvent event, v8::Handle<v8::Object> exec_state, v8::Handle<v8::Object> event_data, v8::Handle<v8::Value> data) { if (event == v8::Break || event == v8::Exception) { // Check that the current function is the expected. CHECK(break_point_hit_count < static_cast<int>(strlen(expected_step_sequence))); const int argc = 1; v8::Handle<v8::Value> argv[argc] = { exec_state }; v8::Handle<v8::Value> result = frame_function_name->Call(exec_state, argc, argv); CHECK(result->IsString()); v8::String::AsciiValue function_name(result->ToString()); CHECK_EQ(1, strlen(*function_name)); CHECK_EQ((*function_name)[0], expected_step_sequence[break_point_hit_count]); // Perform step. break_point_hit_count++; PrepareStep(step_action); }}// Debug event handler which performs a garbage collection.static void DebugEventBreakPointCollectGarbage( v8::DebugEvent event, v8::Handle<v8::Object> exec_state, v8::Handle<v8::Object> event_data, v8::Handle<v8::Value> data) { // Perform a garbage collection when break point is hit and continue. Based // on the number of break points hit either scavenge or mark compact // collector is used. if (event == v8::Break) { break_point_hit_count++; if (break_point_hit_count % 2 == 0) { // Scavenge. Heap::CollectGarbage(0, v8::internal::NEW_SPACE); } else { // Mark sweep (and perhaps compact). Heap::CollectAllGarbage(); } }}// Debug event handler which re-issues a debug break and calls the garbage// collector to have the heap verified.static void DebugEventBreak(v8::DebugEvent event, v8::Handle<v8::Object> exec_state, v8::Handle<v8::Object> event_data, v8::Handle<v8::Value> data) { if (event == v8::Break) { // Count the number of breaks. break_point_hit_count++; // Run the garbage collector to enforce heap verification if option // --verify-heap is set. Heap::CollectGarbage(0, v8::internal::NEW_SPACE); // Set the break flag again to come back here as soon as possible. v8::Debug::DebugBreak(); }}// --- M e s s a g e C a l l b a c k// Message callback which counts the number of messages.int message_callback_count = 0;static void MessageCallbackCountClear() { message_callback_count = 0;}static void MessageCallbackCount(v8::Handle<v8::Message> message, v8::Handle<v8::Value> data) { message_callback_count++;}// --- T h e A c t u a l T e s t s// Test that the debug break function is the expected one for different kinds// of break locations.TEST(DebugStub) { using ::v8::internal::Builtins; v8::HandleScope scope; DebugLocalContext env; CheckDebugBreakFunction(&env, "function f1(){}", "f1", 0, v8::internal::RelocInfo::JS_RETURN, NULL); CheckDebugBreakFunction(&env, "function f2(){x=1;}", "f2", 0, v8::internal::RelocInfo::CODE_TARGET, Builtins::builtin(Builtins::StoreIC_DebugBreak)); CheckDebugBreakFunction(&env, "function f3(){var a=x;}", "f3", 0, v8::internal::RelocInfo::CODE_TARGET_CONTEXT, Builtins::builtin(Builtins::LoadIC_DebugBreak));// TODO(1240753): Make the test architecture independent or split// parts of the debugger into architecture dependent files. This// part currently disabled as it is not portable between IA32/ARM.// Currently on ICs for keyed store/load on ARM.#if !defined (__arm__) && !defined(__thumb__) CheckDebugBreakFunction( &env, "function f4(){var index='propertyName'; var a={}; a[index] = 'x';}", "f4", 0, v8::internal::RelocInfo::CODE_TARGET, Builtins::builtin(Builtins::KeyedStoreIC_DebugBreak)); CheckDebugBreakFunction( &env, "function f5(){var index='propertyName'; var a={}; return a[index];}", "f5", 0, v8::internal::RelocInfo::CODE_TARGET, Builtins::builtin(Builtins::KeyedLoadIC_DebugBreak));#endif // Check the debug break code stubs for call ICs with different number of // parameters. Handle<Code> debug_break_0 = v8::internal::ComputeCallDebugBreak(0); Handle<Code> debug_break_1 = v8::internal::ComputeCallDebugBreak(1); Handle<Code> debug_break_4 = v8::internal::ComputeCallDebugBreak(4); CheckDebugBreakFunction(&env, "function f4_0(){x();}", "f4_0", 0, v8::internal::RelocInfo::CODE_TARGET_CONTEXT, *debug_break_0); CheckDebugBreakFunction(&env, "function f4_1(){x(1);}", "f4_1", 0, v8::internal::RelocInfo::CODE_TARGET_CONTEXT, *debug_break_1); CheckDebugBreakFunction(&env, "function f4_4(){x(1,2,3,4);}", "f4_4", 0, v8::internal::RelocInfo::CODE_TARGET_CONTEXT, *debug_break_4);}// Test that the debug info in the VM is in sync with the functions being// debugged.TEST(DebugInfo) { v8::HandleScope scope; DebugLocalContext env; // Create a couple of functions for the test. v8::Local<v8::Function> foo = CompileFunction(&env, "function foo(){}", "foo"); v8::Local<v8::Function> bar = CompileFunction(&env, "function bar(){}", "bar"); // Initially no functions are debugged. CHECK_EQ(0, v8::internal::GetDebuggedFunctions()->length()); CHECK(!HasDebugInfo(foo)); CHECK(!HasDebugInfo(bar)); // One function (foo) is debugged. int bp1 = SetBreakPoint(foo, 0); CHECK_EQ(1, v8::internal::GetDebuggedFunctions()->length()); CHECK(HasDebugInfo(foo)); CHECK(!HasDebugInfo(bar)); // Two functions are debugged. int bp2 = SetBreakPoint(bar, 0); CHECK_EQ(2, v8::internal::GetDebuggedFunctions()->length()); CHECK(HasDebugInfo(foo)); CHECK(HasDebugInfo(bar)); // One function (bar) is debugged. ClearBreakPoint(bp1); CHECK_EQ(1, v8::internal::GetDebuggedFunctions()->length()); CHECK(!HasDebugInfo(foo)); CHECK(HasDebugInfo(bar)); // No functions are debugged.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -