diff options
| author | Ben Murdoch <benm@google.com> | 2010-10-22 12:50:53 +0100 |
|---|---|---|
| committer | Ben Murdoch <benm@google.com> | 2010-10-22 20:03:06 +0100 |
| commit | f87a203d89e1bbb6708282e0b64dbd13d59b723d (patch) | |
| tree | d7658572059125113d4052a87e2e2c1251419c64 /test | |
| parent | 0d5e116f6aee03185f237311a943491bb079a768 (diff) | |
| download | android_external_v8-f87a203d89e1bbb6708282e0b64dbd13d59b723d.tar.gz android_external_v8-f87a203d89e1bbb6708282e0b64dbd13d59b723d.tar.bz2 android_external_v8-f87a203d89e1bbb6708282e0b64dbd13d59b723d.zip | |
Update V8 to r5675 as required by WebKit r70209
Change-Id: Ib10adb470d41ca8c109ead5fc893b880e18d489f
Diffstat (limited to 'test')
26 files changed, 1386 insertions, 151 deletions
diff --git a/test/cctest/SConscript b/test/cctest/SConscript index 3ec621e6..006653c2 100644 --- a/test/cctest/SConscript +++ b/test/cctest/SConscript @@ -70,6 +70,7 @@ SOURCES = { 'test-sockets.cc', 'test-spaces.cc', 'test-strings.cc', + 'test-strtod.cc', 'test-thread-termination.cc', 'test-threads.cc', 'test-type-info.cc', diff --git a/test/cctest/cctest.status b/test/cctest/cctest.status index d03f5f7a..895e2453 100644 --- a/test/cctest/cctest.status +++ b/test/cctest/cctest.status @@ -35,11 +35,6 @@ test-debug/DebuggerAgent: PASS, (PASS || FAIL) if $system == linux # BUG(382): Weird test. Can't guarantee that it never times out. test-api/ApplyInterruption: PASS || TIMEOUT -# Bug (484): This test which we thought was originally corrected in r5236 -# is reappering. Disabled until bug in test is fixed. This only fails -# when snapshot is on, so I am marking it PASS || FAIL -test-heap-profiler/HeapSnapshotsDiff: PASS || FAIL - # These tests always fail. They are here to test test.py. If # they don't fail then test.py has failed. test-serialize/TestThatAlwaysFails: FAIL diff --git a/test/cctest/test-alloc.cc b/test/cctest/test-alloc.cc index 315a34ed..2936d6e7 100644 --- a/test/cctest/test-alloc.cc +++ b/test/cctest/test-alloc.cc @@ -37,13 +37,13 @@ using namespace v8::internal; static Object* AllocateAfterFailures() { static int attempts = 0; - if (++attempts < 3) return Failure::RetryAfterGC(0); + if (++attempts < 3) return Failure::RetryAfterGC(); // New space. NewSpace* new_space = Heap::new_space(); static const int kNewSpaceFillerSize = ByteArray::SizeFor(0); while (new_space->Available() > kNewSpaceFillerSize) { - int available_before = new_space->Available(); + int available_before = static_cast<int>(new_space->Available()); CHECK(!Heap::AllocateByteArray(0)->IsFailure()); if (available_before == new_space->Available()) { // It seems that we are avoiding new space allocations when diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc index 1b6359b4..fd44aec4 100644 --- a/test/cctest/test-api.cc +++ b/test/cctest/test-api.cc @@ -431,8 +431,8 @@ THREADED_TEST(ScriptMakingExternalString) { LocalContext env; Local<String> source = String::New(two_byte_source); // Trigger GCs so that the newly allocated string moves to old gen. - i::Heap::CollectGarbage(0, i::NEW_SPACE); // in survivor space now - i::Heap::CollectGarbage(0, i::NEW_SPACE); // in old gen now + i::Heap::CollectGarbage(i::NEW_SPACE); // in survivor space now + i::Heap::CollectGarbage(i::NEW_SPACE); // in old gen now bool success = source->MakeExternal(new TestResource(two_byte_source)); CHECK(success); Local<Script> script = Script::Compile(source); @@ -456,8 +456,8 @@ THREADED_TEST(ScriptMakingExternalAsciiString) { LocalContext env; Local<String> source = v8_str(c_source); // Trigger GCs so that the newly allocated string moves to old gen. - i::Heap::CollectGarbage(0, i::NEW_SPACE); // in survivor space now - i::Heap::CollectGarbage(0, i::NEW_SPACE); // in old gen now + i::Heap::CollectGarbage(i::NEW_SPACE); // in survivor space now + i::Heap::CollectGarbage(i::NEW_SPACE); // in old gen now bool success = source->MakeExternal( new TestAsciiResource(i::StrDup(c_source))); CHECK(success); @@ -479,8 +479,8 @@ TEST(MakingExternalStringConditions) { LocalContext env; // Free some space in the new space so that we can check freshness. - i::Heap::CollectGarbage(0, i::NEW_SPACE); - i::Heap::CollectGarbage(0, i::NEW_SPACE); + i::Heap::CollectGarbage(i::NEW_SPACE); + i::Heap::CollectGarbage(i::NEW_SPACE); uint16_t* two_byte_string = AsciiToTwoByteString("small"); Local<String> small_string = String::New(two_byte_string); @@ -489,8 +489,8 @@ TEST(MakingExternalStringConditions) { // We should refuse to externalize newly created small string. CHECK(!small_string->CanMakeExternal()); // Trigger GCs so that the newly allocated string moves to old gen. - i::Heap::CollectGarbage(0, i::NEW_SPACE); // in survivor space now - i::Heap::CollectGarbage(0, i::NEW_SPACE); // in old gen now + i::Heap::CollectGarbage(i::NEW_SPACE); // in survivor space now + i::Heap::CollectGarbage(i::NEW_SPACE); // in old gen now // Old space strings should be accepted. CHECK(small_string->CanMakeExternal()); @@ -525,15 +525,15 @@ TEST(MakingExternalAsciiStringConditions) { LocalContext env; // Free some space in the new space so that we can check freshness. - i::Heap::CollectGarbage(0, i::NEW_SPACE); - i::Heap::CollectGarbage(0, i::NEW_SPACE); + i::Heap::CollectGarbage(i::NEW_SPACE); + i::Heap::CollectGarbage(i::NEW_SPACE); Local<String> small_string = String::New("small"); // We should refuse to externalize newly created small string. CHECK(!small_string->CanMakeExternal()); // Trigger GCs so that the newly allocated string moves to old gen. - i::Heap::CollectGarbage(0, i::NEW_SPACE); // in survivor space now - i::Heap::CollectGarbage(0, i::NEW_SPACE); // in old gen now + i::Heap::CollectGarbage(i::NEW_SPACE); // in survivor space now + i::Heap::CollectGarbage(i::NEW_SPACE); // in old gen now // Old space strings should be accepted. CHECK(small_string->CanMakeExternal()); @@ -565,8 +565,8 @@ THREADED_TEST(UsingExternalString) { String::NewExternal(new TestResource(two_byte_string)); i::Handle<i::String> istring = v8::Utils::OpenHandle(*string); // Trigger GCs so that the newly allocated string moves to old gen. - i::Heap::CollectGarbage(0, i::NEW_SPACE); // in survivor space now - i::Heap::CollectGarbage(0, i::NEW_SPACE); // in old gen now + i::Heap::CollectGarbage(i::NEW_SPACE); // in survivor space now + i::Heap::CollectGarbage(i::NEW_SPACE); // in old gen now i::Handle<i::String> isymbol = i::Factory::SymbolFromString(istring); CHECK(isymbol->IsSymbol()); } @@ -583,8 +583,8 @@ THREADED_TEST(UsingExternalAsciiString) { new TestAsciiResource(i::StrDup(one_byte_string))); i::Handle<i::String> istring = v8::Utils::OpenHandle(*string); // Trigger GCs so that the newly allocated string moves to old gen. - i::Heap::CollectGarbage(0, i::NEW_SPACE); // in survivor space now - i::Heap::CollectGarbage(0, i::NEW_SPACE); // in old gen now + i::Heap::CollectGarbage(i::NEW_SPACE); // in survivor space now + i::Heap::CollectGarbage(i::NEW_SPACE); // in old gen now i::Handle<i::String> isymbol = i::Factory::SymbolFromString(istring); CHECK(isymbol->IsSymbol()); } @@ -602,12 +602,12 @@ THREADED_TEST(ScavengeExternalString) { Local<String> string = String::NewExternal(new TestResource(two_byte_string)); i::Handle<i::String> istring = v8::Utils::OpenHandle(*string); - i::Heap::CollectGarbage(0, i::NEW_SPACE); + i::Heap::CollectGarbage(i::NEW_SPACE); in_new_space = i::Heap::InNewSpace(*istring); CHECK(in_new_space || i::Heap::old_data_space()->Contains(*istring)); CHECK_EQ(0, TestResource::dispose_count); } - i::Heap::CollectGarbage(0, in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE); + i::Heap::CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE); CHECK_EQ(1, TestResource::dispose_count); } @@ -621,12 +621,12 @@ THREADED_TEST(ScavengeExternalAsciiString) { Local<String> string = String::NewExternal( new TestAsciiResource(i::StrDup(one_byte_string))); i::Handle<i::String> istring = v8::Utils::OpenHandle(*string); - i::Heap::CollectGarbage(0, i::NEW_SPACE); + i::Heap::CollectGarbage(i::NEW_SPACE); in_new_space = i::Heap::InNewSpace(*istring); CHECK(in_new_space || i::Heap::old_data_space()->Contains(*istring)); CHECK_EQ(0, TestAsciiResource::dispose_count); } - i::Heap::CollectGarbage(0, in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE); + i::Heap::CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE); CHECK_EQ(1, TestAsciiResource::dispose_count); } @@ -766,6 +766,12 @@ static v8::Handle<Value> construct_call(const v8::Arguments& args) { return args.This(); } +static v8::Handle<Value> Return239(Local<String> name, const AccessorInfo&) { + ApiTestFuzzer::Fuzz(); + return v8_num(239); +} + + THREADED_TEST(FunctionTemplate) { v8::HandleScope scope; LocalContext env; @@ -792,6 +798,7 @@ THREADED_TEST(FunctionTemplate) { Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(construct_call); fun_templ->SetClassName(v8_str("funky")); + fun_templ->InstanceTemplate()->SetAccessor(v8_str("m"), Return239); Local<Function> fun = fun_templ->GetFunction(); env->Global()->Set(v8_str("obj"), fun); Local<Script> script = v8_compile("var s = new obj(); s.x"); @@ -799,6 +806,9 @@ THREADED_TEST(FunctionTemplate) { Local<Value> result = v8_compile("(new obj()).toString()")->Run(); CHECK_EQ(v8_str("[object funky]"), result); + + result = v8_compile("(new obj()).m")->Run(); + CHECK_EQ(239, result->Int32Value()); } } @@ -1485,9 +1495,9 @@ THREADED_TEST(InternalFieldsNativePointers) { char* data = new char[100]; void* aligned = data; - CHECK_EQ(0, reinterpret_cast<uintptr_t>(aligned) & 0x1); + CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(aligned) & 0x1)); void* unaligned = data + 1; - CHECK_EQ(1, reinterpret_cast<uintptr_t>(unaligned) & 0x1); + CHECK_EQ(1, static_cast<int>(reinterpret_cast<uintptr_t>(unaligned) & 0x1)); // Check reading and writing aligned pointers. obj->SetPointerInInternalField(0, aligned); @@ -1517,9 +1527,9 @@ THREADED_TEST(InternalFieldsNativePointersAndExternal) { char* data = new char[100]; void* aligned = data; - CHECK_EQ(0, reinterpret_cast<uintptr_t>(aligned) & 0x1); + CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(aligned) & 0x1)); void* unaligned = data + 1; - CHECK_EQ(1, reinterpret_cast<uintptr_t>(unaligned) & 0x1); + CHECK_EQ(1, static_cast<int>(reinterpret_cast<uintptr_t>(unaligned) & 0x1)); obj->SetPointerInInternalField(0, aligned); i::Heap::CollectAllGarbage(false); @@ -3061,7 +3071,7 @@ THREADED_TEST(IndexedInterceptorWithIndexedAccessor) { static v8::Handle<Value> IdentityIndexedPropertyGetter( uint32_t index, const AccessorInfo& info) { - return v8::Integer::New(index); + return v8::Integer::NewFromUnsigned(index); } @@ -3186,6 +3196,45 @@ THREADED_TEST(IndexedInterceptorWithDifferentIndices) { } +THREADED_TEST(IndexedInterceptorWithNegativeIndices) { + v8::HandleScope scope; + Local<ObjectTemplate> templ = ObjectTemplate::New(); + templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter); + + LocalContext context; + Local<v8::Object> obj = templ->NewInstance(); + context->Global()->Set(v8_str("obj"), obj); + + const char* code = + "try {" + " for (var i = 0; i < 100; i++) {" + " var expected = i;" + " var key = i;" + " if (i == 25) {" + " key = -1;" + " expected = undefined;" + " }" + " if (i == 50) {" + " /* probe minimal Smi number on 32-bit platforms */" + " key = -(1 << 30);" + " expected = undefined;" + " }" + " if (i == 75) {" + " /* probe minimal Smi number on 64-bit platforms */" + " key = 1 << 31;" + " expected = undefined;" + " }" + " var v = obj[key];" + " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;" + " }" + " 'PASSED'" + "} catch(e) {" + " e" + "}"; + ExpectString(code, "PASSED"); +} + + THREADED_TEST(IndexedInterceptorWithNotSmiLookup) { v8::HandleScope scope; Local<ObjectTemplate> templ = ObjectTemplate::New(); @@ -3199,11 +3248,12 @@ THREADED_TEST(IndexedInterceptorWithNotSmiLookup) { "try {" " for (var i = 0; i < 100; i++) {" " var expected = i;" + " var key = i;" " if (i == 50) {" - " i = 'foobar';" + " key = 'foobar';" " expected = undefined;" " }" - " var v = obj[i];" + " var v = obj[key];" " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;" " }" " 'PASSED'" @@ -6469,12 +6519,6 @@ THREADED_TEST(InterceptorLoadICInvalidatedFieldViaGlobal) { } -static v8::Handle<Value> Return239(Local<String> name, const AccessorInfo&) { - ApiTestFuzzer::Fuzz(); - return v8_num(239); -} - - static void SetOnThis(Local<String> name, Local<Value> value, const AccessorInfo& info) { @@ -8059,7 +8103,7 @@ static int GetGlobalObjectsCount() { } -static int GetSurvivingGlobalObjectsCount() { +static void CheckSurvivingGlobalObjectsCount(int expected) { // We need to collect all garbage twice to be sure that everything // has been collected. This is because inline caches are cleared in // the first garbage collection but some of the maps have already @@ -8069,9 +8113,9 @@ static int GetSurvivingGlobalObjectsCount() { i::Heap::CollectAllGarbage(false); int count = GetGlobalObjectsCount(); #ifdef DEBUG - if (count > 0) i::Heap::TracePathToGlobal(); + if (count != expected) i::Heap::TracePathToGlobal(); #endif - return count; + CHECK_EQ(expected, count); } @@ -8080,25 +8124,23 @@ TEST(DontLeakGlobalObjects) { v8::V8::Initialize(); - int count = GetSurvivingGlobalObjectsCount(); - for (int i = 0; i < 5; i++) { { v8::HandleScope scope; LocalContext context; } - CHECK_EQ(count, GetSurvivingGlobalObjectsCount()); + CheckSurvivingGlobalObjectsCount(0); { v8::HandleScope scope; LocalContext context; v8_compile("Date")->Run(); } - CHECK_EQ(count, GetSurvivingGlobalObjectsCount()); + CheckSurvivingGlobalObjectsCount(0); { v8::HandleScope scope; LocalContext context; v8_compile("/aaa/")->Run(); } - CHECK_EQ(count, GetSurvivingGlobalObjectsCount()); + CheckSurvivingGlobalObjectsCount(0); { v8::HandleScope scope; const char* extension_list[] = { "v8/gc" }; @@ -8106,7 +8148,7 @@ TEST(DontLeakGlobalObjects) { LocalContext context(&extensions); v8_compile("gc();")->Run(); } - CHECK_EQ(count, GetSurvivingGlobalObjectsCount()); + CheckSurvivingGlobalObjectsCount(0); } } @@ -10517,6 +10559,45 @@ TEST(CaptureStackTraceForUncaughtException) { } +v8::Handle<Value> AnalyzeStackOfEvalWithSourceURL(const v8::Arguments& args) { + v8::HandleScope scope; + v8::Handle<v8::StackTrace> stackTrace = + v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kDetailed); + CHECK_EQ(5, stackTrace->GetFrameCount()); + v8::Handle<v8::String> url = v8_str("eval_url"); + for (int i = 0; i < 3; i++) { + v8::Handle<v8::String> name = + stackTrace->GetFrame(i)->GetScriptNameOrSourceURL(); + CHECK(!name.IsEmpty()); + CHECK_EQ(url, name); + } + return v8::Undefined(); +} + + +TEST(SourceURLInStackTrace) { + v8::HandleScope scope; + Local<ObjectTemplate> templ = ObjectTemplate::New(); + templ->Set(v8_str("AnalyzeStackOfEvalWithSourceURL"), + v8::FunctionTemplate::New(AnalyzeStackOfEvalWithSourceURL)); + LocalContext context(0, templ); + + const char *source = + "function outer() {\n" + "function bar() {\n" + " AnalyzeStackOfEvalWithSourceURL();\n" + "}\n" + "function foo() {\n" + "\n" + " bar();\n" + "}\n" + "foo();\n" + "}\n" + "eval('(' + outer +')()//@ sourceURL=eval_url');"; + CHECK(CompileRun(source)->IsUndefined()); +} + + // Test that idle notification can be handled and eventually returns true. THREADED_TEST(IdleNotification) { bool rv = false; @@ -11443,3 +11524,234 @@ TEST(BooleanCheckMultipleContexts) { ExpectString(code, ""); } } + + +TEST(DontDeleteCellLoadIC) { + const char* function_code = + "function readCell() { while (true) { return cell; } }"; + + { + // Run the code twice in the first context to initialize the load + // IC for a don't delete cell. + v8::HandleScope scope; + LocalContext context1; + CompileRun("var cell = \"first\";"); + ExpectBoolean("delete cell", false); + CompileRun(function_code); + ExpectString("readCell()", "first"); + ExpectString("readCell()", "first"); + } + + { + // Use a deletable cell in the second context. + v8::HandleScope scope; + LocalContext context2; + CompileRun("cell = \"second\";"); + CompileRun(function_code); + ExpectString("readCell()", "second"); + ExpectBoolean("delete cell", true); + ExpectString("(function() {" + " try {" + " return readCell();" + " } catch(e) {" + " return e.toString();" + " }" + "})()", + "ReferenceError: cell is not defined"); + CompileRun("cell = \"new_second\";"); + i::Heap::CollectAllGarbage(true); + ExpectString("readCell()", "new_second"); + ExpectString("readCell()", "new_second"); + } +} + + +TEST(DontDeleteCellLoadICForceDelete) { + const char* function_code = + "function readCell() { while (true) { return cell; } }"; + + // Run the code twice to initialize the load IC for a don't delete + // cell. + v8::HandleScope scope; + LocalContext context; + CompileRun("var cell = \"value\";"); + ExpectBoolean("delete cell", false); + CompileRun(function_code); + ExpectString("readCell()", "value"); + ExpectString("readCell()", "value"); + + // Delete the cell using the API and check the inlined code works + // correctly. + CHECK(context->Global()->ForceDelete(v8_str("cell"))); + ExpectString("(function() {" + " try {" + " return readCell();" + " } catch(e) {" + " return e.toString();" + " }" + "})()", + "ReferenceError: cell is not defined"); +} + + +TEST(DontDeleteCellLoadICAPI) { + const char* function_code = + "function readCell() { while (true) { return cell; } }"; + + // Run the code twice to initialize the load IC for a don't delete + // cell created using the API. + v8::HandleScope scope; + LocalContext context; + context->Global()->Set(v8_str("cell"), v8_str("value"), v8::DontDelete); + ExpectBoolean("delete cell", false); + CompileRun(function_code); + ExpectString("readCell()", "value"); + ExpectString("readCell()", "value"); + + // Delete the cell using the API and check the inlined code works + // correctly. + CHECK(context->Global()->ForceDelete(v8_str("cell"))); + ExpectString("(function() {" + " try {" + " return readCell();" + " } catch(e) {" + " return e.toString();" + " }" + "})()", + "ReferenceError: cell is not defined"); +} + + +TEST(GlobalLoadICGC) { + const char* function_code = + "function readCell() { while (true) { return cell; } }"; + + // Check inline load code for a don't delete cell is cleared during + // GC. + { + v8::HandleScope scope; + LocalContext context; + CompileRun("var cell = \"value\";"); + ExpectBoolean("delete cell", false); + CompileRun(function_code); + ExpectString("readCell()", "value"); + ExpectString("readCell()", "value"); + } + { + v8::HandleScope scope; + LocalContext context2; + // Hold the code object in the second context. + CompileRun(function_code); + CheckSurvivingGlobalObjectsCount(1); + } + + // Check inline load code for a deletable cell is cleared during GC. + { + v8::HandleScope scope; + LocalContext context; + CompileRun("cell = \"value\";"); + CompileRun(function_code); + ExpectString("readCell()", "value"); + ExpectString("readCell()", "value"); + } + { + v8::HandleScope scope; + LocalContext context2; + // Hold the code object in the second context. + CompileRun(function_code); + CheckSurvivingGlobalObjectsCount(1); + } +} + + +TEST(RegExp) { + v8::HandleScope scope; + LocalContext context; + + v8::Handle<v8::RegExp> re = v8::RegExp::New(v8_str("foo"), v8::RegExp::kNone); + CHECK(re->IsRegExp()); + CHECK(re->GetSource()->Equals(v8_str("foo"))); + CHECK_EQ(re->GetFlags(), v8::RegExp::kNone); + + re = v8::RegExp::New(v8_str("bar"), + static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase | + v8::RegExp::kGlobal)); + CHECK(re->IsRegExp()); + CHECK(re->GetSource()->Equals(v8_str("bar"))); + CHECK_EQ(static_cast<int>(re->GetFlags()), + v8::RegExp::kIgnoreCase | v8::RegExp::kGlobal); + + re = v8::RegExp::New(v8_str("baz"), + static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase | + v8::RegExp::kMultiline)); + CHECK(re->IsRegExp()); + CHECK(re->GetSource()->Equals(v8_str("baz"))); + CHECK_EQ(static_cast<int>(re->GetFlags()), + v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline); + + re = CompileRun("/quux/").As<v8::RegExp>(); + CHECK(re->IsRegExp()); + CHECK(re->GetSource()->Equals(v8_str("quux"))); + CHECK_EQ(re->GetFlags(), v8::RegExp::kNone); + + re = CompileRun("/quux/gm").As<v8::RegExp>(); + CHECK(re->IsRegExp()); + CHECK(re->GetSource()->Equals(v8_str("quux"))); + CHECK_EQ(static_cast<int>(re->GetFlags()), + v8::RegExp::kGlobal | v8::RegExp::kMultiline); + + // Override the RegExp constructor and check the API constructor + // still works. + CompileRun("RegExp = function() {}"); + + re = v8::RegExp::New(v8_str("foobar"), v8::RegExp::kNone); + CHECK(re->IsRegExp()); + CHECK(re->GetSource()->Equals(v8_str("foobar"))); + CHECK_EQ(re->GetFlags(), v8::RegExp::kNone); + + re = v8::RegExp::New(v8_str("foobarbaz"), + static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase | + v8::RegExp::kMultiline)); + CHECK(re->IsRegExp()); + CHECK(re->GetSource()->Equals(v8_str("foobarbaz"))); + CHECK_EQ(static_cast<int>(re->GetFlags()), + v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline); + + context->Global()->Set(v8_str("re"), re); + ExpectTrue("re.test('FoobarbaZ')"); + + v8::TryCatch try_catch; + re = v8::RegExp::New(v8_str("foo["), v8::RegExp::kNone); + CHECK(re.IsEmpty()); + CHECK(try_catch.HasCaught()); + context->Global()->Set(v8_str("ex"), try_catch.Exception()); + ExpectTrue("ex instanceof SyntaxError"); +} + + +static v8::Handle<v8::Value> Getter(v8::Local<v8::String> property, + const v8::AccessorInfo& info ) { + return v8_str("42!"); +} + + +static v8::Handle<v8::Array> Enumerator(const v8::AccessorInfo& info) { + v8::Handle<v8::Array> result = v8::Array::New(); + result->Set(0, v8_str("universalAnswer")); + return result; +} + + +TEST(NamedEnumeratorAndForIn) { + v8::HandleScope handle_scope; + LocalContext context; + v8::Context::Scope context_scope(context.local()); + + v8::Handle<v8::ObjectTemplate> tmpl = v8::ObjectTemplate::New(); + tmpl->SetNamedPropertyHandler(Getter, NULL, NULL, NULL, Enumerator); + context->Global()->Set(v8_str("o"), tmpl->NewInstance()); + v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun( + "var result = []; for (var k in o) result.push(k); result")); + CHECK_EQ(1, result->Length()); + CHECK_EQ(v8_str("universalAnswer"), result->Get(0)); +} diff --git a/test/cctest/test-conversions.cc b/test/cctest/test-conversions.cc index abcd426e..c62bbaaa 100644 --- a/test/cctest/test-conversions.cc +++ b/test/cctest/test-conversions.cc @@ -168,6 +168,38 @@ TEST(MaximumSignificantDigits) { CHECK_EQ(gay_strtod(num, NULL), StringToDouble(num, NO_FLAGS)); } +TEST(MinimumExponent) { + // Same test but with different point-position. + char num[] = + "445014771701440202508199667279499186358524265859260511351695091" + "228726223124931264069530541271189424317838013700808305231545782" + "515453032382772695923684574304409936197089118747150815050941806" + "048037511737832041185193533879641611520514874130831632725201246" + "060231058690536206311752656217652146466431814205051640436322226" + "680064743260560117135282915796422274554896821334728738317548403" + "413978098469341510556195293821919814730032341053661708792231510" + "873354131880491105553390278848567812190177545006298062245710295" + "816371174594568773301103242116891776567137054973871082078224775" + "842509670618916870627821633352993761380751142008862499795052791" + "018709663463944015644907297315659352441231715398102212132212018" + "470035807616260163568645811358486831521563686919762403704226016" + "998291015625000000000000000000000000000000000e-1108"; + + CHECK_EQ(gay_strtod(num, NULL), StringToDouble(num, NO_FLAGS)); + + // Changes the result of strtod (at least in glibc implementation). + num[sizeof(num) - 8] = '1'; + + CHECK_EQ(gay_strtod(num, NULL), StringToDouble(num, NO_FLAGS)); +} + + +TEST(MaximumExponent) { + char num[] = "0.16e309"; + + CHECK_EQ(gay_strtod(num, NULL), StringToDouble(num, NO_FLAGS)); +} + TEST(ExponentNumberStr) { CHECK_EQ(1e1, StringToDouble("1e1", NO_FLAGS)); diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc index f5526cea..d59e2f5a 100644 --- a/test/cctest/test-debug.cc +++ b/test/cctest/test-debug.cc @@ -867,7 +867,7 @@ static void DebugEventBreakPointCollectGarbage( break_point_hit_count++; if (break_point_hit_count % 2 == 0) { // Scavenge. - Heap::CollectGarbage(0, v8::internal::NEW_SPACE); + Heap::CollectGarbage(v8::internal::NEW_SPACE); } else { // Mark sweep compact. Heap::CollectAllGarbage(true); @@ -891,7 +891,7 @@ static void DebugEventBreak(v8::DebugEvent event, // Run the garbage collector to enforce heap verification if option // --verify-heap is set. - Heap::CollectGarbage(0, v8::internal::NEW_SPACE); + Heap::CollectGarbage(v8::internal::NEW_SPACE); // Set the break flag again to come back here as soon as possible. v8::Debug::DebugBreak(); @@ -1322,7 +1322,7 @@ static void CallAndGC(v8::Local<v8::Object> recv, CHECK_EQ(1 + i * 3, break_point_hit_count); // Scavenge and call function. - Heap::CollectGarbage(0, v8::internal::NEW_SPACE); + Heap::CollectGarbage(v8::internal::NEW_SPACE); f->Call(recv, 0, NULL); CHECK_EQ(2 + i * 3, break_point_hit_count); diff --git a/test/cctest/test-decls.cc b/test/cctest/test-decls.cc index 7587da8b..88fa79b7 100644 --- a/test/cctest/test-decls.cc +++ b/test/cctest/test-decls.cc @@ -130,7 +130,7 @@ void DeclarationContext::Check(const char* source, InitializeIfNeeded(); // A retry after a GC may pollute the counts, so perform gc now // to avoid that. - v8::internal::Heap::CollectGarbage(0, v8::internal::NEW_SPACE); + v8::internal::Heap::CollectGarbage(v8::internal::NEW_SPACE); HandleScope scope; TryCatch catcher; catcher.SetVerbose(true); diff --git a/test/cctest/test-heap-profiler.cc b/test/cctest/test-heap-profiler.cc index 5e570f34..b86a3361 100644 --- a/test/cctest/test-heap-profiler.cc +++ b/test/cctest/test-heap-profiler.cc @@ -20,11 +20,6 @@ using i::JSObjectsClusterTree; using i::RetainerHeapProfile; -static void CompileAndRunScript(const char *src) { - v8::Script::Compile(v8::String::New(src))->Run(); -} - - namespace { class ConstructorHeapProfileTestHelper : public i::ConstructorHeapProfile { @@ -58,7 +53,7 @@ TEST(ConstructorProfile) { v8::HandleScope scope; LocalContext env; - CompileAndRunScript( + CompileRun( "function F() {} // A constructor\n" "var f1 = new F();\n" "var f2 = new F();\n"); @@ -359,7 +354,7 @@ TEST(RetainerProfile) { v8::HandleScope scope; LocalContext env; - CompileAndRunScript( + CompileRun( "function A() {}\n" "function B(x) { this.x = x; }\n" "function C(x) { this.x1 = x; this.x2 = x; }\n" @@ -473,7 +468,7 @@ TEST(HeapSnapshot) { LocalContext env1; env1->SetSecurityToken(token1); - CompileAndRunScript( + CompileRun( "function A1() {}\n" "function B1(x) { this.x = x; }\n" "function C1(x) { this.x1 = x; this.x2 = x; }\n" @@ -485,7 +480,7 @@ TEST(HeapSnapshot) { LocalContext env2; env2->SetSecurityToken(token2); - CompileAndRunScript( + CompileRun( "function A2() {}\n" "function B2(x) { return function() { return typeof x; }; }\n" "function C2(x) { this.x1 = x; this.x2 = x; this[1] = x; }\n" @@ -583,7 +578,7 @@ TEST(HeapSnapshotObjectSizes) { // -a-> X1 --a // x -b-> X2 <-| - CompileAndRunScript( + CompileRun( "function X(a, b) { this.a = a; this.b = b; }\n" "x = new X(new X(), new X());\n" "x.a.a = x.b;"); @@ -594,7 +589,7 @@ TEST(HeapSnapshotObjectSizes) { GetProperty(global, v8::HeapGraphEdge::kProperty, "x"); CHECK_NE(NULL, x); const v8::HeapGraphNode* x_prototype = - GetProperty(x, v8::HeapGraphEdge::kProperty, "prototype"); + GetProperty(x, v8::HeapGraphEdge::kProperty, "__proto__"); CHECK_NE(NULL, x_prototype); const v8::HeapGraphNode* x1 = GetProperty(x, v8::HeapGraphEdge::kProperty, "a"); @@ -606,7 +601,7 @@ TEST(HeapSnapshotObjectSizes) { x->GetSelfSize() * 3, x->GetReachableSize() - x_prototype->GetReachableSize()); CHECK_EQ( - x->GetSelfSize() * 3 + x_prototype->GetSelfSize(), x->GetRetainedSize()); + x->GetSelfSize() * 3, x->GetRetainedSize()); CHECK_EQ( x1->GetSelfSize() * 2, x1->GetReachableSize() - x_prototype->GetReachableSize()); @@ -624,7 +619,7 @@ TEST(HeapSnapshotEntryChildren) { v8::HandleScope scope; LocalContext env; - CompileAndRunScript( + CompileRun( "function A() { }\n" "a = new A;"); const v8::HeapSnapshot* snapshot = @@ -648,10 +643,9 @@ TEST(HeapSnapshotCodeObjects) { v8::HandleScope scope; LocalContext env; - CompileAndRunScript( + CompileRun( "function lazy(x) { return x - 1; }\n" "function compiled(x) { return x + 1; }\n" - "var inferred = function(x) { return x; }\n" "var anonymous = (function() { return function() { return 0; } })();\n" "compiled(1)"); const v8::HeapSnapshot* snapshot = @@ -666,18 +660,12 @@ TEST(HeapSnapshotCodeObjects) { GetProperty(global, v8::HeapGraphEdge::kProperty, "lazy"); CHECK_NE(NULL, lazy); CHECK_EQ(v8::HeapGraphNode::kClosure, lazy->GetType()); - const v8::HeapGraphNode* inferred = - GetProperty(global, v8::HeapGraphEdge::kProperty, "inferred"); - CHECK_NE(NULL, inferred); - CHECK_EQ(v8::HeapGraphNode::kClosure, inferred->GetType()); - v8::String::AsciiValue inferred_name(inferred->GetName()); - CHECK_EQ("inferred", *inferred_name); const v8::HeapGraphNode* anonymous = GetProperty(global, v8::HeapGraphEdge::kProperty, "anonymous"); CHECK_NE(NULL, anonymous); CHECK_EQ(v8::HeapGraphNode::kClosure, anonymous->GetType()); v8::String::AsciiValue anonymous_name(anonymous->GetName()); - CHECK_EQ("(anonymous function)", *anonymous_name); + CHECK_EQ("", *anonymous_name); // Find references to code. const v8::HeapGraphNode* compiled_code = @@ -716,6 +704,44 @@ TEST(HeapSnapshotCodeObjects) { } +TEST(HeapSnapshotHeapNumbers) { + v8::HandleScope scope; + LocalContext env; + CompileRun( + "a = 1; // a is Smi\n" + "b = 2.5; // b is HeapNumber"); + const v8::HeapSnapshot* snapshot = + v8::HeapProfiler::TakeSnapshot(v8::String::New("numbers")); + const v8::HeapGraphNode* global = GetGlobalObject(snapshot); + CHECK_EQ(NULL, GetProperty(global, v8::HeapGraphEdge::kProperty, "a")); + const v8::HeapGraphNode* b = + GetProperty(global, v8::HeapGraphEdge::kProperty, "b"); + CHECK_NE(NULL, b); + CHECK_EQ(v8::HeapGraphNode::kHeapNumber, b->GetType()); +} + + +TEST(HeapSnapshotInternalReferences) { + v8::HandleScope scope; + v8::Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(); + global_template->SetInternalFieldCount(2); + LocalContext env(NULL, global_template); + v8::Handle<v8::Object> global_proxy = env->Global(); + v8::Handle<v8::Object> global = global_proxy->GetPrototype().As<v8::Object>(); + CHECK_EQ(2, global->InternalFieldCount()); + v8::Local<v8::Object> obj = v8::Object::New(); + global->SetInternalField(0, v8_num(17)); + global->SetInternalField(1, obj); + const v8::HeapSnapshot* snapshot = + v8::HeapProfiler::TakeSnapshot(v8::String::New("internals")); + const v8::HeapGraphNode* global_node = GetGlobalObject(snapshot); + // The first reference will not present, because it's a Smi. + CHECK_EQ(NULL, GetProperty(global_node, v8::HeapGraphEdge::kInternal, "0")); + // The second reference is to an object. + CHECK_NE(NULL, GetProperty(global_node, v8::HeapGraphEdge::kInternal, "1")); +} + + // Trying to introduce a check helper for uint64_t causes many // overloading ambiguities, so it seems easier just to cast // them to a signed type. @@ -728,7 +754,7 @@ TEST(HeapEntryIdsAndGC) { v8::HandleScope scope; LocalContext env; - CompileAndRunScript( + CompileRun( "function A() {}\n" "function B(x) { this.x = x; }\n" "var a = new A();\n" @@ -784,18 +810,19 @@ TEST(HeapSnapshotsDiff) { v8::HandleScope scope; LocalContext env; - CompileAndRunScript( + CompileRun( "function A() {}\n" "function B(x) { this.x = x; }\n" + "function A2(a) { for (var i = 0; i < a; ++i) this[i] = i; }\n" "var a = new A();\n" "var b = new B(a);"); const v8::HeapSnapshot* snapshot1 = v8::HeapProfiler::TakeSnapshot(v8::String::New("s1")); - CompileAndRunScript( + CompileRun( "delete a;\n" "b.x = null;\n" - "var a = new A();\n" + "var a = new A2(20);\n" "var b2 = new B(a);"); const v8::HeapSnapshot* snapshot2 = v8::HeapProfiler::TakeSnapshot(v8::String::New("s2")); @@ -811,7 +838,7 @@ TEST(HeapSnapshotsDiff) { const v8::HeapGraphNode* node = prop->GetToNode(); if (node->GetType() == v8::HeapGraphNode::kObject) { v8::String::AsciiValue node_name(node->GetName()); - if (strcmp(*node_name, "A") == 0) { + if (strcmp(*node_name, "A2") == 0) { CHECK(IsNodeRetainedAs(node, v8::HeapGraphEdge::kProperty, "a")); CHECK(!found_A); found_A = true; @@ -849,6 +876,19 @@ TEST(HeapSnapshotsDiff) { } +TEST(HeapSnapshotRootPreservedAfterSorting) { + v8::HandleScope scope; + LocalContext env; + const v8::HeapSnapshot* snapshot = + v8::HeapProfiler::TakeSnapshot(v8::String::New("s")); + const v8::HeapGraphNode* root1 = snapshot->GetRoot(); + const_cast<i::HeapSnapshot*>(reinterpret_cast<const i::HeapSnapshot*>( + snapshot))->GetSortedEntriesList(); + const v8::HeapGraphNode* root2 = snapshot->GetRoot(); + CHECK_EQ(root1, root2); +} + + namespace v8 { namespace internal { @@ -914,7 +954,7 @@ TEST(AggregatedHeapSnapshot) { v8::HandleScope scope; LocalContext env; - CompileAndRunScript( + CompileRun( "function A() {}\n" "function B(x) { this.x = x; }\n" "var a = new A();\n" @@ -1035,7 +1075,7 @@ TEST(HeapSnapshotJSONSerialization) { #define STRING_LITERAL_FOR_TEST \ "\"String \\n\\r\\u0008\\u0081\\u0101\\u0801\\u8001\"" - CompileAndRunScript( + CompileRun( "function A(s) { this.s = s; }\n" "function B(x) { this.x = x; }\n" "var a = new A(" STRING_LITERAL_FOR_TEST ");\n" diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc index eec024f3..126ac21a 100644 --- a/test/cctest/test-heap.cc +++ b/test/cctest/test-heap.cc @@ -177,13 +177,11 @@ TEST(Tagging) { int request = 24; CHECK_EQ(request, static_cast<int>(OBJECT_POINTER_ALIGN(request))); CHECK(Smi::FromInt(42)->IsSmi()); - CHECK(Failure::RetryAfterGC(request, NEW_SPACE)->IsFailure()); - CHECK_EQ(request, Failure::RetryAfterGC(request, NEW_SPACE)->requested()); + CHECK(Failure::RetryAfterGC(NEW_SPACE)->IsFailure()); CHECK_EQ(NEW_SPACE, - Failure::RetryAfterGC(request, NEW_SPACE)->allocation_space()); + Failure::RetryAfterGC(NEW_SPACE)->allocation_space()); CHECK_EQ(OLD_POINTER_SPACE, - Failure::RetryAfterGC(request, - OLD_POINTER_SPACE)->allocation_space()); + Failure::RetryAfterGC(OLD_POINTER_SPACE)->allocation_space()); CHECK(Failure::Exception()->IsFailure()); CHECK(Smi::FromInt(Smi::kMinValue)->IsSmi()); CHECK(Smi::FromInt(Smi::kMaxValue)->IsSmi()); @@ -195,8 +193,7 @@ TEST(GarbageCollection) { v8::HandleScope sc; // Check GC. - int free_bytes = Heap::MaxObjectSizeInPagedSpace(); - CHECK(Heap::CollectGarbage(free_bytes, NEW_SPACE)); + Heap::CollectGarbage(NEW_SPACE); Handle<String> name = Factory::LookupAsciiSymbol("theFunction"); Handle<String> prop_name = Factory::LookupAsciiSymbol("theSlot"); @@ -221,7 +218,7 @@ TEST(GarbageCollection) { CHECK_EQ(Smi::FromInt(24), obj->GetProperty(*prop_namex)); } - CHECK(Heap::CollectGarbage(free_bytes, NEW_SPACE)); + Heap::CollectGarbage(NEW_SPACE); // Function should be alive. CHECK(Top::context()->global()->HasLocalProperty(*name)); @@ -239,7 +236,7 @@ TEST(GarbageCollection) { } // After gc, it should survive. - CHECK(Heap::CollectGarbage(free_bytes, NEW_SPACE)); + Heap::CollectGarbage(NEW_SPACE); CHECK(Top::context()->global()->HasLocalProperty(*obj_name)); CHECK(Top::context()->global()->GetProperty(*obj_name)->IsJSObject()); @@ -301,7 +298,7 @@ TEST(GlobalHandles) { } // after gc, it should survive - CHECK(Heap::CollectGarbage(0, NEW_SPACE)); + Heap::CollectGarbage(NEW_SPACE); CHECK((*h1)->IsString()); CHECK((*h2)->IsHeapNumber()); @@ -382,8 +379,8 @@ TEST(WeakGlobalHandlesMark) { h2 = GlobalHandles::Create(*u); } - CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE)); - CHECK(Heap::CollectGarbage(0, NEW_SPACE)); + Heap::CollectGarbage(OLD_POINTER_SPACE); + Heap::CollectGarbage(NEW_SPACE); // Make sure the object is promoted. GlobalHandles::MakeWeak(h2.location(), @@ -392,7 +389,7 @@ TEST(WeakGlobalHandlesMark) { CHECK(!GlobalHandles::IsNearDeath(h1.location())); CHECK(!GlobalHandles::IsNearDeath(h2.location())); - CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE)); + Heap::CollectGarbage(OLD_POINTER_SPACE); CHECK((*h1)->IsString()); @@ -426,7 +423,7 @@ TEST(DeleteWeakGlobalHandle) { CHECK(!WeakPointerCleared); // Mark-compact treats weak reference properly. - CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE)); + Heap::CollectGarbage(OLD_POINTER_SPACE); CHECK(WeakPointerCleared); } @@ -814,8 +811,7 @@ TEST(Iteration) { TEST(LargeObjectSpaceContains) { InitializeVM(); - int free_bytes = Heap::MaxObjectSizeInPagedSpace(); - CHECK(Heap::CollectGarbage(free_bytes, NEW_SPACE)); + Heap::CollectGarbage(NEW_SPACE); Address current_top = Heap::new_space()->top(); Page* page = Page::FromAddress(current_top); @@ -958,6 +954,7 @@ TEST(Regression39128) { CHECK(page->IsRegionDirty(clone_addr + (object_size - kPointerSize))); } + TEST(TestCodeFlushing) { i::FLAG_allow_natives_syntax = true; // If we do not flush code this test is invalid. @@ -1001,3 +998,91 @@ TEST(TestCodeFlushing) { CHECK(function->shared()->is_compiled()); CHECK(function->is_compiled()); } + + +// Count the number of global contexts in the weak list of global contexts. +static int CountGlobalContexts() { + int count = 0; + Object* object = Heap::global_contexts_list(); + while (!object->IsUndefined()) { + count++; + object = Context::cast(object)->get(Context::NEXT_CONTEXT_LINK); + } + return count; +} + + +TEST(TestInternalWeakLists) { + static const int kNumTestContexts = 10; + + v8::HandleScope scope; + v8::Persistent<v8::Context> ctx[kNumTestContexts]; + + CHECK_EQ(0, CountGlobalContexts()); + + // Create a number of global contests which gets linked together. + for (int i = 0; i < kNumTestContexts; i++) { + ctx[i] = v8::Context::New(); + CHECK_EQ(i + 1, CountGlobalContexts()); + + ctx[i]->Enter(); + ctx[i]->Exit(); + } + + // Force compilation cache cleanup. + Heap::CollectAllGarbage(true); + + // Dispose the global contexts one by one. + for (int i = 0; i < kNumTestContexts; i++) { + ctx[i].Dispose(); + ctx[i].Clear(); + + // Scavenge treats these references as strong. + for (int j = 0; j < 10; j++) { + Heap::PerformScavenge(); + CHECK_EQ(kNumTestContexts - i, CountGlobalContexts()); + } + + // Mark compact handles the weak references. + Heap::CollectAllGarbage(true); + CHECK_EQ(kNumTestContexts - i - 1, CountGlobalContexts()); + } + + CHECK_EQ(0, CountGlobalContexts()); +} + + +// Count the number of global contexts in the weak list of global contexts +// causing a GC after the specified number of elements. +static int CountGlobalContextsWithGC(int n) { + int count = 0; + Handle<Object> object(Heap::global_contexts_list()); + while (!object->IsUndefined()) { + count++; + if (count == n) Heap::CollectAllGarbage(true); + object = + Handle<Object>(Context::cast(*object)->get(Context::NEXT_CONTEXT_LINK)); + } + return count; +} + + +TEST(TestInternalWeakListsTraverseWithGC) { + static const int kNumTestContexts = 10; + + v8::HandleScope scope; + v8::Persistent<v8::Context> ctx[kNumTestContexts]; + + CHECK_EQ(0, CountGlobalContexts()); + + // Create an number of contexts and check the length of the weak list both + // with and without GCs while iterating the list. + for (int i = 0; i < kNumTestContexts; i++) { + ctx[i] = v8::Context::New(); + CHECK_EQ(i + 1, CountGlobalContexts()); + CHECK_EQ(i + 1, CountGlobalContextsWithGC(i / 2 + 1)); + + ctx[i]->Enter(); + ctx[i]->Exit(); + } +} diff --git a/test/cctest/test-log-stack-tracer.cc b/test/cctest/test-log-stack-tracer.cc index 9162ffd4..7d7bd406 100644 --- a/test/cctest/test-log-stack-tracer.cc +++ b/test/cctest/test-log-stack-tracer.cc @@ -245,8 +245,8 @@ static v8::Handle<Value> construct_call(const v8::Arguments& args) { args.This()->Set(v8_str("low_bits"), v8_num(low_bits >> 1)); #elif defined(V8_HOST_ARCH_64_BIT) uint64_t fp = reinterpret_cast<uint64_t>(calling_frame->fp()); - int32_t low_bits = fp & 0xffffffff; - int32_t high_bits = fp >> 32; + int32_t low_bits = static_cast<int32_t>(fp & 0xffffffff); + int32_t high_bits = static_cast<int32_t>(fp >> 32); args.This()->Set(v8_str("low_bits"), v8_num(low_bits)); args.This()->Set(v8_str("high_bits"), v8_num(high_bits)); #else diff --git a/test/cctest/test-log.cc b/test/cctest/test-log.cc index b364ae3b..16d0f005 100644 --- a/test/cctest/test-log.cc +++ b/test/cctest/test-log.cc @@ -469,7 +469,7 @@ TEST(ProfMultipleThreads) { CHECK(!sampler.WasSampleStackCalled()); nonJsThread.WaitForRunning(); nonJsThread.SendSigProf(); - CHECK(sampler.WaitForTick()); + CHECK(!sampler.WaitForTick()); CHECK(!sampler.WasSampleStackCalled()); sampler.Stop(); diff --git a/test/cctest/test-macro-assembler-x64.cc b/test/cctest/test-macro-assembler-x64.cc index 3d2b91b5..9b1fc46e 100755 --- a/test/cctest/test-macro-assembler-x64.cc +++ b/test/cctest/test-macro-assembler-x64.cc @@ -519,40 +519,40 @@ TEST(SmiCheck) { __ incq(rax); __ movl(rcx, Immediate(0)); __ Integer32ToSmi(rcx, rcx); - cond = masm->CheckPositiveSmi(rcx); // Zero counts as positive. + cond = masm->CheckNonNegativeSmi(rcx); __ j(NegateCondition(cond), &exit); __ incq(rax); __ xor_(rcx, Immediate(kSmiTagMask)); - cond = masm->CheckPositiveSmi(rcx); // "zero" non-smi. + cond = masm->CheckNonNegativeSmi(rcx); // "zero" non-smi. __ j(cond, &exit); __ incq(rax); __ movq(rcx, Immediate(-1)); __ Integer32ToSmi(rcx, rcx); - cond = masm->CheckPositiveSmi(rcx); // Negative smis are not positive. + cond = masm->CheckNonNegativeSmi(rcx); // Negative smis are not positive. __ j(cond, &exit); __ incq(rax); __ movq(rcx, Immediate(Smi::kMinValue)); __ Integer32ToSmi(rcx, rcx); - cond = masm->CheckPositiveSmi(rcx); // Most negative smi is not positive. + cond = masm->CheckNonNegativeSmi(rcx); // Most negative smi is not positive. __ j(cond, &exit); __ incq(rax); __ xor_(rcx, Immediate(kSmiTagMask)); - cond = masm->CheckPositiveSmi(rcx); // "Negative" non-smi. + cond = masm->CheckNonNegativeSmi(rcx); // "Negative" non-smi. __ j(cond, &exit); __ incq(rax); __ movq(rcx, Immediate(Smi::kMaxValue)); __ Integer32ToSmi(rcx, rcx); - cond = masm->CheckPositiveSmi(rcx); // Most positive smi is positive. + cond = masm->CheckNonNegativeSmi(rcx); // Most positive smi is positive. __ j(NegateCondition(cond), &exit); __ incq(rax); __ xor_(rcx, Immediate(kSmiTagMask)); - cond = masm->CheckPositiveSmi(rcx); // "Positive" non-smi. + cond = masm->CheckNonNegativeSmi(rcx); // "Positive" non-smi. __ j(cond, &exit); // CheckIsMinSmi diff --git a/test/cctest/test-mark-compact.cc b/test/cctest/test-mark-compact.cc index e4ac1b7c..531b1f77 100644 --- a/test/cctest/test-mark-compact.cc +++ b/test/cctest/test-mark-compact.cc @@ -94,7 +94,7 @@ TEST(Promotion) { CHECK(Heap::InSpace(*array, NEW_SPACE)); // Call the m-c collector, so array becomes an old object. - CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE)); + Heap::CollectGarbage(OLD_POINTER_SPACE); // Array now sits in the old space CHECK(Heap::InSpace(*array, OLD_POINTER_SPACE)); @@ -111,7 +111,7 @@ TEST(NoPromotion) { v8::HandleScope sc; // Do a mark compact GC to shrink the heap. - CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE)); + Heap::CollectGarbage(OLD_POINTER_SPACE); // Allocate a big Fixed array in the new space. int size = (Heap::MaxObjectSizeInPagedSpace() - FixedArray::kHeaderSize) / @@ -134,7 +134,7 @@ TEST(NoPromotion) { } // Call mark compact GC, and it should pass. - CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE)); + Heap::CollectGarbage(OLD_POINTER_SPACE); // array should not be promoted because the old space is full. CHECK(Heap::InSpace(*array, NEW_SPACE)); @@ -146,7 +146,7 @@ TEST(MarkCompactCollector) { v8::HandleScope sc; // call mark-compact when heap is empty - CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE)); + Heap::CollectGarbage(OLD_POINTER_SPACE); // keep allocating garbage in new space until it fails const int ARRAY_SIZE = 100; @@ -154,7 +154,7 @@ TEST(MarkCompactCollector) { do { array = Heap::AllocateFixedArray(ARRAY_SIZE); } while (!array->IsFailure()); - CHECK(Heap::CollectGarbage(0, NEW_SPACE)); + Heap::CollectGarbage(NEW_SPACE); array = Heap::AllocateFixedArray(ARRAY_SIZE); CHECK(!array->IsFailure()); @@ -164,7 +164,7 @@ TEST(MarkCompactCollector) { do { mapp = Heap::AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); } while (!mapp->IsFailure()); - CHECK(Heap::CollectGarbage(0, MAP_SPACE)); + Heap::CollectGarbage(MAP_SPACE); mapp = Heap::AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); CHECK(!mapp->IsFailure()); @@ -182,7 +182,7 @@ TEST(MarkCompactCollector) { Top::context()->global()->SetProperty(func_name, function, NONE); JSObject* obj = JSObject::cast(Heap::AllocateJSObject(function)); - CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE)); + Heap::CollectGarbage(OLD_POINTER_SPACE); func_name = String::cast(Heap::LookupAsciiSymbol("theFunction")); CHECK(Top::context()->global()->HasLocalProperty(func_name)); @@ -196,7 +196,7 @@ TEST(MarkCompactCollector) { String* prop_name = String::cast(Heap::LookupAsciiSymbol("theSlot")); obj->SetProperty(prop_name, Smi::FromInt(23), NONE); - CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE)); + Heap::CollectGarbage(OLD_POINTER_SPACE); obj_name = String::cast(Heap::LookupAsciiSymbol("theObject")); CHECK(Top::context()->global()->HasLocalProperty(obj_name)); @@ -264,7 +264,7 @@ TEST(GCCallback) { CHECK_EQ(0, gc_starts); CHECK_EQ(gc_ends, gc_starts); - CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE)); + Heap::CollectGarbage(OLD_POINTER_SPACE); CHECK_EQ(1, gc_starts); CHECK_EQ(gc_ends, gc_starts); } @@ -317,7 +317,7 @@ TEST(ObjectGroups) { GlobalHandles::AddGroup(g2_objects, 2); } // Do a full GC - CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE)); + Heap::CollectGarbage(OLD_POINTER_SPACE); // All object should be alive. CHECK_EQ(0, NumberOfWeakCalls); @@ -335,7 +335,7 @@ TEST(ObjectGroups) { GlobalHandles::AddGroup(g2_objects, 2); } - CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE)); + Heap::CollectGarbage(OLD_POINTER_SPACE); // All objects should be gone. 5 global handles in total. CHECK_EQ(5, NumberOfWeakCalls); diff --git a/test/cctest/test-regexp.cc b/test/cctest/test-regexp.cc index 186350be..11a808e3 100644 --- a/test/cctest/test-regexp.cc +++ b/test/cctest/test-regexp.cc @@ -64,7 +64,7 @@ static bool CheckParse(const char* input) { ZoneScope zone_scope(DELETE_ON_EXIT); FlatStringReader reader(CStrVector(input)); RegExpCompileData result; - return v8::internal::ParseRegExp(&reader, false, &result); + return v8::internal::Parser::ParseRegExp(&reader, false, &result); } @@ -74,7 +74,7 @@ static SmartPointer<const char> Parse(const char* input) { ZoneScope zone_scope(DELETE_ON_EXIT); FlatStringReader reader(CStrVector(input)); RegExpCompileData result; - CHECK(v8::internal::ParseRegExp(&reader, false, &result)); + CHECK(v8::internal::Parser::ParseRegExp(&reader, false, &result)); CHECK(result.tree != NULL); CHECK(result.error.is_null()); SmartPointer<const char> output = result.tree->ToString(); @@ -88,7 +88,7 @@ static bool CheckSimple(const char* input) { ZoneScope zone_scope(DELETE_ON_EXIT); FlatStringReader reader(CStrVector(input)); RegExpCompileData result; - CHECK(v8::internal::ParseRegExp(&reader, false, &result)); + CHECK(v8::internal::Parser::ParseRegExp(&reader, false, &result)); CHECK(result.tree != NULL); CHECK(result.error.is_null()); return result.simple; @@ -106,7 +106,7 @@ static MinMaxPair CheckMinMaxMatch(const char* input) { ZoneScope zone_scope(DELETE_ON_EXIT); FlatStringReader reader(CStrVector(input)); RegExpCompileData result; - CHECK(v8::internal::ParseRegExp(&reader, false, &result)); + CHECK(v8::internal::Parser::ParseRegExp(&reader, false, &result)); CHECK(result.tree != NULL); CHECK(result.error.is_null()); int min_match = result.tree->min_match(); @@ -365,7 +365,7 @@ static void ExpectError(const char* input, ZoneScope zone_scope(DELETE_ON_EXIT); FlatStringReader reader(CStrVector(input)); RegExpCompileData result; - CHECK_EQ(false, v8::internal::ParseRegExp(&reader, false, &result)); + CHECK_EQ(false, v8::internal::Parser::ParseRegExp(&reader, false, &result)); CHECK(result.tree == NULL); CHECK(!result.error.is_null()); SmartPointer<char> str = result.error->ToCString(ALLOW_NULLS); @@ -473,7 +473,7 @@ static RegExpNode* Compile(const char* input, bool multiline, bool is_ascii) { V8::Initialize(NULL); FlatStringReader reader(CStrVector(input)); RegExpCompileData compile_data; - if (!v8::internal::ParseRegExp(&reader, multiline, &compile_data)) + if (!v8::internal::Parser::ParseRegExp(&reader, multiline, &compile_data)) return NULL; Handle<String> pattern = Factory::NewStringFromUtf8(CStrVector(input)); RegExpEngine::Compile(&compile_data, false, multiline, pattern, is_ascii); diff --git a/test/cctest/test-spaces.cc b/test/cctest/test-spaces.cc index 2811ee6c..db8c54fa 100644 --- a/test/cctest/test-spaces.cc +++ b/test/cctest/test-spaces.cc @@ -221,7 +221,7 @@ TEST(LargeObjectSpace) { CHECK(lo->Contains(ho)); while (true) { - int available = lo->Available(); + intptr_t available = lo->Available(); obj = lo->AllocateRaw(lo_size); if (obj->IsFailure()) break; HeapObject::cast(obj)->set_map(faked_map); diff --git a/test/cctest/test-strtod.cc b/test/cctest/test-strtod.cc new file mode 100644 index 00000000..ae1c00d3 --- /dev/null +++ b/test/cctest/test-strtod.cc @@ -0,0 +1,207 @@ +// Copyright 2006-2008 the V8 project authors. All rights reserved. + +#include <stdlib.h> + +#include "v8.h" + +#include "cctest.h" +#include "strtod.h" + +using namespace v8::internal; + +static Vector<const char> StringToVector(const char* str) { + return Vector<const char>(str, StrLength(str)); +} + + +static double StrtodChar(const char* str, int exponent) { + return Strtod(StringToVector(str), exponent); +} + + +TEST(Strtod) { + Vector<const char> vector; + + vector = StringToVector("0"); + CHECK_EQ(0.0, Strtod(vector, 1)); + CHECK_EQ(0.0, Strtod(vector, 2)); + CHECK_EQ(0.0, Strtod(vector, -2)); + CHECK_EQ(0.0, Strtod(vector, -999)); + CHECK_EQ(0.0, Strtod(vector, +999)); + + vector = StringToVector("1"); + CHECK_EQ(1.0, Strtod(vector, 0)); + CHECK_EQ(10.0, Strtod(vector, 1)); + CHECK_EQ(100.0, Strtod(vector, 2)); + CHECK_EQ(1e20, Strtod(vector, 20)); + CHECK_EQ(1e22, Strtod(vector, 22)); + CHECK_EQ(1e23, Strtod(vector, 23)); + CHECK_EQ(1e35, Strtod(vector, 35)); + CHECK_EQ(1e36, Strtod(vector, 36)); + CHECK_EQ(1e37, Strtod(vector, 37)); + CHECK_EQ(1e-1, Strtod(vector, -1)); + CHECK_EQ(1e-2, Strtod(vector, -2)); + CHECK_EQ(1e-5, Strtod(vector, -5)); + CHECK_EQ(1e-20, Strtod(vector, -20)); + CHECK_EQ(1e-22, Strtod(vector, -22)); + CHECK_EQ(1e-23, Strtod(vector, -23)); + CHECK_EQ(1e-25, Strtod(vector, -25)); + CHECK_EQ(1e-39, Strtod(vector, -39)); + + vector = StringToVector("2"); + CHECK_EQ(2.0, Strtod(vector, 0)); + CHECK_EQ(20.0, Strtod(vector, 1)); + CHECK_EQ(200.0, Strtod(vector, 2)); + CHECK_EQ(2e20, Strtod(vector, 20)); + CHECK_EQ(2e22, Strtod(vector, 22)); + CHECK_EQ(2e23, Strtod(vector, 23)); + CHECK_EQ(2e35, Strtod(vector, 35)); + CHECK_EQ(2e36, Strtod(vector, 36)); + CHECK_EQ(2e37, Strtod(vector, 37)); + CHECK_EQ(2e-1, Strtod(vector, -1)); + CHECK_EQ(2e-2, Strtod(vector, -2)); + CHECK_EQ(2e-5, Strtod(vector, -5)); + CHECK_EQ(2e-20, Strtod(vector, -20)); + CHECK_EQ(2e-22, Strtod(vector, -22)); + CHECK_EQ(2e-23, Strtod(vector, -23)); + CHECK_EQ(2e-25, Strtod(vector, -25)); + CHECK_EQ(2e-39, Strtod(vector, -39)); + + vector = StringToVector("9"); + CHECK_EQ(9.0, Strtod(vector, 0)); + CHECK_EQ(90.0, Strtod(vector, 1)); + CHECK_EQ(900.0, Strtod(vector, 2)); + CHECK_EQ(9e20, Strtod(vector, 20)); + CHECK_EQ(9e22, Strtod(vector, 22)); + CHECK_EQ(9e23, Strtod(vector, 23)); + CHECK_EQ(9e35, Strtod(vector, 35)); + CHECK_EQ(9e36, Strtod(vector, 36)); + CHECK_EQ(9e37, Strtod(vector, 37)); + CHECK_EQ(9e-1, Strtod(vector, -1)); + CHECK_EQ(9e-2, Strtod(vector, -2)); + CHECK_EQ(9e-5, Strtod(vector, -5)); + CHECK_EQ(9e-20, Strtod(vector, -20)); + CHECK_EQ(9e-22, Strtod(vector, -22)); + CHECK_EQ(9e-23, Strtod(vector, -23)); + CHECK_EQ(9e-25, Strtod(vector, -25)); + CHECK_EQ(9e-39, Strtod(vector, -39)); + + vector = StringToVector("12345"); + CHECK_EQ(12345.0, Strtod(vector, 0)); + CHECK_EQ(123450.0, Strtod(vector, 1)); + CHECK_EQ(1234500.0, Strtod(vector, 2)); + CHECK_EQ(12345e20, Strtod(vector, 20)); + CHECK_EQ(12345e22, Strtod(vector, 22)); + CHECK_EQ(12345e23, Strtod(vector, 23)); + CHECK_EQ(12345e30, Strtod(vector, 30)); + CHECK_EQ(12345e31, Strtod(vector, 31)); + CHECK_EQ(12345e32, Strtod(vector, 32)); + CHECK_EQ(12345e35, Strtod(vector, 35)); + CHECK_EQ(12345e36, Strtod(vector, 36)); + CHECK_EQ(12345e37, Strtod(vector, 37)); + CHECK_EQ(12345e-1, Strtod(vector, -1)); + CHECK_EQ(12345e-2, Strtod(vector, -2)); + CHECK_EQ(12345e-5, Strtod(vector, -5)); + CHECK_EQ(12345e-20, Strtod(vector, -20)); + CHECK_EQ(12345e-22, Strtod(vector, -22)); + CHECK_EQ(12345e-23, Strtod(vector, -23)); + CHECK_EQ(12345e-25, Strtod(vector, -25)); + CHECK_EQ(12345e-39, Strtod(vector, -39)); + + vector = StringToVector("12345678901234"); + CHECK_EQ(12345678901234.0, Strtod(vector, 0)); + CHECK_EQ(123456789012340.0, Strtod(vector, 1)); + CHECK_EQ(1234567890123400.0, Strtod(vector, 2)); + CHECK_EQ(12345678901234e20, Strtod(vector, 20)); + CHECK_EQ(12345678901234e22, Strtod(vector, 22)); + CHECK_EQ(12345678901234e23, Strtod(vector, 23)); + CHECK_EQ(12345678901234e30, Strtod(vector, 30)); + CHECK_EQ(12345678901234e31, Strtod(vector, 31)); + CHECK_EQ(12345678901234e32, Strtod(vector, 32)); + CHECK_EQ(12345678901234e35, Strtod(vector, 35)); + CHECK_EQ(12345678901234e36, Strtod(vector, 36)); + CHECK_EQ(12345678901234e37, Strtod(vector, 37)); + CHECK_EQ(12345678901234e-1, Strtod(vector, -1)); + CHECK_EQ(12345678901234e-2, Strtod(vector, -2)); + CHECK_EQ(12345678901234e-5, Strtod(vector, -5)); + CHECK_EQ(12345678901234e-20, Strtod(vector, -20)); + CHECK_EQ(12345678901234e-22, Strtod(vector, -22)); + CHECK_EQ(12345678901234e-23, Strtod(vector, -23)); + CHECK_EQ(12345678901234e-25, Strtod(vector, -25)); + CHECK_EQ(12345678901234e-39, Strtod(vector, -39)); + + vector = StringToVector("123456789012345"); + CHECK_EQ(123456789012345.0, Strtod(vector, 0)); + CHECK_EQ(1234567890123450.0, Strtod(vector, 1)); + CHECK_EQ(12345678901234500.0, Strtod(vector, 2)); + CHECK_EQ(123456789012345e20, Strtod(vector, 20)); + CHECK_EQ(123456789012345e22, Strtod(vector, 22)); + CHECK_EQ(123456789012345e23, Strtod(vector, 23)); + CHECK_EQ(123456789012345e35, Strtod(vector, 35)); + CHECK_EQ(123456789012345e36, Strtod(vector, 36)); + CHECK_EQ(123456789012345e37, Strtod(vector, 37)); + CHECK_EQ(123456789012345e39, Strtod(vector, 39)); + CHECK_EQ(123456789012345e-1, Strtod(vector, -1)); + CHECK_EQ(123456789012345e-2, Strtod(vector, -2)); + CHECK_EQ(123456789012345e-5, Strtod(vector, -5)); + CHECK_EQ(123456789012345e-20, Strtod(vector, -20)); + CHECK_EQ(123456789012345e-22, Strtod(vector, -22)); + CHECK_EQ(123456789012345e-23, Strtod(vector, -23)); + CHECK_EQ(123456789012345e-25, Strtod(vector, -25)); + CHECK_EQ(123456789012345e-39, Strtod(vector, -39)); + + CHECK_EQ(0.0, StrtodChar("0", 12345)); + CHECK_EQ(0.0, StrtodChar("", 1324)); + CHECK_EQ(0.0, StrtodChar("000000000", 123)); + CHECK_EQ(0.0, StrtodChar("2", -324)); + CHECK_EQ(4e-324, StrtodChar("3", -324)); + // It would be more readable to put non-zero literals on the left side (i.e. + // CHECK_EQ(1e-325, StrtodChar("1", -325))), but then Gcc complains that + // they are truncated to zero. + CHECK_EQ(0.0, StrtodChar("1", -325)); + CHECK_EQ(0.0, StrtodChar("1", -325)); + CHECK_EQ(0.0, StrtodChar("20000", -328)); + CHECK_EQ(40000e-328, StrtodChar("30000", -328)); + CHECK_EQ(0.0, StrtodChar("10000", -329)); + CHECK_EQ(0.0, StrtodChar("90000", -329)); + CHECK_EQ(0.0, StrtodChar("000000001", -325)); + CHECK_EQ(0.0, StrtodChar("000000001", -325)); + CHECK_EQ(0.0, StrtodChar("0000000020000", -328)); + CHECK_EQ(40000e-328, StrtodChar("00000030000", -328)); + CHECK_EQ(0.0, StrtodChar("0000000010000", -329)); + CHECK_EQ(0.0, StrtodChar("0000000090000", -329)); + + // It would be more readable to put the literals (and not V8_INFINITY) on the + // left side (i.e. CHECK_EQ(1e309, StrtodChar("1", 309))), but then Gcc + // complains that the floating constant exceeds range of 'double'. + CHECK_EQ(V8_INFINITY, StrtodChar("1", 309)); + CHECK_EQ(1e308, StrtodChar("1", 308)); + CHECK_EQ(1234e305, StrtodChar("1234", 305)); + CHECK_EQ(1234e304, StrtodChar("1234", 304)); + CHECK_EQ(V8_INFINITY, StrtodChar("18", 307)); + CHECK_EQ(17e307, StrtodChar("17", 307)); + CHECK_EQ(V8_INFINITY, StrtodChar("0000001", 309)); + CHECK_EQ(1e308, StrtodChar("00000001", 308)); + CHECK_EQ(1234e305, StrtodChar("00000001234", 305)); + CHECK_EQ(1234e304, StrtodChar("000000001234", 304)); + CHECK_EQ(V8_INFINITY, StrtodChar("0000000018", 307)); + CHECK_EQ(17e307, StrtodChar("0000000017", 307)); + CHECK_EQ(V8_INFINITY, StrtodChar("1000000", 303)); + CHECK_EQ(1e308, StrtodChar("100000", 303)); + CHECK_EQ(1234e305, StrtodChar("123400000", 300)); + CHECK_EQ(1234e304, StrtodChar("123400000", 299)); + CHECK_EQ(V8_INFINITY, StrtodChar("180000000", 300)); + CHECK_EQ(17e307, StrtodChar("170000000", 300)); + CHECK_EQ(V8_INFINITY, StrtodChar("00000001000000", 303)); + CHECK_EQ(1e308, StrtodChar("000000000000100000", 303)); + CHECK_EQ(1234e305, StrtodChar("00000000123400000", 300)); + CHECK_EQ(1234e304, StrtodChar("0000000123400000", 299)); + CHECK_EQ(V8_INFINITY, StrtodChar("00000000180000000", 300)); + CHECK_EQ(17e307, StrtodChar("00000000170000000", 300)); + + // The following number is the result of 89255.0/1e-22. Both floating-point + // numbers can be accurately represented with doubles. However on Linux,x86 + // the floating-point stack is set to 80bits and the double-rounding + // introduces an error. + CHECK_EQ(89255e-22, StrtodChar("89255", -22)); +} diff --git a/test/mjsunit/binary-op-newspace.js b/test/mjsunit/binary-op-newspace.js index 40d53b94..032284c6 100644 --- a/test/mjsunit/binary-op-newspace.js +++ b/test/mjsunit/binary-op-newspace.js @@ -25,7 +25,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --max-new-space-size=262144 +// Flags: --max-new-space-size=256 // Check that a mod where the stub code hits a failure in heap number diff --git a/test/mjsunit/int32-ops.js b/test/mjsunit/int32-ops.js new file mode 100644 index 00000000..18839265 --- /dev/null +++ b/test/mjsunit/int32-ops.js @@ -0,0 +1,227 @@ +// Copyright 2010 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Repeat most the tests in smi-ops.js that use SMI_MIN and SMI_MAX, but +// with SMI_MIN and SMI_MAX from the 64-bit platform, which represents all +// signed 32-bit integer values as smis. + +const SMI_MAX = (1 << 30) - 1 + (1 << 30); // Create without overflowing. +const SMI_MIN = -SMI_MAX - 1; // Create without overflowing. +const ONE = 1; +const ONE_HUNDRED = 100; + +const OBJ_42 = new (function() { + this.valueOf = function() { return 42; }; +})(); + +assertEquals(42, OBJ_42.valueOf()); + + +function Add1(x) { + return x + 1; +} + +function Add100(x) { + return x + 100; +} + +function Add1Reversed(x) { + return 1 + x; +} + +function Add100Reversed(x) { + return 100 + x; +} + + +assertEquals(1, Add1(0)); // fast case +assertEquals(1, Add1Reversed(0)); // fast case +assertEquals(SMI_MAX + ONE, Add1(SMI_MAX), "smimax + 1"); +assertEquals(SMI_MAX + ONE, Add1Reversed(SMI_MAX), "1 + smimax"); +assertEquals(42 + ONE, Add1(OBJ_42)); // non-smi +assertEquals(42 + ONE, Add1Reversed(OBJ_42)); // non-smi + +assertEquals(100, Add100(0)); // fast case +assertEquals(100, Add100Reversed(0)); // fast case +assertEquals(SMI_MAX + ONE_HUNDRED, Add100(SMI_MAX), "smimax + 100"); +assertEquals(SMI_MAX + ONE_HUNDRED, Add100Reversed(SMI_MAX), " 100 + smimax"); +assertEquals(42 + ONE_HUNDRED, Add100(OBJ_42)); // non-smi +assertEquals(42 + ONE_HUNDRED, Add100Reversed(OBJ_42)); // non-smi + + + +function Sub1(x) { + return x - 1; +} + +function Sub100(x) { + return x - 100; +} + +function Sub1Reversed(x) { + return 1 - x; +} + +function Sub100Reversed(x) { + return 100 - x; +} + + +assertEquals(0, Sub1(1)); // fast case +assertEquals(-1, Sub1Reversed(2)); // fast case +assertEquals(SMI_MIN - ONE, Sub1(SMI_MIN)); // overflow +assertEquals(ONE - SMI_MIN, Sub1Reversed(SMI_MIN)); // overflow +assertEquals(42 - ONE, Sub1(OBJ_42)); // non-smi +assertEquals(ONE - 42, Sub1Reversed(OBJ_42)); // non-smi + +assertEquals(0, Sub100(100)); // fast case +assertEquals(1, Sub100Reversed(99)); // fast case +assertEquals(SMI_MIN - ONE_HUNDRED, Sub100(SMI_MIN)); // overflow +assertEquals(ONE_HUNDRED - SMI_MIN, Sub100Reversed(SMI_MIN)); // overflow +assertEquals(42 - ONE_HUNDRED, Sub100(OBJ_42)); // non-smi +assertEquals(ONE_HUNDRED - 42, Sub100Reversed(OBJ_42)); // non-smi + + +function Shr1(x) { + return x >>> 1; +} + +function Shr100(x) { + return x >>> 100; +} + +function Shr1Reversed(x) { + return 1 >>> x; +} + +function Shr100Reversed(x) { + return 100 >>> x; +} + +function Sar1(x) { + return x >> 1; +} + +function Sar100(x) { + return x >> 100; +} + +function Sar1Reversed(x) { + return 1 >> x; +} + +function Sar100Reversed(x) { + return 100 >> x; +} + + +assertEquals(0, Shr1(1)); +assertEquals(0, Sar1(1)); +assertEquals(0, Shr1Reversed(2)); +assertEquals(0, Sar1Reversed(2)); +assertEquals(1073741824, Shr1(SMI_MIN)); +assertEquals(-1073741824, Sar1(SMI_MIN)); +assertEquals(1, Shr1Reversed(SMI_MIN)); +assertEquals(1, Sar1Reversed(SMI_MIN)); +assertEquals(21, Shr1(OBJ_42)); +assertEquals(21, Sar1(OBJ_42)); +assertEquals(0, Shr1Reversed(OBJ_42)); +assertEquals(0, Sar1Reversed(OBJ_42)); + +assertEquals(6, Shr100(100), "100 >>> 100"); +assertEquals(6, Sar100(100), "100 >> 100"); +assertEquals(12, Shr100Reversed(99)); +assertEquals(12, Sar100Reversed(99)); +assertEquals(134217728, Shr100(SMI_MIN)); +assertEquals(-134217728, Sar100(SMI_MIN)); +assertEquals(100, Shr100Reversed(SMI_MIN)); +assertEquals(100, Sar100Reversed(SMI_MIN)); +assertEquals(2, Shr100(OBJ_42)); +assertEquals(2, Sar100(OBJ_42)); +assertEquals(0, Shr100Reversed(OBJ_42)); +assertEquals(0, Sar100Reversed(OBJ_42)); + + +function Xor1(x) { + return x ^ 1; +} + +function Xor100(x) { + return x ^ 100; +} + +function Xor1Reversed(x) { + return 1 ^ x; +} + +function Xor100Reversed(x) { + return 100 ^ x; +} + + +assertEquals(0, Xor1(1)); +assertEquals(3, Xor1Reversed(2)); +assertEquals(SMI_MIN + 1, Xor1(SMI_MIN)); +assertEquals(SMI_MIN + 1, Xor1Reversed(SMI_MIN)); +assertEquals(43, Xor1(OBJ_42)); +assertEquals(43, Xor1Reversed(OBJ_42)); + +assertEquals(0, Xor100(100)); +assertEquals(7, Xor100Reversed(99)); +assertEquals(-2147483548, Xor100(SMI_MIN)); +assertEquals(-2147483548, Xor100Reversed(SMI_MIN)); +assertEquals(78, Xor100(OBJ_42)); +assertEquals(78, Xor100Reversed(OBJ_42)); + +var x = 0x23; var y = 0x35; +assertEquals(0x16, x ^ y); + + +// Bitwise not. +var v = 0; +assertEquals(-1, ~v); +v = SMI_MIN; +assertEquals(0x7fffffff, ~v, "~smimin"); +v = SMI_MAX; +assertEquals(-0x80000000, ~v, "~smimax"); + +// Overflowing ++ and --. +v = SMI_MAX; +v++; +assertEquals(0x80000000, v, "smimax++"); +v = SMI_MIN; +v--; +assertEquals(-0x80000001, v, "smimin--"); + +// Check that comparisons of numbers separated by MIN_SMI work. +assertFalse(SMI_MIN > 0); +assertFalse(SMI_MIN + 1 > 1); +assertFalse(SMI_MIN + 1 > 2); +assertFalse(SMI_MIN + 2 > 1); +assertFalse(0 < SMI_MIN); +assertTrue(-1 < SMI_MAX); +assertFalse(SMI_MAX < -1); diff --git a/test/mjsunit/math-abs.js b/test/mjsunit/math-abs.js new file mode 100644 index 00000000..bec1a01c --- /dev/null +++ b/test/mjsunit/math-abs.js @@ -0,0 +1,98 @@ +// Copyright 2010 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Flags: --max-new-space-size=256 + +function zero() { + var x = 0.5; + return (function() { return x - 0.5; })(); +} + +function test() { + assertEquals(0, Math.abs(0)); + assertEquals(0, Math.abs(zero())); + assertEquals(1/0, 1/Math.abs(-0)); // 0 == -0, so we use reciprocals. + assertEquals(Infinity, Math.abs(Infinity)); + assertEquals(Infinity, Math.abs(-Infinity)); + assertNaN(Math.abs(NaN)); + assertNaN(Math.abs(-NaN)); + assertEquals('Infinity', Math.abs(Number('+Infinity').toString())); + assertEquals('Infinity', Math.abs(Number('-Infinity').toString())); + assertEquals('NaN', Math.abs(NaN).toString()); + assertEquals('NaN', Math.abs(-NaN).toString()); + + assertEquals(0.1, Math.abs(0.1)); + assertEquals(0.5, Math.abs(0.5)); + assertEquals(0.1, Math.abs(-0.1)); + assertEquals(0.5, Math.abs(-0.5)); + assertEquals(1, Math.abs(1)); + assertEquals(1.1, Math.abs(1.1)); + assertEquals(1.5, Math.abs(1.5)); + assertEquals(1, Math.abs(-1)); + assertEquals(1.1, Math.abs(-1.1)); + assertEquals(1.5, Math.abs(-1.5)); + + assertEquals(Number.MIN_VALUE, Math.abs(Number.MIN_VALUE)); + assertEquals(Number.MIN_VALUE, Math.abs(-Number.MIN_VALUE)); + assertEquals(Number.MAX_VALUE, Math.abs(Number.MAX_VALUE)); + assertEquals(Number.MAX_VALUE, Math.abs(-Number.MAX_VALUE)); + + // 2^30 is a smi boundary on arm and ia32. + var two_30 = 1 << 30; + + assertEquals(two_30, Math.abs(two_30)); + assertEquals(two_30, Math.abs(-two_30)); + + assertEquals(two_30 + 1, Math.abs(two_30 + 1)); + assertEquals(two_30 + 1, Math.abs(-two_30 - 1)); + + assertEquals(two_30 - 1, Math.abs(two_30 - 1)); + assertEquals(two_30 - 1, Math.abs(-two_30 + 1)); + + // 2^31 is a smi boundary on x64. + var two_31 = 2 * two_30; + + assertEquals(two_31, Math.abs(two_31)); + assertEquals(two_31, Math.abs(-two_31)); + + assertEquals(two_31 + 1, Math.abs(two_31 + 1)); + assertEquals(two_31 + 1, Math.abs(-two_31 - 1)); + + assertEquals(two_31 - 1, Math.abs(two_31 - 1)); + assertEquals(two_31 - 1, Math.abs(-two_31 + 1)); + + assertNaN(Math.abs("not a number")); + assertNaN(Math.abs([1, 2, 3])); + assertEquals(42, Math.abs({valueOf: function() { return 42; } })); + assertEquals(42, Math.abs({valueOf: function() { return -42; } })); +} + + +// Test in a loop to cover the custom IC and GC-related issues. +for (var i = 0; i < 500; i++) { + test(); +} diff --git a/test/mjsunit/math-floor.js b/test/mjsunit/math-floor.js index e56341c8..0d1c0ac5 100644 --- a/test/mjsunit/math-floor.js +++ b/test/mjsunit/math-floor.js @@ -25,7 +25,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --max-new-space-size=262144 +// Flags: --max-new-space-size=256 function zero() { var x = 0.5; diff --git a/test/mjsunit/regexp.js b/test/mjsunit/regexp.js index db8b1338..b57b86d2 100644 --- a/test/mjsunit/regexp.js +++ b/test/mjsunit/regexp.js @@ -502,3 +502,148 @@ for (var i = 0; i < 100; i++) { res[3] = "Glopglyf"; assertEquals("Arglebargle", res.foobar); } + +// Test that we perform the spec required conversions in the correct order. +var log; +var string = "the string"; +var fakeLastIndex = { + valueOf: function() { + log.push("li"); + return 0; + } + }; +var fakeString = { + toString: function() { + log.push("ts"); + return string; + }, + length: 0 + }; + +var re = /str/; +log = []; +re.lastIndex = fakeLastIndex; +var result = re.exec(fakeString); +assertEquals(["str"], result); +assertEquals(["ts", "li"], log); + +// Again, to check if caching interferes. +log = []; +re.lastIndex = fakeLastIndex; +result = re.exec(fakeString); +assertEquals(["str"], result); +assertEquals(["ts", "li"], log); + +// And one more time, just to be certain. +log = []; +re.lastIndex = fakeLastIndex; +result = re.exec(fakeString); +assertEquals(["str"], result); +assertEquals(["ts", "li"], log); + +// Now with a global regexp, where lastIndex is actually used. +re = /str/g; +log = []; +re.lastIndex = fakeLastIndex; +var result = re.exec(fakeString); +assertEquals(["str"], result); +assertEquals(["ts", "li"], log); + +// Again, to check if caching interferes. +log = []; +re.lastIndex = fakeLastIndex; +result = re.exec(fakeString); +assertEquals(["str"], result); +assertEquals(["ts", "li"], log); + +// And one more time, just to be certain. +log = []; +re.lastIndex = fakeLastIndex; +result = re.exec(fakeString); +assertEquals(["str"], result); +assertEquals(["ts", "li"], log); + + +// Check that properties of RegExp have the correct permissions. +var re = /x/g; +var desc = Object.getOwnPropertyDescriptor(re, "global"); +assertEquals(true, desc.value); +assertEquals(false, desc.configurable); +assertEquals(false, desc.enumerable); +assertEquals(false, desc.writable); + +desc = Object.getOwnPropertyDescriptor(re, "multiline"); +assertEquals(false, desc.value); +assertEquals(false, desc.configurable); +assertEquals(false, desc.enumerable); +assertEquals(false, desc.writable); + +desc = Object.getOwnPropertyDescriptor(re, "ignoreCase"); +assertEquals(false, desc.value); +assertEquals(false, desc.configurable); +assertEquals(false, desc.enumerable); +assertEquals(false, desc.writable); + +desc = Object.getOwnPropertyDescriptor(re, "lastIndex"); +assertEquals(0, desc.value); +assertEquals(false, desc.configurable); +assertEquals(false, desc.enumerable); +assertEquals(true, desc.writable); + + +// Check that end-anchored regexps are optimized correctly. +var re = /(?:a|bc)g$/; +assertTrue(re.test("ag")); +assertTrue(re.test("bcg")); +assertTrue(re.test("abcg")); +assertTrue(re.test("zimbag")); +assertTrue(re.test("zimbcg")); + +assertFalse(re.test("g")); +assertFalse(re.test("")); + +// Global regexp (non-zero start). +var re = /(?:a|bc)g$/g; +assertTrue(re.test("ag")); +re.lastIndex = 1; // Near start of string. +assertTrue(re.test("zimbag")); +re.lastIndex = 6; // At end of string. +assertFalse(re.test("zimbag")); +re.lastIndex = 5; // Near end of string. +assertFalse(re.test("zimbag")); +re.lastIndex = 4; +assertTrue(re.test("zimbag")); + +// Anchored at both ends. +var re = /^(?:a|bc)g$/g; +assertTrue(re.test("ag")); +re.lastIndex = 1; +assertFalse(re.test("ag")); +re.lastIndex = 1; +assertFalse(re.test("zag")); + +// Long max_length of RegExp. +var re = /VeryLongRegExp!{1,1000}$/; +assertTrue(re.test("BahoolaVeryLongRegExp!!!!!!")); +assertFalse(re.test("VeryLongRegExp")); +assertFalse(re.test("!")); + +// End anchor inside disjunction. +var re = /(?:a$|bc$)/; +assertTrue(re.test("a")); +assertTrue(re.test("bc")); +assertTrue(re.test("abc")); +assertTrue(re.test("zimzamzumba")); +assertTrue(re.test("zimzamzumbc")); +assertFalse(re.test("c")); +assertFalse(re.test("")); + +// Only partially anchored. +var re = /(?:a|bc$)/; +assertTrue(re.test("a")); +assertTrue(re.test("bc")); +assertEquals(["a"], re.exec("abc")); +assertEquals(4, re.exec("zimzamzumba").index); +assertEquals(["bc"], re.exec("zimzomzumbc")); +assertFalse(re.test("c")); +assertFalse(re.test("")); diff --git a/test/mjsunit/abs.js b/test/mjsunit/regress/regress-58740.js index d1c453c9..ab3e93b5 100644 --- a/test/mjsunit/abs.js +++ b/test/mjsunit/regress/regress-58740.js @@ -25,24 +25,11 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Test Math.sin and Math.abs. +// See: http://code.google.com/p/chromium/issues/detail?id=58740 -assertEquals(1, Math.abs(1)); // Positive SMI. -assertEquals(1, Math.abs(-1)); // Negative SMI. -assertEquals(0.5, Math.abs(0.5)); // Positive double. -assertEquals(0.5, Math.abs(-0.5)); // Negative double. -assertEquals('Infinity', Math.abs(Number('+Infinity').toString())); -assertEquals('Infinity', Math.abs(Number('-Infinity').toString())); -assertEquals('NaN', Math.abs(NaN).toString()); -assertEquals('NaN', Math.abs(-NaN).toString()); - -var minusZero = 1 / (-1 / 0); -function isMinusZero(x) { - return x === 0 && 1 / x < 0; -} - -assertTrue(!isMinusZero(0)); -assertTrue(isMinusZero(minusZero)); -assertEquals(0, Math.abs(minusZero)); -assertTrue(!isMinusZero(Math.abs(minusZero))); -assertTrue(!isMinusZero(Math.abs(0.0))); +var re = /.+/g; +re.exec(""); +re.exec("anystring"); +re=/.+/g; +re.exec(""); +assertEquals(0, re.lastIndex); diff --git a/test/mjsunit/regress/regress-create-exception.js b/test/mjsunit/regress/regress-create-exception.js new file mode 100644 index 00000000..7d53f1cd --- /dev/null +++ b/test/mjsunit/regress/regress-create-exception.js @@ -0,0 +1,58 @@ +// Copyright 2010 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Flags: --max-new-space-size=256 + +// Check for GC bug constructing exceptions. +var v = [1, 2, 3, 4] + +Object.preventExtensions(v); + +function foo() { + var re = /2147483647/; // Equal to 0x7fffffff. + for (var i = 0; i < 10000; i++) { + var ok = false; + try { + var j = 1; + // Allocate some heap numbers in order to randomize the behaviour of the + // garbage collector. 93 is chosen to be a prime number to avoid the + // allocation settling into a too neat pattern. + for (var j = 0; j < i % 93; j++) { + j *= 1.123567; // An arbitrary floating point number. + } + v[0x7fffffff] = 0; // Trigger exception. + assertTrue(false); + return j; // Make sure that future optimizations don't eliminate j. + } catch(e) { + ok = true; + assertTrue(re.test(e)); + } + assertTrue(ok); + } +} + +foo(); diff --git a/test/mjsunit/smi-negative-zero.js b/test/mjsunit/smi-negative-zero.js index 69064431..ea2fa5a9 100644 --- a/test/mjsunit/smi-negative-zero.js +++ b/test/mjsunit/smi-negative-zero.js @@ -98,3 +98,16 @@ assertEquals(-Infinity, one / (-4 % 2), "fiskhest1"); assertEquals(-Infinity, one / (-4 % -2), "fiskhest2"); assertEquals(Infinity, one / (4 % 2), "fiskhest3"); assertEquals(Infinity, one / (4 % -2), "fiskhest4"); + + +// This tests against a singleton -0.0 object being overwritten.gc +x = 0; +z = 3044; + +function foo(x) { + var y = -x + z; + return -x; +} + +assertEquals(0, foo(x)); +assertEquals(0, foo(x)); diff --git a/test/mjsunit/smi-ops.js b/test/mjsunit/smi-ops.js index 499535c0..8fa6fec6 100644 --- a/test/mjsunit/smi-ops.js +++ b/test/mjsunit/smi-ops.js @@ -1,4 +1,4 @@ -// Copyright 2008 the V8 project authors. All rights reserved. +// Copyright 2010 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -25,8 +25,8 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -const SMI_MAX = (1 << 30) - 1; -const SMI_MIN = -(1 << 30); +const SMI_MAX = (1 << 29) - 1 + (1 << 29); // Create without overflowing. +const SMI_MIN = -SMI_MAX - 1; // Create without overflowing. const ONE = 1; const ONE_HUNDRED = 100; @@ -213,6 +213,15 @@ v = SMI_MIN; v--; assertEquals(-0x40000001, v, "smimin--"); +// Check that comparisons of numbers separated by MIN_SMI work. +assertFalse(SMI_MIN > 0); +assertFalse(SMI_MIN + 1 > 1); +assertFalse(SMI_MIN + 1 > 2); +assertFalse(SMI_MIN + 2 > 1); +assertFalse(0 < SMI_MIN); +assertTrue(-1 < SMI_MAX); +assertFalse(SMI_MAX < -1); + // Not actually Smi operations. // Check that relations on unary ops work. var v = -1.2; diff --git a/test/mjsunit/string-indexof-1.js b/test/mjsunit/string-indexof-1.js index c7dcdb83..c5ae4b89 100644 --- a/test/mjsunit/string-indexof-1.js +++ b/test/mjsunit/string-indexof-1.js @@ -97,3 +97,29 @@ assertEquals(1534, long.indexOf("AJABACA", 511), "Long AJABACA, Second J"); pattern = "JABACABADABACABA"; assertEquals(511, long.indexOf(pattern), "Long JABACABA..., First J"); assertEquals(1535, long.indexOf(pattern, 512), "Long JABACABA..., Second J"); + + +// Search for a non-ASCII string in a pure ASCII string. +var asciiString = "arglebargleglopglyfarglebargleglopglyfarglebargleglopglyf"; +assertEquals(-1, asciiString.indexOf("\x2061")); + + +// Search in string containing many non-ASCII chars. +var allCodePoints = []; +for (var i = 0; i < 65536; i++) allCodePoints[i] = i; +var allCharsString = String.fromCharCode.apply(String, allCodePoints); +// Search for string long enough to trigger complex search with ASCII pattern +// and UC16 subject. +assertEquals(-1, allCharsString.indexOf("notfound")); + +// Find substrings. +var lengths = [1, 4, 15]; // Single char, simple and complex. +var indices = [0x5, 0x65, 0x85, 0x105, 0x205, 0x285, 0x2005, 0x2085, 0xfff0]; +for (var lengthIndex = 0; lengthIndex < lengths.length; lengthIndex++) { + var length = lengths[lengthIndex]; + for (var i = 0; i < indices.length; i++) { + var index = indices[i]; + var pattern = allCharsString.substring(index, index + length); + assertEquals(index, allCharsString.indexOf(pattern)); + } +} |
