OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 781 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
792 private: | 792 private: |
793 void ScavengePointer(Object** p) { | 793 void ScavengePointer(Object** p) { |
794 Object* object = *p; | 794 Object* object = *p; |
795 if (!Heap::InNewSpace(object)) return; | 795 if (!Heap::InNewSpace(object)) return; |
796 Heap::ScavengeObject(reinterpret_cast<HeapObject**>(p), | 796 Heap::ScavengeObject(reinterpret_cast<HeapObject**>(p), |
797 reinterpret_cast<HeapObject*>(object)); | 797 reinterpret_cast<HeapObject*>(object)); |
798 } | 798 } |
799 }; | 799 }; |
800 | 800 |
801 | 801 |
802 // A queue of objects promoted during scavenge. Each object is accompanied | 802 // A queue of pointers and maps of to-be-promoted objects during a |
803 // by it's size to avoid dereferencing a map pointer for scanning. | 803 // scavenge collection. |
804 class PromotionQueue { | 804 class PromotionQueue { |
805 public: | 805 public: |
806 void Initialize(Address start_address) { | 806 void Initialize(Address start_address) { |
807 front_ = rear_ = reinterpret_cast<intptr_t*>(start_address); | 807 front_ = rear_ = reinterpret_cast<HeapObject**>(start_address); |
808 } | 808 } |
809 | 809 |
810 bool is_empty() { return front_ <= rear_; } | 810 bool is_empty() { return front_ <= rear_; } |
811 | 811 |
812 void insert(HeapObject* target, int size) { | 812 void insert(HeapObject* object, Map* map) { |
813 *(--rear_) = reinterpret_cast<intptr_t>(target); | 813 *(--rear_) = object; |
814 *(--rear_) = size; | 814 *(--rear_) = map; |
815 // Assert no overflow into live objects. | 815 // Assert no overflow into live objects. |
816 ASSERT(reinterpret_cast<Address>(rear_) >= Heap::new_space()->top()); | 816 ASSERT(reinterpret_cast<Address>(rear_) >= Heap::new_space()->top()); |
817 } | 817 } |
818 | 818 |
819 void remove(HeapObject** target, int* size) { | 819 void remove(HeapObject** object, Map** map) { |
820 *target = reinterpret_cast<HeapObject*>(*(--front_)); | 820 *object = *(--front_); |
821 *size = static_cast<int>(*(--front_)); | 821 *map = Map::cast(*(--front_)); |
822 // Assert no underflow. | 822 // Assert no underflow. |
823 ASSERT(front_ >= rear_); | 823 ASSERT(front_ >= rear_); |
824 } | 824 } |
825 | 825 |
826 private: | 826 private: |
827 // The front of the queue is higher in memory than the rear. | 827 // The front of the queue is higher in memory than the rear. |
828 intptr_t* front_; | 828 HeapObject** front_; |
829 intptr_t* rear_; | 829 HeapObject** rear_; |
830 }; | 830 }; |
831 | 831 |
832 | 832 |
833 // Shared state read by the scavenge collector and set by ScavengeObject. | 833 // Shared state read by the scavenge collector and set by ScavengeObject. |
834 static PromotionQueue promotion_queue; | 834 static PromotionQueue promotion_queue; |
835 | 835 |
836 | 836 |
837 #ifdef DEBUG | 837 #ifdef DEBUG |
838 // Visitor class to verify pointers in code or data space do not point into | 838 // Visitor class to verify pointers in code or data space do not point into |
839 // new space. | 839 // new space. |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1034 Address Heap::DoScavenge(ObjectVisitor* scavenge_visitor, | 1034 Address Heap::DoScavenge(ObjectVisitor* scavenge_visitor, |
1035 Address new_space_front) { | 1035 Address new_space_front) { |
1036 do { | 1036 do { |
1037 ASSERT(new_space_front <= new_space_.top()); | 1037 ASSERT(new_space_front <= new_space_.top()); |
1038 | 1038 |
1039 // The addresses new_space_front and new_space_.top() define a | 1039 // The addresses new_space_front and new_space_.top() define a |
1040 // queue of unprocessed copied objects. Process them until the | 1040 // queue of unprocessed copied objects. Process them until the |
1041 // queue is empty. | 1041 // queue is empty. |
1042 while (new_space_front < new_space_.top()) { | 1042 while (new_space_front < new_space_.top()) { |
1043 HeapObject* object = HeapObject::FromAddress(new_space_front); | 1043 HeapObject* object = HeapObject::FromAddress(new_space_front); |
1044 Map* map = object->map(); | 1044 object->Iterate(scavenge_visitor); |
1045 int size = object->SizeFromMap(map); | 1045 new_space_front += object->Size(); |
1046 object->IterateBody(map->instance_type(), size, scavenge_visitor); | |
1047 new_space_front += size; | |
1048 } | 1046 } |
1049 | 1047 |
1050 // Promote and process all the to-be-promoted objects. | 1048 // Promote and process all the to-be-promoted objects. |
1051 while (!promotion_queue.is_empty()) { | 1049 while (!promotion_queue.is_empty()) { |
1052 HeapObject* target; | 1050 HeapObject* source; |
1053 int size; | 1051 Map* map; |
1054 promotion_queue.remove(&target, &size); | 1052 promotion_queue.remove(&source, &map); |
| 1053 // Copy the from-space object to its new location (given by the |
| 1054 // forwarding address) and fix its map. |
| 1055 HeapObject* target = source->map_word().ToForwardingAddress(); |
| 1056 int size = source->SizeFromMap(map); |
| 1057 CopyBlock(target->address(), source->address(), size); |
| 1058 target->set_map(map); |
1055 | 1059 |
1056 // Promoted object might be already partially visited | 1060 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) |
1057 // during dirty regions iteration. Thus we search specificly | 1061 // Update NewSpace stats if necessary. |
1058 // for pointers to from semispace instead of looking for pointers | 1062 RecordCopiedObject(target); |
1059 // to new space. | 1063 #endif |
| 1064 // Visit the newly copied object for pointers to new space. |
1060 ASSERT(!target->IsMap()); | 1065 ASSERT(!target->IsMap()); |
1061 IterateAndMarkPointersToFromSpace(target->address(), | 1066 IterateAndMarkPointersToNewSpace(target->address(), |
1062 target->address() + size, | 1067 target->address() + size, |
1063 &ScavengePointer); | 1068 &ScavengePointer); |
1064 } | 1069 } |
1065 | 1070 |
1066 // Take another spin if there are now unswept objects in new space | 1071 // Take another spin if there are now unswept objects in new space |
1067 // (there are currently no more unswept promoted objects). | 1072 // (there are currently no more unswept promoted objects). |
1068 } while (new_space_front < new_space_.top()); | 1073 } while (new_space_front < new_space_.top()); |
1069 | 1074 |
1070 return new_space_front; | 1075 return new_space_front; |
1071 } | 1076 } |
1072 | 1077 |
1073 | 1078 |
1074 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) | 1079 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) |
1075 static void RecordCopiedObject(HeapObject* obj) { | 1080 void Heap::RecordCopiedObject(HeapObject* obj) { |
1076 bool should_record = false; | 1081 bool should_record = false; |
1077 #ifdef DEBUG | 1082 #ifdef DEBUG |
1078 should_record = FLAG_heap_stats; | 1083 should_record = FLAG_heap_stats; |
1079 #endif | 1084 #endif |
1080 #ifdef ENABLE_LOGGING_AND_PROFILING | 1085 #ifdef ENABLE_LOGGING_AND_PROFILING |
1081 should_record = should_record || FLAG_log_gc; | 1086 should_record = should_record || FLAG_log_gc; |
1082 #endif | 1087 #endif |
1083 if (should_record) { | 1088 if (should_record) { |
1084 if (Heap::new_space()->Contains(obj)) { | 1089 if (new_space_.Contains(obj)) { |
1085 Heap::new_space()->RecordAllocation(obj); | 1090 new_space_.RecordAllocation(obj); |
1086 } else { | 1091 } else { |
1087 Heap::new_space()->RecordPromotion(obj); | 1092 new_space_.RecordPromotion(obj); |
1088 } | 1093 } |
1089 } | 1094 } |
1090 } | 1095 } |
1091 #endif // defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) | 1096 #endif // defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) |
1092 | 1097 |
1093 | 1098 |
1094 // Helper function used by CopyObject to copy a source object to an | 1099 |
1095 // allocated target object and update the forwarding pointer in the source | 1100 HeapObject* Heap::MigrateObject(HeapObject* source, |
1096 // object. Returns the target object. | 1101 HeapObject* target, |
1097 inline static HeapObject* MigrateObject(HeapObject* source, | 1102 int size) { |
1098 HeapObject* target, | |
1099 int size) { | |
1100 // Copy the content of source to target. | 1103 // Copy the content of source to target. |
1101 Heap::CopyBlock(target->address(), source->address(), size); | 1104 CopyBlock(target->address(), source->address(), size); |
1102 | 1105 |
1103 // Set the forwarding address. | 1106 // Set the forwarding address. |
1104 source->set_map_word(MapWord::FromForwardingAddress(target)); | 1107 source->set_map_word(MapWord::FromForwardingAddress(target)); |
1105 | 1108 |
1106 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) | 1109 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) |
1107 // Update NewSpace stats if necessary. | 1110 // Update NewSpace stats if necessary. |
1108 RecordCopiedObject(target); | 1111 RecordCopiedObject(target); |
1109 #endif | 1112 #endif |
1110 | 1113 |
1111 return target; | 1114 return target; |
1112 } | 1115 } |
1113 | 1116 |
1114 | 1117 |
1115 enum ObjectContents { DATA_OBJECT, POINTER_OBJECT }; | 1118 static inline bool IsShortcutCandidate(HeapObject* object, Map* map) { |
1116 enum SizeRestriction { SMALL, UNKNOWN_SIZE }; | 1119 STATIC_ASSERT(kNotStringTag != 0 && kSymbolTag != 0); |
1117 | 1120 ASSERT(object->map() == map); |
1118 | 1121 InstanceType type = map->instance_type(); |
1119 template<ObjectContents object_contents, SizeRestriction size_restriction> | 1122 if ((type & kShortcutTypeMask) != kShortcutTypeTag) return false; |
1120 static inline void EvacuateObject(Map* map, | 1123 ASSERT(object->IsString() && !object->IsSymbol()); |
1121 HeapObject** slot, | 1124 return ConsString::cast(object)->unchecked_second() == Heap::empty_string(); |
1122 HeapObject* object, | |
1123 int object_size) { | |
1124 ASSERT((size_restriction != SMALL) || | |
1125 (object_size <= Page::kMaxHeapObjectSize)); | |
1126 ASSERT(object->Size() == object_size); | |
1127 | |
1128 if (Heap::ShouldBePromoted(object->address(), object_size)) { | |
1129 Object* result; | |
1130 | |
1131 if ((size_restriction != SMALL) && | |
1132 (object_size > Page::kMaxHeapObjectSize)) { | |
1133 result = Heap::lo_space()->AllocateRawFixedArray(object_size); | |
1134 } else { | |
1135 if (object_contents == DATA_OBJECT) { | |
1136 result = Heap::old_data_space()->AllocateRaw(object_size); | |
1137 } else { | |
1138 result = Heap::old_pointer_space()->AllocateRaw(object_size); | |
1139 } | |
1140 } | |
1141 | |
1142 if (!result->IsFailure()) { | |
1143 HeapObject* target = HeapObject::cast(result); | |
1144 *slot = MigrateObject(object, target, object_size); | |
1145 | |
1146 if (object_contents == POINTER_OBJECT) { | |
1147 promotion_queue.insert(target, object_size); | |
1148 } | |
1149 | |
1150 Heap::tracer()->increment_promoted_objects_size(object_size); | |
1151 return; | |
1152 } | |
1153 } | |
1154 Object* result = Heap::new_space()->AllocateRaw(object_size); | |
1155 ASSERT(!result->IsFailure()); | |
1156 *slot = MigrateObject(object, HeapObject::cast(result), object_size); | |
1157 return; | |
1158 } | |
1159 | |
1160 | |
1161 template<int object_size_in_words, ObjectContents object_contents> | |
1162 static inline void EvacuateObjectOfFixedSize(Map* map, | |
1163 HeapObject** slot, | |
1164 HeapObject* object) { | |
1165 const int object_size = object_size_in_words << kPointerSizeLog2; | |
1166 EvacuateObject<object_contents, SMALL>(map, slot, object, object_size); | |
1167 } | |
1168 | |
1169 | |
1170 template<ObjectContents object_contents> | |
1171 static inline void EvacuateObjectOfFixedSize(Map* map, | |
1172 HeapObject** slot, | |
1173 HeapObject* object) { | |
1174 int object_size = map->instance_size(); | |
1175 EvacuateObject<object_contents, SMALL>(map, slot, object, object_size); | |
1176 } | |
1177 | |
1178 | |
1179 static inline void EvacuateFixedArray(Map* map, | |
1180 HeapObject** slot, | |
1181 HeapObject* object) { | |
1182 int object_size = FixedArray::cast(object)->FixedArraySize(); | |
1183 EvacuateObject<POINTER_OBJECT, UNKNOWN_SIZE>(map, slot, object, object_size); | |
1184 } | |
1185 | |
1186 | |
1187 static inline void EvacuateByteArray(Map* map, | |
1188 HeapObject** slot, | |
1189 HeapObject* object) { | |
1190 int object_size = ByteArray::cast(object)->ByteArraySize(); | |
1191 EvacuateObject<DATA_OBJECT, UNKNOWN_SIZE>(map, slot, object, object_size); | |
1192 } | |
1193 | |
1194 | |
1195 static Scavenger GetScavengerForSize(int object_size, | |
1196 ObjectContents object_contents) { | |
1197 ASSERT(IsAligned(object_size, kPointerSize)); | |
1198 ASSERT(object_size < Page::kMaxHeapObjectSize); | |
1199 | |
1200 switch (object_size >> kPointerSizeLog2) { | |
1201 #define CASE(n) \ | |
1202 case n: \ | |
1203 if (object_contents == DATA_OBJECT) { \ | |
1204 return static_cast<Scavenger>( \ | |
1205 &EvacuateObjectOfFixedSize<n, DATA_OBJECT>); \ | |
1206 } else { \ | |
1207 return static_cast<Scavenger>( \ | |
1208 &EvacuateObjectOfFixedSize<n, POINTER_OBJECT>); \ | |
1209 } | |
1210 | |
1211 CASE(1); | |
1212 CASE(2); | |
1213 CASE(3); | |
1214 CASE(4); | |
1215 CASE(5); | |
1216 CASE(6); | |
1217 CASE(7); | |
1218 CASE(8); | |
1219 CASE(9); | |
1220 CASE(10); | |
1221 CASE(11); | |
1222 CASE(12); | |
1223 CASE(13); | |
1224 CASE(14); | |
1225 CASE(15); | |
1226 CASE(16); | |
1227 default: | |
1228 if (object_contents == DATA_OBJECT) { | |
1229 return static_cast<Scavenger>(&EvacuateObjectOfFixedSize<DATA_OBJECT>); | |
1230 } else { | |
1231 return static_cast<Scavenger>( | |
1232 &EvacuateObjectOfFixedSize<POINTER_OBJECT>); | |
1233 } | |
1234 | |
1235 #undef CASE | |
1236 } | |
1237 } | |
1238 | |
1239 | |
1240 static inline void EvacuateSeqAsciiString(Map* map, | |
1241 HeapObject** slot, | |
1242 HeapObject* object) { | |
1243 int object_size = SeqAsciiString::cast(object)-> | |
1244 SeqAsciiStringSize(map->instance_type()); | |
1245 EvacuateObject<DATA_OBJECT, UNKNOWN_SIZE>(map, slot, object, object_size); | |
1246 } | |
1247 | |
1248 | |
1249 static inline void EvacuateSeqTwoByteString(Map* map, | |
1250 HeapObject** slot, | |
1251 HeapObject* object) { | |
1252 int object_size = SeqTwoByteString::cast(object)-> | |
1253 SeqTwoByteStringSize(map->instance_type()); | |
1254 EvacuateObject<DATA_OBJECT, UNKNOWN_SIZE>(map, slot, object, object_size); | |
1255 } | |
1256 | |
1257 | |
1258 static inline bool IsShortcutCandidate(int type) { | |
1259 return ((type & kShortcutTypeMask) == kShortcutTypeTag); | |
1260 } | |
1261 | |
1262 | |
1263 static inline void EvacuateShortcutCandidate(Map* map, | |
1264 HeapObject** slot, | |
1265 HeapObject* object) { | |
1266 ASSERT(IsShortcutCandidate(map->instance_type())); | |
1267 | |
1268 if (ConsString::cast(object)->unchecked_second() == Heap::empty_string()) { | |
1269 HeapObject* first = | |
1270 HeapObject::cast(ConsString::cast(object)->unchecked_first()); | |
1271 | |
1272 *slot = first; | |
1273 | |
1274 if (!Heap::InNewSpace(first)) { | |
1275 object->set_map_word(MapWord::FromForwardingAddress(first)); | |
1276 return; | |
1277 } | |
1278 | |
1279 MapWord first_word = first->map_word(); | |
1280 if (first_word.IsForwardingAddress()) { | |
1281 HeapObject* target = first_word.ToForwardingAddress(); | |
1282 | |
1283 *slot = target; | |
1284 object->set_map_word(MapWord::FromForwardingAddress(target)); | |
1285 return; | |
1286 } | |
1287 | |
1288 first->map()->Scavenge(slot, first); | |
1289 object->set_map_word(MapWord::FromForwardingAddress(*slot)); | |
1290 return; | |
1291 } | |
1292 | |
1293 int object_size = ConsString::kSize; | |
1294 EvacuateObject<POINTER_OBJECT, SMALL>(map, slot, object, object_size); | |
1295 } | |
1296 | |
1297 | |
1298 Scavenger Heap::GetScavenger(int instance_type, int instance_size) { | |
1299 if (instance_type < FIRST_NONSTRING_TYPE) { | |
1300 switch (instance_type & kStringRepresentationMask) { | |
1301 case kSeqStringTag: | |
1302 if ((instance_type & kStringEncodingMask) == kAsciiStringTag) { | |
1303 return &EvacuateSeqAsciiString; | |
1304 } else { | |
1305 return &EvacuateSeqTwoByteString; | |
1306 } | |
1307 | |
1308 case kConsStringTag: | |
1309 if (IsShortcutCandidate(instance_type)) { | |
1310 return &EvacuateShortcutCandidate; | |
1311 } else { | |
1312 ASSERT(instance_size == ConsString::kSize); | |
1313 return GetScavengerForSize(ConsString::kSize, POINTER_OBJECT); | |
1314 } | |
1315 | |
1316 case kExternalStringTag: | |
1317 ASSERT(instance_size == ExternalString::kSize); | |
1318 return GetScavengerForSize(ExternalString::kSize, DATA_OBJECT); | |
1319 } | |
1320 UNREACHABLE(); | |
1321 } | |
1322 | |
1323 switch (instance_type) { | |
1324 case BYTE_ARRAY_TYPE: | |
1325 return reinterpret_cast<Scavenger>(&EvacuateByteArray); | |
1326 | |
1327 case FIXED_ARRAY_TYPE: | |
1328 return reinterpret_cast<Scavenger>(&EvacuateFixedArray); | |
1329 | |
1330 case JS_OBJECT_TYPE: | |
1331 case JS_CONTEXT_EXTENSION_OBJECT_TYPE: | |
1332 case JS_VALUE_TYPE: | |
1333 case JS_ARRAY_TYPE: | |
1334 case JS_REGEXP_TYPE: | |
1335 case JS_FUNCTION_TYPE: | |
1336 case JS_GLOBAL_PROXY_TYPE: | |
1337 case JS_GLOBAL_OBJECT_TYPE: | |
1338 case JS_BUILTINS_OBJECT_TYPE: | |
1339 return GetScavengerForSize(instance_size, POINTER_OBJECT); | |
1340 | |
1341 case ODDBALL_TYPE: | |
1342 return NULL; | |
1343 | |
1344 case PROXY_TYPE: | |
1345 return GetScavengerForSize(Proxy::kSize, DATA_OBJECT); | |
1346 | |
1347 case MAP_TYPE: | |
1348 return NULL; | |
1349 | |
1350 case CODE_TYPE: | |
1351 return NULL; | |
1352 | |
1353 case JS_GLOBAL_PROPERTY_CELL_TYPE: | |
1354 return NULL; | |
1355 | |
1356 case HEAP_NUMBER_TYPE: | |
1357 case FILLER_TYPE: | |
1358 case PIXEL_ARRAY_TYPE: | |
1359 case EXTERNAL_BYTE_ARRAY_TYPE: | |
1360 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE: | |
1361 case EXTERNAL_SHORT_ARRAY_TYPE: | |
1362 case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE: | |
1363 case EXTERNAL_INT_ARRAY_TYPE: | |
1364 case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE: | |
1365 case EXTERNAL_FLOAT_ARRAY_TYPE: | |
1366 return GetScavengerForSize(instance_size, DATA_OBJECT); | |
1367 | |
1368 case SHARED_FUNCTION_INFO_TYPE: | |
1369 return GetScavengerForSize(SharedFunctionInfo::kAlignedSize, | |
1370 POINTER_OBJECT); | |
1371 | |
1372 #define MAKE_STRUCT_CASE(NAME, Name, name) \ | |
1373 case NAME##_TYPE: | |
1374 STRUCT_LIST(MAKE_STRUCT_CASE) | |
1375 #undef MAKE_STRUCT_CASE | |
1376 return GetScavengerForSize(instance_size, POINTER_OBJECT); | |
1377 default: | |
1378 UNREACHABLE(); | |
1379 return NULL; | |
1380 } | |
1381 } | 1125 } |
1382 | 1126 |
1383 | 1127 |
1384 void Heap::ScavengeObjectSlow(HeapObject** p, HeapObject* object) { | 1128 void Heap::ScavengeObjectSlow(HeapObject** p, HeapObject* object) { |
1385 ASSERT(InFromSpace(object)); | 1129 ASSERT(InFromSpace(object)); |
1386 MapWord first_word = object->map_word(); | 1130 MapWord first_word = object->map_word(); |
1387 ASSERT(!first_word.IsForwardingAddress()); | 1131 ASSERT(!first_word.IsForwardingAddress()); |
1388 Map* map = first_word.ToMap(); | 1132 |
1389 map->Scavenge(p, object); | 1133 // Optimization: Bypass flattened ConsString objects. |
| 1134 if (IsShortcutCandidate(object, first_word.ToMap())) { |
| 1135 object = HeapObject::cast(ConsString::cast(object)->unchecked_first()); |
| 1136 *p = object; |
| 1137 // After patching *p we have to repeat the checks that object is in the |
| 1138 // active semispace of the young generation and not already copied. |
| 1139 if (!InNewSpace(object)) return; |
| 1140 first_word = object->map_word(); |
| 1141 if (first_word.IsForwardingAddress()) { |
| 1142 *p = first_word.ToForwardingAddress(); |
| 1143 return; |
| 1144 } |
| 1145 } |
| 1146 |
| 1147 int object_size = object->SizeFromMap(first_word.ToMap()); |
| 1148 // We rely on live objects in new space to be at least two pointers, |
| 1149 // so we can store the from-space address and map pointer of promoted |
| 1150 // objects in the to space. |
| 1151 ASSERT(object_size >= 2 * kPointerSize); |
| 1152 |
| 1153 // If the object should be promoted, we try to copy it to old space. |
| 1154 if (ShouldBePromoted(object->address(), object_size)) { |
| 1155 Object* result; |
| 1156 if (object_size > MaxObjectSizeInPagedSpace()) { |
| 1157 result = lo_space_->AllocateRawFixedArray(object_size); |
| 1158 if (!result->IsFailure()) { |
| 1159 HeapObject* target = HeapObject::cast(result); |
| 1160 |
| 1161 if (object->IsFixedArray()) { |
| 1162 // Save the from-space object pointer and its map pointer at the |
| 1163 // top of the to space to be swept and copied later. Write the |
| 1164 // forwarding address over the map word of the from-space |
| 1165 // object. |
| 1166 promotion_queue.insert(object, first_word.ToMap()); |
| 1167 object->set_map_word(MapWord::FromForwardingAddress(target)); |
| 1168 |
| 1169 // Give the space allocated for the result a proper map by |
| 1170 // treating it as a free list node (not linked into the free |
| 1171 // list). |
| 1172 FreeListNode* node = FreeListNode::FromAddress(target->address()); |
| 1173 node->set_size(object_size); |
| 1174 |
| 1175 *p = target; |
| 1176 } else { |
| 1177 // In large object space only fixed arrays might possibly contain |
| 1178 // intergenerational references. |
| 1179 // All other objects can be copied immediately and not revisited. |
| 1180 *p = MigrateObject(object, target, object_size); |
| 1181 } |
| 1182 |
| 1183 tracer()->increment_promoted_objects_size(object_size); |
| 1184 return; |
| 1185 } |
| 1186 } else { |
| 1187 OldSpace* target_space = Heap::TargetSpace(object); |
| 1188 ASSERT(target_space == Heap::old_pointer_space_ || |
| 1189 target_space == Heap::old_data_space_); |
| 1190 result = target_space->AllocateRaw(object_size); |
| 1191 if (!result->IsFailure()) { |
| 1192 HeapObject* target = HeapObject::cast(result); |
| 1193 if (target_space == Heap::old_pointer_space_) { |
| 1194 // Save the from-space object pointer and its map pointer at the |
| 1195 // top of the to space to be swept and copied later. Write the |
| 1196 // forwarding address over the map word of the from-space |
| 1197 // object. |
| 1198 promotion_queue.insert(object, first_word.ToMap()); |
| 1199 object->set_map_word(MapWord::FromForwardingAddress(target)); |
| 1200 |
| 1201 // Give the space allocated for the result a proper map by |
| 1202 // treating it as a free list node (not linked into the free |
| 1203 // list). |
| 1204 FreeListNode* node = FreeListNode::FromAddress(target->address()); |
| 1205 node->set_size(object_size); |
| 1206 |
| 1207 *p = target; |
| 1208 } else { |
| 1209 // Objects promoted to the data space can be copied immediately |
| 1210 // and not revisited---we will never sweep that space for |
| 1211 // pointers and the copied objects do not contain pointers to |
| 1212 // new space objects. |
| 1213 *p = MigrateObject(object, target, object_size); |
| 1214 #ifdef DEBUG |
| 1215 VerifyNonPointerSpacePointersVisitor v; |
| 1216 (*p)->Iterate(&v); |
| 1217 #endif |
| 1218 } |
| 1219 tracer()->increment_promoted_objects_size(object_size); |
| 1220 return; |
| 1221 } |
| 1222 } |
| 1223 } |
| 1224 // The object should remain in new space or the old space allocation failed. |
| 1225 Object* result = new_space_.AllocateRaw(object_size); |
| 1226 // Failed allocation at this point is utterly unexpected. |
| 1227 ASSERT(!result->IsFailure()); |
| 1228 *p = MigrateObject(object, HeapObject::cast(result), object_size); |
1390 } | 1229 } |
1391 | 1230 |
1392 | 1231 |
1393 void Heap::ScavengePointer(HeapObject** p) { | 1232 void Heap::ScavengePointer(HeapObject** p) { |
1394 ScavengeObject(p, *p); | 1233 ScavengeObject(p, *p); |
1395 } | 1234 } |
1396 | 1235 |
1397 | 1236 |
1398 Object* Heap::AllocatePartialMap(InstanceType instance_type, | 1237 Object* Heap::AllocatePartialMap(InstanceType instance_type, |
1399 int instance_size) { | 1238 int instance_size) { |
1400 Object* result = AllocateRawMap(); | 1239 Object* result = AllocateRawMap(); |
1401 if (result->IsFailure()) return result; | 1240 if (result->IsFailure()) return result; |
1402 | 1241 |
1403 // Map::cast cannot be used due to uninitialized map field. | 1242 // Map::cast cannot be used due to uninitialized map field. |
1404 reinterpret_cast<Map*>(result)->set_map(raw_unchecked_meta_map()); | 1243 reinterpret_cast<Map*>(result)->set_map(raw_unchecked_meta_map()); |
1405 reinterpret_cast<Map*>(result)->set_instance_type(instance_type); | 1244 reinterpret_cast<Map*>(result)->set_instance_type(instance_type); |
1406 reinterpret_cast<Map*>(result)->set_instance_size(instance_size); | 1245 reinterpret_cast<Map*>(result)->set_instance_size(instance_size); |
1407 reinterpret_cast<Map*>(result)-> | |
1408 set_scavenger(GetScavenger(instance_type, instance_size)); | |
1409 reinterpret_cast<Map*>(result)->set_inobject_properties(0); | 1246 reinterpret_cast<Map*>(result)->set_inobject_properties(0); |
1410 reinterpret_cast<Map*>(result)->set_pre_allocated_property_fields(0); | 1247 reinterpret_cast<Map*>(result)->set_pre_allocated_property_fields(0); |
1411 reinterpret_cast<Map*>(result)->set_unused_property_fields(0); | 1248 reinterpret_cast<Map*>(result)->set_unused_property_fields(0); |
1412 reinterpret_cast<Map*>(result)->set_bit_field(0); | 1249 reinterpret_cast<Map*>(result)->set_bit_field(0); |
1413 reinterpret_cast<Map*>(result)->set_bit_field2(0); | 1250 reinterpret_cast<Map*>(result)->set_bit_field2(0); |
1414 return result; | 1251 return result; |
1415 } | 1252 } |
1416 | 1253 |
1417 | 1254 |
1418 Object* Heap::AllocateMap(InstanceType instance_type, int instance_size) { | 1255 Object* Heap::AllocateMap(InstanceType instance_type, int instance_size) { |
1419 Object* result = AllocateRawMap(); | 1256 Object* result = AllocateRawMap(); |
1420 if (result->IsFailure()) return result; | 1257 if (result->IsFailure()) return result; |
1421 | 1258 |
1422 Map* map = reinterpret_cast<Map*>(result); | 1259 Map* map = reinterpret_cast<Map*>(result); |
1423 map->set_map(meta_map()); | 1260 map->set_map(meta_map()); |
1424 map->set_instance_type(instance_type); | 1261 map->set_instance_type(instance_type); |
1425 map->set_scavenger(GetScavenger(instance_type, instance_size)); | |
1426 map->set_prototype(null_value()); | 1262 map->set_prototype(null_value()); |
1427 map->set_constructor(null_value()); | 1263 map->set_constructor(null_value()); |
1428 map->set_instance_size(instance_size); | 1264 map->set_instance_size(instance_size); |
1429 map->set_inobject_properties(0); | 1265 map->set_inobject_properties(0); |
1430 map->set_pre_allocated_property_fields(0); | 1266 map->set_pre_allocated_property_fields(0); |
1431 map->set_instance_descriptors(empty_descriptor_array()); | 1267 map->set_instance_descriptors(empty_descriptor_array()); |
1432 map->set_code_cache(empty_fixed_array()); | 1268 map->set_code_cache(empty_fixed_array()); |
1433 map->set_unused_property_fields(0); | 1269 map->set_unused_property_fields(0); |
1434 map->set_bit_field(0); | 1270 map->set_bit_field(0); |
1435 map->set_bit_field2((1 << Map::kIsExtensible) | (1 << Map::kHasFastElements)); | 1271 map->set_bit_field2((1 << Map::kIsExtensible) | (1 << Map::kHasFastElements)); |
(...skipping 2412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3848 IteratePointersInDirtyRegion(pointer_fields_start, | 3684 IteratePointersInDirtyRegion(pointer_fields_start, |
3849 pointer_fields_end, | 3685 pointer_fields_end, |
3850 copy_object_func) | 3686 copy_object_func) |
3851 || contains_pointers_to_new_space; | 3687 || contains_pointers_to_new_space; |
3852 } | 3688 } |
3853 | 3689 |
3854 return contains_pointers_to_new_space; | 3690 return contains_pointers_to_new_space; |
3855 } | 3691 } |
3856 | 3692 |
3857 | 3693 |
3858 void Heap::IterateAndMarkPointersToFromSpace(Address start, | 3694 void Heap::IterateAndMarkPointersToNewSpace(Address start, |
3859 Address end, | 3695 Address end, |
3860 ObjectSlotCallback callback) { | 3696 ObjectSlotCallback callback) { |
3861 Address slot_address = start; | 3697 Address slot_address = start; |
3862 Page* page = Page::FromAddress(start); | 3698 Page* page = Page::FromAddress(start); |
3863 | 3699 |
3864 uint32_t marks = page->GetRegionMarks(); | 3700 uint32_t marks = page->GetRegionMarks(); |
3865 | 3701 |
3866 while (slot_address < end) { | 3702 while (slot_address < end) { |
3867 Object** slot = reinterpret_cast<Object**>(slot_address); | 3703 Object** slot = reinterpret_cast<Object**>(slot_address); |
3868 if (Heap::InFromSpace(*slot)) { | 3704 if (Heap::InNewSpace(*slot)) { |
3869 ASSERT((*slot)->IsHeapObject()); | 3705 ASSERT((*slot)->IsHeapObject()); |
3870 callback(reinterpret_cast<HeapObject**>(slot)); | 3706 callback(reinterpret_cast<HeapObject**>(slot)); |
3871 if (Heap::InNewSpace(*slot)) { | 3707 if (Heap::InNewSpace(*slot)) { |
3872 ASSERT((*slot)->IsHeapObject()); | 3708 ASSERT((*slot)->IsHeapObject()); |
3873 marks |= page->GetRegionMaskForAddress(slot_address); | 3709 marks |= page->GetRegionMaskForAddress(slot_address); |
3874 } | 3710 } |
3875 } | 3711 } |
3876 slot_address += kPointerSize; | 3712 slot_address += kPointerSize; |
3877 } | 3713 } |
3878 | 3714 |
(...skipping 1116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4995 void ExternalStringTable::TearDown() { | 4831 void ExternalStringTable::TearDown() { |
4996 new_space_strings_.Free(); | 4832 new_space_strings_.Free(); |
4997 old_space_strings_.Free(); | 4833 old_space_strings_.Free(); |
4998 } | 4834 } |
4999 | 4835 |
5000 | 4836 |
5001 List<Object*> ExternalStringTable::new_space_strings_; | 4837 List<Object*> ExternalStringTable::new_space_strings_; |
5002 List<Object*> ExternalStringTable::old_space_strings_; | 4838 List<Object*> ExternalStringTable::old_space_strings_; |
5003 | 4839 |
5004 } } // namespace v8::internal | 4840 } } // namespace v8::internal |
OLD | NEW |