OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 | 2 |
3 #include <stdlib.h> | 3 #include <stdlib.h> |
4 | 4 |
5 #include "v8.h" | 5 #include "v8.h" |
6 | 6 |
7 #include "compilation-cache.h" | 7 #include "compilation-cache.h" |
8 #include "execution.h" | 8 #include "execution.h" |
9 #include "factory.h" | 9 #include "factory.h" |
10 #include "macro-assembler.h" | 10 #include "macro-assembler.h" |
11 #include "global-handles.h" | 11 #include "global-handles.h" |
12 #include "stub-cache.h" | 12 #include "stub-cache.h" |
13 #include "cctest.h" | 13 #include "cctest.h" |
14 | 14 |
15 using namespace v8::internal; | 15 using namespace v8::internal; |
16 | 16 |
17 static v8::Persistent<v8::Context> env; | 17 static v8::Persistent<v8::Context> env; |
18 | 18 |
19 static void InitializeVM() { | 19 static void InitializeVM() { |
20 if (env.IsEmpty()) env = v8::Context::New(); | 20 if (env.IsEmpty()) env = v8::Context::New(); |
21 v8::HandleScope scope; | 21 v8::HandleScope scope; |
22 env->Enter(); | 22 env->Enter(); |
23 } | 23 } |
24 | 24 |
25 | 25 |
26 // Go through all incremental marking steps in one swoop. | 26 // Go through all incremental marking steps in one swoop. |
27 static void SimulateIncrementalMarking() { | 27 static void SimulateIncrementalMarking() { |
28 IncrementalMarking* marking = HEAP->incremental_marking(); | 28 IncrementalMarking* marking = HEAP->incremental_marking(); |
29 CHECK(marking->IsStopped()); | 29 CHECK(marking->IsMarking() || marking->IsStopped()); |
30 marking->Start(); | 30 if (marking->IsStopped()) { |
| 31 marking->Start(); |
| 32 } |
31 CHECK(marking->IsMarking()); | 33 CHECK(marking->IsMarking()); |
32 while (!marking->IsComplete()) { | 34 while (!marking->IsComplete()) { |
33 marking->Step(MB, IncrementalMarking::NO_GC_VIA_STACK_GUARD); | 35 marking->Step(MB, IncrementalMarking::NO_GC_VIA_STACK_GUARD); |
34 } | 36 } |
35 CHECK(marking->IsComplete()); | 37 CHECK(marking->IsComplete()); |
36 } | 38 } |
37 | 39 |
38 | 40 |
39 static void CheckMap(Map* map, int type, int instance_size) { | 41 static void CheckMap(Map* map, int type, int instance_size) { |
40 CHECK(map->IsHeapObject()); | 42 CHECK(map->IsHeapObject()); |
(...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
406 { | 408 { |
407 HandleScope scope; | 409 HandleScope scope; |
408 | 410 |
409 Handle<Object> i = FACTORY->NewStringFromAscii(CStrVector("fisk")); | 411 Handle<Object> i = FACTORY->NewStringFromAscii(CStrVector("fisk")); |
410 Handle<Object> u = FACTORY->NewNumber(1.12344); | 412 Handle<Object> u = FACTORY->NewNumber(1.12344); |
411 | 413 |
412 h1 = global_handles->Create(*i); | 414 h1 = global_handles->Create(*i); |
413 h2 = global_handles->Create(*u); | 415 h2 = global_handles->Create(*u); |
414 } | 416 } |
415 | 417 |
| 418 // Make sure the objects are promoted. |
416 HEAP->CollectGarbage(OLD_POINTER_SPACE); | 419 HEAP->CollectGarbage(OLD_POINTER_SPACE); |
417 HEAP->CollectGarbage(NEW_SPACE); | 420 HEAP->CollectGarbage(NEW_SPACE); |
418 // Make sure the object is promoted. | 421 CHECK(!HEAP->InNewSpace(*h1) && !HEAP->InNewSpace(*h2)); |
419 | 422 |
420 global_handles->MakeWeak(h2.location(), | 423 global_handles->MakeWeak(h2.location(), |
421 reinterpret_cast<void*>(1234), | 424 reinterpret_cast<void*>(1234), |
422 &TestWeakGlobalHandleCallback); | 425 &TestWeakGlobalHandleCallback); |
423 CHECK(!GlobalHandles::IsNearDeath(h1.location())); | 426 CHECK(!GlobalHandles::IsNearDeath(h1.location())); |
424 CHECK(!GlobalHandles::IsNearDeath(h2.location())); | 427 CHECK(!GlobalHandles::IsNearDeath(h2.location())); |
425 | 428 |
426 HEAP->CollectGarbage(OLD_POINTER_SPACE); | 429 // Incremental marking potentially marked handles before they turned weak. |
| 430 HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); |
427 | 431 |
428 CHECK((*h1)->IsString()); | 432 CHECK((*h1)->IsString()); |
429 | 433 |
430 CHECK(WeakPointerCleared); | 434 CHECK(WeakPointerCleared); |
431 CHECK(!GlobalHandles::IsNearDeath(h1.location())); | 435 CHECK(!GlobalHandles::IsNearDeath(h1.location())); |
432 | 436 |
433 global_handles->Destroy(h1.location()); | 437 global_handles->Destroy(h1.location()); |
434 } | 438 } |
435 | 439 |
436 | 440 |
(...skipping 591 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1028 CHECK(function->shared()->is_compiled()); | 1032 CHECK(function->shared()->is_compiled()); |
1029 | 1033 |
1030 // The code will survive at least two GCs. | 1034 // The code will survive at least two GCs. |
1031 HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); | 1035 HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); |
1032 HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); | 1036 HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); |
1033 CHECK(function->shared()->is_compiled()); | 1037 CHECK(function->shared()->is_compiled()); |
1034 | 1038 |
1035 // Simulate several GCs that use incremental marking. | 1039 // Simulate several GCs that use incremental marking. |
1036 const int kAgingThreshold = 6; | 1040 const int kAgingThreshold = 6; |
1037 for (int i = 0; i < kAgingThreshold; i++) { | 1041 for (int i = 0; i < kAgingThreshold; i++) { |
1038 HEAP->incremental_marking()->Abort(); | |
1039 SimulateIncrementalMarking(); | 1042 SimulateIncrementalMarking(); |
1040 HEAP->CollectAllGarbage(Heap::kNoGCFlags); | 1043 HEAP->CollectAllGarbage(Heap::kNoGCFlags); |
1041 } | 1044 } |
1042 CHECK(!function->shared()->is_compiled() || function->IsOptimized()); | 1045 CHECK(!function->shared()->is_compiled() || function->IsOptimized()); |
1043 CHECK(!function->is_compiled() || function->IsOptimized()); | 1046 CHECK(!function->is_compiled() || function->IsOptimized()); |
1044 | 1047 |
1045 // This compile will compile the function again. | 1048 // This compile will compile the function again. |
1046 { v8::HandleScope scope; | 1049 { v8::HandleScope scope; |
1047 CompileRun("foo();"); | 1050 CompileRun("foo();"); |
1048 } | 1051 } |
1049 | 1052 |
1050 // Simulate several GCs that use incremental marking but make sure | 1053 // Simulate several GCs that use incremental marking but make sure |
1051 // the loop breaks once the function is enqueued as a candidate. | 1054 // the loop breaks once the function is enqueued as a candidate. |
1052 for (int i = 0; i < kAgingThreshold; i++) { | 1055 for (int i = 0; i < kAgingThreshold; i++) { |
1053 HEAP->incremental_marking()->Abort(); | |
1054 SimulateIncrementalMarking(); | 1056 SimulateIncrementalMarking(); |
1055 if (!function->next_function_link()->IsUndefined()) break; | 1057 if (!function->next_function_link()->IsUndefined()) break; |
1056 HEAP->CollectAllGarbage(Heap::kNoGCFlags); | 1058 HEAP->CollectAllGarbage(Heap::kNoGCFlags); |
1057 } | 1059 } |
1058 | 1060 |
1059 // Force optimization while incremental marking is active and while | 1061 // Force optimization while incremental marking is active and while |
1060 // the function is enqueued as a candidate. | 1062 // the function is enqueued as a candidate. |
1061 { v8::HandleScope scope; | 1063 { v8::HandleScope scope; |
1062 CompileRun("%OptimizeFunctionOnNextCall(foo); foo();"); | 1064 CompileRun("%OptimizeFunctionOnNextCall(foo); foo();"); |
1063 } | 1065 } |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1218 count++; | 1220 count++; |
1219 object = JSFunction::cast(object)->next_function_link(); | 1221 object = JSFunction::cast(object)->next_function_link(); |
1220 } | 1222 } |
1221 return count; | 1223 return count; |
1222 } | 1224 } |
1223 | 1225 |
1224 | 1226 |
1225 TEST(TestInternalWeakLists) { | 1227 TEST(TestInternalWeakLists) { |
1226 v8::V8::Initialize(); | 1228 v8::V8::Initialize(); |
1227 | 1229 |
| 1230 // Some flags turn Scavenge collections into Mark-sweep collections |
| 1231 // and hence are incompatible with this test case. |
| 1232 if (FLAG_gc_global || FLAG_stress_compaction) return; |
| 1233 |
1228 static const int kNumTestContexts = 10; | 1234 static const int kNumTestContexts = 10; |
1229 | 1235 |
1230 v8::HandleScope scope; | 1236 v8::HandleScope scope; |
1231 v8::Persistent<v8::Context> ctx[kNumTestContexts]; | 1237 v8::Persistent<v8::Context> ctx[kNumTestContexts]; |
1232 | 1238 |
1233 CHECK_EQ(0, CountNativeContexts()); | 1239 CHECK_EQ(0, CountNativeContexts()); |
1234 | 1240 |
1235 // Create a number of global contests which gets linked together. | 1241 // Create a number of global contests which gets linked together. |
1236 for (int i = 0; i < kNumTestContexts; i++) { | 1242 for (int i = 0; i < kNumTestContexts; i++) { |
1237 ctx[i] = v8::Context::New(); | 1243 ctx[i] = v8::Context::New(); |
(...skipping 701 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1939 CHECK_EQ(0, f->shared()->opt_count()); | 1945 CHECK_EQ(0, f->shared()->opt_count()); |
1940 CHECK_EQ(0, f->shared()->code()->profiler_ticks()); | 1946 CHECK_EQ(0, f->shared()->code()->profiler_ticks()); |
1941 } | 1947 } |
1942 | 1948 |
1943 | 1949 |
1944 // Test that HAllocateObject will always return an object in new-space. | 1950 // Test that HAllocateObject will always return an object in new-space. |
1945 TEST(OptimizedAllocationAlwaysInNewSpace) { | 1951 TEST(OptimizedAllocationAlwaysInNewSpace) { |
1946 i::FLAG_allow_natives_syntax = true; | 1952 i::FLAG_allow_natives_syntax = true; |
1947 InitializeVM(); | 1953 InitializeVM(); |
1948 if (!i::V8::UseCrankshaft() || i::FLAG_always_opt) return; | 1954 if (!i::V8::UseCrankshaft() || i::FLAG_always_opt) return; |
| 1955 if (i::FLAG_gc_global || i::FLAG_stress_compaction) return; |
1949 v8::HandleScope scope; | 1956 v8::HandleScope scope; |
1950 | 1957 |
1951 SimulateFullSpace(HEAP->new_space()); | 1958 SimulateFullSpace(HEAP->new_space()); |
1952 AlwaysAllocateScope always_allocate; | 1959 AlwaysAllocateScope always_allocate; |
1953 v8::Local<v8::Value> res = CompileRun( | 1960 v8::Local<v8::Value> res = CompileRun( |
1954 "function c(x) {" | 1961 "function c(x) {" |
1955 " this.x = x;" | 1962 " this.x = x;" |
1956 " for (var i = 0; i < 32; i++) {" | 1963 " for (var i = 0; i < 32; i++) {" |
1957 " this['x' + i] = x;" | 1964 " this['x' + i] = x;" |
1958 " }" | 1965 " }" |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2114 for (int i = 0; i < number_of_test_pages; i++) { | 2121 for (int i = 0; i < number_of_test_pages; i++) { |
2115 AlwaysAllocateScope always_allocate; | 2122 AlwaysAllocateScope always_allocate; |
2116 SimulateFullSpace(old_pointer_space); | 2123 SimulateFullSpace(old_pointer_space); |
2117 FACTORY->NewFixedArray(1, TENURED); | 2124 FACTORY->NewFixedArray(1, TENURED); |
2118 } | 2125 } |
2119 CHECK_EQ(number_of_test_pages + 1, old_pointer_space->CountTotalPages()); | 2126 CHECK_EQ(number_of_test_pages + 1, old_pointer_space->CountTotalPages()); |
2120 | 2127 |
2121 // Triggering one GC will cause a lot of garbage to be discovered but | 2128 // Triggering one GC will cause a lot of garbage to be discovered but |
2122 // even spread across all allocated pages. | 2129 // even spread across all allocated pages. |
2123 HEAP->CollectAllGarbage(Heap::kNoGCFlags, "triggered for preparation"); | 2130 HEAP->CollectAllGarbage(Heap::kNoGCFlags, "triggered for preparation"); |
2124 CHECK_EQ(number_of_test_pages + 1, old_pointer_space->CountTotalPages()); | 2131 CHECK_GE(number_of_test_pages + 1, old_pointer_space->CountTotalPages()); |
2125 | 2132 |
2126 // Triggering subsequent GCs should cause at least half of the pages | 2133 // Triggering subsequent GCs should cause at least half of the pages |
2127 // to be released to the OS after at most two cycles. | 2134 // to be released to the OS after at most two cycles. |
2128 HEAP->CollectAllGarbage(Heap::kNoGCFlags, "triggered by test 1"); | 2135 HEAP->CollectAllGarbage(Heap::kNoGCFlags, "triggered by test 1"); |
2129 CHECK_GE(number_of_test_pages + 1, old_pointer_space->CountTotalPages()); | 2136 CHECK_GE(number_of_test_pages + 1, old_pointer_space->CountTotalPages()); |
2130 HEAP->CollectAllGarbage(Heap::kNoGCFlags, "triggered by test 2"); | 2137 HEAP->CollectAllGarbage(Heap::kNoGCFlags, "triggered by test 2"); |
2131 CHECK_GE(number_of_test_pages + 1, old_pointer_space->CountTotalPages() * 2); | 2138 CHECK_GE(number_of_test_pages + 1, old_pointer_space->CountTotalPages() * 2); |
2132 | 2139 |
2133 // Triggering a last-resort GC should cause all pages to be released to the | 2140 // Triggering a last-resort GC should cause all pages to be released to the |
2134 // OS so that other processes can seize the memory. If we get a failure here | 2141 // OS so that other processes can seize the memory. If we get a failure here |
(...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2561 // Simulate incremental marking so that the functions are enqueued as | 2568 // Simulate incremental marking so that the functions are enqueued as |
2562 // code flushing candidates. Then optimize one function. Finally | 2569 // code flushing candidates. Then optimize one function. Finally |
2563 // finish the GC to complete code flushing. | 2570 // finish the GC to complete code flushing. |
2564 SimulateIncrementalMarking(); | 2571 SimulateIncrementalMarking(); |
2565 CompileRun("%OptimizeFunctionOnNextCall(g); g(3);"); | 2572 CompileRun("%OptimizeFunctionOnNextCall(g); g(3);"); |
2566 HEAP->CollectAllGarbage(Heap::kNoGCFlags); | 2573 HEAP->CollectAllGarbage(Heap::kNoGCFlags); |
2567 | 2574 |
2568 // Unoptimized code is missing and the deoptimizer will go ballistic. | 2575 // Unoptimized code is missing and the deoptimizer will go ballistic. |
2569 CompileRun("g('bozo');"); | 2576 CompileRun("g('bozo');"); |
2570 } | 2577 } |
OLD | NEW |