diff options
author | Ryan Dahl <ry@tinyclouds.org> | 2010-03-26 09:09:40 -0700 |
---|---|---|
committer | Ryan Dahl <ry@tinyclouds.org> | 2010-03-26 09:09:40 -0700 |
commit | 6192b8659a3dedb86393cfb78121a26f2a3e31e6 (patch) | |
tree | 78b74bbdc1a7cdd8989e32db309050d6e51ba346 /deps/v8/test | |
parent | bb00fef3cd2ff446aa5c1894fb4830f83750018a (diff) | |
download | node-new-6192b8659a3dedb86393cfb78121a26f2a3e31e6.tar.gz |
Upgrade V8 to 2.1.10
Diffstat (limited to 'deps/v8/test')
-rw-r--r-- | deps/v8/test/cctest/test-api.cc | 62 | ||||
-rw-r--r-- | deps/v8/test/cctest/test-conversions.cc | 87 | ||||
-rw-r--r-- | deps/v8/test/cctest/test-heap.cc | 112 | ||||
-rw-r--r-- | deps/v8/test/mjsunit/str-to-num.js | 22 |
4 files changed, 283 insertions, 0 deletions
diff --git a/deps/v8/test/cctest/test-api.cc b/deps/v8/test/cctest/test-api.cc index e57914370d..84fdd68b4b 100644 --- a/deps/v8/test/cctest/test-api.cc +++ b/deps/v8/test/cctest/test-api.cc @@ -2644,6 +2644,36 @@ THREADED_TEST(NamedInterceptorPropertyRead) { } +THREADED_TEST(NamedInterceptorDictionaryIC) { + v8::HandleScope scope; + Local<ObjectTemplate> templ = ObjectTemplate::New(); + templ->SetNamedPropertyHandler(XPropertyGetter); + LocalContext context; + // Create an object with a named interceptor. + context->Global()->Set(v8_str("interceptor_obj"), templ->NewInstance()); + Local<Script> script = Script::Compile(v8_str("interceptor_obj.x")); + for (int i = 0; i < 10; i++) { + Local<Value> result = script->Run(); + CHECK_EQ(result, v8_str("x")); + } + // Create a slow case object and a function accessing a property in + // that slow case object (with dictionary probing in generated + // code). Then force object with a named interceptor into slow-case, + // pass it to the function, and check that the interceptor is called + // instead of accessing the local property. + Local<Value> result = + CompileRun("function get_x(o) { return o.x; };" + "var obj = { x : 42, y : 0 };" + "delete obj.y;" + "for (var i = 0; i < 10; i++) get_x(obj);" + "interceptor_obj.x = 42;" + "interceptor_obj.y = 10;" + "delete interceptor_obj.y;" + "get_x(interceptor_obj)"); + CHECK_EQ(result, v8_str("x")); +} + + static v8::Handle<Value> SetXOnPrototypeGetter(Local<String> property, const AccessorInfo& info) { // Set x on the prototype object and do not handle the get request. @@ -5974,6 +6004,38 @@ THREADED_TEST(InterceptorLoadICInvalidatedField) { } +static int interceptor_load_not_handled_calls = 0; +static v8::Handle<Value> InterceptorLoadNotHandled(Local<String> name, + const AccessorInfo& info) { + ++interceptor_load_not_handled_calls; + return v8::Handle<v8::Value>(); +} + + +// Test how post-interceptor lookups are done in the non-cacheable +// case: the interceptor should not be invoked during this lookup. +THREADED_TEST(InterceptorLoadICPostInterceptor) { + interceptor_load_not_handled_calls = 0; + CheckInterceptorLoadIC(InterceptorLoadNotHandled, + "receiver = new Object();" + "receiver.__proto__ = o;" + "proto = new Object();" + "/* Make proto a slow-case object. */" + "for (var i = 0; i < 1000; i++) {" + " proto[\"xxxxxxxx\" + i] = [];" + "}" + "proto.x = 17;" + "o.__proto__ = proto;" + "var result = 0;" + "for (var i = 0; i < 1000; i++) {" + " result += receiver.x;" + "}" + "result;", + 17 * 1000); + CHECK_EQ(1000, interceptor_load_not_handled_calls); +} + + // Test the case when we stored field into // a stub, but it got invalidated later on due to override on // global object which is between interceptor and fields' holders. diff --git a/deps/v8/test/cctest/test-conversions.cc b/deps/v8/test/cctest/test-conversions.cc index 35ab46f250..abcd426ec4 100644 --- a/deps/v8/test/cctest/test-conversions.cc +++ b/deps/v8/test/cctest/test-conversions.cc @@ -41,6 +41,10 @@ TEST(Octal) { CHECK_EQ(7.0, StringToDouble("07", ALLOW_HEX)); CHECK_EQ(10.0, StringToDouble("010", ALLOW_HEX)); CHECK_EQ(77.0, StringToDouble("077", ALLOW_HEX)); + + const double x = 010000000000; // Power of 2, no rounding errors. + CHECK_EQ(x * x * x * x * x, StringToDouble("01" "0000000000" "0000000000" + "0000000000" "0000000000" "0000000000", ALLOW_OCTALS)); } @@ -80,6 +84,8 @@ TEST(MalformedOctal) { TEST(TrailingJunk) { CHECK_EQ(8.0, StringToDouble("8q", ALLOW_TRAILING_JUNK)); CHECK_EQ(63.0, StringToDouble("077qqq", ALLOW_OCTALS | ALLOW_TRAILING_JUNK)); + CHECK_EQ(10.0, StringToDouble("10e", ALLOW_OCTALS | ALLOW_TRAILING_JUNK)); + CHECK_EQ(10.0, StringToDouble("10e-", ALLOW_OCTALS | ALLOW_TRAILING_JUNK)); } @@ -91,6 +97,87 @@ TEST(NonStrDecimalLiteral) { CHECK_EQ(0.0, StringToDouble(" ", NO_FLAGS)); } +TEST(IntegerStrLiteral) { + CHECK_EQ(0.0, StringToDouble("0.0", NO_FLAGS)); + CHECK_EQ(0.0, StringToDouble("0", NO_FLAGS)); + CHECK_EQ(0.0, StringToDouble("00", NO_FLAGS)); + CHECK_EQ(0.0, StringToDouble("000", NO_FLAGS)); + CHECK_EQ(1.0, StringToDouble("1", NO_FLAGS)); + CHECK_EQ(-1.0, StringToDouble("-1", NO_FLAGS)); + CHECK_EQ(-1.0, StringToDouble(" - 1 ", NO_FLAGS)); + CHECK_EQ(1.0, StringToDouble(" + 1 ", NO_FLAGS)); + + CHECK_EQ(0.0, StringToDouble("0e0", ALLOW_HEX | ALLOW_OCTALS)); + CHECK_EQ(0.0, StringToDouble("0e1", ALLOW_HEX | ALLOW_OCTALS)); + CHECK_EQ(0.0, StringToDouble("0e-1", ALLOW_HEX | ALLOW_OCTALS)); + CHECK_EQ(0.0, StringToDouble("0e-100000", ALLOW_HEX | ALLOW_OCTALS)); + CHECK_EQ(0.0, StringToDouble("0e+100000", ALLOW_HEX | ALLOW_OCTALS)); + CHECK_EQ(0.0, StringToDouble("0.", ALLOW_HEX | ALLOW_OCTALS)); +} + +TEST(LongNumberStr) { + CHECK_EQ(1e10, StringToDouble("1" "0000000000", NO_FLAGS)); + CHECK_EQ(1e20, StringToDouble("1" "0000000000" "0000000000", NO_FLAGS)); + + CHECK_EQ(1e60, StringToDouble("1" "0000000000" "0000000000" "0000000000" + "0000000000" "0000000000" "0000000000", NO_FLAGS)); + + CHECK_EQ(1e-2, StringToDouble("." "0" "1", NO_FLAGS)); + CHECK_EQ(1e-11, StringToDouble("." "0000000000" "1", NO_FLAGS)); + CHECK_EQ(1e-21, StringToDouble("." "0000000000" "0000000000" "1", NO_FLAGS)); + + CHECK_EQ(1e-61, StringToDouble("." "0000000000" "0000000000" "0000000000" + "0000000000" "0000000000" "0000000000" "1", NO_FLAGS)); + + + // x = 24414062505131248.0 and y = 24414062505131252.0 are representable in + // double. Check chat z = (x + y) / 2 is rounded to x... + CHECK_EQ(24414062505131248.0, + StringToDouble("24414062505131250.0", NO_FLAGS)); + + // ... and z = (x + y) / 2 + delta is rounded to y. + CHECK_EQ(24414062505131252.0, + StringToDouble("24414062505131250.000000001", NO_FLAGS)); +} + + +extern "C" double gay_strtod(const char* s00, const char** se); + + +TEST(MaximumSignificantDigits) { + char num[] = + "4.4501477170144020250819966727949918635852426585926051135169509" + "122872622312493126406953054127118942431783801370080830523154578" + "251545303238277269592368457430440993619708911874715081505094180" + "604803751173783204118519353387964161152051487413083163272520124" + "606023105869053620631175265621765214646643181420505164043632222" + "668006474326056011713528291579642227455489682133472873831754840" + "341397809846934151055619529382191981473003234105366170879223151" + "087335413188049110555339027884856781219017754500629806224571029" + "581637117459456877330110324211689177656713705497387108207822477" + "584250967061891687062782163335299376138075114200886249979505279" + "101870966346394401564490729731565935244123171539810221213221201" + "847003580761626016356864581135848683152156368691976240370422601" + "6998291015625000000000000000000000000000000000e-308"; + + 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(ExponentNumberStr) { + CHECK_EQ(1e1, StringToDouble("1e1", NO_FLAGS)); + CHECK_EQ(1e1, StringToDouble("1e+1", NO_FLAGS)); + CHECK_EQ(1e-1, StringToDouble("1e-1", NO_FLAGS)); + CHECK_EQ(1e100, StringToDouble("1e+100", NO_FLAGS)); + CHECK_EQ(1e-100, StringToDouble("1e-100", NO_FLAGS)); + CHECK_EQ(1e-106, StringToDouble(".000001e-100", NO_FLAGS)); +} + class OneBit1: public BitField<uint32_t, 0, 1> {}; class OneBit2: public BitField<uint32_t, 7, 1> {}; class EightBit1: public BitField<uint32_t, 0, 8> {}; diff --git a/deps/v8/test/cctest/test-heap.cc b/deps/v8/test/cctest/test-heap.cc index 2b88f0f94e..bfadd208b6 100644 --- a/deps/v8/test/cctest/test-heap.cc +++ b/deps/v8/test/cctest/test-heap.cc @@ -852,3 +852,115 @@ TEST(LargeObjectSpaceContains) { CHECK(Heap::new_space()->Contains(addr)); CHECK(!Heap::lo_space()->Contains(addr)); } + + +TEST(EmptyHandleEscapeFrom) { + InitializeVM(); + + v8::HandleScope scope; + Handle<JSObject> runaway; + + { + v8::HandleScope nested; + Handle<JSObject> empty; + runaway = empty.EscapeFrom(&nested); + } + + CHECK(runaway.is_null()); +} + + +static int LenFromSize(int size) { + return (size - FixedArray::kHeaderSize) / kPointerSize; +} + + +TEST(Regression39128) { + // Test case for crbug.com/39128. + InitializeVM(); + + // Increase the chance of 'bump-the-pointer' allocation in old space. + bool force_compaction = true; + Heap::CollectAllGarbage(force_compaction); + + v8::HandleScope scope; + + // The plan: create JSObject which references objects in new space. + // Then clone this object (forcing it to go into old space) and check + // that only bits pertaining to the object are updated in remembered set. + + // Step 1: prepare a map for the object. We add 1 inobject property to it. + Handle<JSFunction> object_ctor(Top::global_context()->object_function()); + CHECK(object_ctor->has_initial_map()); + Handle<Map> object_map(object_ctor->initial_map()); + // Create a map with single inobject property. + Handle<Map> my_map = Factory::CopyMap(object_map, 1); + int n_properties = my_map->inobject_properties(); + CHECK_GT(n_properties, 0); + + int object_size = my_map->instance_size(); + + // Step 2: allocate a lot of objects so to almost fill new space: we need + // just enough room to allocate JSObject and thus fill the newspace. + + int allocation_amount = Min(FixedArray::kMaxSize, + Heap::MaxObjectSizeInNewSpace()); + int allocation_len = LenFromSize(allocation_amount); + NewSpace* new_space = Heap::new_space(); + Address* top_addr = new_space->allocation_top_address(); + Address* limit_addr = new_space->allocation_limit_address(); + while ((*limit_addr - *top_addr) > allocation_amount) { + CHECK(!Heap::always_allocate()); + Object* array = Heap::AllocateFixedArray(allocation_len); + CHECK(!array->IsFailure()); + CHECK(new_space->Contains(array)); + } + + // Step 3: now allocate fixed array and JSObject to fill the whole new space. + int to_fill = *limit_addr - *top_addr - object_size; + int fixed_array_len = LenFromSize(to_fill); + CHECK(fixed_array_len < FixedArray::kMaxLength); + + CHECK(!Heap::always_allocate()); + Object* array = Heap::AllocateFixedArray(fixed_array_len); + CHECK(!array->IsFailure()); + CHECK(new_space->Contains(array)); + + Object* object = Heap::AllocateJSObjectFromMap(*my_map); + CHECK(!object->IsFailure()); + CHECK(new_space->Contains(object)); + JSObject* jsobject = JSObject::cast(object); + CHECK_EQ(0, jsobject->elements()->length()); + CHECK_EQ(0, jsobject->properties()->length()); + // Create a reference to object in new space in jsobject. + jsobject->FastPropertyAtPut(-1, array); + + CHECK_EQ(0L, (*limit_addr - *top_addr)); + + // Step 4: clone jsobject, but force always allocate first to create a clone + // in old pointer space. + Address old_pointer_space_top = Heap::old_pointer_space()->top(); + AlwaysAllocateScope aa_scope; + Object* clone_obj = Heap::CopyJSObject(jsobject); + CHECK(!object->IsFailure()); + JSObject* clone = JSObject::cast(clone_obj); + if (clone->address() != old_pointer_space_top) { + // Alas, got allocated from free list, we cannot do checks. + return; + } + CHECK(Heap::old_pointer_space()->Contains(clone->address())); + + // Step 5: verify validity of remembered set. + Address clone_addr = clone->address(); + Page* page = Page::FromAddress(clone_addr); + // Check that remembered set tracks a reference from inobject property 1. + CHECK(page->IsRSetSet(clone_addr, object_size - kPointerSize)); + // Probe several addresses after the object. + for (int i = 0; i < 7; i++) { + int offset = object_size + i * kPointerSize; + if (clone_addr + offset >= page->ObjectAreaEnd()) { + break; + } + CHECK(!page->IsRSetSet(clone_addr, offset)); + } +} diff --git a/deps/v8/test/mjsunit/str-to-num.js b/deps/v8/test/mjsunit/str-to-num.js index 12a3716247..f7a9c2d709 100644 --- a/deps/v8/test/mjsunit/str-to-num.js +++ b/deps/v8/test/mjsunit/str-to-num.js @@ -29,6 +29,19 @@ function toNumber(val) { return Number(val); } +function repeat(s, num) { + var result = ''; + while (num > 0) { + if ((num & 1) != 0) result += s; + s += s; + num >>= 1; + } + + return result; +} + +assertEquals('0000000000', repeat('0', 10)); + // assertEquals(, toNumber()); @@ -61,6 +74,7 @@ assertEquals(Infinity, toNumber("+Infinity "), "+Infinity"); assertEquals(0, toNumber("0")); assertEquals(0, toNumber("+0")); assertEquals(-0, toNumber("-0")); +assertEquals(-Infinity, 1 / toNumber("-0")); assertEquals(1, toNumber("1")); assertEquals(1, toNumber("+1")); @@ -130,11 +144,16 @@ assertEquals(15, toNumber("0Xf")); assertEquals(15, toNumber("0XF")); assertEquals(0, toNumber("0x000")); +assertEquals(-Infinity, 1 / toNumber("-0x000")); +assertEquals(0, toNumber("0x000" + repeat('0', 1000))); assertEquals(9, toNumber("0x009")); assertEquals(10, toNumber("0x00a")); assertEquals(10, toNumber("0x00A")); assertEquals(15, toNumber("0x00f")); assertEquals(15, toNumber("0x00F")); +assertEquals(Infinity, toNumber("0x" + repeat('0', 1000) + '1' + + repeat('0', 1000))); +assertEquals(-Infinity, toNumber("-0x1" + repeat('0', 1000))); assertEquals(0, toNumber("00")); assertEquals(1, toNumber("01")); @@ -156,3 +175,6 @@ assertTrue(isNaN(toNumber("0x100 junk")), "0x100 junk"); assertTrue(isNaN(toNumber("100.0 junk")), "100.0 junk"); assertTrue(isNaN(toNumber(".1e4 junk")), ".1e4 junk"); assertTrue(isNaN(toNumber("Infinity junk")), "Infinity junk"); +assertTrue(isNaN(toNumber("1e")), "1e"); +assertTrue(isNaN(toNumber("1e ")), "1e_"); +assertTrue(isNaN(toNumber("1" + repeat('0', 1000) + 'junk')), "1e1000 junk"); |