| 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. | 
|  | 27 static void SimulateIncrementalMarking() { | 
|  | 28   IncrementalMarking* marking = HEAP->incremental_marking(); | 
|  | 29   CHECK(marking->IsStopped()); | 
|  | 30   marking->Start(); | 
|  | 31   CHECK(marking->IsMarking()); | 
|  | 32   while (!marking->IsComplete()) { | 
|  | 33     marking->Step(MB, IncrementalMarking::NO_GC_VIA_STACK_GUARD); | 
|  | 34   } | 
|  | 35   CHECK(marking->IsComplete()); | 
|  | 36 } | 
|  | 37 | 
|  | 38 | 
| 26 static void CheckMap(Map* map, int type, int instance_size) { | 39 static void CheckMap(Map* map, int type, int instance_size) { | 
| 27   CHECK(map->IsHeapObject()); | 40   CHECK(map->IsHeapObject()); | 
| 28 #ifdef DEBUG | 41 #ifdef DEBUG | 
| 29   CHECK(HEAP->Contains(map)); | 42   CHECK(HEAP->Contains(map)); | 
| 30 #endif | 43 #endif | 
| 31   CHECK_EQ(HEAP->meta_map(), map->map()); | 44   CHECK_EQ(HEAP->meta_map(), map->map()); | 
| 32   CHECK_EQ(type, map->instance_type()); | 45   CHECK_EQ(type, map->instance_type()); | 
| 33   CHECK_EQ(instance_size, map->instance_size()); | 46   CHECK_EQ(instance_size, map->instance_size()); | 
| 34 } | 47 } | 
| 35 | 48 | 
| (...skipping 899 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 935   JSObject* clone = JSObject::cast(clone_obj); | 948   JSObject* clone = JSObject::cast(clone_obj); | 
| 936   if (clone->address() != old_pointer_space_top) { | 949   if (clone->address() != old_pointer_space_top) { | 
| 937     // Alas, got allocated from free list, we cannot do checks. | 950     // Alas, got allocated from free list, we cannot do checks. | 
| 938     return; | 951     return; | 
| 939   } | 952   } | 
| 940   CHECK(HEAP->old_pointer_space()->Contains(clone->address())); | 953   CHECK(HEAP->old_pointer_space()->Contains(clone->address())); | 
| 941 } | 954 } | 
| 942 | 955 | 
| 943 | 956 | 
| 944 TEST(TestCodeFlushing) { | 957 TEST(TestCodeFlushing) { | 
| 945   i::FLAG_allow_natives_syntax = true; |  | 
| 946   // If we do not flush code this test is invalid. | 958   // If we do not flush code this test is invalid. | 
| 947   if (!FLAG_flush_code) return; | 959   if (!FLAG_flush_code) return; | 
|  | 960   i::FLAG_allow_natives_syntax = true; | 
| 948   InitializeVM(); | 961   InitializeVM(); | 
| 949   v8::HandleScope scope; | 962   v8::HandleScope scope; | 
| 950   const char* source = "function foo() {" | 963   const char* source = "function foo() {" | 
| 951                        "  var x = 42;" | 964                        "  var x = 42;" | 
| 952                        "  var y = 42;" | 965                        "  var y = 42;" | 
| 953                        "  var z = x + y;" | 966                        "  var z = x + y;" | 
| 954                        "};" | 967                        "};" | 
| 955                        "foo()"; | 968                        "foo()"; | 
| 956   Handle<String> foo_name = FACTORY->LookupAsciiSymbol("foo"); | 969   Handle<String> foo_name = FACTORY->LookupAsciiSymbol("foo"); | 
| 957 | 970 | 
| 958   // This compile will add the code to the compilation cache. | 971   // This compile will add the code to the compilation cache. | 
| 959   { v8::HandleScope scope; | 972   { v8::HandleScope scope; | 
| 960     CompileRun(source); | 973     CompileRun(source); | 
| 961   } | 974   } | 
| 962 | 975 | 
| 963   // Check function is compiled. | 976   // Check function is compiled. | 
| 964   Object* func_value = Isolate::Current()->context()->global_object()-> | 977   Object* func_value = Isolate::Current()->context()->global_object()-> | 
| 965       GetProperty(*foo_name)->ToObjectChecked(); | 978       GetProperty(*foo_name)->ToObjectChecked(); | 
| 966   CHECK(func_value->IsJSFunction()); | 979   CHECK(func_value->IsJSFunction()); | 
| 967   Handle<JSFunction> function(JSFunction::cast(func_value)); | 980   Handle<JSFunction> function(JSFunction::cast(func_value)); | 
| 968   CHECK(function->shared()->is_compiled()); | 981   CHECK(function->shared()->is_compiled()); | 
| 969 | 982 | 
| 970   // TODO(1609) Currently incremental marker does not support code flushing. | 983   // The code will survive at least two GCs. | 
| 971   HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); | 984   HEAP->CollectAllGarbage(Heap::kNoGCFlags); | 
| 972   HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); | 985   HEAP->CollectAllGarbage(Heap::kNoGCFlags); | 
| 973 |  | 
| 974   CHECK(function->shared()->is_compiled()); | 986   CHECK(function->shared()->is_compiled()); | 
| 975 | 987 | 
| 976   HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); | 988   // Simulate several GCs that use full marking. | 
| 977   HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); | 989   const int kAgingThreshold = 6; | 
| 978   HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); | 990   for (int i = 0; i < kAgingThreshold; i++) { | 
| 979   HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); | 991     HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); | 
| 980   HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); | 992   } | 
| 981   HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); |  | 
| 982 | 993 | 
| 983   // foo should no longer be in the compilation cache | 994   // foo should no longer be in the compilation cache | 
| 984   CHECK(!function->shared()->is_compiled() || function->IsOptimized()); | 995   CHECK(!function->shared()->is_compiled() || function->IsOptimized()); | 
| 985   CHECK(!function->is_compiled() || function->IsOptimized()); | 996   CHECK(!function->is_compiled() || function->IsOptimized()); | 
| 986   // Call foo to get it recompiled. | 997   // Call foo to get it recompiled. | 
| 987   CompileRun("foo()"); | 998   CompileRun("foo()"); | 
| 988   CHECK(function->shared()->is_compiled()); | 999   CHECK(function->shared()->is_compiled()); | 
| 989   CHECK(function->is_compiled()); | 1000   CHECK(function->is_compiled()); | 
| 990 } | 1001 } | 
| 991 | 1002 | 
| 992 | 1003 | 
|  | 1004 TEST(TestCodeFlushingIncremental) { | 
|  | 1005   // If we do not flush code this test is invalid. | 
|  | 1006   if (!FLAG_flush_code) return; | 
|  | 1007   i::FLAG_allow_natives_syntax = true; | 
|  | 1008   InitializeVM(); | 
|  | 1009   v8::HandleScope scope; | 
|  | 1010   const char* source = "function foo() {" | 
|  | 1011                        "  var x = 42;" | 
|  | 1012                        "  var y = 42;" | 
|  | 1013                        "  var z = x + y;" | 
|  | 1014                        "};" | 
|  | 1015                        "foo()"; | 
|  | 1016   Handle<String> foo_name = FACTORY->LookupAsciiSymbol("foo"); | 
|  | 1017 | 
|  | 1018   // This compile will add the code to the compilation cache. | 
|  | 1019   { v8::HandleScope scope; | 
|  | 1020     CompileRun(source); | 
|  | 1021   } | 
|  | 1022 | 
|  | 1023   // Check function is compiled. | 
|  | 1024   Object* func_value = Isolate::Current()->context()->global_object()-> | 
|  | 1025       GetProperty(*foo_name)->ToObjectChecked(); | 
|  | 1026   CHECK(func_value->IsJSFunction()); | 
|  | 1027   Handle<JSFunction> function(JSFunction::cast(func_value)); | 
|  | 1028   CHECK(function->shared()->is_compiled()); | 
|  | 1029 | 
|  | 1030   // The code will survive at least two GCs. | 
|  | 1031   HEAP->CollectAllGarbage(Heap::kNoGCFlags); | 
|  | 1032   HEAP->CollectAllGarbage(Heap::kNoGCFlags); | 
|  | 1033   CHECK(function->shared()->is_compiled()); | 
|  | 1034 | 
|  | 1035   // Simulate several GCs that use incremental marking. | 
|  | 1036   const int kAgingThreshold = 6; | 
|  | 1037   for (int i = 0; i < kAgingThreshold; i++) { | 
|  | 1038     HEAP->incremental_marking()->Abort(); | 
|  | 1039     SimulateIncrementalMarking(); | 
|  | 1040     HEAP->CollectAllGarbage(Heap::kNoGCFlags); | 
|  | 1041   } | 
|  | 1042   CHECK(!function->shared()->is_compiled() || function->IsOptimized()); | 
|  | 1043   CHECK(!function->is_compiled() || function->IsOptimized()); | 
|  | 1044 | 
|  | 1045   // This compile will compile the function again. | 
|  | 1046   { v8::HandleScope scope; | 
|  | 1047     CompileRun("foo();"); | 
|  | 1048   } | 
|  | 1049 | 
|  | 1050   // Simulate several GCs that use incremental marking but make sure | 
|  | 1051   // the loop breaks once the function is enqueued as a candidate. | 
|  | 1052   for (int i = 0; i < kAgingThreshold; i++) { | 
|  | 1053     HEAP->incremental_marking()->Abort(); | 
|  | 1054     SimulateIncrementalMarking(); | 
|  | 1055     if (!function->next_function_link()->IsUndefined()) break; | 
|  | 1056     HEAP->CollectAllGarbage(Heap::kNoGCFlags); | 
|  | 1057   } | 
|  | 1058 | 
|  | 1059   // Force optimization while incremental marking is active and while | 
|  | 1060   // the function is enqueued as a candidate. | 
|  | 1061   { v8::HandleScope scope; | 
|  | 1062     CompileRun("%OptimizeFunctionOnNextCall(foo); foo();"); | 
|  | 1063   } | 
|  | 1064 | 
|  | 1065   // Simulate one final GC to make sure the candidate queue is sane. | 
|  | 1066   HEAP->CollectAllGarbage(Heap::kNoGCFlags); | 
|  | 1067   CHECK(function->shared()->is_compiled() || !function->IsOptimized()); | 
|  | 1068   CHECK(function->is_compiled() || !function->IsOptimized()); | 
|  | 1069 } | 
|  | 1070 | 
|  | 1071 | 
| 993 // Count the number of native contexts in the weak list of native contexts. | 1072 // Count the number of native contexts in the weak list of native contexts. | 
| 994 int CountNativeContexts() { | 1073 int CountNativeContexts() { | 
| 995   int count = 0; | 1074   int count = 0; | 
| 996   Object* object = HEAP->native_contexts_list(); | 1075   Object* object = HEAP->native_contexts_list(); | 
| 997   while (!object->IsUndefined()) { | 1076   while (!object->IsUndefined()) { | 
| 998     count++; | 1077     count++; | 
| 999     object = Context::cast(object)->get(Context::NEXT_CONTEXT_LINK); | 1078     object = Context::cast(object)->get(Context::NEXT_CONTEXT_LINK); | 
| 1000   } | 1079   } | 
| 1001   return count; | 1080   return count; | 
| 1002 } | 1081 } | 
| (...skipping 757 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1760 | 1839 | 
| 1761   CHECK(HEAP->InNewSpace(*o)); | 1840   CHECK(HEAP->InNewSpace(*o)); | 
| 1762 } | 1841 } | 
| 1763 | 1842 | 
| 1764 | 1843 | 
| 1765 static int CountMapTransitions(Map* map) { | 1844 static int CountMapTransitions(Map* map) { | 
| 1766   return map->transitions()->number_of_transitions(); | 1845   return map->transitions()->number_of_transitions(); | 
| 1767 } | 1846 } | 
| 1768 | 1847 | 
| 1769 | 1848 | 
| 1770 // Go through all incremental marking steps in one swoop. |  | 
| 1771 static void SimulateIncrementalMarking() { |  | 
| 1772   IncrementalMarking* marking = HEAP->incremental_marking(); |  | 
| 1773   CHECK(marking->IsStopped()); |  | 
| 1774   marking->Start(); |  | 
| 1775   CHECK(marking->IsMarking()); |  | 
| 1776   while (!marking->IsComplete()) { |  | 
| 1777     marking->Step(MB, IncrementalMarking::NO_GC_VIA_STACK_GUARD); |  | 
| 1778   } |  | 
| 1779   CHECK(marking->IsComplete()); |  | 
| 1780 } |  | 
| 1781 |  | 
| 1782 |  | 
| 1783 // Test that map transitions are cleared and maps are collected with | 1849 // Test that map transitions are cleared and maps are collected with | 
| 1784 // incremental marking as well. | 1850 // incremental marking as well. | 
| 1785 TEST(Regress1465) { | 1851 TEST(Regress1465) { | 
| 1786   i::FLAG_allow_natives_syntax = true; | 1852   i::FLAG_allow_natives_syntax = true; | 
| 1787   i::FLAG_trace_incremental_marking = true; | 1853   i::FLAG_trace_incremental_marking = true; | 
| 1788   InitializeVM(); | 1854   InitializeVM(); | 
| 1789   v8::HandleScope scope; | 1855   v8::HandleScope scope; | 
| 1790   static const int transitions_count = 256; | 1856   static const int transitions_count = 256; | 
| 1791 | 1857 | 
| 1792   { | 1858   { | 
| (...skipping 511 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2304   Handle<Object> call_function(call); | 2370   Handle<Object> call_function(call); | 
| 2305 | 2371 | 
| 2306   // Now we are ready to mess up the heap. | 2372   // Now we are ready to mess up the heap. | 
| 2307   HEAP->CollectAllGarbage(Heap::kReduceMemoryFootprintMask); | 2373   HEAP->CollectAllGarbage(Heap::kReduceMemoryFootprintMask); | 
| 2308 | 2374 | 
| 2309   // Either heap verification caught the problem already or we go kaboom once | 2375   // Either heap verification caught the problem already or we go kaboom once | 
| 2310   // the CallIC is executed the next time. | 2376   // the CallIC is executed the next time. | 
| 2311   USE(global->SetProperty(*name, *call_function, NONE, kNonStrictMode)); | 2377   USE(global->SetProperty(*name, *call_function, NONE, kNonStrictMode)); | 
| 2312   CompileRun("call();"); | 2378   CompileRun("call();"); | 
| 2313 } | 2379 } | 
| OLD | NEW | 
|---|