| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 173 value = heap->NumberFromInt32(Smi::kMinValue)->ToObjectChecked(); | 173 value = heap->NumberFromInt32(Smi::kMinValue)->ToObjectChecked(); |
| 174 CHECK(value->IsSmi()); | 174 CHECK(value->IsSmi()); |
| 175 CHECK(value->IsNumber()); | 175 CHECK(value->IsNumber()); |
| 176 CHECK_EQ(Smi::kMinValue, Smi::cast(value)->value()); | 176 CHECK_EQ(Smi::kMinValue, Smi::cast(value)->value()); |
| 177 | 177 |
| 178 value = heap->NumberFromInt32(Smi::kMaxValue)->ToObjectChecked(); | 178 value = heap->NumberFromInt32(Smi::kMaxValue)->ToObjectChecked(); |
| 179 CHECK(value->IsSmi()); | 179 CHECK(value->IsSmi()); |
| 180 CHECK(value->IsNumber()); | 180 CHECK(value->IsNumber()); |
| 181 CHECK_EQ(Smi::kMaxValue, Smi::cast(value)->value()); | 181 CHECK_EQ(Smi::kMaxValue, Smi::cast(value)->value()); |
| 182 | 182 |
| 183 #ifndef V8_TARGET_ARCH_X64 | 183 #if !defined(V8_TARGET_ARCH_X64) && !defined(V8_TARGET_ARCH_A64) |
| 184 // TODO(lrn): We need a NumberFromIntptr function in order to test this. | 184 // TODO(lrn): We need a NumberFromIntptr function in order to test this. |
| 185 value = heap->NumberFromInt32(Smi::kMinValue - 1)->ToObjectChecked(); | 185 value = heap->NumberFromInt32(Smi::kMinValue - 1)->ToObjectChecked(); |
| 186 CHECK(value->IsHeapNumber()); | 186 CHECK(value->IsHeapNumber()); |
| 187 CHECK(value->IsNumber()); | 187 CHECK(value->IsNumber()); |
| 188 CHECK_EQ(static_cast<double>(Smi::kMinValue - 1), value->Number()); | 188 CHECK_EQ(static_cast<double>(Smi::kMinValue - 1), value->Number()); |
| 189 #endif | 189 #endif |
| 190 | 190 |
| 191 MaybeObject* maybe_value = | 191 MaybeObject* maybe_value = |
| 192 heap->NumberFromUint32(static_cast<uint32_t>(Smi::kMaxValue) + 1); | 192 heap->NumberFromUint32(static_cast<uint32_t>(Smi::kMaxValue) + 1); |
| 193 value = maybe_value->ToObjectChecked(); | 193 value = maybe_value->ToObjectChecked(); |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 426 h1 = global_handles->Create(*i); | 426 h1 = global_handles->Create(*i); |
| 427 h2 = global_handles->Create(*u); | 427 h2 = global_handles->Create(*u); |
| 428 } | 428 } |
| 429 | 429 |
| 430 std::pair<Handle<Object>*, int> handle_and_id(&h2, 1234); | 430 std::pair<Handle<Object>*, int> handle_and_id(&h2, 1234); |
| 431 GlobalHandles::MakeWeak(h2.location(), | 431 GlobalHandles::MakeWeak(h2.location(), |
| 432 reinterpret_cast<void*>(&handle_and_id), | 432 reinterpret_cast<void*>(&handle_and_id), |
| 433 &TestWeakGlobalHandleCallback); | 433 &TestWeakGlobalHandleCallback); |
| 434 | 434 |
| 435 // Scavenge treats weak pointers as normal roots. | 435 // Scavenge treats weak pointers as normal roots. |
| 436 heap->PerformScavenge(); | 436 heap->CollectGarbage(NEW_SPACE); |
| 437 | 437 |
| 438 CHECK((*h1)->IsString()); | 438 CHECK((*h1)->IsString()); |
| 439 CHECK((*h2)->IsHeapNumber()); | 439 CHECK((*h2)->IsHeapNumber()); |
| 440 | 440 |
| 441 CHECK(!WeakPointerCleared); | 441 CHECK(!WeakPointerCleared); |
| 442 CHECK(!global_handles->IsNearDeath(h2.location())); | 442 CHECK(!global_handles->IsNearDeath(h2.location())); |
| 443 CHECK(!global_handles->IsNearDeath(h1.location())); | 443 CHECK(!global_handles->IsNearDeath(h1.location())); |
| 444 | 444 |
| 445 GlobalHandles::Destroy(h1.location()); | 445 GlobalHandles::Destroy(h1.location()); |
| 446 GlobalHandles::Destroy(h2.location()); | 446 GlobalHandles::Destroy(h2.location()); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 511 Handle<Object> i = factory->NewStringFromAscii(CStrVector("fisk")); | 511 Handle<Object> i = factory->NewStringFromAscii(CStrVector("fisk")); |
| 512 h = global_handles->Create(*i); | 512 h = global_handles->Create(*i); |
| 513 } | 513 } |
| 514 | 514 |
| 515 std::pair<Handle<Object>*, int> handle_and_id(&h, 1234); | 515 std::pair<Handle<Object>*, int> handle_and_id(&h, 1234); |
| 516 GlobalHandles::MakeWeak(h.location(), | 516 GlobalHandles::MakeWeak(h.location(), |
| 517 reinterpret_cast<void*>(&handle_and_id), | 517 reinterpret_cast<void*>(&handle_and_id), |
| 518 &TestWeakGlobalHandleCallback); | 518 &TestWeakGlobalHandleCallback); |
| 519 | 519 |
| 520 // Scanvenge does not recognize weak reference. | 520 // Scanvenge does not recognize weak reference. |
| 521 heap->PerformScavenge(); | 521 heap->CollectGarbage(NEW_SPACE); |
| 522 | 522 |
| 523 CHECK(!WeakPointerCleared); | 523 CHECK(!WeakPointerCleared); |
| 524 | 524 |
| 525 // Mark-compact treats weak reference properly. | 525 // Mark-compact treats weak reference properly. |
| 526 heap->CollectGarbage(OLD_POINTER_SPACE); | 526 heap->CollectGarbage(OLD_POINTER_SPACE); |
| 527 | 527 |
| 528 CHECK(WeakPointerCleared); | 528 CHECK(WeakPointerCleared); |
| 529 } | 529 } |
| 530 | 530 |
| 531 | 531 |
| (...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 911 FAST_HOLEY_ELEMENTS, | 911 FAST_HOLEY_ELEMENTS, |
| 912 TENURED); | 912 TENURED); |
| 913 | 913 |
| 914 // Allocate a small string to OLD_DATA_SPACE and NEW_SPACE | 914 // Allocate a small string to OLD_DATA_SPACE and NEW_SPACE |
| 915 objs[next_objs_index++] = | 915 objs[next_objs_index++] = |
| 916 factory->NewStringFromAscii(CStrVector("abcdefghij")); | 916 factory->NewStringFromAscii(CStrVector("abcdefghij")); |
| 917 objs[next_objs_index++] = | 917 objs[next_objs_index++] = |
| 918 factory->NewStringFromAscii(CStrVector("abcdefghij"), TENURED); | 918 factory->NewStringFromAscii(CStrVector("abcdefghij"), TENURED); |
| 919 | 919 |
| 920 // Allocate a large string (for large object space). | 920 // Allocate a large string (for large object space). |
| 921 int large_size = Page::kMaxNonCodeHeapObjectSize + 1; | 921 int large_size = Page::kMaxRegularHeapObjectSize + 1; |
| 922 char* str = new char[large_size]; | 922 char* str = new char[large_size]; |
| 923 for (int i = 0; i < large_size - 1; ++i) str[i] = 'a'; | 923 for (int i = 0; i < large_size - 1; ++i) str[i] = 'a'; |
| 924 str[large_size - 1] = '\0'; | 924 str[large_size - 1] = '\0'; |
| 925 objs[next_objs_index++] = | 925 objs[next_objs_index++] = |
| 926 factory->NewStringFromAscii(CStrVector(str), TENURED); | 926 factory->NewStringFromAscii(CStrVector(str), TENURED); |
| 927 delete[] str; | 927 delete[] str; |
| 928 | 928 |
| 929 // Add a Map object to look for. | 929 // Add a Map object to look for. |
| 930 objs[next_objs_index++] = Handle<Map>(HeapObject::cast(*objs[0])->map()); | 930 objs[next_objs_index++] = Handle<Map>(HeapObject::cast(*objs[0])->map()); |
| 931 | 931 |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 980 Handle<Map> my_map = factory->CopyMap(object_map, 1); | 980 Handle<Map> my_map = factory->CopyMap(object_map, 1); |
| 981 int n_properties = my_map->inobject_properties(); | 981 int n_properties = my_map->inobject_properties(); |
| 982 CHECK_GT(n_properties, 0); | 982 CHECK_GT(n_properties, 0); |
| 983 | 983 |
| 984 int object_size = my_map->instance_size(); | 984 int object_size = my_map->instance_size(); |
| 985 | 985 |
| 986 // Step 2: allocate a lot of objects so to almost fill new space: we need | 986 // Step 2: allocate a lot of objects so to almost fill new space: we need |
| 987 // just enough room to allocate JSObject and thus fill the newspace. | 987 // just enough room to allocate JSObject and thus fill the newspace. |
| 988 | 988 |
| 989 int allocation_amount = Min(FixedArray::kMaxSize, | 989 int allocation_amount = Min(FixedArray::kMaxSize, |
| 990 Page::kMaxNonCodeHeapObjectSize + kPointerSize); | 990 Page::kMaxRegularHeapObjectSize + kPointerSize); |
| 991 int allocation_len = LenFromSize(allocation_amount); | 991 int allocation_len = LenFromSize(allocation_amount); |
| 992 NewSpace* new_space = heap->new_space(); | 992 NewSpace* new_space = heap->new_space(); |
| 993 Address* top_addr = new_space->allocation_top_address(); | 993 Address* top_addr = new_space->allocation_top_address(); |
| 994 Address* limit_addr = new_space->allocation_limit_address(); | 994 Address* limit_addr = new_space->allocation_limit_address(); |
| 995 while ((*limit_addr - *top_addr) > allocation_amount) { | 995 while ((*limit_addr - *top_addr) > allocation_amount) { |
| 996 CHECK(!heap->always_allocate()); | 996 CHECK(!heap->always_allocate()); |
| 997 Object* array = heap->AllocateFixedArray(allocation_len)->ToObjectChecked(); | 997 Object* array = heap->AllocateFixedArray(allocation_len)->ToObjectChecked(); |
| 998 CHECK(!array->IsFailure()); | 998 CHECK(!array->IsFailure()); |
| 999 CHECK(new_space->Contains(array)); | 999 CHECK(new_space->Contains(array)); |
| 1000 } | 1000 } |
| (...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1429 CompileRun("f4()"); | 1429 CompileRun("f4()"); |
| 1430 CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[i])); | 1430 CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[i])); |
| 1431 CompileRun("f5()"); | 1431 CompileRun("f5()"); |
| 1432 CHECK_EQ(opt ? 5 : 0, CountOptimizedUserFunctions(ctx[i])); | 1432 CHECK_EQ(opt ? 5 : 0, CountOptimizedUserFunctions(ctx[i])); |
| 1433 | 1433 |
| 1434 // Remove function f1, and | 1434 // Remove function f1, and |
| 1435 CompileRun("f1=null"); | 1435 CompileRun("f1=null"); |
| 1436 | 1436 |
| 1437 // Scavenge treats these references as strong. | 1437 // Scavenge treats these references as strong. |
| 1438 for (int j = 0; j < 10; j++) { | 1438 for (int j = 0; j < 10; j++) { |
| 1439 CcTest::heap()->PerformScavenge(); | 1439 CcTest::heap()->CollectGarbage(NEW_SPACE); |
| 1440 CHECK_EQ(opt ? 5 : 0, CountOptimizedUserFunctions(ctx[i])); | 1440 CHECK_EQ(opt ? 5 : 0, CountOptimizedUserFunctions(ctx[i])); |
| 1441 } | 1441 } |
| 1442 | 1442 |
| 1443 // Mark compact handles the weak references. | 1443 // Mark compact handles the weak references. |
| 1444 isolate->compilation_cache()->Clear(); | 1444 isolate->compilation_cache()->Clear(); |
| 1445 heap->CollectAllGarbage(Heap::kNoGCFlags); | 1445 heap->CollectAllGarbage(Heap::kNoGCFlags); |
| 1446 CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[i])); | 1446 CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[i])); |
| 1447 | 1447 |
| 1448 // Get rid of f3 and f5 in the same way. | 1448 // Get rid of f3 and f5 in the same way. |
| 1449 CompileRun("f3=null"); | 1449 CompileRun("f3=null"); |
| 1450 for (int j = 0; j < 10; j++) { | 1450 for (int j = 0; j < 10; j++) { |
| 1451 CcTest::heap()->PerformScavenge(); | 1451 CcTest::heap()->CollectGarbage(NEW_SPACE); |
| 1452 CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[i])); | 1452 CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[i])); |
| 1453 } | 1453 } |
| 1454 CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags); | 1454 CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags); |
| 1455 CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctions(ctx[i])); | 1455 CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctions(ctx[i])); |
| 1456 CompileRun("f5=null"); | 1456 CompileRun("f5=null"); |
| 1457 for (int j = 0; j < 10; j++) { | 1457 for (int j = 0; j < 10; j++) { |
| 1458 CcTest::heap()->PerformScavenge(); | 1458 CcTest::heap()->CollectGarbage(NEW_SPACE); |
| 1459 CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctions(ctx[i])); | 1459 CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctions(ctx[i])); |
| 1460 } | 1460 } |
| 1461 CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags); | 1461 CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags); |
| 1462 CHECK_EQ(opt ? 2 : 0, CountOptimizedUserFunctions(ctx[i])); | 1462 CHECK_EQ(opt ? 2 : 0, CountOptimizedUserFunctions(ctx[i])); |
| 1463 | 1463 |
| 1464 ctx[i]->Exit(); | 1464 ctx[i]->Exit(); |
| 1465 } | 1465 } |
| 1466 | 1466 |
| 1467 // Force compilation cache cleanup. | 1467 // Force compilation cache cleanup. |
| 1468 CcTest::heap()->NotifyContextDisposed(); | 1468 CcTest::heap()->NotifyContextDisposed(); |
| 1469 CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags); | 1469 CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags); |
| 1470 | 1470 |
| 1471 // Dispose the native contexts one by one. | 1471 // Dispose the native contexts one by one. |
| 1472 for (int i = 0; i < kNumTestContexts; i++) { | 1472 for (int i = 0; i < kNumTestContexts; i++) { |
| 1473 // TODO(dcarney): is there a better way to do this? | 1473 // TODO(dcarney): is there a better way to do this? |
| 1474 i::Object** unsafe = reinterpret_cast<i::Object**>(*ctx[i]); | 1474 i::Object** unsafe = reinterpret_cast<i::Object**>(*ctx[i]); |
| 1475 *unsafe = CcTest::heap()->undefined_value(); | 1475 *unsafe = CcTest::heap()->undefined_value(); |
| 1476 ctx[i].Clear(); | 1476 ctx[i].Clear(); |
| 1477 | 1477 |
| 1478 // Scavenge treats these references as strong. | 1478 // Scavenge treats these references as strong. |
| 1479 for (int j = 0; j < 10; j++) { | 1479 for (int j = 0; j < 10; j++) { |
| 1480 CcTest::heap()->PerformScavenge(); | 1480 CcTest::heap()->CollectGarbage(i::NEW_SPACE); |
| 1481 CHECK_EQ(kNumTestContexts - i, CountNativeContexts()); | 1481 CHECK_EQ(kNumTestContexts - i, CountNativeContexts()); |
| 1482 } | 1482 } |
| 1483 | 1483 |
| 1484 // Mark compact handles the weak references. | 1484 // Mark compact handles the weak references. |
| 1485 CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags); | 1485 CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags); |
| 1486 CHECK_EQ(kNumTestContexts - i - 1, CountNativeContexts()); | 1486 CHECK_EQ(kNumTestContexts - i - 1, CountNativeContexts()); |
| 1487 } | 1487 } |
| 1488 | 1488 |
| 1489 CHECK_EQ(0, CountNativeContexts()); | 1489 CHECK_EQ(0, CountNativeContexts()); |
| 1490 } | 1490 } |
| (...skipping 693 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2184 Handle<JSObject> o = | 2184 Handle<JSObject> o = |
| 2185 v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(res)); | 2185 v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(res)); |
| 2186 | 2186 |
| 2187 CHECK(CcTest::heap()->InNewSpace(*o)); | 2187 CHECK(CcTest::heap()->InNewSpace(*o)); |
| 2188 } | 2188 } |
| 2189 | 2189 |
| 2190 | 2190 |
| 2191 TEST(OptimizedPretenuringAllocationFolding) { | 2191 TEST(OptimizedPretenuringAllocationFolding) { |
| 2192 i::FLAG_allow_natives_syntax = true; | 2192 i::FLAG_allow_natives_syntax = true; |
| 2193 i::FLAG_max_new_space_size = 2048; | 2193 i::FLAG_max_new_space_size = 2048; |
| 2194 i::FLAG_allocation_site_pretenuring = false; |
| 2194 CcTest::InitializeVM(); | 2195 CcTest::InitializeVM(); |
| 2195 if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return; | 2196 if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return; |
| 2196 if (i::FLAG_gc_global || i::FLAG_stress_compaction) return; | 2197 if (i::FLAG_gc_global || i::FLAG_stress_compaction) return; |
| 2197 v8::HandleScope scope(CcTest::isolate()); | 2198 v8::HandleScope scope(CcTest::isolate()); |
| 2198 CcTest::heap()->SetNewSpaceHighPromotionModeActive(true); | 2199 CcTest::heap()->SetNewSpaceHighPromotionModeActive(true); |
| 2199 | 2200 |
| 2200 v8::Local<v8::Value> res = CompileRun( | 2201 v8::Local<v8::Value> res = CompileRun( |
| 2201 "function DataObject() {" | 2202 "function DataObject() {" |
| 2202 " this.a = 1.1;" | 2203 " this.a = 1.1;" |
| 2203 " this.b = [{}];" | 2204 " this.b = [{}];" |
| 2204 " this.c = 1.2;" | 2205 " this.c = 1.2;" |
| 2205 " this.d = [{}];" | 2206 " this.d = [{}];" |
| 2206 " this.e = 1.3;" | 2207 " this.e = 1.3;" |
| 2207 " this.f = [{}];" | 2208 " this.f = [{}];" |
| 2208 "}" | 2209 "}" |
| 2209 "var number_elements = 20000;" | 2210 "var number_elements = 20000;" |
| 2210 "var elements = new Array();" | 2211 "var elements = new Array();" |
| 2211 "function f() {" | 2212 "function f() {" |
| 2212 " for (var i = 0; i < 20000-1; i++) {" | 2213 " for (var i = 0; i < number_elements; i++) {" |
| 2213 " elements[i] = new DataObject();" | 2214 " elements[i] = new DataObject();" |
| 2214 " }" | 2215 " }" |
| 2215 " return new DataObject()" | 2216 " return elements[number_elements-1]" |
| 2216 "};" | 2217 "};" |
| 2217 "f(); f(); f();" | 2218 "f(); f(); f();" |
| 2218 "%OptimizeFunctionOnNextCall(f);" | 2219 "%OptimizeFunctionOnNextCall(f);" |
| 2219 "f();"); | 2220 "f();"); |
| 2220 | 2221 |
| 2221 Handle<JSObject> o = | 2222 Handle<JSObject> o = |
| 2222 v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(res)); | 2223 v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(res)); |
| 2223 | 2224 |
| 2224 CHECK(CcTest::heap()->InOldDataSpace(o->RawFastPropertyAt(0))); | 2225 CHECK(CcTest::heap()->InOldDataSpace(o->RawFastPropertyAt(0))); |
| 2225 CHECK(CcTest::heap()->InOldPointerSpace(o->RawFastPropertyAt(1))); | 2226 CHECK(CcTest::heap()->InOldPointerSpace(o->RawFastPropertyAt(1))); |
| 2226 CHECK(CcTest::heap()->InOldDataSpace(o->RawFastPropertyAt(2))); | 2227 CHECK(CcTest::heap()->InOldDataSpace(o->RawFastPropertyAt(2))); |
| 2227 CHECK(CcTest::heap()->InOldPointerSpace(o->RawFastPropertyAt(3))); | 2228 CHECK(CcTest::heap()->InOldPointerSpace(o->RawFastPropertyAt(3))); |
| 2228 CHECK(CcTest::heap()->InOldDataSpace(o->RawFastPropertyAt(4))); | 2229 CHECK(CcTest::heap()->InOldDataSpace(o->RawFastPropertyAt(4))); |
| 2229 CHECK(CcTest::heap()->InOldPointerSpace(o->RawFastPropertyAt(5))); | 2230 CHECK(CcTest::heap()->InOldPointerSpace(o->RawFastPropertyAt(5))); |
| 2230 } | 2231 } |
| 2231 | 2232 |
| 2232 | 2233 |
| 2233 TEST(OptimizedPretenuringAllocationFoldingBlocks) { | 2234 TEST(OptimizedPretenuringAllocationFoldingBlocks) { |
| 2234 i::FLAG_allow_natives_syntax = true; | 2235 i::FLAG_allow_natives_syntax = true; |
| 2235 i::FLAG_max_new_space_size = 2048; | 2236 i::FLAG_max_new_space_size = 2048; |
| 2237 i::FLAG_allocation_site_pretenuring = false; |
| 2236 CcTest::InitializeVM(); | 2238 CcTest::InitializeVM(); |
| 2237 if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return; | 2239 if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return; |
| 2238 if (i::FLAG_gc_global || i::FLAG_stress_compaction) return; | 2240 if (i::FLAG_gc_global || i::FLAG_stress_compaction) return; |
| 2239 v8::HandleScope scope(CcTest::isolate()); | 2241 v8::HandleScope scope(CcTest::isolate()); |
| 2240 CcTest::heap()->SetNewSpaceHighPromotionModeActive(true); | 2242 CcTest::heap()->SetNewSpaceHighPromotionModeActive(true); |
| 2241 | 2243 |
| 2242 v8::Local<v8::Value> res = CompileRun( | 2244 v8::Local<v8::Value> res = CompileRun( |
| 2243 "var number_elements = 30000;" | 2245 "var number_elements = 30000;" |
| 2244 "var elements = new Array(number_elements);" | 2246 "var elements = new Array(number_elements);" |
| 2245 "function DataObject() {" | 2247 "function DataObject() {" |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2367 | 2369 |
| 2368 TEST(OptimizedPretenuringdoubleArrayLiterals) { | 2370 TEST(OptimizedPretenuringdoubleArrayLiterals) { |
| 2369 i::FLAG_allow_natives_syntax = true; | 2371 i::FLAG_allow_natives_syntax = true; |
| 2370 i::FLAG_max_new_space_size = 2048; | 2372 i::FLAG_max_new_space_size = 2048; |
| 2371 CcTest::InitializeVM(); | 2373 CcTest::InitializeVM(); |
| 2372 if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return; | 2374 if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return; |
| 2373 if (i::FLAG_gc_global || i::FLAG_stress_compaction) return; | 2375 if (i::FLAG_gc_global || i::FLAG_stress_compaction) return; |
| 2374 v8::HandleScope scope(CcTest::isolate()); | 2376 v8::HandleScope scope(CcTest::isolate()); |
| 2375 | 2377 |
| 2376 v8::Local<v8::Value> res = CompileRun( | 2378 v8::Local<v8::Value> res = CompileRun( |
| 2377 "var number_elements = 20000;" | 2379 "var number_elements = 30000;" |
| 2378 "var elements = new Array(number_elements);" | 2380 "var elements = new Array(number_elements);" |
| 2379 "function f() {" | 2381 "function f() {" |
| 2380 " for (var i = 0; i < number_elements; i++) {" | 2382 " for (var i = 0; i < number_elements; i++) {" |
| 2381 " elements[i] = [1.1, 2.2, 3.3];" | 2383 " elements[i] = [1.1, 2.2, 3.3];" |
| 2382 " }" | 2384 " }" |
| 2383 " return elements[number_elements - 1];" | 2385 " return elements[number_elements - 1];" |
| 2384 "};" | 2386 "};" |
| 2385 "f(); f(); f();" | 2387 "f(); f(); f();" |
| 2386 "%OptimizeFunctionOnNextCall(f);" | 2388 "%OptimizeFunctionOnNextCall(f);" |
| 2387 "f();"); | 2389 "f();"); |
| (...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2817 // Check size. | 2819 // Check size. |
| 2818 DescriptorArray* descriptors = internal_obj->map()->instance_descriptors(); | 2820 DescriptorArray* descriptors = internal_obj->map()->instance_descriptors(); |
| 2819 ObjectHashTable* hashtable = ObjectHashTable::cast( | 2821 ObjectHashTable* hashtable = ObjectHashTable::cast( |
| 2820 internal_obj->RawFastPropertyAt(descriptors->GetFieldIndex(0))); | 2822 internal_obj->RawFastPropertyAt(descriptors->GetFieldIndex(0))); |
| 2821 // HashTable header (5) and 4 initial entries (8). | 2823 // HashTable header (5) and 4 initial entries (8). |
| 2822 CHECK_LE(hashtable->SizeFor(hashtable->length()), 13 * kPointerSize); | 2824 CHECK_LE(hashtable->SizeFor(hashtable->length()), 13 * kPointerSize); |
| 2823 } | 2825 } |
| 2824 } | 2826 } |
| 2825 | 2827 |
| 2826 | 2828 |
| 2827 TEST(IncrementalMarkingClearsTypeFeedbackCells) { | 2829 TEST(IncrementalMarkingClearsTypeFeedbackInfo) { |
| 2828 if (i::FLAG_always_opt) return; | 2830 if (i::FLAG_always_opt) return; |
| 2829 CcTest::InitializeVM(); | 2831 CcTest::InitializeVM(); |
| 2830 v8::HandleScope scope(CcTest::isolate()); | 2832 v8::HandleScope scope(CcTest::isolate()); |
| 2831 v8::Local<v8::Value> fun1, fun2; | 2833 v8::Local<v8::Value> fun1, fun2; |
| 2832 | 2834 |
| 2833 { | 2835 { |
| 2834 LocalContext env; | 2836 LocalContext env; |
| 2835 CompileRun("function fun() {};"); | 2837 CompileRun("function fun() {};"); |
| 2836 fun1 = env->Global()->Get(v8_str("fun")); | 2838 fun1 = env->Global()->Get(v8_str("fun")); |
| 2837 } | 2839 } |
| 2838 | 2840 |
| 2839 { | 2841 { |
| 2840 LocalContext env; | 2842 LocalContext env; |
| 2841 CompileRun("function fun() {};"); | 2843 CompileRun("function fun() {};"); |
| 2842 fun2 = env->Global()->Get(v8_str("fun")); | 2844 fun2 = env->Global()->Get(v8_str("fun")); |
| 2843 } | 2845 } |
| 2844 | 2846 |
| 2845 // Prepare function f that contains type feedback for closures | 2847 // Prepare function f that contains type feedback for closures |
| 2846 // originating from two different native contexts. | 2848 // originating from two different native contexts. |
| 2847 CcTest::global()->Set(v8_str("fun1"), fun1); | 2849 CcTest::global()->Set(v8_str("fun1"), fun1); |
| 2848 CcTest::global()->Set(v8_str("fun2"), fun2); | 2850 CcTest::global()->Set(v8_str("fun2"), fun2); |
| 2849 CompileRun("function f(a, b) { a(); b(); } f(fun1, fun2);"); | 2851 CompileRun("function f(a, b) { a(); b(); } f(fun1, fun2);"); |
| 2852 |
| 2850 Handle<JSFunction> f = | 2853 Handle<JSFunction> f = |
| 2851 v8::Utils::OpenHandle( | 2854 v8::Utils::OpenHandle( |
| 2852 *v8::Handle<v8::Function>::Cast( | 2855 *v8::Handle<v8::Function>::Cast( |
| 2853 CcTest::global()->Get(v8_str("f")))); | 2856 CcTest::global()->Get(v8_str("f")))); |
| 2854 Handle<TypeFeedbackCells> cells(TypeFeedbackInfo::cast( | |
| 2855 f->shared()->code()->type_feedback_info())->type_feedback_cells()); | |
| 2856 | 2857 |
| 2857 CHECK_EQ(2, cells->CellCount()); | 2858 Handle<FixedArray> feedback_vector(TypeFeedbackInfo::cast( |
| 2858 CHECK(cells->GetCell(0)->value()->IsJSFunction()); | 2859 f->shared()->code()->type_feedback_info())->feedback_vector()); |
| 2859 CHECK(cells->GetCell(1)->value()->IsJSFunction()); | 2860 |
| 2861 CHECK_EQ(2, feedback_vector->length()); |
| 2862 CHECK(feedback_vector->get(0)->IsJSFunction()); |
| 2863 CHECK(feedback_vector->get(1)->IsJSFunction()); |
| 2860 | 2864 |
| 2861 SimulateIncrementalMarking(); | 2865 SimulateIncrementalMarking(); |
| 2862 CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags); | 2866 CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags); |
| 2863 | 2867 |
| 2864 CHECK_EQ(2, cells->CellCount()); | 2868 CHECK_EQ(2, feedback_vector->length()); |
| 2865 CHECK(cells->GetCell(0)->value()->IsTheHole()); | 2869 CHECK(feedback_vector->get(0)->IsTheHole()); |
| 2866 CHECK(cells->GetCell(1)->value()->IsTheHole()); | 2870 CHECK(feedback_vector->get(1)->IsTheHole()); |
| 2867 } | 2871 } |
| 2868 | 2872 |
| 2869 | 2873 |
| 2870 static Code* FindFirstIC(Code* code, Code::Kind kind) { | 2874 static Code* FindFirstIC(Code* code, Code::Kind kind) { |
| 2871 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) | | 2875 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) | |
| 2872 RelocInfo::ModeMask(RelocInfo::CONSTRUCT_CALL) | | 2876 RelocInfo::ModeMask(RelocInfo::CONSTRUCT_CALL) | |
| 2873 RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID); | 2877 RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID); |
| 2874 for (RelocIterator it(code, mask); !it.done(); it.next()) { | 2878 for (RelocIterator it(code, mask); !it.done(); it.next()) { |
| 2875 RelocInfo* info = it.rinfo(); | 2879 RelocInfo* info = it.rinfo(); |
| 2876 Code* target = Code::GetCodeFromTargetAddress(info->target_address()); | 2880 Code* target = Code::GetCodeFromTargetAddress(info->target_address()); |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3025 CompileRun(accessor); | 3029 CompileRun(accessor); |
| 3026 CcTest::heap()->CollectAllAvailableGarbage(); | 3030 CcTest::heap()->CollectAllAvailableGarbage(); |
| 3027 | 3031 |
| 3028 // External source has been released. | 3032 // External source has been released. |
| 3029 CHECK(resource->IsDisposed()); | 3033 CHECK(resource->IsDisposed()); |
| 3030 delete resource; | 3034 delete resource; |
| 3031 } | 3035 } |
| 3032 | 3036 |
| 3033 | 3037 |
| 3034 TEST(ReleaseStackTraceData) { | 3038 TEST(ReleaseStackTraceData) { |
| 3039 if (i::FLAG_always_opt) { |
| 3040 // TODO(ulan): Remove this once the memory leak via code_next_link is fixed. |
| 3041 // See: https://codereview.chromium.org/181833004/ |
| 3042 return; |
| 3043 } |
| 3035 FLAG_use_ic = false; // ICs retain objects. | 3044 FLAG_use_ic = false; // ICs retain objects. |
| 3036 FLAG_concurrent_recompilation = false; | 3045 FLAG_concurrent_recompilation = false; |
| 3037 CcTest::InitializeVM(); | 3046 CcTest::InitializeVM(); |
| 3038 static const char* source1 = "var error = null; " | 3047 static const char* source1 = "var error = null; " |
| 3039 /* Normal Error */ "try { " | 3048 /* Normal Error */ "try { " |
| 3040 " throw new Error(); " | 3049 " throw new Error(); " |
| 3041 "} catch (e) { " | 3050 "} catch (e) { " |
| 3042 " error = e; " | 3051 " error = e; " |
| 3043 "} "; | 3052 "} "; |
| 3044 static const char* source2 = "var error = null; " | 3053 static const char* source2 = "var error = null; " |
| (...skipping 25 matching lines...) Expand all Loading... |
| 3070 // supposed to (untypically) write to the receiver, not the holder. This is | 3079 // supposed to (untypically) write to the receiver, not the holder. This is |
| 3071 // to emulate the behavior of a data property. | 3080 // to emulate the behavior of a data property. |
| 3072 | 3081 |
| 3073 ReleaseStackTraceDataTest(source1, getter); | 3082 ReleaseStackTraceDataTest(source1, getter); |
| 3074 ReleaseStackTraceDataTest(source2, getter); | 3083 ReleaseStackTraceDataTest(source2, getter); |
| 3075 ReleaseStackTraceDataTest(source3, getter); | 3084 ReleaseStackTraceDataTest(source3, getter); |
| 3076 ReleaseStackTraceDataTest(source4, getter); | 3085 ReleaseStackTraceDataTest(source4, getter); |
| 3077 } | 3086 } |
| 3078 | 3087 |
| 3079 | 3088 |
| 3080 TEST(Regression144230) { | |
| 3081 i::FLAG_stress_compaction = false; | |
| 3082 CcTest::InitializeVM(); | |
| 3083 Isolate* isolate = CcTest::i_isolate(); | |
| 3084 Heap* heap = isolate->heap(); | |
| 3085 HandleScope scope(isolate); | |
| 3086 | |
| 3087 // First make sure that the uninitialized CallIC stub is on a single page | |
| 3088 // that will later be selected as an evacuation candidate. | |
| 3089 { | |
| 3090 HandleScope inner_scope(isolate); | |
| 3091 AlwaysAllocateScope always_allocate; | |
| 3092 SimulateFullSpace(heap->code_space()); | |
| 3093 isolate->stub_cache()->ComputeCallInitialize(9); | |
| 3094 } | |
| 3095 | |
| 3096 // Second compile a CallIC and execute it once so that it gets patched to | |
| 3097 // the pre-monomorphic stub. These code objects are on yet another page. | |
| 3098 { | |
| 3099 HandleScope inner_scope(isolate); | |
| 3100 AlwaysAllocateScope always_allocate; | |
| 3101 SimulateFullSpace(heap->code_space()); | |
| 3102 CompileRun("var o = { f:function(a,b,c,d,e,f,g,h,i) {}};" | |
| 3103 "function call() { o.f(1,2,3,4,5,6,7,8,9); };" | |
| 3104 "call();"); | |
| 3105 } | |
| 3106 | |
| 3107 // Third we fill up the last page of the code space so that it does not get | |
| 3108 // chosen as an evacuation candidate. | |
| 3109 { | |
| 3110 HandleScope inner_scope(isolate); | |
| 3111 AlwaysAllocateScope always_allocate; | |
| 3112 CompileRun("for (var i = 0; i < 2000; i++) {" | |
| 3113 " eval('function f' + i + '() { return ' + i +'; };' +" | |
| 3114 " 'f' + i + '();');" | |
| 3115 "}"); | |
| 3116 } | |
| 3117 heap->CollectAllGarbage(Heap::kNoGCFlags); | |
| 3118 | |
| 3119 // Fourth is the tricky part. Make sure the code containing the CallIC is | |
| 3120 // visited first without clearing the IC. The shared function info is then | |
| 3121 // visited later, causing the CallIC to be cleared. | |
| 3122 Handle<String> name = isolate->factory()->InternalizeUtf8String("call"); | |
| 3123 Handle<GlobalObject> global(isolate->context()->global_object()); | |
| 3124 Handle<Smi> zero(Smi::FromInt(0), isolate); | |
| 3125 MaybeObject* maybe_call = global->GetProperty(*name); | |
| 3126 JSFunction* call = JSFunction::cast(maybe_call->ToObjectChecked()); | |
| 3127 JSReceiver::SetProperty(global, name, zero, NONE, kNonStrictMode); | |
| 3128 isolate->compilation_cache()->Clear(); | |
| 3129 call->shared()->set_ic_age(heap->global_ic_age() + 1); | |
| 3130 Handle<Object> call_code(call->code(), isolate); | |
| 3131 Handle<Object> call_function(call, isolate); | |
| 3132 | |
| 3133 // Now we are ready to mess up the heap. | |
| 3134 heap->CollectAllGarbage(Heap::kReduceMemoryFootprintMask); | |
| 3135 | |
| 3136 // Either heap verification caught the problem already or we go kaboom once | |
| 3137 // the CallIC is executed the next time. | |
| 3138 JSReceiver::SetProperty(global, name, call_function, NONE, kNonStrictMode); | |
| 3139 CompileRun("call();"); | |
| 3140 } | |
| 3141 | |
| 3142 | |
| 3143 TEST(Regress159140) { | 3089 TEST(Regress159140) { |
| 3144 i::FLAG_allow_natives_syntax = true; | 3090 i::FLAG_allow_natives_syntax = true; |
| 3145 i::FLAG_flush_code_incrementally = true; | 3091 i::FLAG_flush_code_incrementally = true; |
| 3146 CcTest::InitializeVM(); | 3092 CcTest::InitializeVM(); |
| 3147 Isolate* isolate = CcTest::i_isolate(); | 3093 Isolate* isolate = CcTest::i_isolate(); |
| 3148 Heap* heap = isolate->heap(); | 3094 Heap* heap = isolate->heap(); |
| 3149 HandleScope scope(isolate); | 3095 HandleScope scope(isolate); |
| 3150 | 3096 |
| 3151 // Perform one initial GC to enable code flushing. | 3097 // Perform one initial GC to enable code flushing. |
| 3152 heap->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); | 3098 heap->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); |
| (...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3537 while (data->next < data->limit) { | 3483 while (data->next < data->limit) { |
| 3538 Handle<Object> obj(heap->empty_string(), isolate); | 3484 Handle<Object> obj(heap->empty_string(), isolate); |
| 3539 } | 3485 } |
| 3540 // An entire block of handles has been filled. | 3486 // An entire block of handles has been filled. |
| 3541 // Next handle would require a new block. | 3487 // Next handle would require a new block. |
| 3542 ASSERT(data->next == data->limit); | 3488 ASSERT(data->next == data->limit); |
| 3543 | 3489 |
| 3544 DeferredHandleScope deferred(isolate); | 3490 DeferredHandleScope deferred(isolate); |
| 3545 DummyVisitor visitor; | 3491 DummyVisitor visitor; |
| 3546 isolate->handle_scope_implementer()->Iterate(&visitor); | 3492 isolate->handle_scope_implementer()->Iterate(&visitor); |
| 3547 deferred.Detach(); | 3493 delete deferred.Detach(); |
| 3548 } | 3494 } |
| 3549 | 3495 |
| 3550 | 3496 |
| 3551 TEST(IncrementalMarkingStepMakesBigProgressWithLargeObjects) { | 3497 TEST(IncrementalMarkingStepMakesBigProgressWithLargeObjects) { |
| 3552 CcTest::InitializeVM(); | 3498 CcTest::InitializeVM(); |
| 3553 v8::HandleScope scope(CcTest::isolate()); | 3499 v8::HandleScope scope(CcTest::isolate()); |
| 3554 CompileRun("function f(n) {" | 3500 CompileRun("function f(n) {" |
| 3555 " var a = new Array(n);" | 3501 " var a = new Array(n);" |
| 3556 " for (var i = 0; i < n; i += 100) a[i] = i;" | 3502 " for (var i = 0; i < n; i += 100) a[i] = i;" |
| 3557 "};" | 3503 "};" |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3740 code = scope.CloseAndEscape(Handle<Code>(bar->code())); | 3686 code = scope.CloseAndEscape(Handle<Code>(bar->code())); |
| 3741 } | 3687 } |
| 3742 | 3688 |
| 3743 // Now make sure that a gc should get rid of the function | 3689 // Now make sure that a gc should get rid of the function |
| 3744 for (int i = 0; i < 4; i++) { | 3690 for (int i = 0; i < 4; i++) { |
| 3745 heap->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); | 3691 heap->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); |
| 3746 } | 3692 } |
| 3747 | 3693 |
| 3748 ASSERT(code->marked_for_deoptimization()); | 3694 ASSERT(code->marked_for_deoptimization()); |
| 3749 } | 3695 } |
| OLD | NEW |