diff options
Diffstat (limited to 'deps/v8/test/cctest/test-debug.cc')
-rw-r--r-- | deps/v8/test/cctest/test-debug.cc | 265 |
1 files changed, 189 insertions, 76 deletions
diff --git a/deps/v8/test/cctest/test-debug.cc b/deps/v8/test/cctest/test-debug.cc index 5c0b0f392d..2f0674a34d 100644 --- a/deps/v8/test/cctest/test-debug.cc +++ b/deps/v8/test/cctest/test-debug.cc @@ -36,7 +36,6 @@ #include "src/debug.h" #include "src/deoptimizer.h" #include "src/frames.h" -#include "src/stub-cache.h" #include "src/utils.h" #include "test/cctest/cctest.h" @@ -74,16 +73,23 @@ using ::v8::internal::StrLength; class DebugLocalContext { public: inline DebugLocalContext( + v8::Isolate* isolate, v8::ExtensionConfiguration* extensions = 0, + v8::Handle<v8::ObjectTemplate> global_template = + v8::Handle<v8::ObjectTemplate>(), + v8::Handle<v8::Value> global_object = v8::Handle<v8::Value>()) + : scope_(isolate), + context_(v8::Context::New(isolate, extensions, global_template, + global_object)) { + context_->Enter(); + } + inline DebugLocalContext( v8::ExtensionConfiguration* extensions = 0, v8::Handle<v8::ObjectTemplate> global_template = v8::Handle<v8::ObjectTemplate>(), v8::Handle<v8::Value> global_object = v8::Handle<v8::Value>()) : scope_(CcTest::isolate()), - context_( - v8::Context::New(CcTest::isolate(), - extensions, - global_template, - global_object)) { + context_(v8::Context::New(CcTest::isolate(), extensions, + global_template, global_object)) { context_->Enter(); } inline ~DebugLocalContext() { @@ -108,7 +114,7 @@ class DebugLocalContext { Handle<JSGlobalProxy> global(Handle<JSGlobalProxy>::cast( v8::Utils::OpenHandle(*context_->Global()))); Handle<v8::internal::String> debug_string = - factory->InternalizeOneByteString(STATIC_ASCII_VECTOR("debug")); + factory->InternalizeOneByteString(STATIC_CHAR_VECTOR("debug")); v8::internal::Runtime::DefineObjectProperty(global, debug_string, handle(debug_context->global_proxy(), isolate), DONT_ENUM).Check(); } @@ -138,8 +144,7 @@ static v8::Local<v8::Function> CompileFunction(v8::Isolate* isolate, const char* source, const char* function_name) { v8::Script::Compile(v8::String::NewFromUtf8(isolate, source))->Run(); - v8::Local<v8::Object> global = - CcTest::isolate()->GetCurrentContext()->Global(); + v8::Local<v8::Object> global = isolate->GetCurrentContext()->Global(); return v8::Local<v8::Function>::Cast( global->Get(v8::String::NewFromUtf8(isolate, function_name))); } @@ -670,6 +675,8 @@ static void DebugEventBreakPointHitCount( int exception_hit_count = 0; int uncaught_exception_hit_count = 0; int last_js_stack_height = -1; +v8::Handle<v8::Function> debug_event_listener_callback; +int debug_event_listener_callback_result; static void DebugEventCounterClear() { break_point_hit_count = 0; @@ -710,9 +717,17 @@ static void DebugEventCounter( static const int kArgc = 1; v8::Handle<v8::Value> argv[kArgc] = { exec_state }; // Using exec_state as receiver is just to have a receiver. - v8::Handle<v8::Value> result = frame_count->Call(exec_state, kArgc, argv); + v8::Handle<v8::Value> result = frame_count->Call(exec_state, kArgc, argv); last_js_stack_height = result->Int32Value(); } + + // Run callback from DebugEventListener and check the result. + if (!debug_event_listener_callback.IsEmpty()) { + v8::Handle<v8::Value> result = + debug_event_listener_callback->Call(event_data, 0, NULL); + CHECK(!result.IsEmpty()); + CHECK_EQ(debug_event_listener_callback_result, result->Int32Value()); + } } @@ -750,6 +765,7 @@ static void DebugEventEvaluate( CHECK_NE(debug->break_id(), 0); if (event == v8::Break) { + break_point_hit_count++; for (int i = 0; checks[i].expr != NULL; i++) { const int argc = 3; v8::Handle<v8::Value> argv[argc] = { @@ -2391,7 +2407,7 @@ TEST(DebugEvaluate) { }; // Simple test function. The "y=0" is in the function foo to provide a break - // location. For "y=0" the "y" is at position 15 in the barbar function + // location. For "y=0" the "y" is at position 15 in the foo function // therefore setting breakpoint at position 15 will break at "y=0" and // setting it higher will break after. v8::Local<v8::Function> foo = CompileFunction(&env, @@ -2424,6 +2440,34 @@ TEST(DebugEvaluate) { checks = checks_hh; foo->Call(env->Global(), 1, argv_foo); + // Test that overriding Object.prototype will not interfere into evaluation + // on call frame. + v8::Local<v8::Function> zoo = + CompileFunction(&env, + "x = undefined;" + "function zoo(t) {" + " var a=x;" + " Object.prototype.x = 42;" + " x=t;" + " y=0;" // To ensure break location. + " delete Object.prototype.x;" + " x=a;" + "}", + "zoo"); + const int zoo_break_position = 50; + + // Arguments with one parameter "Hello, world!" + v8::Handle<v8::Value> argv_zoo[1] = { + v8::String::NewFromUtf8(env->GetIsolate(), "Hello, world!")}; + + // Call zoo with breakpoint set at y=0. + DebugEventCounterClear(); + bp = SetBreakPoint(zoo, zoo_break_position); + checks = checks_hu; + zoo->Call(env->Global(), 1, argv_zoo); + CHECK_EQ(1, break_point_hit_count); + ClearBreakPoint(bp); + // Test function with an inner function. The "y=0" is in function barbar // to provide a break location. For "y=0" the "y" is at position 8 in the // barbar function therefore setting breakpoint at position 8 will break at @@ -3968,6 +4012,43 @@ TEST(BreakOnException) { } +TEST(EvalJSInDebugEventListenerOnNativeReThrownException) { + DebugLocalContext env; + v8::HandleScope scope(env->GetIsolate()); + env.ExposeDebug(); + + // Create functions for testing break on exception. + v8::Local<v8::Function> noThrowJS = CompileFunction( + &env, "function noThrowJS(){var a=[1]; a.push(2); return a.length;}", + "noThrowJS"); + + debug_event_listener_callback = noThrowJS; + debug_event_listener_callback_result = 2; + + v8::V8::AddMessageListener(MessageCallbackCount); + v8::Debug::SetDebugEventListener(DebugEventCounter); + // Break on uncaught exception + ChangeBreakOnException(false, true); + DebugEventCounterClear(); + MessageCallbackCountClear(); + + // ReThrow native error + { + v8::TryCatch tryCatch; + env->GetIsolate()->ThrowException(v8::Exception::TypeError( + v8::String::NewFromUtf8(env->GetIsolate(), "Type error"))); + CHECK(tryCatch.HasCaught()); + tryCatch.ReThrow(); + } + CHECK_EQ(1, exception_hit_count); + CHECK_EQ(1, uncaught_exception_hit_count); + CHECK_EQ(0, message_callback_count); // FIXME: Should it be 1 ? + CHECK(!debug_event_listener_callback.IsEmpty()); + + debug_event_listener_callback.Clear(); +} + + // Test break on exception from compiler errors. When compiling using // v8::Script::Compile there is no JavaScript stack whereas when compiling using // eval there are JavaScript frames. @@ -4151,10 +4232,11 @@ TEST(DebugBreak) { // Set the debug break flag. v8::Debug::DebugBreak(env->GetIsolate()); + CHECK(v8::Debug::CheckDebugBreak(env->GetIsolate())); // Call all functions with different argument count. break_point_hit_count = 0; - for (unsigned int i = 0; i < ARRAY_SIZE(argv); i++) { + for (unsigned int i = 0; i < arraysize(argv); i++) { f0->Call(env->Global(), i, argv); f1->Call(env->Global(), i, argv); f2->Call(env->Global(), i, argv); @@ -4162,7 +4244,7 @@ TEST(DebugBreak) { } // One break for each function called. - CHECK_EQ(4 * ARRAY_SIZE(argv), break_point_hit_count); + CHECK_EQ(4 * arraysize(argv), break_point_hit_count); // Get rid of the debug event listener. v8::Debug::SetDebugEventListener(NULL); @@ -4183,6 +4265,12 @@ TEST(DisableBreak) { const char* src = "function f() {g()};function g(){i=0; while(i<10){i++}}"; v8::Local<v8::Function> f = CompileFunction(&env, src, "f"); + // Set, test and cancel debug break. + v8::Debug::DebugBreak(env->GetIsolate()); + CHECK(v8::Debug::CheckDebugBreak(env->GetIsolate())); + v8::Debug::CancelDebugBreak(env->GetIsolate()); + CHECK(!v8::Debug::CheckDebugBreak(env->GetIsolate())); + // Set the debug break flag. v8::Debug::DebugBreak(env->GetIsolate()); @@ -4377,10 +4465,6 @@ TEST(InterceptorPropertyMirror) { "named_values[%d] instanceof debug.PropertyMirror", i); CHECK(CompileRun(buffer.start())->BooleanValue()); - SNPrintF(buffer, "named_values[%d].propertyType()", i); - CHECK_EQ(v8::internal::INTERCEPTOR, - CompileRun(buffer.start())->Int32Value()); - SNPrintF(buffer, "named_values[%d].isNative()", i); CHECK(CompileRun(buffer.start())->BooleanValue()); } @@ -4696,7 +4780,7 @@ TEST(NoHiddenProperties) { // The Wait() call blocks a thread until it is called for the Nth time, then all // calls return. Each ThreadBarrier object can only be used once. template <int N> -class ThreadBarrier V8_FINAL { +class ThreadBarrier FINAL { public: ThreadBarrier() : num_blocked_(0) {} @@ -5106,12 +5190,20 @@ class V8Thread : public v8::base::Thread { public: V8Thread() : Thread(Options("V8Thread")) {} void Run(); + v8::Isolate* isolate() { return isolate_; } + + private: + v8::Isolate* isolate_; }; class DebuggerThread : public v8::base::Thread { public: - DebuggerThread() : Thread(Options("DebuggerThread")) {} + explicit DebuggerThread(v8::Isolate* isolate) + : Thread(Options("DebuggerThread")), isolate_(isolate) {} void Run(); + + private: + v8::Isolate* isolate_; }; @@ -5154,22 +5246,25 @@ void V8Thread::Run() { "\n" "foo();\n"; - v8::Isolate* isolate = CcTest::isolate(); - v8::Isolate::Scope isolate_scope(isolate); - DebugLocalContext env; - v8::HandleScope scope(env->GetIsolate()); - v8::Debug::SetMessageHandler(&ThreadedMessageHandler); - v8::Handle<v8::ObjectTemplate> global_template = - v8::ObjectTemplate::New(env->GetIsolate()); - global_template->Set( - v8::String::NewFromUtf8(env->GetIsolate(), "ThreadedAtBarrier1"), - v8::FunctionTemplate::New(isolate, ThreadedAtBarrier1)); - v8::Handle<v8::Context> context = v8::Context::New(isolate, - NULL, - global_template); - v8::Context::Scope context_scope(context); - - CompileRun(source); + isolate_ = v8::Isolate::New(); + threaded_debugging_barriers.barrier_3.Wait(); + { + v8::Isolate::Scope isolate_scope(isolate_); + DebugLocalContext env(isolate_); + v8::HandleScope scope(isolate_); + v8::Debug::SetMessageHandler(&ThreadedMessageHandler); + v8::Handle<v8::ObjectTemplate> global_template = + v8::ObjectTemplate::New(env->GetIsolate()); + global_template->Set( + v8::String::NewFromUtf8(env->GetIsolate(), "ThreadedAtBarrier1"), + v8::FunctionTemplate::New(isolate_, ThreadedAtBarrier1)); + v8::Handle<v8::Context> context = + v8::Context::New(isolate_, NULL, global_template); + v8::Context::Scope context_scope(context); + + CompileRun(source); + } + isolate_->Dispose(); } @@ -5185,21 +5280,21 @@ void DebuggerThread::Run() { "\"type\":\"request\"," "\"command\":\"continue\"}"; - v8::Isolate* isolate = CcTest::isolate(); threaded_debugging_barriers.barrier_1.Wait(); - v8::Debug::DebugBreak(isolate); + v8::Debug::DebugBreak(isolate_); threaded_debugging_barriers.barrier_2.Wait(); - v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_1, buffer)); - v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_2, buffer)); + v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_1, buffer)); + v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_2, buffer)); } TEST(ThreadedDebugging) { - DebuggerThread debugger_thread; V8Thread v8_thread; // Create a V8 environment v8_thread.Start(); + threaded_debugging_barriers.barrier_3.Wait(); + DebuggerThread debugger_thread(v8_thread.isolate()); debugger_thread.Start(); v8_thread.Join(); @@ -5218,17 +5313,24 @@ class BreakpointsV8Thread : public v8::base::Thread { public: BreakpointsV8Thread() : Thread(Options("BreakpointsV8Thread")) {} void Run(); + + v8::Isolate* isolate() { return isolate_; } + + private: + v8::Isolate* isolate_; }; class BreakpointsDebuggerThread : public v8::base::Thread { public: - explicit BreakpointsDebuggerThread(bool global_evaluate) + BreakpointsDebuggerThread(bool global_evaluate, v8::Isolate* isolate) : Thread(Options("BreakpointsDebuggerThread")), - global_evaluate_(global_evaluate) {} + global_evaluate_(global_evaluate), + isolate_(isolate) {} void Run(); private: bool global_evaluate_; + v8::Isolate* isolate_; }; @@ -5273,16 +5375,20 @@ void BreakpointsV8Thread::Run() { const char* source_2 = "cat(17);\n" "cat(19);\n"; - v8::Isolate* isolate = CcTest::isolate(); - v8::Isolate::Scope isolate_scope(isolate); - DebugLocalContext env; - v8::HandleScope scope(isolate); - v8::Debug::SetMessageHandler(&BreakpointsMessageHandler); - - CompileRun(source_1); - breakpoints_barriers->barrier_1.Wait(); - breakpoints_barriers->barrier_2.Wait(); - CompileRun(source_2); + isolate_ = v8::Isolate::New(); + breakpoints_barriers->barrier_3.Wait(); + { + v8::Isolate::Scope isolate_scope(isolate_); + DebugLocalContext env(isolate_); + v8::HandleScope scope(isolate_); + v8::Debug::SetMessageHandler(&BreakpointsMessageHandler); + + CompileRun(source_1); + breakpoints_barriers->barrier_1.Wait(); + breakpoints_barriers->barrier_2.Wait(); + CompileRun(source_2); + } + isolate_->Dispose(); } @@ -5348,14 +5454,12 @@ void BreakpointsDebuggerThread::Run() { "\"command\":\"continue\"}"; - v8::Isolate* isolate = CcTest::isolate(); - v8::Isolate::Scope isolate_scope(isolate); // v8 thread initializes, runs source_1 breakpoints_barriers->barrier_1.Wait(); // 1:Set breakpoint in cat() (will get id 1). - v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_1, buffer)); + v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_1, buffer)); // 2:Set breakpoint in dog() (will get id 2). - v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_2, buffer)); + v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_2, buffer)); breakpoints_barriers->barrier_2.Wait(); // V8 thread starts compiling source_2. // Automatic break happens, to run queued commands @@ -5367,43 +5471,42 @@ void BreakpointsDebuggerThread::Run() { // Must have hit breakpoint #1. CHECK_EQ(1, break_event_breakpoint_id); // 4:Evaluate dog() (which has a breakpoint). - v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_3, buffer)); + v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_3, buffer)); // V8 thread hits breakpoint in dog(). breakpoints_barriers->semaphore_1.Wait(); // wait for break event // Must have hit breakpoint #2. CHECK_EQ(2, break_event_breakpoint_id); // 5:Evaluate (x + 1). - v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_4, buffer)); + v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_4, buffer)); // Evaluate (x + 1) finishes. breakpoints_barriers->semaphore_1.Wait(); // Must have result 108. CHECK_EQ(108, evaluate_int_result); // 6:Continue evaluation of dog(). - v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_5, buffer)); + v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_5, buffer)); // Evaluate dog() finishes. breakpoints_barriers->semaphore_1.Wait(); // Must have result 107. CHECK_EQ(107, evaluate_int_result); // 7:Continue evaluation of source_2, finish cat(17), hit breakpoint // in cat(19). - v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_6, buffer)); + v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_6, buffer)); // Message callback gets break event. breakpoints_barriers->semaphore_1.Wait(); // wait for break event // Must have hit breakpoint #1. CHECK_EQ(1, break_event_breakpoint_id); // 8: Evaluate dog() with breaks disabled. - v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_7, buffer)); + v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_7, buffer)); // Evaluate dog() finishes. breakpoints_barriers->semaphore_1.Wait(); // Must have result 116. CHECK_EQ(116, evaluate_int_result); // 9: Continue evaluation of source2, reach end. - v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_8, buffer)); + v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_8, buffer)); } void TestRecursiveBreakpointsGeneric(bool global_evaluate) { - BreakpointsDebuggerThread breakpoints_debugger_thread(global_evaluate); BreakpointsV8Thread breakpoints_v8_thread; // Create a V8 environment @@ -5411,6 +5514,9 @@ void TestRecursiveBreakpointsGeneric(bool global_evaluate) { breakpoints_barriers = &stack_allocated_breakpoints_barriers; breakpoints_v8_thread.Start(); + breakpoints_barriers->barrier_3.Wait(); + BreakpointsDebuggerThread breakpoints_debugger_thread( + global_evaluate, breakpoints_v8_thread.isolate()); breakpoints_debugger_thread.Start(); breakpoints_v8_thread.Join(); @@ -6522,6 +6628,10 @@ TEST(ProcessDebugMessages) { } +class SendCommandThread; +static SendCommandThread* send_command_thread_ = NULL; + + class SendCommandThread : public v8::base::Thread { public: explicit SendCommandThread(v8::Isolate* isolate) @@ -6529,9 +6639,12 @@ class SendCommandThread : public v8::base::Thread { semaphore_(0), isolate_(isolate) {} - static void ProcessDebugMessages(v8::Isolate* isolate, void* data) { - v8::Debug::ProcessDebugMessages(); - reinterpret_cast<v8::base::Semaphore*>(data)->Signal(); + static void CountingAndSignallingMessageHandler( + const v8::Debug::Message& message) { + if (message.IsResponse()) { + counting_message_handler_counter++; + send_command_thread_->semaphore_.Signal(); + } } virtual void Run() { @@ -6545,21 +6658,22 @@ class SendCommandThread : public v8::base::Thread { int length = AsciiToUtf16(scripts_command, buffer); // Send scripts command. - for (int i = 0; i < 100; i++) { + for (int i = 0; i < 20; i++) { + v8::base::ElapsedTimer timer; + timer.Start(); CHECK_EQ(i, counting_message_handler_counter); // Queue debug message. v8::Debug::SendCommand(isolate_, buffer, length); - // Synchronize with the main thread to force message processing. - isolate_->RequestInterrupt(ProcessDebugMessages, &semaphore_); + // Wait for the message handler to pick up the response. semaphore_.Wait(); + i::PrintF("iteration %d took %f ms\n", i, + timer.Elapsed().InMillisecondsF()); } v8::V8::TerminateExecution(isolate_); } - void StartSending() { - semaphore_.Signal(); - } + void StartSending() { semaphore_.Signal(); } private: v8::base::Semaphore semaphore_; @@ -6567,8 +6681,6 @@ class SendCommandThread : public v8::base::Thread { }; -static SendCommandThread* send_command_thread_ = NULL; - static void StartSendingCommands( const v8::FunctionCallbackInfo<v8::Value>& info) { send_command_thread_->StartSending(); @@ -6582,7 +6694,8 @@ TEST(ProcessDebugMessagesThreaded) { counting_message_handler_counter = 0; - v8::Debug::SetMessageHandler(CountingMessageHandler); + v8::Debug::SetMessageHandler( + SendCommandThread::CountingAndSignallingMessageHandler); send_command_thread_ = new SendCommandThread(isolate); send_command_thread_->Start(); @@ -6592,7 +6705,7 @@ TEST(ProcessDebugMessagesThreaded) { CompileRun("start(); while (true) { }"); - CHECK_EQ(100, counting_message_handler_counter); + CHECK_EQ(20, counting_message_handler_counter); v8::Debug::SetMessageHandler(NULL); CheckDebuggerUnloaded(); |