| 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 19 matching lines...) Expand all  Loading... | 
|    30 #include "accessors.h" |    30 #include "accessors.h" | 
|    31 #include "api.h" |    31 #include "api.h" | 
|    32 #include "bootstrapper.h" |    32 #include "bootstrapper.h" | 
|    33 #include "codegen-inl.h" |    33 #include "codegen-inl.h" | 
|    34 #include "compilation-cache.h" |    34 #include "compilation-cache.h" | 
|    35 #include "debug.h" |    35 #include "debug.h" | 
|    36 #include "heap-profiler.h" |    36 #include "heap-profiler.h" | 
|    37 #include "global-handles.h" |    37 #include "global-handles.h" | 
|    38 #include "mark-compact.h" |    38 #include "mark-compact.h" | 
|    39 #include "natives.h" |    39 #include "natives.h" | 
 |    40 #include "objects-visiting.h" | 
|    40 #include "scanner.h" |    41 #include "scanner.h" | 
|    41 #include "scopeinfo.h" |    42 #include "scopeinfo.h" | 
|    42 #include "snapshot.h" |    43 #include "snapshot.h" | 
|    43 #include "v8threads.h" |    44 #include "v8threads.h" | 
|    44 #if V8_TARGET_ARCH_ARM && !V8_INTERPRETED_REGEXP |    45 #if V8_TARGET_ARCH_ARM && !V8_INTERPRETED_REGEXP | 
|    45 #include "regexp-macro-assembler.h" |    46 #include "regexp-macro-assembler.h" | 
|    46 #include "arm/regexp-macro-assembler-arm.h" |    47 #include "arm/regexp-macro-assembler-arm.h" | 
|    47 #endif |    48 #endif | 
|    48  |    49  | 
|    49  |    50  | 
| (...skipping 975 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1025       // String got promoted.  Move it to the old string list. |  1026       // String got promoted.  Move it to the old string list. | 
|  1026       ExternalStringTable::AddOldString(target); |  1027       ExternalStringTable::AddOldString(target); | 
|  1027     } |  1028     } | 
|  1028   } |  1029   } | 
|  1029  |  1030  | 
|  1030   ASSERT(last <= end); |  1031   ASSERT(last <= end); | 
|  1031   ExternalStringTable::ShrinkNewStrings(static_cast<int>(last - start)); |  1032   ExternalStringTable::ShrinkNewStrings(static_cast<int>(last - start)); | 
|  1032 } |  1033 } | 
|  1033  |  1034  | 
|  1034  |  1035  | 
 |  1036 class NewSpaceScavenger : public StaticNewSpaceVisitor<NewSpaceScavenger> { | 
 |  1037  public: | 
 |  1038   static inline void VisitPointer(Object** p) { | 
 |  1039     Object* object = *p; | 
 |  1040     if (!Heap::InNewSpace(object)) return; | 
 |  1041     Heap::ScavengeObject(reinterpret_cast<HeapObject**>(p), | 
 |  1042                          reinterpret_cast<HeapObject*>(object)); | 
 |  1043   } | 
 |  1044 }; | 
 |  1045  | 
 |  1046  | 
|  1035 Address Heap::DoScavenge(ObjectVisitor* scavenge_visitor, |  1047 Address Heap::DoScavenge(ObjectVisitor* scavenge_visitor, | 
|  1036                          Address new_space_front) { |  1048                          Address new_space_front) { | 
|  1037   do { |  1049   do { | 
|  1038     ASSERT(new_space_front <= new_space_.top()); |  1050     ASSERT(new_space_front <= new_space_.top()); | 
|  1039  |  1051  | 
|  1040     // The addresses new_space_front and new_space_.top() define a |  1052     // The addresses new_space_front and new_space_.top() define a | 
|  1041     // queue of unprocessed copied objects.  Process them until the |  1053     // queue of unprocessed copied objects.  Process them until the | 
|  1042     // queue is empty. |  1054     // queue is empty. | 
|  1043     while (new_space_front < new_space_.top()) { |  1055     while (new_space_front < new_space_.top()) { | 
|  1044       HeapObject* object = HeapObject::FromAddress(new_space_front); |  1056       HeapObject* object = HeapObject::FromAddress(new_space_front); | 
|  1045       Map* map = object->map(); |  1057       new_space_front += NewSpaceScavenger::IterateBody(object->map(), object); | 
|  1046       int size = object->SizeFromMap(map); |  | 
|  1047       object->IterateBody(map->instance_type(), size, scavenge_visitor); |  | 
|  1048       new_space_front += size; |  | 
|  1049     } |  1058     } | 
|  1050  |  1059  | 
|  1051     // Promote and process all the to-be-promoted objects. |  1060     // Promote and process all the to-be-promoted objects. | 
|  1052     while (!promotion_queue.is_empty()) { |  1061     while (!promotion_queue.is_empty()) { | 
|  1053       HeapObject* target; |  1062       HeapObject* target; | 
|  1054       int size; |  1063       int size; | 
|  1055       promotion_queue.remove(&target, &size); |  1064       promotion_queue.remove(&target, &size); | 
|  1056  |  1065  | 
|  1057       // Promoted object might be already partially visited |  1066       // Promoted object might be already partially visited | 
|  1058       // during dirty regions iteration. Thus we search specificly |  1067       // during dirty regions iteration. Thus we search specificly | 
|  1059       // for pointers to from semispace instead of looking for pointers |  1068       // for pointers to from semispace instead of looking for pointers | 
|  1060       // to new space. |  1069       // to new space. | 
|  1061       ASSERT(!target->IsMap()); |  1070       ASSERT(!target->IsMap()); | 
|  1062       IterateAndMarkPointersToFromSpace(target->address(), |  1071       IterateAndMarkPointersToFromSpace(target->address(), | 
|  1063                                         target->address() + size, |  1072                                         target->address() + size, | 
|  1064                                         &ScavengePointer); |  1073                                         &ScavengePointer); | 
|  1065     } |  1074     } | 
|  1066  |  1075  | 
|  1067     // Take another spin if there are now unswept objects in new space |  1076     // Take another spin if there are now unswept objects in new space | 
|  1068     // (there are currently no more unswept promoted objects). |  1077     // (there are currently no more unswept promoted objects). | 
|  1069   } while (new_space_front < new_space_.top()); |  1078   } while (new_space_front < new_space_.top()); | 
|  1070  |  1079  | 
|  1071   return new_space_front; |  1080   return new_space_front; | 
|  1072 } |  1081 } | 
|  1073  |  1082  | 
|  1074  |  1083  | 
 |  1084 class ScavengingVisitor : public StaticVisitorBase { | 
 |  1085  public: | 
 |  1086   static void Initialize() { | 
 |  1087     table_.Register(kVisitSeqAsciiString, &EvacuateSeqAsciiString); | 
 |  1088     table_.Register(kVisitSeqTwoByteString, &EvacuateSeqTwoByteString); | 
 |  1089     table_.Register(kVisitShortcutCandidate, &EvacuateShortcutCandidate); | 
 |  1090     table_.Register(kVisitByteArray, &EvacuateByteArray); | 
 |  1091     table_.Register(kVisitFixedArray, &EvacuateFixedArray); | 
 |  1092  | 
 |  1093     typedef ObjectEvacuationStrategy<POINTER_OBJECT> PointerObject; | 
 |  1094  | 
 |  1095     table_.Register(kVisitConsString, | 
 |  1096                     &ObjectEvacuationStrategy<POINTER_OBJECT>:: | 
 |  1097                         VisitSpecialized<ConsString::kSize>); | 
 |  1098  | 
 |  1099     table_.Register(kVisitSharedFunctionInfo, | 
 |  1100                     &ObjectEvacuationStrategy<POINTER_OBJECT>:: | 
 |  1101                         VisitSpecialized<SharedFunctionInfo::kSize>); | 
 |  1102  | 
 |  1103     table_.RegisterSpecializations<ObjectEvacuationStrategy<DATA_OBJECT>, | 
 |  1104                                    kVisitDataObject, | 
 |  1105                                    kVisitDataObjectGeneric>(); | 
 |  1106  | 
 |  1107     table_.RegisterSpecializations<ObjectEvacuationStrategy<POINTER_OBJECT>, | 
 |  1108                                    kVisitJSObject, | 
 |  1109                                    kVisitJSObjectGeneric>(); | 
 |  1110  | 
 |  1111     table_.RegisterSpecializations<ObjectEvacuationStrategy<POINTER_OBJECT>, | 
 |  1112                                    kVisitStruct, | 
 |  1113                                    kVisitStructGeneric>(); | 
 |  1114   } | 
 |  1115  | 
 |  1116  | 
 |  1117   static inline void Scavenge(Map* map, HeapObject** slot, HeapObject* obj) { | 
 |  1118     table_.GetVisitor(map)(map, slot, obj); | 
 |  1119   } | 
 |  1120  | 
 |  1121  | 
 |  1122  private: | 
 |  1123   enum ObjectContents  { DATA_OBJECT, POINTER_OBJECT }; | 
 |  1124   enum SizeRestriction { SMALL, UNKNOWN_SIZE }; | 
 |  1125  | 
|  1075 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) |  1126 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) | 
|  1076 static void RecordCopiedObject(HeapObject* obj) { |  1127   static void RecordCopiedObject(HeapObject* obj) { | 
|  1077   bool should_record = false; |  1128     bool should_record = false; | 
|  1078 #ifdef DEBUG |  1129 #ifdef DEBUG | 
|  1079   should_record = FLAG_heap_stats; |  1130     should_record = FLAG_heap_stats; | 
|  1080 #endif |  1131 #endif | 
|  1081 #ifdef ENABLE_LOGGING_AND_PROFILING |  1132 #ifdef ENABLE_LOGGING_AND_PROFILING | 
|  1082   should_record = should_record || FLAG_log_gc; |  1133     should_record = should_record || FLAG_log_gc; | 
|  1083 #endif |  1134 #endif | 
|  1084   if (should_record) { |  1135     if (should_record) { | 
|  1085     if (Heap::new_space()->Contains(obj)) { |  1136       if (Heap::new_space()->Contains(obj)) { | 
|  1086       Heap::new_space()->RecordAllocation(obj); |  1137         Heap::new_space()->RecordAllocation(obj); | 
|  1087     } else { |  1138       } else { | 
|  1088       Heap::new_space()->RecordPromotion(obj); |  1139         Heap::new_space()->RecordPromotion(obj); | 
|  1089     } |  1140       } | 
|  1090   } |  1141     } | 
|  1091 } |  1142   } | 
|  1092 #endif  // defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) |  1143 #endif  // defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) | 
|  1093  |  1144  | 
|  1094  |  1145   // Helper function used by CopyObject to copy a source object to an | 
|  1095 // Helper function used by CopyObject to copy a source object to an |  1146   // allocated target object and update the forwarding pointer in the source | 
|  1096 // allocated target object and update the forwarding pointer in the source |  1147   // object.  Returns the target object. | 
|  1097 // object.  Returns the target object. |  1148   INLINE(static HeapObject* MigrateObject(HeapObject* source, | 
|  1098 inline static HeapObject* MigrateObject(HeapObject* source, |  1149                                           HeapObject* target, | 
|  1099                                         HeapObject* target, |  1150                                           int size)) { | 
|  1100                                         int size) { |  1151     // Copy the content of source to target. | 
|  1101   // Copy the content of source to target. |  1152     Heap::CopyBlock(target->address(), source->address(), size); | 
|  1102   Heap::CopyBlock(target->address(), source->address(), size); |  1153  | 
|  1103  |  1154     // Set the forwarding address. | 
|  1104   // Set the forwarding address. |  1155     source->set_map_word(MapWord::FromForwardingAddress(target)); | 
|  1105   source->set_map_word(MapWord::FromForwardingAddress(target)); |  | 
|  1106  |  1156  | 
|  1107 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) |  1157 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) | 
|  1108   // Update NewSpace stats if necessary. |  1158     // Update NewSpace stats if necessary. | 
|  1109   RecordCopiedObject(target); |  1159     RecordCopiedObject(target); | 
|  1110 #endif |  1160 #endif | 
|  1111   HEAP_PROFILE(ObjectMoveEvent(source->address(), target->address())); |  1161     HEAP_PROFILE(ObjectMoveEvent(source->address(), target->address())); | 
|  1112  |  1162  | 
|  1113   return target; |  1163     return target; | 
|  1114 } |  1164   } | 
|  1115  |  1165  | 
|  1116  |  1166  | 
|  1117 enum ObjectContents  { DATA_OBJECT, POINTER_OBJECT }; |  1167   template<ObjectContents object_contents, SizeRestriction size_restriction> | 
|  1118 enum SizeRestriction { SMALL, UNKNOWN_SIZE }; |  1168   static inline void EvacuateObject(Map* map, | 
|  1119  |  1169                                     HeapObject** slot, | 
|  1120  |  1170                                     HeapObject* object, | 
|  1121 template<ObjectContents object_contents, SizeRestriction size_restriction> |  1171                                     int object_size) { | 
|  1122 static inline void EvacuateObject(Map* map, |  1172     ASSERT((size_restriction != SMALL) || | 
|  1123                                   HeapObject** slot, |  1173            (object_size <= Page::kMaxHeapObjectSize)); | 
|  1124                                   HeapObject* object, |  1174     ASSERT(object->Size() == object_size); | 
|  1125                                   int object_size) { |  1175  | 
|  1126   ASSERT((size_restriction != SMALL) || |  1176     if (Heap::ShouldBePromoted(object->address(), object_size)) { | 
|  1127          (object_size <= Page::kMaxHeapObjectSize)); |  1177       Object* result; | 
|  1128   ASSERT(object->Size() == object_size); |  1178  | 
|  1129  |  1179       if ((size_restriction != SMALL) && | 
|  1130   if (Heap::ShouldBePromoted(object->address(), object_size)) { |  1180           (object_size > Page::kMaxHeapObjectSize)) { | 
|  1131     Object* result; |  1181         result = Heap::lo_space()->AllocateRawFixedArray(object_size); | 
|  1132  |  | 
|  1133     if ((size_restriction != SMALL) && |  | 
|  1134         (object_size > Page::kMaxHeapObjectSize)) { |  | 
|  1135       result = Heap::lo_space()->AllocateRawFixedArray(object_size); |  | 
|  1136     } else { |  | 
|  1137       if (object_contents == DATA_OBJECT) { |  | 
|  1138         result = Heap::old_data_space()->AllocateRaw(object_size); |  | 
|  1139       } else { |  1182       } else { | 
|  1140         result = Heap::old_pointer_space()->AllocateRaw(object_size); |  1183         if (object_contents == DATA_OBJECT) { | 
|  1141       } |  1184           result = Heap::old_data_space()->AllocateRaw(object_size); | 
|  1142     } |  1185         } else { | 
|  1143  |  1186           result = Heap::old_pointer_space()->AllocateRaw(object_size); | 
|  1144     if (!result->IsFailure()) { |  1187         } | 
|  1145       HeapObject* target = HeapObject::cast(result); |  1188       } | 
|  1146       *slot = MigrateObject(object, target, object_size); |  1189  | 
|  1147  |  1190       if (!result->IsFailure()) { | 
|  1148       if (object_contents == POINTER_OBJECT) { |  1191         HeapObject* target = HeapObject::cast(result); | 
|  1149         promotion_queue.insert(target, object_size); |  1192         *slot = MigrateObject(object, target, object_size); | 
|  1150       } |  1193  | 
|  1151  |  1194         if (object_contents == POINTER_OBJECT) { | 
|  1152       Heap::tracer()->increment_promoted_objects_size(object_size); |  1195           promotion_queue.insert(target, object_size); | 
|  1153       return; |  1196         } | 
|  1154     } |  1197  | 
|  1155   } |  1198         Heap::tracer()->increment_promoted_objects_size(object_size); | 
|  1156   Object* result = Heap::new_space()->AllocateRaw(object_size); |  1199         return; | 
|  1157   ASSERT(!result->IsFailure()); |  1200       } | 
|  1158   *slot = MigrateObject(object, HeapObject::cast(result), object_size); |  1201     } | 
|  1159   return; |  1202     Object* result = Heap::new_space()->AllocateRaw(object_size); | 
|  1160 } |  1203     ASSERT(!result->IsFailure()); | 
|  1161  |  1204     *slot = MigrateObject(object, HeapObject::cast(result), object_size); | 
|  1162  |  1205     return; | 
|  1163 template<int object_size_in_words, ObjectContents object_contents> |  1206   } | 
|  1164 static inline void EvacuateObjectOfFixedSize(Map* map, |  1207  | 
|  1165                                              HeapObject** slot, |  1208  | 
|  1166                                              HeapObject* object) { |  1209   static inline void EvacuateFixedArray(Map* map, | 
|  1167   const int object_size = object_size_in_words << kPointerSizeLog2; |  1210                                         HeapObject** slot, | 
|  1168   EvacuateObject<object_contents, SMALL>(map, slot, object, object_size); |  1211                                         HeapObject* object) { | 
|  1169 } |  1212     int object_size = FixedArray::BodyDescriptor::SizeOf(map, object); | 
|  1170  |  1213     EvacuateObject<POINTER_OBJECT, UNKNOWN_SIZE>(map, | 
|  1171  |  1214                                                  slot, | 
|  1172 template<ObjectContents object_contents> |  1215                                                  object, | 
|  1173 static inline void EvacuateObjectOfFixedSize(Map* map, |  1216                                                  object_size); | 
|  1174                                              HeapObject** slot, |  1217   } | 
|  1175                                              HeapObject* object) { |  1218  | 
|  1176   int object_size = map->instance_size(); |  1219  | 
|  1177   EvacuateObject<object_contents, SMALL>(map, slot, object, object_size); |  1220   static inline void EvacuateByteArray(Map* map, | 
|  1178 } |  1221                                        HeapObject** slot, | 
|  1179  |  1222                                        HeapObject* object) { | 
|  1180  |  1223     int object_size = reinterpret_cast<ByteArray*>(object)->ByteArraySize(); | 
|  1181 static inline void EvacuateFixedArray(Map* map, |  1224     EvacuateObject<DATA_OBJECT, UNKNOWN_SIZE>(map, slot, object, object_size); | 
|  1182                                       HeapObject** slot, |  1225   } | 
|  1183                                       HeapObject* object) { |  1226  | 
|  1184   int object_size = FixedArray::cast(object)->FixedArraySize(); |  1227  | 
|  1185   EvacuateObject<POINTER_OBJECT, UNKNOWN_SIZE>(map, slot, object, object_size); |  1228   static inline void EvacuateSeqAsciiString(Map* map, | 
|  1186 } |  | 
|  1187  |  | 
|  1188  |  | 
|  1189 static inline void EvacuateByteArray(Map* map, |  | 
|  1190                                      HeapObject** slot, |  | 
|  1191                                      HeapObject* object) { |  | 
|  1192   int object_size = ByteArray::cast(object)->ByteArraySize(); |  | 
|  1193   EvacuateObject<DATA_OBJECT, UNKNOWN_SIZE>(map, slot, object, object_size); |  | 
|  1194 } |  | 
|  1195  |  | 
|  1196  |  | 
|  1197 static Scavenger GetScavengerForSize(int object_size, |  | 
|  1198                                      ObjectContents object_contents) { |  | 
|  1199   ASSERT(IsAligned(object_size, kPointerSize)); |  | 
|  1200   ASSERT(object_size < Page::kMaxHeapObjectSize); |  | 
|  1201  |  | 
|  1202   switch (object_size >> kPointerSizeLog2) { |  | 
|  1203 #define CASE(n)                                           \ |  | 
|  1204     case n:                                               \ |  | 
|  1205       if (object_contents == DATA_OBJECT) {               \ |  | 
|  1206         return static_cast<Scavenger>(                    \ |  | 
|  1207           &EvacuateObjectOfFixedSize<n, DATA_OBJECT>);    \ |  | 
|  1208       } else {                                            \ |  | 
|  1209         return static_cast<Scavenger>(                    \ |  | 
|  1210           &EvacuateObjectOfFixedSize<n, POINTER_OBJECT>); \ |  | 
|  1211       } |  | 
|  1212  |  | 
|  1213     CASE(1); |  | 
|  1214     CASE(2); |  | 
|  1215     CASE(3); |  | 
|  1216     CASE(4); |  | 
|  1217     CASE(5); |  | 
|  1218     CASE(6); |  | 
|  1219     CASE(7); |  | 
|  1220     CASE(8); |  | 
|  1221     CASE(9); |  | 
|  1222     CASE(10); |  | 
|  1223     CASE(11); |  | 
|  1224     CASE(12); |  | 
|  1225     CASE(13); |  | 
|  1226     CASE(14); |  | 
|  1227     CASE(15); |  | 
|  1228     CASE(16); |  | 
|  1229     default: |  | 
|  1230       if (object_contents == DATA_OBJECT) { |  | 
|  1231         return static_cast<Scavenger>(&EvacuateObjectOfFixedSize<DATA_OBJECT>); |  | 
|  1232       } else { |  | 
|  1233         return static_cast<Scavenger>( |  | 
|  1234             &EvacuateObjectOfFixedSize<POINTER_OBJECT>); |  | 
|  1235       } |  | 
|  1236  |  | 
|  1237 #undef CASE |  | 
|  1238   } |  | 
|  1239 } |  | 
|  1240  |  | 
|  1241  |  | 
|  1242 static inline void EvacuateSeqAsciiString(Map* map, |  | 
|  1243                                           HeapObject** slot, |  | 
|  1244                                           HeapObject* object) { |  | 
|  1245   int object_size = SeqAsciiString::cast(object)-> |  | 
|  1246       SeqAsciiStringSize(map->instance_type()); |  | 
|  1247   EvacuateObject<DATA_OBJECT, UNKNOWN_SIZE>(map, slot, object, object_size); |  | 
|  1248 } |  | 
|  1249  |  | 
|  1250  |  | 
|  1251 static inline void EvacuateSeqTwoByteString(Map* map, |  | 
|  1252                                             HeapObject** slot, |  1229                                             HeapObject** slot, | 
|  1253                                             HeapObject* object) { |  1230                                             HeapObject* object) { | 
|  1254   int object_size = SeqTwoByteString::cast(object)-> |  1231     int object_size = SeqAsciiString::cast(object)-> | 
|  1255       SeqTwoByteStringSize(map->instance_type()); |  1232         SeqAsciiStringSize(map->instance_type()); | 
|  1256   EvacuateObject<DATA_OBJECT, UNKNOWN_SIZE>(map, slot, object, object_size); |  1233     EvacuateObject<DATA_OBJECT, UNKNOWN_SIZE>(map, slot, object, object_size); | 
|  1257 } |  1234   } | 
|  1258  |  1235  | 
|  1259  |  1236  | 
|  1260 static inline bool IsShortcutCandidate(int type) { |  1237   static inline void EvacuateSeqTwoByteString(Map* map, | 
|  1261   return ((type & kShortcutTypeMask) == kShortcutTypeTag); |  1238                                               HeapObject** slot, | 
|  1262 } |  1239                                               HeapObject* object) { | 
|  1263  |  1240     int object_size = SeqTwoByteString::cast(object)-> | 
|  1264  |  1241         SeqTwoByteStringSize(map->instance_type()); | 
|  1265 static inline void EvacuateShortcutCandidate(Map* map, |  1242     EvacuateObject<DATA_OBJECT, UNKNOWN_SIZE>(map, slot, object, object_size); | 
|  1266                                              HeapObject** slot, |  1243   } | 
|  1267                                              HeapObject* object) { |  1244  | 
|  1268   ASSERT(IsShortcutCandidate(map->instance_type())); |  1245  | 
|  1269  |  1246   static inline bool IsShortcutCandidate(int type) { | 
|  1270   if (ConsString::cast(object)->unchecked_second() == Heap::empty_string()) { |  1247     return ((type & kShortcutTypeMask) == kShortcutTypeTag); | 
|  1271     HeapObject* first = |  1248   } | 
|  1272         HeapObject::cast(ConsString::cast(object)->unchecked_first()); |  1249  | 
|  1273  |  1250   static inline void EvacuateShortcutCandidate(Map* map, | 
|  1274     *slot = first; |  1251                                                HeapObject** slot, | 
|  1275  |  1252                                                HeapObject* object) { | 
|  1276     if (!Heap::InNewSpace(first)) { |  1253     ASSERT(IsShortcutCandidate(map->instance_type())); | 
|  1277       object->set_map_word(MapWord::FromForwardingAddress(first)); |  1254  | 
 |  1255     if (ConsString::cast(object)->unchecked_second() == Heap::empty_string()) { | 
 |  1256       HeapObject* first = | 
 |  1257           HeapObject::cast(ConsString::cast(object)->unchecked_first()); | 
 |  1258  | 
 |  1259       *slot = first; | 
 |  1260  | 
 |  1261       if (!Heap::InNewSpace(first)) { | 
 |  1262         object->set_map_word(MapWord::FromForwardingAddress(first)); | 
 |  1263         return; | 
 |  1264       } | 
 |  1265  | 
 |  1266       MapWord first_word = first->map_word(); | 
 |  1267       if (first_word.IsForwardingAddress()) { | 
 |  1268         HeapObject* target = first_word.ToForwardingAddress(); | 
 |  1269  | 
 |  1270         *slot = target; | 
 |  1271         object->set_map_word(MapWord::FromForwardingAddress(target)); | 
 |  1272         return; | 
 |  1273       } | 
 |  1274  | 
 |  1275       Scavenge(first->map(), slot, first); | 
 |  1276       object->set_map_word(MapWord::FromForwardingAddress(*slot)); | 
|  1278       return; |  1277       return; | 
|  1279     } |  1278     } | 
|  1280  |  1279  | 
|  1281     MapWord first_word = first->map_word(); |  1280     int object_size = ConsString::kSize; | 
|  1282     if (first_word.IsForwardingAddress()) { |  1281     EvacuateObject<POINTER_OBJECT, SMALL>(map, slot, object, object_size); | 
|  1283       HeapObject* target = first_word.ToForwardingAddress(); |  1282   } | 
|  1284  |  1283  | 
|  1285       *slot = target; |  1284   template<ObjectContents object_contents> | 
|  1286       object->set_map_word(MapWord::FromForwardingAddress(target)); |  1285   class ObjectEvacuationStrategy { | 
|  1287       return; |  1286    public: | 
|  1288     } |  1287     template<int object_size> | 
|  1289  |  1288     static inline void VisitSpecialized(Map* map, | 
|  1290     first->map()->Scavenge(slot, first); |  1289                                         HeapObject** slot, | 
|  1291     object->set_map_word(MapWord::FromForwardingAddress(*slot)); |  1290                                         HeapObject* object) { | 
|  1292     return; |  1291       EvacuateObject<object_contents, SMALL>(map, slot, object, object_size); | 
|  1293   } |  1292     } | 
|  1294  |  1293  | 
|  1295   int object_size = ConsString::kSize; |  1294     static inline void Visit(Map* map, | 
|  1296   EvacuateObject<POINTER_OBJECT, SMALL>(map, slot, object, object_size); |  1295                              HeapObject** slot, | 
|  1297 } |  1296                              HeapObject* object) { | 
|  1298  |  1297       int object_size = map->instance_size(); | 
|  1299  |  1298       EvacuateObject<object_contents, SMALL>(map, slot, object, object_size); | 
|  1300 Scavenger Heap::GetScavenger(int instance_type, int instance_size) { |  1299     } | 
|  1301   if (instance_type < FIRST_NONSTRING_TYPE) { |  1300   }; | 
|  1302     switch (instance_type & kStringRepresentationMask) { |  1301  | 
|  1303       case kSeqStringTag: |  1302   typedef void (*Callback)(Map* map, HeapObject** slot, HeapObject* object); | 
|  1304         if ((instance_type & kStringEncodingMask) == kAsciiStringTag) { |  1303  | 
|  1305           return &EvacuateSeqAsciiString; |  1304   static VisitorDispatchTable<Callback> table_; | 
|  1306         } else { |  1305 }; | 
|  1307           return &EvacuateSeqTwoByteString; |  1306  | 
|  1308         } |  1307  | 
|  1309  |  1308 VisitorDispatchTable<ScavengingVisitor::Callback> ScavengingVisitor::table_; | 
|  1310       case kConsStringTag: |  | 
|  1311         if (IsShortcutCandidate(instance_type)) { |  | 
|  1312           return &EvacuateShortcutCandidate; |  | 
|  1313         } else { |  | 
|  1314           ASSERT(instance_size == ConsString::kSize); |  | 
|  1315           return GetScavengerForSize(ConsString::kSize, POINTER_OBJECT); |  | 
|  1316         } |  | 
|  1317  |  | 
|  1318       case kExternalStringTag: |  | 
|  1319         ASSERT(instance_size == ExternalString::kSize); |  | 
|  1320         return GetScavengerForSize(ExternalString::kSize, DATA_OBJECT); |  | 
|  1321     } |  | 
|  1322     UNREACHABLE(); |  | 
|  1323   } |  | 
|  1324  |  | 
|  1325   switch (instance_type) { |  | 
|  1326     case BYTE_ARRAY_TYPE: |  | 
|  1327       return reinterpret_cast<Scavenger>(&EvacuateByteArray); |  | 
|  1328  |  | 
|  1329     case FIXED_ARRAY_TYPE: |  | 
|  1330       return reinterpret_cast<Scavenger>(&EvacuateFixedArray); |  | 
|  1331  |  | 
|  1332     case JS_OBJECT_TYPE: |  | 
|  1333     case JS_CONTEXT_EXTENSION_OBJECT_TYPE: |  | 
|  1334     case JS_VALUE_TYPE: |  | 
|  1335     case JS_ARRAY_TYPE: |  | 
|  1336     case JS_REGEXP_TYPE: |  | 
|  1337     case JS_FUNCTION_TYPE: |  | 
|  1338     case JS_GLOBAL_PROXY_TYPE: |  | 
|  1339     case JS_GLOBAL_OBJECT_TYPE: |  | 
|  1340     case JS_BUILTINS_OBJECT_TYPE: |  | 
|  1341       return GetScavengerForSize(instance_size, POINTER_OBJECT); |  | 
|  1342  |  | 
|  1343     case ODDBALL_TYPE: |  | 
|  1344       return NULL; |  | 
|  1345  |  | 
|  1346     case PROXY_TYPE: |  | 
|  1347       return GetScavengerForSize(Proxy::kSize, DATA_OBJECT); |  | 
|  1348  |  | 
|  1349     case MAP_TYPE: |  | 
|  1350       return NULL; |  | 
|  1351  |  | 
|  1352     case CODE_TYPE: |  | 
|  1353       return NULL; |  | 
|  1354  |  | 
|  1355     case JS_GLOBAL_PROPERTY_CELL_TYPE: |  | 
|  1356       return NULL; |  | 
|  1357  |  | 
|  1358     case HEAP_NUMBER_TYPE: |  | 
|  1359     case FILLER_TYPE: |  | 
|  1360     case PIXEL_ARRAY_TYPE: |  | 
|  1361     case EXTERNAL_BYTE_ARRAY_TYPE: |  | 
|  1362     case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE: |  | 
|  1363     case EXTERNAL_SHORT_ARRAY_TYPE: |  | 
|  1364     case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE: |  | 
|  1365     case EXTERNAL_INT_ARRAY_TYPE: |  | 
|  1366     case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE: |  | 
|  1367     case EXTERNAL_FLOAT_ARRAY_TYPE: |  | 
|  1368       return GetScavengerForSize(instance_size, DATA_OBJECT); |  | 
|  1369  |  | 
|  1370     case SHARED_FUNCTION_INFO_TYPE: |  | 
|  1371       return GetScavengerForSize(SharedFunctionInfo::kAlignedSize, |  | 
|  1372                                  POINTER_OBJECT); |  | 
|  1373  |  | 
|  1374 #define MAKE_STRUCT_CASE(NAME, Name, name) \ |  | 
|  1375         case NAME##_TYPE: |  | 
|  1376       STRUCT_LIST(MAKE_STRUCT_CASE) |  | 
|  1377 #undef MAKE_STRUCT_CASE |  | 
|  1378           return GetScavengerForSize(instance_size, POINTER_OBJECT); |  | 
|  1379     default: |  | 
|  1380       UNREACHABLE(); |  | 
|  1381       return NULL; |  | 
|  1382   } |  | 
|  1383 } |  | 
|  1384  |  1309  | 
|  1385  |  1310  | 
|  1386 void Heap::ScavengeObjectSlow(HeapObject** p, HeapObject* object) { |  1311 void Heap::ScavengeObjectSlow(HeapObject** p, HeapObject* object) { | 
|  1387   ASSERT(InFromSpace(object)); |  1312   ASSERT(InFromSpace(object)); | 
|  1388   MapWord first_word = object->map_word(); |  1313   MapWord first_word = object->map_word(); | 
|  1389   ASSERT(!first_word.IsForwardingAddress()); |  1314   ASSERT(!first_word.IsForwardingAddress()); | 
|  1390   Map* map = first_word.ToMap(); |  1315   Map* map = first_word.ToMap(); | 
|  1391   map->Scavenge(p, object); |  1316   ScavengingVisitor::Scavenge(map, p, object); | 
|  1392 } |  1317 } | 
|  1393  |  1318  | 
|  1394  |  1319  | 
|  1395 void Heap::ScavengePointer(HeapObject** p) { |  1320 void Heap::ScavengePointer(HeapObject** p) { | 
|  1396   ScavengeObject(p, *p); |  1321   ScavengeObject(p, *p); | 
|  1397 } |  1322 } | 
|  1398  |  1323  | 
|  1399  |  1324  | 
|  1400 Object* Heap::AllocatePartialMap(InstanceType instance_type, |  1325 Object* Heap::AllocatePartialMap(InstanceType instance_type, | 
|  1401                                  int instance_size) { |  1326                                  int instance_size) { | 
|  1402   Object* result = AllocateRawMap(); |  1327   Object* result = AllocateRawMap(); | 
|  1403   if (result->IsFailure()) return result; |  1328   if (result->IsFailure()) return result; | 
|  1404  |  1329  | 
|  1405   // Map::cast cannot be used due to uninitialized map field. |  1330   // Map::cast cannot be used due to uninitialized map field. | 
|  1406   reinterpret_cast<Map*>(result)->set_map(raw_unchecked_meta_map()); |  1331   reinterpret_cast<Map*>(result)->set_map(raw_unchecked_meta_map()); | 
|  1407   reinterpret_cast<Map*>(result)->set_instance_type(instance_type); |  1332   reinterpret_cast<Map*>(result)->set_instance_type(instance_type); | 
|  1408   reinterpret_cast<Map*>(result)->set_instance_size(instance_size); |  1333   reinterpret_cast<Map*>(result)->set_instance_size(instance_size); | 
|  1409   reinterpret_cast<Map*>(result)-> |  1334   reinterpret_cast<Map*>(result)-> | 
|  1410       set_scavenger(GetScavenger(instance_type, instance_size)); |  1335       set_visitor_id( | 
 |  1336           StaticVisitorBase::GetVisitorId(instance_type, instance_size)); | 
|  1411   reinterpret_cast<Map*>(result)->set_inobject_properties(0); |  1337   reinterpret_cast<Map*>(result)->set_inobject_properties(0); | 
|  1412   reinterpret_cast<Map*>(result)->set_pre_allocated_property_fields(0); |  1338   reinterpret_cast<Map*>(result)->set_pre_allocated_property_fields(0); | 
|  1413   reinterpret_cast<Map*>(result)->set_unused_property_fields(0); |  1339   reinterpret_cast<Map*>(result)->set_unused_property_fields(0); | 
|  1414   reinterpret_cast<Map*>(result)->set_bit_field(0); |  1340   reinterpret_cast<Map*>(result)->set_bit_field(0); | 
|  1415   reinterpret_cast<Map*>(result)->set_bit_field2(0); |  1341   reinterpret_cast<Map*>(result)->set_bit_field2(0); | 
|  1416   return result; |  1342   return result; | 
|  1417 } |  1343 } | 
|  1418  |  1344  | 
|  1419  |  1345  | 
|  1420 Object* Heap::AllocateMap(InstanceType instance_type, int instance_size) { |  1346 Object* Heap::AllocateMap(InstanceType instance_type, int instance_size) { | 
|  1421   Object* result = AllocateRawMap(); |  1347   Object* result = AllocateRawMap(); | 
|  1422   if (result->IsFailure()) return result; |  1348   if (result->IsFailure()) return result; | 
|  1423  |  1349  | 
|  1424   Map* map = reinterpret_cast<Map*>(result); |  1350   Map* map = reinterpret_cast<Map*>(result); | 
|  1425   map->set_map(meta_map()); |  1351   map->set_map(meta_map()); | 
|  1426   map->set_instance_type(instance_type); |  1352   map->set_instance_type(instance_type); | 
|  1427   map->set_scavenger(GetScavenger(instance_type, instance_size)); |  1353   map->set_visitor_id( | 
 |  1354       StaticVisitorBase::GetVisitorId(instance_type, instance_size)); | 
|  1428   map->set_prototype(null_value()); |  1355   map->set_prototype(null_value()); | 
|  1429   map->set_constructor(null_value()); |  1356   map->set_constructor(null_value()); | 
|  1430   map->set_instance_size(instance_size); |  1357   map->set_instance_size(instance_size); | 
|  1431   map->set_inobject_properties(0); |  1358   map->set_inobject_properties(0); | 
|  1432   map->set_pre_allocated_property_fields(0); |  1359   map->set_pre_allocated_property_fields(0); | 
|  1433   map->set_instance_descriptors(empty_descriptor_array()); |  1360   map->set_instance_descriptors(empty_descriptor_array()); | 
|  1434   map->set_code_cache(empty_fixed_array()); |  1361   map->set_code_cache(empty_fixed_array()); | 
|  1435   map->set_unused_property_fields(0); |  1362   map->set_unused_property_fields(0); | 
|  1436   map->set_bit_field(0); |  1363   map->set_bit_field(0); | 
|  1437   map->set_bit_field2((1 << Map::kIsExtensible) | (1 << Map::kHasFastElements)); |  1364   map->set_bit_field2((1 << Map::kIsExtensible) | (1 << Map::kHasFastElements)); | 
| (...skipping 2729 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  4167   // call Heap::TearDown() to release allocated memory. |  4094   // call Heap::TearDown() to release allocated memory. | 
|  4168   // |  4095   // | 
|  4169   // If the heap is not yet configured (eg, through the API), configure it. |  4096   // If the heap is not yet configured (eg, through the API), configure it. | 
|  4170   // Configuration is based on the flags new-space-size (really the semispace |  4097   // Configuration is based on the flags new-space-size (really the semispace | 
|  4171   // size) and old-space-size if set or the initial values of semispace_size_ |  4098   // size) and old-space-size if set or the initial values of semispace_size_ | 
|  4172   // and old_generation_size_ otherwise. |  4099   // and old_generation_size_ otherwise. | 
|  4173   if (!heap_configured) { |  4100   if (!heap_configured) { | 
|  4174     if (!ConfigureHeapDefault()) return false; |  4101     if (!ConfigureHeapDefault()) return false; | 
|  4175   } |  4102   } | 
|  4176  |  4103  | 
 |  4104   ScavengingVisitor::Initialize(); | 
 |  4105   NewSpaceScavenger::Initialize(); | 
 |  4106   MarkCompactCollector::Initialize(); | 
 |  4107  | 
|  4177   // Setup memory allocator and reserve a chunk of memory for new |  4108   // Setup memory allocator and reserve a chunk of memory for new | 
|  4178   // space.  The chunk is double the size of the requested reserved |  4109   // space.  The chunk is double the size of the requested reserved | 
|  4179   // new space size to ensure that we can find a pair of semispaces that |  4110   // new space size to ensure that we can find a pair of semispaces that | 
|  4180   // are contiguous and aligned to their size. |  4111   // are contiguous and aligned to their size. | 
|  4181   if (!MemoryAllocator::Setup(MaxReserved())) return false; |  4112   if (!MemoryAllocator::Setup(MaxReserved())) return false; | 
|  4182   void* chunk = |  4113   void* chunk = | 
|  4183       MemoryAllocator::ReserveInitialChunk(4 * reserved_semispace_size_); |  4114       MemoryAllocator::ReserveInitialChunk(4 * reserved_semispace_size_); | 
|  4184   if (chunk == NULL) return false; |  4115   if (chunk == NULL) return false; | 
|  4185  |  4116  | 
|  4186   // Align the pair of semispaces to their size, which must be a power |  4117   // Align the pair of semispaces to their size, which must be a power | 
| (...skipping 664 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  4851         PrintF(MarkCompactCollector::HasCompacted() ? "mc" : "ms"); |  4782         PrintF(MarkCompactCollector::HasCompacted() ? "mc" : "ms"); | 
|  4852         break; |  4783         break; | 
|  4853       default: |  4784       default: | 
|  4854         UNREACHABLE(); |  4785         UNREACHABLE(); | 
|  4855     } |  4786     } | 
|  4856     PrintF(" "); |  4787     PrintF(" "); | 
|  4857  |  4788  | 
|  4858     PrintF("external=%d ", static_cast<int>(scopes_[Scope::EXTERNAL])); |  4789     PrintF("external=%d ", static_cast<int>(scopes_[Scope::EXTERNAL])); | 
|  4859     PrintF("mark=%d ", static_cast<int>(scopes_[Scope::MC_MARK])); |  4790     PrintF("mark=%d ", static_cast<int>(scopes_[Scope::MC_MARK])); | 
|  4860     PrintF("sweep=%d ", static_cast<int>(scopes_[Scope::MC_SWEEP])); |  4791     PrintF("sweep=%d ", static_cast<int>(scopes_[Scope::MC_SWEEP])); | 
 |  4792     PrintF("sweepns=%d ", static_cast<int>(scopes_[Scope::MC_SWEEP_NEWSPACE])); | 
|  4861     PrintF("compact=%d ", static_cast<int>(scopes_[Scope::MC_COMPACT])); |  4793     PrintF("compact=%d ", static_cast<int>(scopes_[Scope::MC_COMPACT])); | 
|  4862     PrintF("flushcode=%d ", static_cast<int>(scopes_[Scope::MC_FLUSH_CODE])); |  4794     PrintF("flushcode=%d ", static_cast<int>(scopes_[Scope::MC_FLUSH_CODE])); | 
|  4863  |  4795  | 
|  4864     PrintF("total_size_before=%d ", start_size_); |  4796     PrintF("total_size_before=%d ", start_size_); | 
|  4865     PrintF("total_size_after=%d ", Heap::SizeOfObjects()); |  4797     PrintF("total_size_after=%d ", Heap::SizeOfObjects()); | 
|  4866     PrintF("holes_size_before=%d ", in_free_list_or_wasted_before_gc_); |  4798     PrintF("holes_size_before=%d ", in_free_list_or_wasted_before_gc_); | 
|  4867     PrintF("holes_size_after=%d ", CountTotalHolesSize()); |  4799     PrintF("holes_size_after=%d ", CountTotalHolesSize()); | 
|  4868  |  4800  | 
|  4869     PrintF("allocated=%d ", allocated_since_last_gc_); |  4801     PrintF("allocated=%d ", allocated_since_last_gc_); | 
|  4870     PrintF("promoted=%d ", promoted_objects_size_); |  4802     PrintF("promoted=%d ", promoted_objects_size_); | 
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  5002 void ExternalStringTable::TearDown() { |  4934 void ExternalStringTable::TearDown() { | 
|  5003   new_space_strings_.Free(); |  4935   new_space_strings_.Free(); | 
|  5004   old_space_strings_.Free(); |  4936   old_space_strings_.Free(); | 
|  5005 } |  4937 } | 
|  5006  |  4938  | 
|  5007  |  4939  | 
|  5008 List<Object*> ExternalStringTable::new_space_strings_; |  4940 List<Object*> ExternalStringTable::new_space_strings_; | 
|  5009 List<Object*> ExternalStringTable::old_space_strings_; |  4941 List<Object*> ExternalStringTable::old_space_strings_; | 
|  5010  |  4942  | 
|  5011 } }  // namespace v8::internal |  4943 } }  // namespace v8::internal | 
| OLD | NEW |