| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 401 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 412 : MemoryChunk::IN_TO_SPACE)); | 412 : MemoryChunk::IN_TO_SPACE)); |
| 413 heap->incremental_marking()->SetNewSpacePageFlags(chunk); | 413 heap->incremental_marking()->SetNewSpacePageFlags(chunk); |
| 414 return static_cast<NewSpacePage*>(chunk); | 414 return static_cast<NewSpacePage*>(chunk); |
| 415 } | 415 } |
| 416 | 416 |
| 417 | 417 |
| 418 void NewSpacePage::InitializeAsAnchor(SemiSpace* semi_space) { | 418 void NewSpacePage::InitializeAsAnchor(SemiSpace* semi_space) { |
| 419 set_owner(semi_space); | 419 set_owner(semi_space); |
| 420 set_next_chunk(this); | 420 set_next_chunk(this); |
| 421 set_prev_chunk(this); | 421 set_prev_chunk(this); |
| 422 // Flags marks this invalid page as not being in new-space. |
| 423 // All real new-space pages will be in new-space. |
| 424 SetFlags(0, ~0); |
| 422 } | 425 } |
| 423 | 426 |
| 424 | 427 |
| 425 MemoryChunk* MemoryChunk::Initialize(Heap* heap, | 428 MemoryChunk* MemoryChunk::Initialize(Heap* heap, |
| 426 Address base, | 429 Address base, |
| 427 size_t size, | 430 size_t size, |
| 428 Executability executable, | 431 Executability executable, |
| 429 Space* owner) { | 432 Space* owner) { |
| 430 MemoryChunk* chunk = FromAddress(base); | 433 MemoryChunk* chunk = FromAddress(base); |
| 431 | 434 |
| (...skipping 525 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 957 if (!from_space_.Grow()) { | 960 if (!from_space_.Grow()) { |
| 958 // If we managed to grow to space but couldn't grow from space, | 961 // If we managed to grow to space but couldn't grow from space, |
| 959 // attempt to shrink to space. | 962 // attempt to shrink to space. |
| 960 if (!to_space_.ShrinkTo(from_space_.Capacity())) { | 963 if (!to_space_.ShrinkTo(from_space_.Capacity())) { |
| 961 // We are in an inconsistent state because we could not | 964 // We are in an inconsistent state because we could not |
| 962 // commit/uncommit memory from new space. | 965 // commit/uncommit memory from new space. |
| 963 V8::FatalProcessOutOfMemory("Failed to grow new space."); | 966 V8::FatalProcessOutOfMemory("Failed to grow new space."); |
| 964 } | 967 } |
| 965 } | 968 } |
| 966 } | 969 } |
| 967 allocation_info_.limit = to_space_.high(); | 970 allocation_info_.limit = to_space_.page_high(); |
| 968 ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); | 971 ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); |
| 969 } | 972 } |
| 970 | 973 |
| 971 | 974 |
| 972 void NewSpace::Shrink() { | 975 void NewSpace::Shrink() { |
| 973 int new_capacity = Max(InitialCapacity(), 2 * SizeAsInt()); | 976 int new_capacity = Max(InitialCapacity(), 2 * SizeAsInt()); |
| 974 int rounded_new_capacity = | 977 int rounded_new_capacity = |
| 975 RoundUp(new_capacity, static_cast<int>(OS::AllocateAlignment())); | 978 RoundUp(new_capacity, static_cast<int>(OS::AllocateAlignment())); |
| 976 if (rounded_new_capacity < Capacity() && | 979 if (rounded_new_capacity < Capacity() && |
| 977 to_space_.ShrinkTo(rounded_new_capacity)) { | 980 to_space_.ShrinkTo(rounded_new_capacity)) { |
| 978 // Only shrink from space if we managed to shrink to space. | 981 // Only shrink from space if we managed to shrink to space. |
| 979 if (!from_space_.ShrinkTo(rounded_new_capacity)) { | 982 if (!from_space_.ShrinkTo(rounded_new_capacity)) { |
| 980 // If we managed to shrink to space but couldn't shrink from | 983 // If we managed to shrink to space but couldn't shrink from |
| 981 // space, attempt to grow to space again. | 984 // space, attempt to grow to space again. |
| 982 if (!to_space_.GrowTo(from_space_.Capacity())) { | 985 if (!to_space_.GrowTo(from_space_.Capacity())) { |
| 983 // We are in an inconsistent state because we could not | 986 // We are in an inconsistent state because we could not |
| 984 // commit/uncommit memory from new space. | 987 // commit/uncommit memory from new space. |
| 985 V8::FatalProcessOutOfMemory("Failed to shrink new space."); | 988 V8::FatalProcessOutOfMemory("Failed to shrink new space."); |
| 986 } | 989 } |
| 987 } | 990 } |
| 988 } | 991 } |
| 989 allocation_info_.limit = to_space_.high(); | 992 allocation_info_.limit = to_space_.page_high(); |
| 993 ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); |
| 994 } |
| 995 |
| 996 |
| 997 void NewSpace::UpdateAllocationInfo() { |
| 998 allocation_info_.top = to_space_.page_low(); |
| 999 allocation_info_.limit = to_space_.page_high(); |
| 990 ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); | 1000 ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); |
| 991 } | 1001 } |
| 992 | 1002 |
| 993 | 1003 |
| 994 void NewSpace::ResetAllocationInfo() { | 1004 void NewSpace::ResetAllocationInfo() { |
| 995 to_space_.Reset(); | 1005 to_space_.Reset(); |
| 996 allocation_info_.top = to_space_.page_low(); | 1006 UpdateAllocationInfo(); |
| 997 allocation_info_.limit = to_space_.high(); | 1007 // Clear all mark-bits in the to-space. |
| 998 ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); | 1008 NewSpacePageIterator it(to_space_.space_low(), to_space_.space_high()); |
| 1009 while (it.has_next()) { |
| 1010 NewSpacePage* page = it.next(); |
| 1011 page->markbits()->Clear(); |
| 1012 } |
| 1013 } |
| 1014 |
| 1015 |
| 1016 bool NewSpace::AddFreshPage() { |
| 1017 Address top = allocation_info_.top; |
| 1018 if (top == NewSpacePage::FromLimit(top)->body()) { |
| 1019 // The current page is already empty. Don't try to make another. |
| 1020 |
| 1021 // We should only get here if someone asks to allocate more |
| 1022 // than what can be stored in a single page. |
| 1023 // TODO(gc): Change the limit on new-space allocation to prevent this |
| 1024 // from happening (all such allocations should go directly to LOSpace). |
| 1025 return false; |
| 1026 } |
| 1027 if (!to_space_.AdvancePage()) { |
| 1028 // Failed to get a new page in to-space. |
| 1029 return false; |
| 1030 } |
| 1031 // Clear remainder of current page. |
| 1032 int remaining_in_page = |
| 1033 static_cast<int>(NewSpacePage::FromLimit(top)->body_limit() - top); |
| 1034 heap()->CreateFillerObjectAt(top, remaining_in_page); |
| 1035 UpdateAllocationInfo(); |
| 1036 return true; |
| 999 } | 1037 } |
| 1000 | 1038 |
| 1001 | 1039 |
| 1002 #ifdef DEBUG | 1040 #ifdef DEBUG |
| 1003 // We do not use the SemispaceIterator because verification doesn't assume | 1041 // We do not use the SemiSpaceIterator because verification doesn't assume |
| 1004 // that it works (it depends on the invariants we are checking). | 1042 // that it works (it depends on the invariants we are checking). |
| 1005 void NewSpace::Verify() { | 1043 void NewSpace::Verify() { |
| 1006 // The allocation pointer should be in the space or at the very end. | 1044 // The allocation pointer should be in the space or at the very end. |
| 1007 ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); | 1045 ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); |
| 1008 | 1046 |
| 1009 // There should be objects packed in from the low address up to the | 1047 // There should be objects packed in from the low address up to the |
| 1010 // allocation pointer. | 1048 // allocation pointer. |
| 1011 Address current = to_space_.low(); | 1049 NewSpacePage* page = to_space_.first_page(); |
| 1012 while (current < top()) { | 1050 Address current = page->body(); |
| 1051 CHECK_EQ(current, to_space_.space_low()); |
| 1052 CHECK(end_page->ContainsLimit(top())); |
| 1053 |
| 1054 while (current != top()) { |
| 1055 if (current == page->body_limit()) { |
| 1056 // At end of page, switch to next page. |
| 1057 page = page->next_page(); |
| 1058 // Next page should be valid. |
| 1059 CHECK(!page->is_anchor()); |
| 1060 current = page->body(); |
| 1061 } |
| 1062 // The allocation pointer should not be in the middle of an object. |
| 1063 CHECK(!page->ContainsLimit(top()) || current < top()); |
| 1064 |
| 1013 HeapObject* object = HeapObject::FromAddress(current); | 1065 HeapObject* object = HeapObject::FromAddress(current); |
| 1014 | 1066 |
| 1015 // The first word should be a map, and we expect all map pointers to | 1067 // The first word should be a map, and we expect all map pointers to |
| 1016 // be in map space. | 1068 // be in map space. |
| 1017 Map* map = object->map(); | 1069 Map* map = object->map(); |
| 1018 CHECK(map->IsMap()); | 1070 CHECK(map->IsMap()); |
| 1019 CHECK(heap()->map_space()->Contains(map)); | 1071 CHECK(heap()->map_space()->Contains(map)); |
| 1020 | 1072 |
| 1021 // The object should not be code or a map. | 1073 // The object should not be code or a map. |
| 1022 CHECK(!object->IsMap()); | 1074 CHECK(!object->IsMap()); |
| 1023 CHECK(!object->IsCode()); | 1075 CHECK(!object->IsCode()); |
| 1024 | 1076 |
| 1025 // The object itself should look OK. | 1077 // The object itself should look OK. |
| 1026 object->Verify(); | 1078 object->Verify(); |
| 1027 | 1079 |
| 1028 // All the interior pointers should be contained in the heap. | 1080 // All the interior pointers should be contained in the heap. |
| 1029 VerifyPointersVisitor visitor; | 1081 VerifyPointersVisitor visitor; |
| 1030 int size = object->Size(); | 1082 int size = object->Size(); |
| 1031 object->IterateBody(map->instance_type(), size, &visitor); | 1083 object->IterateBody(map->instance_type(), size, &visitor); |
| 1032 | 1084 |
| 1033 current += size; | 1085 current += size; |
| 1034 } | 1086 } |
| 1035 | 1087 |
| 1036 // The allocation pointer should not be in the middle of an object. | |
| 1037 ASSERT(current == top()); | |
| 1038 | |
| 1039 // Check semi-spaces. | 1088 // Check semi-spaces. |
| 1040 ASSERT_EQ(from_space_.id(), kFromSpace); | 1089 ASSERT_EQ(from_space_.id(), kFromSpace); |
| 1041 ASSERT_EQ(to_space_.id(), kToSpace); | 1090 ASSERT_EQ(to_space_.id(), kToSpace); |
| 1042 from_space_.Verify(); | 1091 from_space_.Verify(); |
| 1043 to_space_.Verify(); | 1092 to_space_.Verify(); |
| 1044 } | 1093 } |
| 1045 #endif | 1094 #endif |
| 1046 | 1095 |
| 1047 | 1096 |
| 1048 bool SemiSpace::Commit() { | 1097 bool SemiSpace::Commit() { |
| 1049 ASSERT(!is_committed()); | 1098 ASSERT(!is_committed()); |
| 1099 // TODO(gc): Rewrite completely when switching to n-page new-space. |
| 1100 // Create one page. |
| 1101 int pagesize = Page::kPageSize; |
| 1050 if (!heap()->isolate()->memory_allocator()->CommitBlock( | 1102 if (!heap()->isolate()->memory_allocator()->CommitBlock( |
| 1051 start_, capacity_, executable())) { | 1103 start_, pagesize, executable())) { |
| 1052 return false; | 1104 return false; |
| 1053 } | 1105 } |
| 1054 committed_ = true; | |
| 1055 // TODO(gc): When more than one page is present, initialize and | |
| 1056 // chain them all. | |
| 1057 NewSpacePage* page = NewSpacePage::Initialize(heap(), start_, this); | 1106 NewSpacePage* page = NewSpacePage::Initialize(heap(), start_, this); |
| 1058 page->InsertAfter(&anchor_); | 1107 page->InsertAfter(&anchor_); |
| 1059 current_page_ = anchor_.next_page(); | 1108 |
| 1109 // Maybe create a second. |
| 1110 if (capacity_ >= 2 * pagesize) { |
| 1111 Address last_page_address = |
| 1112 start_ + ((capacity_ - pagesize) & ~Page::kPageAlignmentMask); |
| 1113 if (heap()->isolate()->memory_allocator()->CommitBlock( |
| 1114 last_page_address, pagesize, executable())) { |
| 1115 NewSpacePage* last_page = NewSpacePage::Initialize(heap(), |
| 1116 last_page_address, |
| 1117 this); |
| 1118 last_page->InsertAfter(page); |
| 1119 } else { |
| 1120 UNREACHABLE(); // TODO(gc): Don't rely on this. Splitting the commit |
| 1121 // is only temporary. |
| 1122 } |
| 1123 } |
| 1124 |
| 1125 committed_ = true; |
| 1126 Reset(); |
| 1060 return true; | 1127 return true; |
| 1061 } | 1128 } |
| 1062 | 1129 |
| 1063 | 1130 |
| 1064 bool SemiSpace::Uncommit() { | 1131 bool SemiSpace::Uncommit() { |
| 1065 ASSERT(is_committed()); | 1132 ASSERT(is_committed()); |
| 1066 if (!heap()->isolate()->memory_allocator()->UncommitBlock( | 1133 // TODO(gc): Rewrite completely when switching to n-page new-space. |
| 1067 start_, capacity_)) { | 1134 NewSpacePage* last_page = anchor()->prev_page(); |
| 1068 return false; | 1135 while (last_page != anchor()) { |
| 1136 NewSpacePage* temp_page = last_page->prev_page(); |
| 1137 last_page->Unlink(); |
| 1138 if (!heap()->isolate()->memory_allocator()->UncommitBlock( |
| 1139 last_page->address(), Page::kPageSize)) { |
| 1140 return false; |
| 1141 } |
| 1142 last_page = temp_page; |
| 1069 } | 1143 } |
| 1144 |
| 1070 committed_ = false; | 1145 committed_ = false; |
| 1071 return true; | 1146 return true; |
| 1072 } | 1147 } |
| 1073 | 1148 |
| 1074 | 1149 |
| 1075 void SemiSpace::Reset() { | 1150 void SemiSpace::Reset() { |
| 1076 ASSERT(anchor_.next_page() != &anchor_); | 1151 ASSERT(anchor_.next_page() != &anchor_); |
| 1077 current_page_ = anchor_.next_page(); | 1152 current_page_ = anchor_.next_page(); |
| 1078 } | 1153 } |
| 1079 | 1154 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1105 bool SemiSpace::Setup(Address start, | 1180 bool SemiSpace::Setup(Address start, |
| 1106 int initial_capacity, | 1181 int initial_capacity, |
| 1107 int maximum_capacity) { | 1182 int maximum_capacity) { |
| 1108 // Creates a space in the young generation. The constructor does not | 1183 // Creates a space in the young generation. The constructor does not |
| 1109 // allocate memory from the OS. A SemiSpace is given a contiguous chunk of | 1184 // allocate memory from the OS. A SemiSpace is given a contiguous chunk of |
| 1110 // memory of size 'capacity' when set up, and does not grow or shrink | 1185 // memory of size 'capacity' when set up, and does not grow or shrink |
| 1111 // otherwise. In the mark-compact collector, the memory region of the from | 1186 // otherwise. In the mark-compact collector, the memory region of the from |
| 1112 // space is used as the marking stack. It requires contiguous memory | 1187 // space is used as the marking stack. It requires contiguous memory |
| 1113 // addresses. | 1188 // addresses. |
| 1114 ASSERT(maximum_capacity >= Page::kPageSize); | 1189 ASSERT(maximum_capacity >= Page::kPageSize); |
| 1115 if (initial_capacity < Page::kPageSize) { | 1190 initial_capacity_ = initial_capacity & ~Page::kPageAlignmentMask; |
| 1116 initial_capacity = Page::kPageSize; | |
| 1117 } else { | |
| 1118 initial_capacity &= ~Page::kPageAlignmentMask; | |
| 1119 } | |
| 1120 initial_capacity_ = initial_capacity; | |
| 1121 capacity_ = initial_capacity; | 1191 capacity_ = initial_capacity; |
| 1122 maximum_capacity_ = maximum_capacity; | 1192 maximum_capacity_ = maximum_capacity; |
| 1123 committed_ = false; | 1193 committed_ = false; |
| 1124 start_ = start; | 1194 start_ = start; |
| 1125 address_mask_ = ~(maximum_capacity - 1); | 1195 address_mask_ = ~(maximum_capacity - 1); |
| 1126 object_mask_ = address_mask_ | kHeapObjectTagMask; | 1196 object_mask_ = address_mask_ | kHeapObjectTagMask; |
| 1127 object_expected_ = reinterpret_cast<uintptr_t>(start) | kHeapObjectTag; | 1197 object_expected_ = reinterpret_cast<uintptr_t>(start) | kHeapObjectTag; |
| 1128 age_mark_ = start_; | 1198 age_mark_ = start_; |
| 1129 | 1199 |
| 1130 return Commit(); | 1200 return Commit(); |
| 1131 } | 1201 } |
| 1132 | 1202 |
| 1133 | 1203 |
| 1134 void SemiSpace::TearDown() { | 1204 void SemiSpace::TearDown() { |
| 1135 start_ = NULL; | 1205 start_ = NULL; |
| 1136 capacity_ = 0; | 1206 capacity_ = 0; |
| 1137 } | 1207 } |
| 1138 | 1208 |
| 1139 | 1209 |
| 1140 bool SemiSpace::Grow() { | 1210 bool SemiSpace::Grow() { |
| 1141 return false; // TODO(gc): Temporary hack while semispaces are only one page. | 1211 return false; // TODO(gc): Temporary hack while semispaces are only one page. |
| 1142 // Double the semispace size but only up to maximum capacity. | 1212 // Double the semispace size but only up to maximum capacity. |
| 1143 int maximum_extra = maximum_capacity_ - capacity_; | 1213 int maximum_extra = maximum_capacity_ - capacity_; |
| 1144 int extra = Min(RoundUp(capacity_, static_cast<int>(OS::AllocateAlignment())), | 1214 int extra = Min(RoundUp(capacity_, static_cast<int>(OS::AllocateAlignment())), |
| 1145 maximum_extra); | 1215 maximum_extra); |
| 1146 if (!heap()->isolate()->memory_allocator()->CommitBlock( | 1216 if (!heap()->isolate()->memory_allocator()->CommitBlock( |
| 1147 high(), extra, executable())) { | 1217 space_high(), extra, executable())) { |
| 1148 return false; | 1218 return false; |
| 1149 } | 1219 } |
| 1150 capacity_ += extra; | 1220 capacity_ += extra; |
| 1151 return true; | 1221 return true; |
| 1152 } | 1222 } |
| 1153 | 1223 |
| 1154 | 1224 |
| 1155 bool SemiSpace::GrowTo(int new_capacity) { | 1225 bool SemiSpace::GrowTo(int new_capacity) { |
| 1156 return false; // TODO(gc): Temporary hack while semispaces are only one page. | 1226 return false; // TODO(gc): Temporary hack while semispaces are only one page. |
| 1157 ASSERT(new_capacity <= maximum_capacity_); | 1227 ASSERT(new_capacity <= maximum_capacity_); |
| 1158 ASSERT(new_capacity > capacity_); | 1228 ASSERT(new_capacity > capacity_); |
| 1159 size_t delta = new_capacity - capacity_; | 1229 size_t delta = new_capacity - capacity_; |
| 1160 ASSERT(IsAligned(delta, OS::AllocateAlignment())); | 1230 ASSERT(IsAligned(delta, OS::AllocateAlignment())); |
| 1161 if (!heap()->isolate()->memory_allocator()->CommitBlock( | 1231 if (!heap()->isolate()->memory_allocator()->CommitBlock( |
| 1162 high(), delta, executable())) { | 1232 space_high(), delta, executable())) { |
| 1163 return false; | 1233 return false; |
| 1164 } | 1234 } |
| 1165 capacity_ = new_capacity; | 1235 capacity_ = new_capacity; |
| 1166 return true; | 1236 return true; |
| 1167 } | 1237 } |
| 1168 | 1238 |
| 1169 | 1239 |
| 1170 bool SemiSpace::ShrinkTo(int new_capacity) { | 1240 bool SemiSpace::ShrinkTo(int new_capacity) { |
| 1171 return false; // TODO(gc): Temporary hack while semispaces are only one page. | 1241 return false; // TODO(gc): Temporary hack while semispaces are only one page. |
| 1172 ASSERT(new_capacity >= initial_capacity_); | 1242 ASSERT(new_capacity >= initial_capacity_); |
| 1173 ASSERT(new_capacity < capacity_); | 1243 ASSERT(new_capacity < capacity_); |
| 1174 size_t delta = capacity_ - new_capacity; | 1244 size_t delta = capacity_ - new_capacity; |
| 1175 ASSERT(IsAligned(delta, OS::AllocateAlignment())); | 1245 ASSERT(IsAligned(delta, OS::AllocateAlignment())); |
| 1176 if (!heap()->isolate()->memory_allocator()->UncommitBlock( | 1246 if (!heap()->isolate()->memory_allocator()->UncommitBlock( |
| 1177 high() - delta, delta)) { | 1247 space_high() - delta, delta)) { |
| 1178 return false; | 1248 return false; |
| 1179 } | 1249 } |
| 1180 capacity_ = new_capacity; | 1250 capacity_ = new_capacity; |
| 1181 return true; | 1251 return true; |
| 1182 } | 1252 } |
| 1183 | 1253 |
| 1184 | 1254 |
| 1185 void SemiSpace::FlipPages(intptr_t flags, intptr_t mask) { | 1255 void SemiSpace::FlipPages(intptr_t flags, intptr_t mask) { |
| 1186 anchor_.set_owner(this); | 1256 anchor_.set_owner(this); |
| 1187 // Fixup back-pointers to anchor. Address of anchor changes | 1257 // Fixup back-pointers to anchor. Address of anchor changes |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1221 CHECK(page->semi_space() == this); | 1291 CHECK(page->semi_space() == this); |
| 1222 CHECK(page->InNewSpace()); | 1292 CHECK(page->InNewSpace()); |
| 1223 CHECK(page->IsFlagSet(is_from_space ? MemoryChunk::IN_FROM_SPACE | 1293 CHECK(page->IsFlagSet(is_from_space ? MemoryChunk::IN_FROM_SPACE |
| 1224 : MemoryChunk::IN_TO_SPACE)); | 1294 : MemoryChunk::IN_TO_SPACE)); |
| 1225 CHECK(!page->IsFlagSet(is_from_space ? MemoryChunk::IN_TO_SPACE | 1295 CHECK(!page->IsFlagSet(is_from_space ? MemoryChunk::IN_TO_SPACE |
| 1226 : MemoryChunk::IN_FROM_SPACE)); | 1296 : MemoryChunk::IN_FROM_SPACE)); |
| 1227 CHECK(page->prev_page()->next_page() == page); | 1297 CHECK(page->prev_page()->next_page() == page); |
| 1228 page = page->next_page(); | 1298 page = page->next_page(); |
| 1229 } | 1299 } |
| 1230 } | 1300 } |
| 1301 |
| 1302 |
| 1303 void SemiSpace::ValidateRange(Address start, Address end) { |
| 1304 // Addresses belong to same semi-space |
| 1305 NewSpacePage* page = NewSpacePage::FromAddress(start); |
| 1306 NewSpacePage* end_page = NewSpacePage::FromLimit(end); |
| 1307 SemiSpace* space = page->semi_space(); |
| 1308 CHECK_EQ(space, end_page->semi_space()); |
| 1309 // Start address is before end address, either on same page, |
| 1310 // or end address is on a later page in the linked list of |
| 1311 // semi-space pages. |
| 1312 if (page == end_page) { |
| 1313 CHECK(start <= end); |
| 1314 } else { |
| 1315 while (page != end_page) { |
| 1316 page = page->next_page(); |
| 1317 CHECK_NE(page, space->anchor()); |
| 1318 } |
| 1319 } |
| 1320 } |
| 1231 #endif | 1321 #endif |
| 1232 | 1322 |
| 1233 | 1323 |
| 1234 // ----------------------------------------------------------------------------- | 1324 // ----------------------------------------------------------------------------- |
| 1235 // SemiSpaceIterator implementation. | 1325 // SemiSpaceIterator implementation. |
| 1236 SemiSpaceIterator::SemiSpaceIterator(NewSpace* space) { | 1326 SemiSpaceIterator::SemiSpaceIterator(NewSpace* space) { |
| 1237 Initialize(space, space->bottom(), space->top(), NULL); | 1327 Initialize(space->bottom(), space->top(), NULL); |
| 1238 } | 1328 } |
| 1239 | 1329 |
| 1240 | 1330 |
| 1241 SemiSpaceIterator::SemiSpaceIterator(NewSpace* space, | 1331 SemiSpaceIterator::SemiSpaceIterator(NewSpace* space, |
| 1242 HeapObjectCallback size_func) { | 1332 HeapObjectCallback size_func) { |
| 1243 Initialize(space, space->bottom(), space->top(), size_func); | 1333 Initialize(space->bottom(), space->top(), size_func); |
| 1244 } | 1334 } |
| 1245 | 1335 |
| 1246 | 1336 |
| 1247 SemiSpaceIterator::SemiSpaceIterator(NewSpace* space, Address start) { | 1337 SemiSpaceIterator::SemiSpaceIterator(NewSpace* space, Address start) { |
| 1248 Initialize(space, start, space->top(), NULL); | 1338 Initialize(start, space->top(), NULL); |
| 1249 } | 1339 } |
| 1250 | 1340 |
| 1251 | 1341 |
| 1252 void SemiSpaceIterator::Initialize(NewSpace* space, | 1342 SemiSpaceIterator::SemiSpaceIterator(Address from, Address to) { |
| 1253 Address start, | 1343 Initialize(from, to, NULL); |
| 1344 } |
| 1345 |
| 1346 |
| 1347 void SemiSpaceIterator::Initialize(Address start, |
| 1254 Address end, | 1348 Address end, |
| 1255 HeapObjectCallback size_func) { | 1349 HeapObjectCallback size_func) { |
| 1256 ASSERT(space->ToSpaceContains(start)); | 1350 #ifdef DEBUG |
| 1257 ASSERT(space->ToSpaceLow() <= end | 1351 SemiSpace::ValidateRange(start, end); |
| 1258 && end <= space->ToSpaceHigh()); | 1352 #endif |
| 1259 space_ = &space->to_space_; | 1353 NewSpacePage* page = NewSpacePage::FromAddress(start); |
| 1260 current_ = start; | 1354 current_ = start; |
| 1261 NewSpacePage* page = NewSpacePage::FromAddress(start); | |
| 1262 current_page_limit_ = page->body() + page->body_size(); | |
| 1263 if (current_page_limit_ > end) current_page_limit_ = end; | |
| 1264 limit_ = end; | 1355 limit_ = end; |
| 1356 current_page_limit_ = page->body_limit(); |
| 1265 size_func_ = size_func; | 1357 size_func_ = size_func; |
| 1266 } | 1358 } |
| 1267 | 1359 |
| 1268 | 1360 |
| 1269 #ifdef DEBUG | 1361 #ifdef DEBUG |
| 1270 // heap_histograms is shared, always clear it before using it. | 1362 // heap_histograms is shared, always clear it before using it. |
| 1271 static void ClearHistograms() { | 1363 static void ClearHistograms() { |
| 1272 Isolate* isolate = Isolate::Current(); | 1364 Isolate* isolate = Isolate::Current(); |
| 1273 // We reset the name each time, though it hasn't changed. | 1365 // We reset the name each time, though it hasn't changed. |
| 1274 #define DEF_TYPE_NAME(name) isolate->heap_histograms()[name].set_name(#name); | 1366 #define DEF_TYPE_NAME(name) isolate->heap_histograms()[name].set_name(#name); |
| (...skipping 1077 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2352 for (HeapObject* obj = obj_it.Next(); obj != NULL; obj = obj_it.Next()) { | 2444 for (HeapObject* obj = obj_it.Next(); obj != NULL; obj = obj_it.Next()) { |
| 2353 if (obj->IsCode()) { | 2445 if (obj->IsCode()) { |
| 2354 Code* code = Code::cast(obj); | 2446 Code* code = Code::cast(obj); |
| 2355 isolate->code_kind_statistics()[code->kind()] += code->Size(); | 2447 isolate->code_kind_statistics()[code->kind()] += code->Size(); |
| 2356 } | 2448 } |
| 2357 } | 2449 } |
| 2358 } | 2450 } |
| 2359 #endif // DEBUG | 2451 #endif // DEBUG |
| 2360 | 2452 |
| 2361 } } // namespace v8::internal | 2453 } } // namespace v8::internal |
| OLD | NEW |