| 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 "execution.h" | 7 #include "execution.h" |
| 8 #include "factory.h" | 8 #include "factory.h" |
| 9 #include "macro-assembler.h" | 9 #include "macro-assembler.h" |
| 10 #include "global-handles.h" | 10 #include "global-handles.h" |
| (...skipping 858 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 869 HEAP->CollectAllGarbage(Heap::kNoGCFlags); | 869 HEAP->CollectAllGarbage(Heap::kNoGCFlags); |
| 870 | 870 |
| 871 v8::HandleScope scope; | 871 v8::HandleScope scope; |
| 872 | 872 |
| 873 // The plan: create JSObject which references objects in new space. | 873 // The plan: create JSObject which references objects in new space. |
| 874 // Then clone this object (forcing it to go into old space) and check | 874 // Then clone this object (forcing it to go into old space) and check |
| 875 // that region dirty marks are updated correctly. | 875 // that region dirty marks are updated correctly. |
| 876 | 876 |
| 877 // Step 1: prepare a map for the object. We add 1 inobject property to it. | 877 // Step 1: prepare a map for the object. We add 1 inobject property to it. |
| 878 Handle<JSFunction> object_ctor( | 878 Handle<JSFunction> object_ctor( |
| 879 Isolate::Current()->global_context()->object_function()); | 879 Isolate::Current()->native_context()->object_function()); |
| 880 CHECK(object_ctor->has_initial_map()); | 880 CHECK(object_ctor->has_initial_map()); |
| 881 Handle<Map> object_map(object_ctor->initial_map()); | 881 Handle<Map> object_map(object_ctor->initial_map()); |
| 882 // Create a map with single inobject property. | 882 // Create a map with single inobject property. |
| 883 Handle<Map> my_map = FACTORY->CopyMap(object_map, 1); | 883 Handle<Map> my_map = FACTORY->CopyMap(object_map, 1); |
| 884 int n_properties = my_map->inobject_properties(); | 884 int n_properties = my_map->inobject_properties(); |
| 885 CHECK_GT(n_properties, 0); | 885 CHECK_GT(n_properties, 0); |
| 886 | 886 |
| 887 int object_size = my_map->instance_size(); | 887 int object_size = my_map->instance_size(); |
| 888 | 888 |
| 889 // Step 2: allocate a lot of objects so to almost fill new space: we need | 889 // Step 2: allocate a lot of objects so to almost fill new space: we need |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 978 // foo should no longer be in the compilation cache | 978 // foo should no longer be in the compilation cache |
| 979 CHECK(!function->shared()->is_compiled() || function->IsOptimized()); | 979 CHECK(!function->shared()->is_compiled() || function->IsOptimized()); |
| 980 CHECK(!function->is_compiled() || function->IsOptimized()); | 980 CHECK(!function->is_compiled() || function->IsOptimized()); |
| 981 // Call foo to get it recompiled. | 981 // Call foo to get it recompiled. |
| 982 CompileRun("foo()"); | 982 CompileRun("foo()"); |
| 983 CHECK(function->shared()->is_compiled()); | 983 CHECK(function->shared()->is_compiled()); |
| 984 CHECK(function->is_compiled()); | 984 CHECK(function->is_compiled()); |
| 985 } | 985 } |
| 986 | 986 |
| 987 | 987 |
| 988 // Count the number of global contexts in the weak list of global contexts. | 988 // Count the number of native contexts in the weak list of native contexts. |
| 989 int CountGlobalContexts() { | 989 int CountNativeContexts() { |
| 990 int count = 0; | 990 int count = 0; |
| 991 Object* object = HEAP->global_contexts_list(); | 991 Object* object = HEAP->native_contexts_list(); |
| 992 while (!object->IsUndefined()) { | 992 while (!object->IsUndefined()) { |
| 993 count++; | 993 count++; |
| 994 object = Context::cast(object)->get(Context::NEXT_CONTEXT_LINK); | 994 object = Context::cast(object)->get(Context::NEXT_CONTEXT_LINK); |
| 995 } | 995 } |
| 996 return count; | 996 return count; |
| 997 } | 997 } |
| 998 | 998 |
| 999 | 999 |
| 1000 // Count the number of user functions in the weak list of optimized | 1000 // Count the number of user functions in the weak list of optimized |
| 1001 // functions attached to a global context. | 1001 // functions attached to a native context. |
| 1002 static int CountOptimizedUserFunctions(v8::Handle<v8::Context> context) { | 1002 static int CountOptimizedUserFunctions(v8::Handle<v8::Context> context) { |
| 1003 int count = 0; | 1003 int count = 0; |
| 1004 Handle<Context> icontext = v8::Utils::OpenHandle(*context); | 1004 Handle<Context> icontext = v8::Utils::OpenHandle(*context); |
| 1005 Object* object = icontext->get(Context::OPTIMIZED_FUNCTIONS_LIST); | 1005 Object* object = icontext->get(Context::OPTIMIZED_FUNCTIONS_LIST); |
| 1006 while (object->IsJSFunction() && !JSFunction::cast(object)->IsBuiltin()) { | 1006 while (object->IsJSFunction() && !JSFunction::cast(object)->IsBuiltin()) { |
| 1007 count++; | 1007 count++; |
| 1008 object = JSFunction::cast(object)->next_function_link(); | 1008 object = JSFunction::cast(object)->next_function_link(); |
| 1009 } | 1009 } |
| 1010 return count; | 1010 return count; |
| 1011 } | 1011 } |
| 1012 | 1012 |
| 1013 | 1013 |
| 1014 TEST(TestInternalWeakLists) { | 1014 TEST(TestInternalWeakLists) { |
| 1015 v8::V8::Initialize(); | 1015 v8::V8::Initialize(); |
| 1016 | 1016 |
| 1017 static const int kNumTestContexts = 10; | 1017 static const int kNumTestContexts = 10; |
| 1018 | 1018 |
| 1019 v8::HandleScope scope; | 1019 v8::HandleScope scope; |
| 1020 v8::Persistent<v8::Context> ctx[kNumTestContexts]; | 1020 v8::Persistent<v8::Context> ctx[kNumTestContexts]; |
| 1021 | 1021 |
| 1022 CHECK_EQ(0, CountGlobalContexts()); | 1022 CHECK_EQ(0, CountNativeContexts()); |
| 1023 | 1023 |
| 1024 // Create a number of global contests which gets linked together. | 1024 // Create a number of global contests which gets linked together. |
| 1025 for (int i = 0; i < kNumTestContexts; i++) { | 1025 for (int i = 0; i < kNumTestContexts; i++) { |
| 1026 ctx[i] = v8::Context::New(); | 1026 ctx[i] = v8::Context::New(); |
| 1027 | 1027 |
| 1028 bool opt = (FLAG_always_opt && i::V8::UseCrankshaft()); | 1028 bool opt = (FLAG_always_opt && i::V8::UseCrankshaft()); |
| 1029 | 1029 |
| 1030 CHECK_EQ(i + 1, CountGlobalContexts()); | 1030 CHECK_EQ(i + 1, CountNativeContexts()); |
| 1031 | 1031 |
| 1032 ctx[i]->Enter(); | 1032 ctx[i]->Enter(); |
| 1033 | 1033 |
| 1034 // Create a handle scope so no function objects get stuch in the outer | 1034 // Create a handle scope so no function objects get stuch in the outer |
| 1035 // handle scope | 1035 // handle scope |
| 1036 v8::HandleScope scope; | 1036 v8::HandleScope scope; |
| 1037 const char* source = "function f1() { };" | 1037 const char* source = "function f1() { };" |
| 1038 "function f2() { };" | 1038 "function f2() { };" |
| 1039 "function f3() { };" | 1039 "function f3() { };" |
| 1040 "function f4() { };" | 1040 "function f4() { };" |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1080 } | 1080 } |
| 1081 HEAP->CollectAllGarbage(Heap::kNoGCFlags); | 1081 HEAP->CollectAllGarbage(Heap::kNoGCFlags); |
| 1082 CHECK_EQ(opt ? 2 : 0, CountOptimizedUserFunctions(ctx[i])); | 1082 CHECK_EQ(opt ? 2 : 0, CountOptimizedUserFunctions(ctx[i])); |
| 1083 | 1083 |
| 1084 ctx[i]->Exit(); | 1084 ctx[i]->Exit(); |
| 1085 } | 1085 } |
| 1086 | 1086 |
| 1087 // Force compilation cache cleanup. | 1087 // Force compilation cache cleanup. |
| 1088 HEAP->CollectAllGarbage(Heap::kNoGCFlags); | 1088 HEAP->CollectAllGarbage(Heap::kNoGCFlags); |
| 1089 | 1089 |
| 1090 // Dispose the global contexts one by one. | 1090 // Dispose the native contexts one by one. |
| 1091 for (int i = 0; i < kNumTestContexts; i++) { | 1091 for (int i = 0; i < kNumTestContexts; i++) { |
| 1092 ctx[i].Dispose(); | 1092 ctx[i].Dispose(); |
| 1093 ctx[i].Clear(); | 1093 ctx[i].Clear(); |
| 1094 | 1094 |
| 1095 // Scavenge treats these references as strong. | 1095 // Scavenge treats these references as strong. |
| 1096 for (int j = 0; j < 10; j++) { | 1096 for (int j = 0; j < 10; j++) { |
| 1097 HEAP->PerformScavenge(); | 1097 HEAP->PerformScavenge(); |
| 1098 CHECK_EQ(kNumTestContexts - i, CountGlobalContexts()); | 1098 CHECK_EQ(kNumTestContexts - i, CountNativeContexts()); |
| 1099 } | 1099 } |
| 1100 | 1100 |
| 1101 // Mark compact handles the weak references. | 1101 // Mark compact handles the weak references. |
| 1102 HEAP->CollectAllGarbage(Heap::kNoGCFlags); | 1102 HEAP->CollectAllGarbage(Heap::kNoGCFlags); |
| 1103 CHECK_EQ(kNumTestContexts - i - 1, CountGlobalContexts()); | 1103 CHECK_EQ(kNumTestContexts - i - 1, CountNativeContexts()); |
| 1104 } | 1104 } |
| 1105 | 1105 |
| 1106 CHECK_EQ(0, CountGlobalContexts()); | 1106 CHECK_EQ(0, CountNativeContexts()); |
| 1107 } | 1107 } |
| 1108 | 1108 |
| 1109 | 1109 |
| 1110 // Count the number of global contexts in the weak list of global contexts | 1110 // Count the number of native contexts in the weak list of native contexts |
| 1111 // causing a GC after the specified number of elements. | 1111 // causing a GC after the specified number of elements. |
| 1112 static int CountGlobalContextsWithGC(int n) { | 1112 static int CountNativeContextsWithGC(int n) { |
| 1113 int count = 0; | 1113 int count = 0; |
| 1114 Handle<Object> object(HEAP->global_contexts_list()); | 1114 Handle<Object> object(HEAP->native_contexts_list()); |
| 1115 while (!object->IsUndefined()) { | 1115 while (!object->IsUndefined()) { |
| 1116 count++; | 1116 count++; |
| 1117 if (count == n) HEAP->CollectAllGarbage(Heap::kNoGCFlags); | 1117 if (count == n) HEAP->CollectAllGarbage(Heap::kNoGCFlags); |
| 1118 object = | 1118 object = |
| 1119 Handle<Object>(Context::cast(*object)->get(Context::NEXT_CONTEXT_LINK)); | 1119 Handle<Object>(Context::cast(*object)->get(Context::NEXT_CONTEXT_LINK)); |
| 1120 } | 1120 } |
| 1121 return count; | 1121 return count; |
| 1122 } | 1122 } |
| 1123 | 1123 |
| 1124 | 1124 |
| 1125 // Count the number of user functions in the weak list of optimized | 1125 // Count the number of user functions in the weak list of optimized |
| 1126 // functions attached to a global context causing a GC after the | 1126 // functions attached to a native context causing a GC after the |
| 1127 // specified number of elements. | 1127 // specified number of elements. |
| 1128 static int CountOptimizedUserFunctionsWithGC(v8::Handle<v8::Context> context, | 1128 static int CountOptimizedUserFunctionsWithGC(v8::Handle<v8::Context> context, |
| 1129 int n) { | 1129 int n) { |
| 1130 int count = 0; | 1130 int count = 0; |
| 1131 Handle<Context> icontext = v8::Utils::OpenHandle(*context); | 1131 Handle<Context> icontext = v8::Utils::OpenHandle(*context); |
| 1132 Handle<Object> object(icontext->get(Context::OPTIMIZED_FUNCTIONS_LIST)); | 1132 Handle<Object> object(icontext->get(Context::OPTIMIZED_FUNCTIONS_LIST)); |
| 1133 while (object->IsJSFunction() && | 1133 while (object->IsJSFunction() && |
| 1134 !Handle<JSFunction>::cast(object)->IsBuiltin()) { | 1134 !Handle<JSFunction>::cast(object)->IsBuiltin()) { |
| 1135 count++; | 1135 count++; |
| 1136 if (count == n) HEAP->CollectAllGarbage(Heap::kNoGCFlags); | 1136 if (count == n) HEAP->CollectAllGarbage(Heap::kNoGCFlags); |
| 1137 object = Handle<Object>( | 1137 object = Handle<Object>( |
| 1138 Object::cast(JSFunction::cast(*object)->next_function_link())); | 1138 Object::cast(JSFunction::cast(*object)->next_function_link())); |
| 1139 } | 1139 } |
| 1140 return count; | 1140 return count; |
| 1141 } | 1141 } |
| 1142 | 1142 |
| 1143 | 1143 |
| 1144 TEST(TestInternalWeakListsTraverseWithGC) { | 1144 TEST(TestInternalWeakListsTraverseWithGC) { |
| 1145 v8::V8::Initialize(); | 1145 v8::V8::Initialize(); |
| 1146 | 1146 |
| 1147 static const int kNumTestContexts = 10; | 1147 static const int kNumTestContexts = 10; |
| 1148 | 1148 |
| 1149 v8::HandleScope scope; | 1149 v8::HandleScope scope; |
| 1150 v8::Persistent<v8::Context> ctx[kNumTestContexts]; | 1150 v8::Persistent<v8::Context> ctx[kNumTestContexts]; |
| 1151 | 1151 |
| 1152 CHECK_EQ(0, CountGlobalContexts()); | 1152 CHECK_EQ(0, CountNativeContexts()); |
| 1153 | 1153 |
| 1154 // Create an number of contexts and check the length of the weak list both | 1154 // Create an number of contexts and check the length of the weak list both |
| 1155 // with and without GCs while iterating the list. | 1155 // with and without GCs while iterating the list. |
| 1156 for (int i = 0; i < kNumTestContexts; i++) { | 1156 for (int i = 0; i < kNumTestContexts; i++) { |
| 1157 ctx[i] = v8::Context::New(); | 1157 ctx[i] = v8::Context::New(); |
| 1158 CHECK_EQ(i + 1, CountGlobalContexts()); | 1158 CHECK_EQ(i + 1, CountNativeContexts()); |
| 1159 CHECK_EQ(i + 1, CountGlobalContextsWithGC(i / 2 + 1)); | 1159 CHECK_EQ(i + 1, CountNativeContextsWithGC(i / 2 + 1)); |
| 1160 } | 1160 } |
| 1161 | 1161 |
| 1162 bool opt = (FLAG_always_opt && i::V8::UseCrankshaft()); | 1162 bool opt = (FLAG_always_opt && i::V8::UseCrankshaft()); |
| 1163 | 1163 |
| 1164 // Compile a number of functions the length of the weak list of optimized | 1164 // Compile a number of functions the length of the weak list of optimized |
| 1165 // functions both with and without GCs while iterating the list. | 1165 // functions both with and without GCs while iterating the list. |
| 1166 ctx[0]->Enter(); | 1166 ctx[0]->Enter(); |
| 1167 const char* source = "function f1() { };" | 1167 const char* source = "function f1() { };" |
| 1168 "function f2() { };" | 1168 "function f2() { };" |
| 1169 "function f3() { };" | 1169 "function f3() { };" |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1359 HeapIterator iterator; | 1359 HeapIterator iterator; |
| 1360 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { | 1360 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { |
| 1361 if (obj->IsGlobalObject()) count++; | 1361 if (obj->IsGlobalObject()) count++; |
| 1362 } | 1362 } |
| 1363 return count; | 1363 return count; |
| 1364 } | 1364 } |
| 1365 | 1365 |
| 1366 | 1366 |
| 1367 // Test that we don't embed maps from foreign contexts into | 1367 // Test that we don't embed maps from foreign contexts into |
| 1368 // optimized code. | 1368 // optimized code. |
| 1369 TEST(LeakGlobalContextViaMap) { | 1369 TEST(LeakNativeContextViaMap) { |
| 1370 i::FLAG_allow_natives_syntax = true; | 1370 i::FLAG_allow_natives_syntax = true; |
| 1371 v8::HandleScope outer_scope; | 1371 v8::HandleScope outer_scope; |
| 1372 v8::Persistent<v8::Context> ctx1 = v8::Context::New(); | 1372 v8::Persistent<v8::Context> ctx1 = v8::Context::New(); |
| 1373 v8::Persistent<v8::Context> ctx2 = v8::Context::New(); | 1373 v8::Persistent<v8::Context> ctx2 = v8::Context::New(); |
| 1374 ctx1->Enter(); | 1374 ctx1->Enter(); |
| 1375 | 1375 |
| 1376 HEAP->CollectAllAvailableGarbage(); | 1376 HEAP->CollectAllAvailableGarbage(); |
| 1377 CHECK_EQ(4, NumberOfGlobalObjects()); | 1377 CHECK_EQ(4, NumberOfGlobalObjects()); |
| 1378 | 1378 |
| 1379 { | 1379 { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1396 HEAP->CollectAllAvailableGarbage(); | 1396 HEAP->CollectAllAvailableGarbage(); |
| 1397 CHECK_EQ(2, NumberOfGlobalObjects()); | 1397 CHECK_EQ(2, NumberOfGlobalObjects()); |
| 1398 ctx2.Dispose(); | 1398 ctx2.Dispose(); |
| 1399 HEAP->CollectAllAvailableGarbage(); | 1399 HEAP->CollectAllAvailableGarbage(); |
| 1400 CHECK_EQ(0, NumberOfGlobalObjects()); | 1400 CHECK_EQ(0, NumberOfGlobalObjects()); |
| 1401 } | 1401 } |
| 1402 | 1402 |
| 1403 | 1403 |
| 1404 // Test that we don't embed functions from foreign contexts into | 1404 // Test that we don't embed functions from foreign contexts into |
| 1405 // optimized code. | 1405 // optimized code. |
| 1406 TEST(LeakGlobalContextViaFunction) { | 1406 TEST(LeakNativeContextViaFunction) { |
| 1407 i::FLAG_allow_natives_syntax = true; | 1407 i::FLAG_allow_natives_syntax = true; |
| 1408 v8::HandleScope outer_scope; | 1408 v8::HandleScope outer_scope; |
| 1409 v8::Persistent<v8::Context> ctx1 = v8::Context::New(); | 1409 v8::Persistent<v8::Context> ctx1 = v8::Context::New(); |
| 1410 v8::Persistent<v8::Context> ctx2 = v8::Context::New(); | 1410 v8::Persistent<v8::Context> ctx2 = v8::Context::New(); |
| 1411 ctx1->Enter(); | 1411 ctx1->Enter(); |
| 1412 | 1412 |
| 1413 HEAP->CollectAllAvailableGarbage(); | 1413 HEAP->CollectAllAvailableGarbage(); |
| 1414 CHECK_EQ(4, NumberOfGlobalObjects()); | 1414 CHECK_EQ(4, NumberOfGlobalObjects()); |
| 1415 | 1415 |
| 1416 { | 1416 { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1431 ctx1.Dispose(); | 1431 ctx1.Dispose(); |
| 1432 } | 1432 } |
| 1433 HEAP->CollectAllAvailableGarbage(); | 1433 HEAP->CollectAllAvailableGarbage(); |
| 1434 CHECK_EQ(2, NumberOfGlobalObjects()); | 1434 CHECK_EQ(2, NumberOfGlobalObjects()); |
| 1435 ctx2.Dispose(); | 1435 ctx2.Dispose(); |
| 1436 HEAP->CollectAllAvailableGarbage(); | 1436 HEAP->CollectAllAvailableGarbage(); |
| 1437 CHECK_EQ(0, NumberOfGlobalObjects()); | 1437 CHECK_EQ(0, NumberOfGlobalObjects()); |
| 1438 } | 1438 } |
| 1439 | 1439 |
| 1440 | 1440 |
| 1441 TEST(LeakGlobalContextViaMapKeyed) { | 1441 TEST(LeakNativeContextViaMapKeyed) { |
| 1442 i::FLAG_allow_natives_syntax = true; | 1442 i::FLAG_allow_natives_syntax = true; |
| 1443 v8::HandleScope outer_scope; | 1443 v8::HandleScope outer_scope; |
| 1444 v8::Persistent<v8::Context> ctx1 = v8::Context::New(); | 1444 v8::Persistent<v8::Context> ctx1 = v8::Context::New(); |
| 1445 v8::Persistent<v8::Context> ctx2 = v8::Context::New(); | 1445 v8::Persistent<v8::Context> ctx2 = v8::Context::New(); |
| 1446 ctx1->Enter(); | 1446 ctx1->Enter(); |
| 1447 | 1447 |
| 1448 HEAP->CollectAllAvailableGarbage(); | 1448 HEAP->CollectAllAvailableGarbage(); |
| 1449 CHECK_EQ(4, NumberOfGlobalObjects()); | 1449 CHECK_EQ(4, NumberOfGlobalObjects()); |
| 1450 | 1450 |
| 1451 { | 1451 { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1466 ctx1.Dispose(); | 1466 ctx1.Dispose(); |
| 1467 } | 1467 } |
| 1468 HEAP->CollectAllAvailableGarbage(); | 1468 HEAP->CollectAllAvailableGarbage(); |
| 1469 CHECK_EQ(2, NumberOfGlobalObjects()); | 1469 CHECK_EQ(2, NumberOfGlobalObjects()); |
| 1470 ctx2.Dispose(); | 1470 ctx2.Dispose(); |
| 1471 HEAP->CollectAllAvailableGarbage(); | 1471 HEAP->CollectAllAvailableGarbage(); |
| 1472 CHECK_EQ(0, NumberOfGlobalObjects()); | 1472 CHECK_EQ(0, NumberOfGlobalObjects()); |
| 1473 } | 1473 } |
| 1474 | 1474 |
| 1475 | 1475 |
| 1476 TEST(LeakGlobalContextViaMapProto) { | 1476 TEST(LeakNativeContextViaMapProto) { |
| 1477 i::FLAG_allow_natives_syntax = true; | 1477 i::FLAG_allow_natives_syntax = true; |
| 1478 v8::HandleScope outer_scope; | 1478 v8::HandleScope outer_scope; |
| 1479 v8::Persistent<v8::Context> ctx1 = v8::Context::New(); | 1479 v8::Persistent<v8::Context> ctx1 = v8::Context::New(); |
| 1480 v8::Persistent<v8::Context> ctx2 = v8::Context::New(); | 1480 v8::Persistent<v8::Context> ctx2 = v8::Context::New(); |
| 1481 ctx1->Enter(); | 1481 ctx1->Enter(); |
| 1482 | 1482 |
| 1483 HEAP->CollectAllAvailableGarbage(); | 1483 HEAP->CollectAllAvailableGarbage(); |
| 1484 CHECK_EQ(4, NumberOfGlobalObjects()); | 1484 CHECK_EQ(4, NumberOfGlobalObjects()); |
| 1485 | 1485 |
| 1486 { | 1486 { |
| (...skipping 546 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2033 fun1 = env->Global()->Get(v8_str("fun")); | 2033 fun1 = env->Global()->Get(v8_str("fun")); |
| 2034 } | 2034 } |
| 2035 | 2035 |
| 2036 { | 2036 { |
| 2037 LocalContext env; | 2037 LocalContext env; |
| 2038 CompileRun("function fun() {};"); | 2038 CompileRun("function fun() {};"); |
| 2039 fun2 = env->Global()->Get(v8_str("fun")); | 2039 fun2 = env->Global()->Get(v8_str("fun")); |
| 2040 } | 2040 } |
| 2041 | 2041 |
| 2042 // Prepare function f that contains type feedback for closures | 2042 // Prepare function f that contains type feedback for closures |
| 2043 // originating from two different global contexts. | 2043 // originating from two different native contexts. |
| 2044 v8::Context::GetCurrent()->Global()->Set(v8_str("fun1"), fun1); | 2044 v8::Context::GetCurrent()->Global()->Set(v8_str("fun1"), fun1); |
| 2045 v8::Context::GetCurrent()->Global()->Set(v8_str("fun2"), fun2); | 2045 v8::Context::GetCurrent()->Global()->Set(v8_str("fun2"), fun2); |
| 2046 CompileRun("function f(a, b) { a(); b(); } f(fun1, fun2);"); | 2046 CompileRun("function f(a, b) { a(); b(); } f(fun1, fun2);"); |
| 2047 Handle<JSFunction> f = | 2047 Handle<JSFunction> f = |
| 2048 v8::Utils::OpenHandle( | 2048 v8::Utils::OpenHandle( |
| 2049 *v8::Handle<v8::Function>::Cast( | 2049 *v8::Handle<v8::Function>::Cast( |
| 2050 v8::Context::GetCurrent()->Global()->Get(v8_str("f")))); | 2050 v8::Context::GetCurrent()->Global()->Get(v8_str("f")))); |
| 2051 Handle<TypeFeedbackCells> cells(TypeFeedbackInfo::cast( | 2051 Handle<TypeFeedbackCells> cells(TypeFeedbackInfo::cast( |
| 2052 f->shared()->code()->type_feedback_info())->type_feedback_cells()); | 2052 f->shared()->code()->type_feedback_info())->type_feedback_cells()); |
| 2053 | 2053 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 2079 return NULL; | 2079 return NULL; |
| 2080 } | 2080 } |
| 2081 | 2081 |
| 2082 | 2082 |
| 2083 TEST(IncrementalMarkingPreservesMonomorhpicIC) { | 2083 TEST(IncrementalMarkingPreservesMonomorhpicIC) { |
| 2084 if (i::FLAG_always_opt) return; | 2084 if (i::FLAG_always_opt) return; |
| 2085 InitializeVM(); | 2085 InitializeVM(); |
| 2086 v8::HandleScope scope; | 2086 v8::HandleScope scope; |
| 2087 | 2087 |
| 2088 // Prepare function f that contains a monomorphic IC for object | 2088 // Prepare function f that contains a monomorphic IC for object |
| 2089 // originating from the same global context. | 2089 // originating from the same native context. |
| 2090 CompileRun("function fun() { this.x = 1; }; var obj = new fun();" | 2090 CompileRun("function fun() { this.x = 1; }; var obj = new fun();" |
| 2091 "function f(o) { return o.x; } f(obj); f(obj);"); | 2091 "function f(o) { return o.x; } f(obj); f(obj);"); |
| 2092 Handle<JSFunction> f = | 2092 Handle<JSFunction> f = |
| 2093 v8::Utils::OpenHandle( | 2093 v8::Utils::OpenHandle( |
| 2094 *v8::Handle<v8::Function>::Cast( | 2094 *v8::Handle<v8::Function>::Cast( |
| 2095 v8::Context::GetCurrent()->Global()->Get(v8_str("f")))); | 2095 v8::Context::GetCurrent()->Global()->Get(v8_str("f")))); |
| 2096 | 2096 |
| 2097 Code* ic_before = FindFirstIC(f->shared()->code(), Code::LOAD_IC); | 2097 Code* ic_before = FindFirstIC(f->shared()->code(), Code::LOAD_IC); |
| 2098 CHECK(ic_before->ic_state() == MONOMORPHIC); | 2098 CHECK(ic_before->ic_state() == MONOMORPHIC); |
| 2099 | 2099 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2113 v8::HandleScope scope; | 2113 v8::HandleScope scope; |
| 2114 v8::Local<v8::Value> obj1; | 2114 v8::Local<v8::Value> obj1; |
| 2115 | 2115 |
| 2116 { | 2116 { |
| 2117 LocalContext env; | 2117 LocalContext env; |
| 2118 CompileRun("function fun() { this.x = 1; }; var obj = new fun();"); | 2118 CompileRun("function fun() { this.x = 1; }; var obj = new fun();"); |
| 2119 obj1 = env->Global()->Get(v8_str("obj")); | 2119 obj1 = env->Global()->Get(v8_str("obj")); |
| 2120 } | 2120 } |
| 2121 | 2121 |
| 2122 // Prepare function f that contains a monomorphic IC for object | 2122 // Prepare function f that contains a monomorphic IC for object |
| 2123 // originating from a different global context. | 2123 // originating from a different native context. |
| 2124 v8::Context::GetCurrent()->Global()->Set(v8_str("obj1"), obj1); | 2124 v8::Context::GetCurrent()->Global()->Set(v8_str("obj1"), obj1); |
| 2125 CompileRun("function f(o) { return o.x; } f(obj1); f(obj1);"); | 2125 CompileRun("function f(o) { return o.x; } f(obj1); f(obj1);"); |
| 2126 Handle<JSFunction> f = | 2126 Handle<JSFunction> f = |
| 2127 v8::Utils::OpenHandle( | 2127 v8::Utils::OpenHandle( |
| 2128 *v8::Handle<v8::Function>::Cast( | 2128 *v8::Handle<v8::Function>::Cast( |
| 2129 v8::Context::GetCurrent()->Global()->Get(v8_str("f")))); | 2129 v8::Context::GetCurrent()->Global()->Get(v8_str("f")))); |
| 2130 | 2130 |
| 2131 Code* ic_before = FindFirstIC(f->shared()->code(), Code::LOAD_IC); | 2131 Code* ic_before = FindFirstIC(f->shared()->code(), Code::LOAD_IC); |
| 2132 CHECK(ic_before->ic_state() == MONOMORPHIC); | 2132 CHECK(ic_before->ic_state() == MONOMORPHIC); |
| 2133 | 2133 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2153 obj1 = env->Global()->Get(v8_str("obj")); | 2153 obj1 = env->Global()->Get(v8_str("obj")); |
| 2154 } | 2154 } |
| 2155 | 2155 |
| 2156 { | 2156 { |
| 2157 LocalContext env; | 2157 LocalContext env; |
| 2158 CompileRun("function fun() { this.x = 2; }; var obj = new fun();"); | 2158 CompileRun("function fun() { this.x = 2; }; var obj = new fun();"); |
| 2159 obj2 = env->Global()->Get(v8_str("obj")); | 2159 obj2 = env->Global()->Get(v8_str("obj")); |
| 2160 } | 2160 } |
| 2161 | 2161 |
| 2162 // Prepare function f that contains a polymorphic IC for objects | 2162 // Prepare function f that contains a polymorphic IC for objects |
| 2163 // originating from two different global contexts. | 2163 // originating from two different native contexts. |
| 2164 v8::Context::GetCurrent()->Global()->Set(v8_str("obj1"), obj1); | 2164 v8::Context::GetCurrent()->Global()->Set(v8_str("obj1"), obj1); |
| 2165 v8::Context::GetCurrent()->Global()->Set(v8_str("obj2"), obj2); | 2165 v8::Context::GetCurrent()->Global()->Set(v8_str("obj2"), obj2); |
| 2166 CompileRun("function f(o) { return o.x; } f(obj1); f(obj1); f(obj2);"); | 2166 CompileRun("function f(o) { return o.x; } f(obj1); f(obj1); f(obj2);"); |
| 2167 Handle<JSFunction> f = | 2167 Handle<JSFunction> f = |
| 2168 v8::Utils::OpenHandle( | 2168 v8::Utils::OpenHandle( |
| 2169 *v8::Handle<v8::Function>::Cast( | 2169 *v8::Handle<v8::Function>::Cast( |
| 2170 v8::Context::GetCurrent()->Global()->Get(v8_str("f")))); | 2170 v8::Context::GetCurrent()->Global()->Get(v8_str("f")))); |
| 2171 | 2171 |
| 2172 Code* ic_before = FindFirstIC(f->shared()->code(), Code::LOAD_IC); | 2172 Code* ic_before = FindFirstIC(f->shared()->code(), Code::LOAD_IC); |
| 2173 CHECK(ic_before->ic_state() == MEGAMORPHIC); | 2173 CHECK(ic_before->ic_state() == MEGAMORPHIC); |
| 2174 | 2174 |
| 2175 // Fire context dispose notification. | 2175 // Fire context dispose notification. |
| 2176 v8::V8::ContextDisposedNotification(); | 2176 v8::V8::ContextDisposedNotification(); |
| 2177 SimulateIncrementalMarking(); | 2177 SimulateIncrementalMarking(); |
| 2178 HEAP->CollectAllGarbage(Heap::kNoGCFlags); | 2178 HEAP->CollectAllGarbage(Heap::kNoGCFlags); |
| 2179 | 2179 |
| 2180 Code* ic_after = FindFirstIC(f->shared()->code(), Code::LOAD_IC); | 2180 Code* ic_after = FindFirstIC(f->shared()->code(), Code::LOAD_IC); |
| 2181 CHECK(ic_after->ic_state() == UNINITIALIZED); | 2181 CHECK(ic_after->ic_state() == UNINITIALIZED); |
| 2182 } | 2182 } |
| OLD | NEW |