Update V8 to r5675 as required by WebKit r70209
Change-Id: Ib10adb470d41ca8c109ead5fc893b880e18d489f
diff --git a/test/cctest/SConscript b/test/cctest/SConscript
index 3ec621e..006653c 100644
--- a/test/cctest/SConscript
+++ b/test/cctest/SConscript
@@ -70,6 +70,7 @@
'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 d03f5f7..895e245 100644
--- a/test/cctest/cctest.status
+++ b/test/cctest/cctest.status
@@ -35,11 +35,6 @@
# 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 315a34e..2936d6e 100644
--- a/test/cctest/test-alloc.cc
+++ b/test/cctest/test-alloc.cc
@@ -37,13 +37,13 @@
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 1b6359b..fd44aec 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -431,8 +431,8 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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(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 @@
"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 @@
}
-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 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 @@
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 @@
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 @@
LocalContext context(&extensions);
v8_compile("gc();")->Run();
}
- CHECK_EQ(count, GetSurvivingGlobalObjectsCount());
+ CheckSurvivingGlobalObjectsCount(0);
}
}
@@ -10517,6 +10559,45 @@
}
+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 @@
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 abcd426..c62bbaa 100644
--- a/test/cctest/test-conversions.cc
+++ b/test/cctest/test-conversions.cc
@@ -168,6 +168,38 @@
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 f5526ce..d59e2f5 100644
--- a/test/cctest/test-debug.cc
+++ b/test/cctest/test-debug.cc
@@ -867,7 +867,7 @@
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 @@
// 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 @@
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 7587da8..88fa79b 100644
--- a/test/cctest/test-decls.cc
+++ b/test/cctest/test-decls.cc
@@ -130,7 +130,7 @@
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 5e570f3..b86a336 100644
--- a/test/cctest/test-heap-profiler.cc
+++ b/test/cctest/test-heap-profiler.cc
@@ -20,11 +20,6 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// -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 @@
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 @@
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 @@
v8::HandleScope scope;
LocalContext env;
- CompileAndRunScript(
+ CompileRun(
"function A() { }\n"
"a = new A;");
const v8::HeapSnapshot* snapshot =
@@ -648,10 +643,9 @@
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 @@
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(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 @@
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 @@
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 @@
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(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 @@
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 @@
#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 eec024f..126ac21 100644
--- a/test/cctest/test-heap.cc
+++ b/test/cctest/test-heap.cc
@@ -177,13 +177,11 @@
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 @@
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 @@
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 @@
}
// 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 @@
}
// 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 @@
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 @@
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 @@
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(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 @@
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 @@
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 9162ffd..7d7bd40 100644
--- a/test/cctest/test-log-stack-tracer.cc
+++ b/test/cctest/test-log-stack-tracer.cc
@@ -245,8 +245,8 @@
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 b364ae3..16d0f00 100644
--- a/test/cctest/test-log.cc
+++ b/test/cctest/test-log.cc
@@ -469,7 +469,7 @@
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 3d2b91b..9b1fc46 100755
--- a/test/cctest/test-macro-assembler-x64.cc
+++ b/test/cctest/test-macro-assembler-x64.cc
@@ -519,40 +519,40 @@
__ 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 e4ac1b7..531b1f7 100644
--- a/test/cctest/test-mark-compact.cc
+++ b/test/cctest/test-mark-compact.cc
@@ -94,7 +94,7 @@
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 @@
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 @@
}
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 186350b..11a808e 100644
--- a/test/cctest/test-regexp.cc
+++ b/test/cctest/test-regexp.cc
@@ -64,7 +64,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 2811ee6..db8c54f 100644
--- a/test/cctest/test-spaces.cc
+++ b/test/cctest/test-spaces.cc
@@ -221,7 +221,7 @@
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 0000000..ae1c00d
--- /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 40d53b9..032284c 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 0000000..1883926
--- /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 0000000..bec1a01
--- /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 e56341c..0d1c0ac 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 db8b133..b57b86d 100644
--- a/test/mjsunit/regexp.js
+++ b/test/mjsunit/regexp.js
@@ -502,3 +502,148 @@
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
similarity index 67%
rename from test/mjsunit/abs.js
rename to test/mjsunit/regress/regress-58740.js
index d1c453c..ab3e93b 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/abs.js b/test/mjsunit/regress/regress-create-exception.js
similarity index 64%
copy from test/mjsunit/abs.js
copy to test/mjsunit/regress/regress-create-exception.js
index d1c453c..7d53f1c 100644
--- a/test/mjsunit/abs.js
+++ b/test/mjsunit/regress/regress-create-exception.js
@@ -25,24 +25,34 @@
// (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.
+// Flags: --max-new-space-size=256
-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());
+// Check for GC bug constructing exceptions.
+var v = [1, 2, 3, 4]
-var minusZero = 1 / (-1 / 0);
-function isMinusZero(x) {
- return x === 0 && 1 / x < 0;
+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);
+ }
}
-assertTrue(!isMinusZero(0));
-assertTrue(isMinusZero(minusZero));
-assertEquals(0, Math.abs(minusZero));
-assertTrue(!isMinusZero(Math.abs(minusZero)));
-assertTrue(!isMinusZero(Math.abs(0.0)));
+foo();
diff --git a/test/mjsunit/smi-negative-zero.js b/test/mjsunit/smi-negative-zero.js
index 6906443..ea2fa5a 100644
--- a/test/mjsunit/smi-negative-zero.js
+++ b/test/mjsunit/smi-negative-zero.js
@@ -98,3 +98,16 @@
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 499535c..8fa6fec 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--;
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 c7dcdb8..c5ae4b8 100644
--- a/test/mjsunit/string-indexof-1.js
+++ b/test/mjsunit/string-indexof-1.js
@@ -97,3 +97,29 @@
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));
+ }
+}