diff options
Diffstat (limited to 'V8Binding/v8/test/cctest')
-rw-r--r-- | V8Binding/v8/test/cctest/SConscript | 4 | ||||
-rw-r--r-- | V8Binding/v8/test/cctest/cctest.status | 6 | ||||
-rw-r--r-- | V8Binding/v8/test/cctest/test-api.cc | 190 | ||||
-rw-r--r-- | V8Binding/v8/test/cctest/test-ast.cc | 4 | ||||
-rw-r--r-- | V8Binding/v8/test/cctest/test-debug.cc | 68 | ||||
-rw-r--r-- | V8Binding/v8/test/cctest/test-heap.cc | 2 | ||||
-rw-r--r-- | V8Binding/v8/test/cctest/test-log-stack-tracer.cc (renamed from V8Binding/v8/test/cctest/test-log-ia32.cc) | 12 | ||||
-rw-r--r-- | V8Binding/v8/test/cctest/test-log.cc | 44 | ||||
-rw-r--r-- | V8Binding/v8/test/cctest/test-regexp.cc | 2 |
9 files changed, 312 insertions, 20 deletions
diff --git a/V8Binding/v8/test/cctest/SConscript b/V8Binding/v8/test/cctest/SConscript index 7506d29..112ecd6 100644 --- a/V8Binding/v8/test/cctest/SConscript +++ b/V8Binding/v8/test/cctest/SConscript @@ -63,9 +63,9 @@ SOURCES = { 'arch:ia32': [ 'test-assembler-ia32.cc', 'test-disasm-ia32.cc', - 'test-log-ia32.cc' + 'test-log-stack-tracer.cc' ], - 'arch:x64': ['test-assembler-x64.cc'], + 'arch:x64': ['test-assembler-x64.cc', 'test-log-stack-tracer.cc'], 'os:linux': ['test-platform-linux.cc'], 'os:macos': ['test-platform-macos.cc'], 'os:nullos': ['test-platform-nullos.cc'], diff --git a/V8Binding/v8/test/cctest/cctest.status b/V8Binding/v8/test/cctest/cctest.status index b234ca3..9abe408 100644 --- a/V8Binding/v8/test/cctest/cctest.status +++ b/V8Binding/v8/test/cctest/cctest.status @@ -63,7 +63,6 @@ test-api/TryCatchInTryFinally: FAIL [ $arch == x64 ] -test-regexp/Graph: PASS || CRASH || FAIL test-decls/Present: CRASH || FAIL test-decls/Unknown: CRASH || FAIL test-decls/Appearing: CRASH || FAIL @@ -113,10 +112,9 @@ test-debug/RecursiveBreakpoints: CRASH || FAIL test-debug/DebuggerUnload: CRASH || FAIL test-debug/DebuggerHostDispatch: CRASH || FAIL test-debug/DebugBreakInMessageHandler: CRASH || FAIL -test-api/HugeConsStringOutOfMemory: CRASH || FAIL -test-api/OutOfMemory: CRASH || FAIL -test-api/OutOfMemoryNested: CRASH || FAIL +test-debug/NoDebugBreakInAfterCompileMessageHandler: CRASH || FAIL test-api/Threading: CRASH || FAIL +test-api/Threading2: PASS || TIMEOUT test-api/TryCatchSourceInfo: CRASH || FAIL test-api/RegExpInterruption: PASS || TIMEOUT test-api/RegExpStringModification: PASS || TIMEOUT diff --git a/V8Binding/v8/test/cctest/test-api.cc b/V8Binding/v8/test/cctest/test-api.cc index 806e711..35ac031 100644 --- a/V8Binding/v8/test/cctest/test-api.cc +++ b/V8Binding/v8/test/cctest/test-api.cc @@ -633,6 +633,53 @@ THREADED_TEST(FunctionTemplate) { } +THREADED_TEST(FindInstanceInPrototypeChain) { + v8::HandleScope scope; + LocalContext env; + + Local<v8::FunctionTemplate> base = v8::FunctionTemplate::New(); + Local<v8::FunctionTemplate> derived = v8::FunctionTemplate::New(); + Local<v8::FunctionTemplate> other = v8::FunctionTemplate::New(); + derived->Inherit(base); + + Local<v8::Function> base_function = base->GetFunction(); + Local<v8::Function> derived_function = derived->GetFunction(); + Local<v8::Function> other_function = other->GetFunction(); + + Local<v8::Object> base_instance = base_function->NewInstance(); + Local<v8::Object> derived_instance = derived_function->NewInstance(); + Local<v8::Object> derived_instance2 = derived_function->NewInstance(); + Local<v8::Object> other_instance = other_function->NewInstance(); + derived_instance2->Set(v8_str("__proto__"), derived_instance); + other_instance->Set(v8_str("__proto__"), derived_instance2); + + // base_instance is only an instance of base. + CHECK_EQ(base_instance, + base_instance->FindInstanceInPrototypeChain(base)); + CHECK(base_instance->FindInstanceInPrototypeChain(derived).IsEmpty()); + CHECK(base_instance->FindInstanceInPrototypeChain(other).IsEmpty()); + + // derived_instance is an instance of base and derived. + CHECK_EQ(derived_instance, + derived_instance->FindInstanceInPrototypeChain(base)); + CHECK_EQ(derived_instance, + derived_instance->FindInstanceInPrototypeChain(derived)); + CHECK(derived_instance->FindInstanceInPrototypeChain(other).IsEmpty()); + + // other_instance is an instance of other and its immediate + // prototype derived_instance2 is an instance of base and derived. + // Note, derived_instance is an instance of base and derived too, + // but it comes after derived_instance2 in the prototype chain of + // other_instance. + CHECK_EQ(derived_instance2, + other_instance->FindInstanceInPrototypeChain(base)); + CHECK_EQ(derived_instance2, + other_instance->FindInstanceInPrototypeChain(derived)); + CHECK_EQ(other_instance, + other_instance->FindInstanceInPrototypeChain(other)); +} + + static v8::Handle<Value> handle_property(Local<String> name, const AccessorInfo&) { ApiTestFuzzer::Fuzz(); @@ -7548,3 +7595,146 @@ THREADED_TEST(Regress16276) { context->DetachGlobal(); CHECK_EQ(42, CompileRun("f(this).foo")->Int32Value()); } + + +THREADED_TEST(PixelArray) { + v8::HandleScope scope; + LocalContext context; + const int kElementCount = 40; + uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount)); + i::Handle<i::PixelArray> pixels = i::Factory::NewPixelArray(kElementCount, + pixel_data); + i::Heap::CollectAllGarbage(); // Force GC to trigger verification. + for (int i = 0; i < kElementCount; i++) { + pixels->set(i, i); + } + i::Heap::CollectAllGarbage(); // Force GC to trigger verification. + for (int i = 0; i < kElementCount; i++) { + CHECK_EQ(i, pixels->get(i)); + CHECK_EQ(i, pixel_data[i]); + } + + v8::Handle<v8::Object> obj = v8::Object::New(); + i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj); + // Set the elements to be the pixels. + // jsobj->set_elements(*pixels); + obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount); + CHECK_EQ(1, i::Smi::cast(jsobj->GetElement(1))->value()); + obj->Set(v8_str("field"), v8::Int32::New(1503)); + context->Global()->Set(v8_str("pixels"), obj); + v8::Handle<v8::Value> result = CompileRun("pixels.field"); + CHECK_EQ(1503, result->Int32Value()); + result = CompileRun("pixels[1]"); + CHECK_EQ(1, result->Int32Value()); + result = CompileRun("var sum = 0;" + "for (var i = 0; i < 8; i++) {" + " sum += pixels[i];" + "}" + "sum;"); + CHECK_EQ(28, result->Int32Value()); + + i::Handle<i::Smi> value(i::Smi::FromInt(2)); + i::SetElement(jsobj, 1, value); + CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(1))->value()); + *value.location() = i::Smi::FromInt(256); + i::SetElement(jsobj, 1, value); + CHECK_EQ(255, i::Smi::cast(jsobj->GetElement(1))->value()); + *value.location() = i::Smi::FromInt(-1); + i::SetElement(jsobj, 1, value); + CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(1))->value()); + + result = CompileRun("for (var i = 0; i < 8; i++) {" + " pixels[i] = (i * 65) - 109;" + "}" + "pixels[1] + pixels[6];"); + CHECK_EQ(255, result->Int32Value()); + CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(0))->value()); + CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(1))->value()); + CHECK_EQ(21, i::Smi::cast(jsobj->GetElement(2))->value()); + CHECK_EQ(86, i::Smi::cast(jsobj->GetElement(3))->value()); + CHECK_EQ(151, i::Smi::cast(jsobj->GetElement(4))->value()); + CHECK_EQ(216, i::Smi::cast(jsobj->GetElement(5))->value()); + CHECK_EQ(255, i::Smi::cast(jsobj->GetElement(6))->value()); + CHECK_EQ(255, i::Smi::cast(jsobj->GetElement(7))->value()); + result = CompileRun("var sum = 0;" + "for (var i = 0; i < 8; i++) {" + " sum += pixels[i];" + "}" + "sum;"); + CHECK_EQ(984, result->Int32Value()); + + result = CompileRun("for (var i = 0; i < 8; i++) {" + " pixels[i] = (i * 1.1);" + "}" + "pixels[1] + pixels[6];"); + CHECK_EQ(8, result->Int32Value()); + CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(0))->value()); + CHECK_EQ(1, i::Smi::cast(jsobj->GetElement(1))->value()); + CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(2))->value()); + CHECK_EQ(3, i::Smi::cast(jsobj->GetElement(3))->value()); + CHECK_EQ(4, i::Smi::cast(jsobj->GetElement(4))->value()); + CHECK_EQ(6, i::Smi::cast(jsobj->GetElement(5))->value()); + CHECK_EQ(7, i::Smi::cast(jsobj->GetElement(6))->value()); + CHECK_EQ(8, i::Smi::cast(jsobj->GetElement(7))->value()); + + result = CompileRun("for (var i = 0; i < 8; i++) {" + " pixels[7] = undefined;" + "}" + "pixels[7];"); + CHECK_EQ(0, result->Int32Value()); + CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(7))->value()); + + result = CompileRun("for (var i = 0; i < 8; i++) {" + " pixels[6] = '2.3';" + "}" + "pixels[6];"); + CHECK_EQ(2, result->Int32Value()); + CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(6))->value()); + + result = CompileRun("for (var i = 0; i < 8; i++) {" + " pixels[5] = NaN;" + "}" + "pixels[5];"); + CHECK_EQ(0, result->Int32Value()); + CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(5))->value()); + + result = CompileRun("for (var i = 0; i < 8; i++) {" + " pixels[8] = Infinity;" + "}" + "pixels[8];"); + CHECK_EQ(255, result->Int32Value()); + CHECK_EQ(255, i::Smi::cast(jsobj->GetElement(8))->value()); + + result = CompileRun("for (var i = 0; i < 8; i++) {" + " pixels[9] = -Infinity;" + "}" + "pixels[9];"); + CHECK_EQ(0, result->Int32Value()); + CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(9))->value()); + + result = CompileRun("pixels[3] = 33;" + "delete pixels[3];" + "pixels[3];"); + CHECK_EQ(33, result->Int32Value()); + + result = CompileRun("pixels[0] = 10; pixels[1] = 11;" + "pixels[2] = 12; pixels[3] = 13;" + "pixels.__defineGetter__('2'," + "function() { return 120; });" + "pixels[2];"); + CHECK_EQ(12, result->Int32Value()); + + result = CompileRun("var js_array = new Array(40);" + "js_array[0] = 77;" + "js_array;"); + CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value()); + + result = CompileRun("pixels[1] = 23;" + "pixels.__proto__ = [];" + "js_array.__proto__ = pixels;" + "js_array.concat(pixels);"); + CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value()); + CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value()); + + free(pixel_data); +} diff --git a/V8Binding/v8/test/cctest/test-ast.cc b/V8Binding/v8/test/cctest/test-ast.cc index 2054348..9931f56 100644 --- a/V8Binding/v8/test/cctest/test-ast.cc +++ b/V8Binding/v8/test/cctest/test-ast.cc @@ -35,11 +35,11 @@ using namespace v8::internal; TEST(List) { - List<Node*>* list = new List<Node*>(0); + List<AstNode*>* list = new List<AstNode*>(0); CHECK_EQ(0, list->length()); ZoneScope zone_scope(DELETE_ON_EXIT); - Node* node = new EmptyStatement(); + AstNode* node = new EmptyStatement(); list->Add(node); CHECK_EQ(1, list->length()); CHECK_EQ(node, list->at(0)); diff --git a/V8Binding/v8/test/cctest/test-debug.cc b/V8Binding/v8/test/cctest/test-debug.cc index fddd000..9e2c38d 100644 --- a/V8Binding/v8/test/cctest/test-debug.cc +++ b/V8Binding/v8/test/cctest/test-debug.cc @@ -4875,7 +4875,7 @@ TEST(DebugBreakInMessageHandler) { v8::Debug::SetMessageHandler2(DebugBreakMessageHandler); // Test functions. - const char* script = "function f() { debugger; } function g() { }"; + const char* script = "function f() { debugger; g(); } function g() { }"; CompileRun(script); v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f"))); @@ -4954,8 +4954,10 @@ TEST(RegExpDebugBreak) { v8::Debug::DebugBreak(); result = f->Call(env->Global(), argc, argv); - CHECK_EQ(20, break_point_hit_count); - CHECK_EQ("exec", last_function_hit); + // Check that there was only one break event. Matching RegExp should not + // cause Break events. + CHECK_EQ(1, break_point_hit_count); + CHECK_EQ("f", last_function_hit); } #endif // V8_NATIVE_REGEXP @@ -5295,3 +5297,63 @@ TEST(ProvisionalBreakpointOnLineOutOfRange) { ClearBreakPointFromJS(sbp2); v8::Debug::SetMessageHandler2(NULL); } + + +static void BreakMessageHandler(const v8::Debug::Message& message) { + if (message.IsEvent() && message.GetEvent() == v8::Break) { + // Count the number of breaks. + break_point_hit_count++; + + v8::HandleScope scope; + v8::Handle<v8::String> json = message.GetJSON(); + + SendContinueCommand(); + } else if (message.IsEvent() && message.GetEvent() == v8::AfterCompile) { + v8::HandleScope scope; + + bool is_debug_break = i::StackGuard::IsDebugBreak(); + // Force DebugBreak flag while serializer is working. + i::StackGuard::DebugBreak(); + + // Force serialization to trigger some internal JS execution. + v8::Handle<v8::String> json = message.GetJSON(); + + // Restore previous state. + if (is_debug_break) { + i::StackGuard::DebugBreak(); + } else { + i::StackGuard::Continue(i::DEBUGBREAK); + } + } +} + + +// Test that if DebugBreak is forced it is ignored when code from +// debug-delay.js is executed. +TEST(NoDebugBreakInAfterCompileMessageHandler) { + v8::HandleScope scope; + DebugLocalContext env; + + // Register a debug event listener which sets the break flag and counts. + v8::Debug::SetMessageHandler2(BreakMessageHandler); + + // Set the debug break flag. + v8::Debug::DebugBreak(); + + // Create a function for testing stepping. + const char* src = "function f() { eval('var x = 10;'); } "; + v8::Local<v8::Function> f = CompileFunction(&env, src, "f"); + + // There should be only one break event. + CHECK_EQ(1, break_point_hit_count); + + // Set the debug break flag again. + v8::Debug::DebugBreak(); + f->Call(env->Global(), 0, NULL); + // There should be one more break event when the script is evaluated in 'f'. + CHECK_EQ(2, break_point_hit_count); + + // Get rid of the debug message handler. + v8::Debug::SetMessageHandler2(NULL); + CheckDebuggerUnloaded(); +} diff --git a/V8Binding/v8/test/cctest/test-heap.cc b/V8Binding/v8/test/cctest/test-heap.cc index 5163ff9..6b5907c 100644 --- a/V8Binding/v8/test/cctest/test-heap.cc +++ b/V8Binding/v8/test/cctest/test-heap.cc @@ -653,7 +653,7 @@ TEST(JSArray) { uint32_t int_length = 0; CHECK(Array::IndexFromObject(length, &int_length)); CHECK_EQ(length, array->length()); - CHECK(!array->HasFastElements()); // Must be in slow mode. + CHECK(array->HasDictionaryElements()); // Must be in slow mode. // array[length] = name. array->SetElement(int_length, name); diff --git a/V8Binding/v8/test/cctest/test-log-ia32.cc b/V8Binding/v8/test/cctest/test-log-stack-tracer.cc index a40a800..1ef0a93 100644 --- a/V8Binding/v8/test/cctest/test-log-ia32.cc +++ b/V8Binding/v8/test/cctest/test-log-stack-tracer.cc @@ -50,7 +50,7 @@ static void DoTrace(Address fp) { trace_env.sample->fp = reinterpret_cast<uintptr_t>(fp); // sp is only used to define stack high bound trace_env.sample->sp = - reinterpret_cast<unsigned int>(trace_env.sample) - 10240; + reinterpret_cast<uintptr_t>(trace_env.sample) - 10240; StackTracer::Trace(trace_env.sample); } @@ -130,7 +130,10 @@ v8::Handle<v8::FunctionTemplate> TraceExtension::GetNativeFunction( Address TraceExtension::GetFP(const v8::Arguments& args) { CHECK_EQ(1, args.Length()); - Address fp = reinterpret_cast<Address>(args[0]->Int32Value() << 2); + // CodeGenerator::GenerateGetFramePointer pushes EBP / RBP value + // on stack. In 64-bit mode we can't use Smi operations code because + // they check that value is within Smi bounds. + Address fp = *reinterpret_cast<Address*>(*args[0]); printf("Trace: %p\n", fp); return fp; } @@ -330,8 +333,11 @@ static void CFuncDoTrace() { Address fp; #ifdef __GNUC__ fp = reinterpret_cast<Address>(__builtin_frame_address(0)); -#elif defined _MSC_VER +#elif defined _MSC_VER && defined V8_TARGET_ARCH_IA32 __asm mov [fp], ebp // NOLINT +#elif defined _MSC_VER && defined V8_TARGET_ARCH_X64 + // FIXME: I haven't really tried to compile it. + __asm movq [fp], rbp // NOLINT #endif DoTrace(fp); } diff --git a/V8Binding/v8/test/cctest/test-log.cc b/V8Binding/v8/test/cctest/test-log.cc index f3f7efc..df58234 100644 --- a/V8Binding/v8/test/cctest/test-log.cc +++ b/V8Binding/v8/test/cctest/test-log.cc @@ -4,8 +4,12 @@ #ifdef ENABLE_LOGGING_AND_PROFILING -#include "v8.h" +#ifdef __linux__ +#include <signal.h> +#include <unistd.h> +#endif +#include "v8.h" #include "log.h" #include "cctest.h" @@ -144,8 +148,25 @@ class LoggerTestHelper : public AllStatic { using v8::internal::LoggerTestHelper; +// Under Linux, we need to check if signals were delivered to avoid false +// positives. Under other platforms profiling is done via a high-priority +// thread, so this case never happen. +static bool was_sigprof_received = true; +#ifdef __linux__ + +struct sigaction old_sigprof_handler; + +static void SigProfSignalHandler(int signal, siginfo_t* info, void* context) { + if (signal != SIGPROF) return; + was_sigprof_received = true; + old_sigprof_handler.sa_sigaction(signal, info, context); +} + +#endif // __linux__ + + static int CheckThatProfilerWorks(int log_pos) { - Logger::ResumeProfiler(); + Logger::ResumeProfiler(v8::PROFILER_MODULE_CPU); CHECK(LoggerTestHelper::IsSamplerActive()); // Verify that the current map of compiled functions has been logged. @@ -160,6 +181,18 @@ static int CheckThatProfilerWorks(int log_pos) { const char* code_creation = "\ncode-creation,"; // eq. to /^code-creation,/ CHECK_NE(NULL, strstr(buffer.start(), code_creation)); +#ifdef __linux__ + // Intercept SIGPROF handler to make sure that the test process + // had received it. Under load, system can defer it causing test failure. + // It is important to execute this after 'ResumeProfiler'. + was_sigprof_received = false; + struct sigaction sa; + sa.sa_sigaction = SigProfSignalHandler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_SIGINFO; + CHECK_EQ(0, sigaction(SIGPROF, &sa, &old_sigprof_handler)); +#endif // __linux__ + // Force compiler to generate new code by parametrizing source. EmbeddedVector<char, 100> script_src; i::OS::SNPrintF(script_src, @@ -170,9 +203,11 @@ static int CheckThatProfilerWorks(int log_pos) { const double end_time = i::OS::TimeCurrentMillis() + 200; while (i::OS::TimeCurrentMillis() < end_time) { CompileAndRunScript(script_src.start()); + // Yield CPU to give Profiler thread a chance to process ticks. + i::OS::Sleep(1); } - Logger::PauseProfiler(); + Logger::PauseProfiler(v8::PROFILER_MODULE_CPU); CHECK(!LoggerTestHelper::IsSamplerActive()); // Wait 50 msecs to allow Profiler thread to process the last @@ -189,7 +224,8 @@ static int CheckThatProfilerWorks(int log_pos) { buffer[log_size] = '\0'; const char* tick = "\ntick,"; CHECK_NE(NULL, strstr(buffer.start(), code_creation)); - CHECK_NE(NULL, strstr(buffer.start(), tick)); + const bool ticks_found = strstr(buffer.start(), tick) != NULL; + CHECK_EQ(was_sigprof_received, ticks_found); return log_pos; } diff --git a/V8Binding/v8/test/cctest/test-regexp.cc b/V8Binding/v8/test/cctest/test-regexp.cc index 33a83c7..8d8326c 100644 --- a/V8Binding/v8/test/cctest/test-regexp.cc +++ b/V8Binding/v8/test/cctest/test-regexp.cc @@ -35,7 +35,7 @@ #include "zone-inl.h" #include "parser.h" #include "ast.h" -#include "jsregexp-inl.h" +#include "jsregexp.h" #include "regexp-macro-assembler.h" #include "regexp-macro-assembler-irregexp.h" #ifdef V8_TARGET_ARCH_ARM |