| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 43 #include "scanner-base.h" | 43 #include "scanner-base.h" |
| 44 #include "scopeinfo.h" | 44 #include "scopeinfo.h" |
| 45 #include "snapshot.h" | 45 #include "snapshot.h" |
| 46 #include "v8threads.h" | 46 #include "v8threads.h" |
| 47 #include "vm-state-inl.h" | 47 #include "vm-state-inl.h" |
| 48 #if V8_TARGET_ARCH_ARM && !V8_INTERPRETED_REGEXP | 48 #if V8_TARGET_ARCH_ARM && !V8_INTERPRETED_REGEXP |
| 49 #include "regexp-macro-assembler.h" | 49 #include "regexp-macro-assembler.h" |
| 50 #include "arm/regexp-macro-assembler-arm.h" | 50 #include "arm/regexp-macro-assembler-arm.h" |
| 51 #endif | 51 #endif |
| 52 | 52 |
| 53 | |
| 54 namespace v8 { | 53 namespace v8 { |
| 55 namespace internal { | 54 namespace internal { |
| 56 | 55 |
| 57 | 56 |
| 58 String* Heap::hidden_symbol_; | |
| 59 Object* Heap::roots_[Heap::kRootListLength]; | |
| 60 Object* Heap::global_contexts_list_; | |
| 61 | |
| 62 | |
| 63 NewSpace Heap::new_space_; | |
| 64 OldSpace* Heap::old_pointer_space_ = NULL; | |
| 65 OldSpace* Heap::old_data_space_ = NULL; | |
| 66 OldSpace* Heap::code_space_ = NULL; | |
| 67 MapSpace* Heap::map_space_ = NULL; | |
| 68 CellSpace* Heap::cell_space_ = NULL; | |
| 69 LargeObjectSpace* Heap::lo_space_ = NULL; | |
| 70 | |
| 71 static const intptr_t kMinimumPromotionLimit = 2 * MB; | 57 static const intptr_t kMinimumPromotionLimit = 2 * MB; |
| 72 static const intptr_t kMinimumAllocationLimit = 8 * MB; | 58 static const intptr_t kMinimumAllocationLimit = 8 * MB; |
| 73 | 59 |
| 74 intptr_t Heap::old_gen_promotion_limit_ = kMinimumPromotionLimit; | |
| 75 intptr_t Heap::old_gen_allocation_limit_ = kMinimumAllocationLimit; | |
| 76 | 60 |
| 77 int Heap::old_gen_exhausted_ = false; | 61 static Mutex* gc_initializer_mutex = OS::CreateMutex(); |
| 78 | 62 |
| 79 int Heap::amount_of_external_allocated_memory_ = 0; | |
| 80 int Heap::amount_of_external_allocated_memory_at_last_global_gc_ = 0; | |
| 81 | 63 |
| 64 Heap::Heap() |
| 65 : isolate_(NULL), |
| 82 // semispace_size_ should be a power of 2 and old_generation_size_ should be | 66 // semispace_size_ should be a power of 2 and old_generation_size_ should be |
| 83 // a multiple of Page::kPageSize. | 67 // a multiple of Page::kPageSize. |
| 84 #if defined(ANDROID) | 68 #if defined(ANDROID) |
| 85 static const int default_max_semispace_size_ = 2*MB; | 69 reserved_semispace_size_(2*MB), |
| 86 intptr_t Heap::max_old_generation_size_ = 192*MB; | 70 max_semispace_size_(2*MB), |
| 87 int Heap::initial_semispace_size_ = 128*KB; | 71 initial_semispace_size_(128*KB), |
| 88 intptr_t Heap::code_range_size_ = 0; | 72 max_old_generation_size_(192*MB), |
| 89 intptr_t Heap::max_executable_size_ = max_old_generation_size_; | 73 max_executable_size_(max_old_generation_size_), |
| 74 code_range_size_(0), |
| 90 #elif defined(V8_TARGET_ARCH_X64) | 75 #elif defined(V8_TARGET_ARCH_X64) |
| 91 static const int default_max_semispace_size_ = 16*MB; | 76 reserved_semispace_size_(16*MB), |
| 92 intptr_t Heap::max_old_generation_size_ = 1*GB; | 77 max_semispace_size_(16*MB), |
| 93 int Heap::initial_semispace_size_ = 1*MB; | 78 initial_semispace_size_(1*MB), |
| 94 intptr_t Heap::code_range_size_ = 512*MB; | 79 max_old_generation_size_(1*GB), |
| 95 intptr_t Heap::max_executable_size_ = 256*MB; | 80 max_executable_size_(256*MB), |
| 81 code_range_size_(512*MB), |
| 96 #else | 82 #else |
| 97 static const int default_max_semispace_size_ = 8*MB; | 83 reserved_semispace_size_(8*MB), |
| 98 intptr_t Heap::max_old_generation_size_ = 512*MB; | 84 max_semispace_size_(8*MB), |
| 99 int Heap::initial_semispace_size_ = 512*KB; | 85 initial_semispace_size_(512*KB), |
| 100 intptr_t Heap::code_range_size_ = 0; | 86 max_old_generation_size_(512*MB), |
| 101 intptr_t Heap::max_executable_size_ = 128*MB; | 87 max_executable_size_(128*MB), |
| 88 code_range_size_(0), |
| 89 #endif |
| 90 // Variables set based on semispace_size_ and old_generation_size_ in |
| 91 // ConfigureHeap (survived_since_last_expansion_, external_allocation_limit_) |
| 92 // Will be 4 * reserved_semispace_size_ to ensure that young |
| 93 // generation can be aligned to its size. |
| 94 survived_since_last_expansion_(0), |
| 95 always_allocate_scope_depth_(0), |
| 96 linear_allocation_scope_depth_(0), |
| 97 contexts_disposed_(0), |
| 98 new_space_(this), |
| 99 old_pointer_space_(NULL), |
| 100 old_data_space_(NULL), |
| 101 code_space_(NULL), |
| 102 map_space_(NULL), |
| 103 cell_space_(NULL), |
| 104 lo_space_(NULL), |
| 105 gc_state_(NOT_IN_GC), |
| 106 mc_count_(0), |
| 107 ms_count_(0), |
| 108 gc_count_(0), |
| 109 unflattened_strings_length_(0), |
| 110 #ifdef DEBUG |
| 111 allocation_allowed_(true), |
| 112 allocation_timeout_(0), |
| 113 disallow_allocation_failure_(false), |
| 114 debug_utils_(NULL), |
| 115 #endif // DEBUG |
| 116 old_gen_promotion_limit_(kMinimumPromotionLimit), |
| 117 old_gen_allocation_limit_(kMinimumAllocationLimit), |
| 118 external_allocation_limit_(0), |
| 119 amount_of_external_allocated_memory_(0), |
| 120 amount_of_external_allocated_memory_at_last_global_gc_(0), |
| 121 old_gen_exhausted_(false), |
| 122 hidden_symbol_(NULL), |
| 123 global_gc_prologue_callback_(NULL), |
| 124 global_gc_epilogue_callback_(NULL), |
| 125 gc_safe_size_of_old_object_(NULL), |
| 126 tracer_(NULL), |
| 127 young_survivors_after_last_gc_(0), |
| 128 high_survival_rate_period_length_(0), |
| 129 survival_rate_(0), |
| 130 previous_survival_rate_trend_(Heap::STABLE), |
| 131 survival_rate_trend_(Heap::STABLE), |
| 132 max_gc_pause_(0), |
| 133 max_alive_after_gc_(0), |
| 134 min_in_mutator_(kMaxInt), |
| 135 alive_after_last_gc_(0), |
| 136 last_gc_end_timestamp_(0.0), |
| 137 page_watermark_invalidated_mark_(1 << Page::WATERMARK_INVALIDATED), |
| 138 number_idle_notifications_(0), |
| 139 last_idle_notification_gc_count_(0), |
| 140 last_idle_notification_gc_count_init_(false), |
| 141 configured_(false), |
| 142 is_safe_to_read_maps_(true) { |
| 143 // Allow build-time customization of the max semispace size. Building |
| 144 // V8 with snapshots and a non-default max semispace size is much |
| 145 // easier if you can define it as part of the build environment. |
| 146 #if defined(V8_MAX_SEMISPACE_SIZE) |
| 147 max_semispace_size_ = reserved_semispace_size_ = V8_MAX_SEMISPACE_SIZE; |
| 102 #endif | 148 #endif |
| 103 | 149 |
| 104 // Allow build-time customization of the max semispace size. Building | 150 memset(roots_, 0, sizeof(roots_[0]) * kRootListLength); |
| 105 // V8 with snapshots and a non-default max semispace size is much | 151 global_contexts_list_ = NULL; |
| 106 // easier if you can define it as part of the build environment. | 152 mark_compact_collector_.heap_ = this; |
| 107 #if defined(V8_MAX_SEMISPACE_SIZE) | 153 external_string_table_.heap_ = this; |
| 108 int Heap::max_semispace_size_ = V8_MAX_SEMISPACE_SIZE; | 154 } |
| 109 #else | |
| 110 int Heap::max_semispace_size_ = default_max_semispace_size_; | |
| 111 #endif | |
| 112 | 155 |
| 113 // The snapshot semispace size will be the default semispace size if | |
| 114 // snapshotting is used and will be the requested semispace size as | |
| 115 // set up by ConfigureHeap otherwise. | |
| 116 int Heap::reserved_semispace_size_ = Heap::max_semispace_size_; | |
| 117 | |
| 118 List<Heap::GCPrologueCallbackPair> Heap::gc_prologue_callbacks_; | |
| 119 List<Heap::GCEpilogueCallbackPair> Heap::gc_epilogue_callbacks_; | |
| 120 | |
| 121 GCCallback Heap::global_gc_prologue_callback_ = NULL; | |
| 122 GCCallback Heap::global_gc_epilogue_callback_ = NULL; | |
| 123 HeapObjectCallback Heap::gc_safe_size_of_old_object_ = NULL; | |
| 124 | |
| 125 // Variables set based on semispace_size_ and old_generation_size_ in | |
| 126 // ConfigureHeap. | |
| 127 | |
| 128 // Will be 4 * reserved_semispace_size_ to ensure that young | |
| 129 // generation can be aligned to its size. | |
| 130 int Heap::survived_since_last_expansion_ = 0; | |
| 131 intptr_t Heap::external_allocation_limit_ = 0; | |
| 132 | |
| 133 Heap::HeapState Heap::gc_state_ = NOT_IN_GC; | |
| 134 | |
| 135 int Heap::mc_count_ = 0; | |
| 136 int Heap::ms_count_ = 0; | |
| 137 unsigned int Heap::gc_count_ = 0; | |
| 138 | |
| 139 GCTracer* Heap::tracer_ = NULL; | |
| 140 | |
| 141 int Heap::unflattened_strings_length_ = 0; | |
| 142 | |
| 143 int Heap::always_allocate_scope_depth_ = 0; | |
| 144 int Heap::linear_allocation_scope_depth_ = 0; | |
| 145 int Heap::contexts_disposed_ = 0; | |
| 146 | |
| 147 int Heap::young_survivors_after_last_gc_ = 0; | |
| 148 int Heap::high_survival_rate_period_length_ = 0; | |
| 149 double Heap::survival_rate_ = 0; | |
| 150 Heap::SurvivalRateTrend Heap::previous_survival_rate_trend_ = Heap::STABLE; | |
| 151 Heap::SurvivalRateTrend Heap::survival_rate_trend_ = Heap::STABLE; | |
| 152 | |
| 153 #ifdef DEBUG | |
| 154 bool Heap::allocation_allowed_ = true; | |
| 155 | |
| 156 int Heap::allocation_timeout_ = 0; | |
| 157 bool Heap::disallow_allocation_failure_ = false; | |
| 158 #endif // DEBUG | |
| 159 | |
| 160 intptr_t GCTracer::alive_after_last_gc_ = 0; | |
| 161 double GCTracer::last_gc_end_timestamp_ = 0.0; | |
| 162 int GCTracer::max_gc_pause_ = 0; | |
| 163 intptr_t GCTracer::max_alive_after_gc_ = 0; | |
| 164 int GCTracer::min_in_mutator_ = kMaxInt; | |
| 165 | 156 |
| 166 intptr_t Heap::Capacity() { | 157 intptr_t Heap::Capacity() { |
| 167 if (!HasBeenSetup()) return 0; | 158 if (!HasBeenSetup()) return 0; |
| 168 | 159 |
| 169 return new_space_.Capacity() + | 160 return new_space_.Capacity() + |
| 170 old_pointer_space_->Capacity() + | 161 old_pointer_space_->Capacity() + |
| 171 old_data_space_->Capacity() + | 162 old_data_space_->Capacity() + |
| 172 code_space_->Capacity() + | 163 code_space_->Capacity() + |
| 173 map_space_->Capacity() + | 164 map_space_->Capacity() + |
| 174 cell_space_->Capacity(); | 165 cell_space_->Capacity(); |
| 175 } | 166 } |
| 176 | 167 |
| 177 | 168 |
| 178 intptr_t Heap::CommittedMemory() { | 169 intptr_t Heap::CommittedMemory() { |
| 179 if (!HasBeenSetup()) return 0; | 170 if (!HasBeenSetup()) return 0; |
| 180 | 171 |
| 181 return new_space_.CommittedMemory() + | 172 return new_space_.CommittedMemory() + |
| 182 old_pointer_space_->CommittedMemory() + | 173 old_pointer_space_->CommittedMemory() + |
| 183 old_data_space_->CommittedMemory() + | 174 old_data_space_->CommittedMemory() + |
| 184 code_space_->CommittedMemory() + | 175 code_space_->CommittedMemory() + |
| 185 map_space_->CommittedMemory() + | 176 map_space_->CommittedMemory() + |
| 186 cell_space_->CommittedMemory() + | 177 cell_space_->CommittedMemory() + |
| 187 lo_space_->Size(); | 178 lo_space_->Size(); |
| 188 } | 179 } |
| 189 | 180 |
| 190 intptr_t Heap::CommittedMemoryExecutable() { | 181 intptr_t Heap::CommittedMemoryExecutable() { |
| 191 if (!HasBeenSetup()) return 0; | 182 if (!HasBeenSetup()) return 0; |
| 192 | 183 |
| 193 return MemoryAllocator::SizeExecutable(); | 184 return isolate()->memory_allocator()->SizeExecutable(); |
| 194 } | 185 } |
| 195 | 186 |
| 196 | 187 |
| 197 intptr_t Heap::Available() { | 188 intptr_t Heap::Available() { |
| 198 if (!HasBeenSetup()) return 0; | 189 if (!HasBeenSetup()) return 0; |
| 199 | 190 |
| 200 return new_space_.Available() + | 191 return new_space_.Available() + |
| 201 old_pointer_space_->Available() + | 192 old_pointer_space_->Available() + |
| 202 old_data_space_->Available() + | 193 old_data_space_->Available() + |
| 203 code_space_->Available() + | 194 code_space_->Available() + |
| 204 map_space_->Available() + | 195 map_space_->Available() + |
| 205 cell_space_->Available(); | 196 cell_space_->Available(); |
| 206 } | 197 } |
| 207 | 198 |
| 208 | 199 |
| 209 bool Heap::HasBeenSetup() { | 200 bool Heap::HasBeenSetup() { |
| 210 return old_pointer_space_ != NULL && | 201 return old_pointer_space_ != NULL && |
| 211 old_data_space_ != NULL && | 202 old_data_space_ != NULL && |
| 212 code_space_ != NULL && | 203 code_space_ != NULL && |
| 213 map_space_ != NULL && | 204 map_space_ != NULL && |
| 214 cell_space_ != NULL && | 205 cell_space_ != NULL && |
| 215 lo_space_ != NULL; | 206 lo_space_ != NULL; |
| 216 } | 207 } |
| 217 | 208 |
| 218 | 209 |
| 219 int Heap::GcSafeSizeOfOldObject(HeapObject* object) { | 210 int Heap::GcSafeSizeOfOldObject(HeapObject* object) { |
| 220 ASSERT(!Heap::InNewSpace(object)); // Code only works for old objects. | 211 ASSERT(!HEAP->InNewSpace(object)); // Code only works for old objects. |
| 221 ASSERT(!MarkCompactCollector::are_map_pointers_encoded()); | 212 ASSERT(!HEAP->mark_compact_collector()->are_map_pointers_encoded()); |
| 222 MapWord map_word = object->map_word(); | 213 MapWord map_word = object->map_word(); |
| 223 map_word.ClearMark(); | 214 map_word.ClearMark(); |
| 224 map_word.ClearOverflow(); | 215 map_word.ClearOverflow(); |
| 225 return object->SizeFromMap(map_word.ToMap()); | 216 return object->SizeFromMap(map_word.ToMap()); |
| 226 } | 217 } |
| 227 | 218 |
| 228 | 219 |
| 229 int Heap::GcSafeSizeOfOldObjectWithEncodedMap(HeapObject* object) { | 220 int Heap::GcSafeSizeOfOldObjectWithEncodedMap(HeapObject* object) { |
| 230 ASSERT(!Heap::InNewSpace(object)); // Code only works for old objects. | 221 ASSERT(!HEAP->InNewSpace(object)); // Code only works for old objects. |
| 231 ASSERT(MarkCompactCollector::are_map_pointers_encoded()); | 222 ASSERT(HEAP->mark_compact_collector()->are_map_pointers_encoded()); |
| 232 uint32_t marker = Memory::uint32_at(object->address()); | 223 uint32_t marker = Memory::uint32_at(object->address()); |
| 233 if (marker == MarkCompactCollector::kSingleFreeEncoding) { | 224 if (marker == MarkCompactCollector::kSingleFreeEncoding) { |
| 234 return kIntSize; | 225 return kIntSize; |
| 235 } else if (marker == MarkCompactCollector::kMultiFreeEncoding) { | 226 } else if (marker == MarkCompactCollector::kMultiFreeEncoding) { |
| 236 return Memory::int_at(object->address() + kIntSize); | 227 return Memory::int_at(object->address() + kIntSize); |
| 237 } else { | 228 } else { |
| 238 MapWord map_word = object->map_word(); | 229 MapWord map_word = object->map_word(); |
| 239 Address map_address = map_word.DecodeMapAddress(Heap::map_space()); | 230 Address map_address = map_word.DecodeMapAddress(HEAP->map_space()); |
| 240 Map* map = reinterpret_cast<Map*>(HeapObject::FromAddress(map_address)); | 231 Map* map = reinterpret_cast<Map*>(HeapObject::FromAddress(map_address)); |
| 241 return object->SizeFromMap(map); | 232 return object->SizeFromMap(map); |
| 242 } | 233 } |
| 243 } | 234 } |
| 244 | 235 |
| 245 | 236 |
| 246 GarbageCollector Heap::SelectGarbageCollector(AllocationSpace space) { | 237 GarbageCollector Heap::SelectGarbageCollector(AllocationSpace space) { |
| 247 // Is global GC requested? | 238 // Is global GC requested? |
| 248 if (space != NEW_SPACE || FLAG_gc_global) { | 239 if (space != NEW_SPACE || FLAG_gc_global) { |
| 249 Counters::gc_compactor_caused_by_request.Increment(); | 240 isolate_->counters()->gc_compactor_caused_by_request()->Increment(); |
| 250 return MARK_COMPACTOR; | 241 return MARK_COMPACTOR; |
| 251 } | 242 } |
| 252 | 243 |
| 253 // Is enough data promoted to justify a global GC? | 244 // Is enough data promoted to justify a global GC? |
| 254 if (OldGenerationPromotionLimitReached()) { | 245 if (OldGenerationPromotionLimitReached()) { |
| 255 Counters::gc_compactor_caused_by_promoted_data.Increment(); | 246 isolate_->counters()->gc_compactor_caused_by_promoted_data()->Increment(); |
| 256 return MARK_COMPACTOR; | 247 return MARK_COMPACTOR; |
| 257 } | 248 } |
| 258 | 249 |
| 259 // Have allocation in OLD and LO failed? | 250 // Have allocation in OLD and LO failed? |
| 260 if (old_gen_exhausted_) { | 251 if (old_gen_exhausted_) { |
| 261 Counters::gc_compactor_caused_by_oldspace_exhaustion.Increment(); | 252 isolate_->counters()-> |
| 253 gc_compactor_caused_by_oldspace_exhaustion()->Increment(); |
| 262 return MARK_COMPACTOR; | 254 return MARK_COMPACTOR; |
| 263 } | 255 } |
| 264 | 256 |
| 265 // Is there enough space left in OLD to guarantee that a scavenge can | 257 // Is there enough space left in OLD to guarantee that a scavenge can |
| 266 // succeed? | 258 // succeed? |
| 267 // | 259 // |
| 268 // Note that MemoryAllocator->MaxAvailable() undercounts the memory available | 260 // Note that MemoryAllocator->MaxAvailable() undercounts the memory available |
| 269 // for object promotion. It counts only the bytes that the memory | 261 // for object promotion. It counts only the bytes that the memory |
| 270 // allocator has not yet allocated from the OS and assigned to any space, | 262 // allocator has not yet allocated from the OS and assigned to any space, |
| 271 // and does not count available bytes already in the old space or code | 263 // and does not count available bytes already in the old space or code |
| 272 // space. Undercounting is safe---we may get an unrequested full GC when | 264 // space. Undercounting is safe---we may get an unrequested full GC when |
| 273 // a scavenge would have succeeded. | 265 // a scavenge would have succeeded. |
| 274 if (MemoryAllocator::MaxAvailable() <= new_space_.Size()) { | 266 if (isolate_->memory_allocator()->MaxAvailable() <= new_space_.Size()) { |
| 275 Counters::gc_compactor_caused_by_oldspace_exhaustion.Increment(); | 267 isolate_->counters()-> |
| 268 gc_compactor_caused_by_oldspace_exhaustion()->Increment(); |
| 276 return MARK_COMPACTOR; | 269 return MARK_COMPACTOR; |
| 277 } | 270 } |
| 278 | 271 |
| 279 // Default | 272 // Default |
| 280 return SCAVENGER; | 273 return SCAVENGER; |
| 281 } | 274 } |
| 282 | 275 |
| 283 | 276 |
| 284 // TODO(1238405): Combine the infrastructure for --heap-stats and | 277 // TODO(1238405): Combine the infrastructure for --heap-stats and |
| 285 // --log-gc to avoid the complicated preprocessor and flag testing. | 278 // --log-gc to avoid the complicated preprocessor and flag testing. |
| (...skipping 24 matching lines...) Expand all Loading... |
| 310 } | 303 } |
| 311 #endif | 304 #endif |
| 312 } | 305 } |
| 313 | 306 |
| 314 | 307 |
| 315 #if defined(ENABLE_LOGGING_AND_PROFILING) | 308 #if defined(ENABLE_LOGGING_AND_PROFILING) |
| 316 void Heap::PrintShortHeapStatistics() { | 309 void Heap::PrintShortHeapStatistics() { |
| 317 if (!FLAG_trace_gc_verbose) return; | 310 if (!FLAG_trace_gc_verbose) return; |
| 318 PrintF("Memory allocator, used: %8" V8_PTR_PREFIX "d" | 311 PrintF("Memory allocator, used: %8" V8_PTR_PREFIX "d" |
| 319 ", available: %8" V8_PTR_PREFIX "d\n", | 312 ", available: %8" V8_PTR_PREFIX "d\n", |
| 320 MemoryAllocator::Size(), | 313 isolate_->memory_allocator()->Size(), |
| 321 MemoryAllocator::Available()); | 314 isolate_->memory_allocator()->Available()); |
| 322 PrintF("New space, used: %8" V8_PTR_PREFIX "d" | 315 PrintF("New space, used: %8" V8_PTR_PREFIX "d" |
| 323 ", available: %8" V8_PTR_PREFIX "d\n", | 316 ", available: %8" V8_PTR_PREFIX "d\n", |
| 324 Heap::new_space_.Size(), | 317 Heap::new_space_.Size(), |
| 325 new_space_.Available()); | 318 new_space_.Available()); |
| 326 PrintF("Old pointers, used: %8" V8_PTR_PREFIX "d" | 319 PrintF("Old pointers, used: %8" V8_PTR_PREFIX "d" |
| 327 ", available: %8" V8_PTR_PREFIX "d" | 320 ", available: %8" V8_PTR_PREFIX "d" |
| 328 ", waste: %8" V8_PTR_PREFIX "d\n", | 321 ", waste: %8" V8_PTR_PREFIX "d\n", |
| 329 old_pointer_space_->Size(), | 322 old_pointer_space_->Size(), |
| 330 old_pointer_space_->Available(), | 323 old_pointer_space_->Available(), |
| 331 old_pointer_space_->Waste()); | 324 old_pointer_space_->Waste()); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 376 #elif defined(DEBUG) | 369 #elif defined(DEBUG) |
| 377 if (FLAG_heap_stats) ReportHeapStatistics("After GC"); | 370 if (FLAG_heap_stats) ReportHeapStatistics("After GC"); |
| 378 #elif defined(ENABLE_LOGGING_AND_PROFILING) | 371 #elif defined(ENABLE_LOGGING_AND_PROFILING) |
| 379 if (FLAG_log_gc) new_space_.ReportStatistics(); | 372 if (FLAG_log_gc) new_space_.ReportStatistics(); |
| 380 #endif | 373 #endif |
| 381 } | 374 } |
| 382 #endif // defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) | 375 #endif // defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) |
| 383 | 376 |
| 384 | 377 |
| 385 void Heap::GarbageCollectionPrologue() { | 378 void Heap::GarbageCollectionPrologue() { |
| 386 TranscendentalCache::Clear(); | 379 isolate_->transcendental_cache()->Clear(); |
| 387 ClearJSFunctionResultCaches(); | 380 ClearJSFunctionResultCaches(); |
| 388 gc_count_++; | 381 gc_count_++; |
| 389 unflattened_strings_length_ = 0; | 382 unflattened_strings_length_ = 0; |
| 390 #ifdef DEBUG | 383 #ifdef DEBUG |
| 391 ASSERT(allocation_allowed_ && gc_state_ == NOT_IN_GC); | 384 ASSERT(allocation_allowed_ && gc_state_ == NOT_IN_GC); |
| 392 allow_allocation(false); | 385 allow_allocation(false); |
| 393 | 386 |
| 394 if (FLAG_verify_heap) { | 387 if (FLAG_verify_heap) { |
| 395 Verify(); | 388 Verify(); |
| 396 } | 389 } |
| (...skipping 20 matching lines...) Expand all Loading... |
| 417 void Heap::GarbageCollectionEpilogue() { | 410 void Heap::GarbageCollectionEpilogue() { |
| 418 LiveObjectList::GCEpilogue(); | 411 LiveObjectList::GCEpilogue(); |
| 419 #ifdef DEBUG | 412 #ifdef DEBUG |
| 420 allow_allocation(true); | 413 allow_allocation(true); |
| 421 ZapFromSpace(); | 414 ZapFromSpace(); |
| 422 | 415 |
| 423 if (FLAG_verify_heap) { | 416 if (FLAG_verify_heap) { |
| 424 Verify(); | 417 Verify(); |
| 425 } | 418 } |
| 426 | 419 |
| 427 if (FLAG_print_global_handles) GlobalHandles::Print(); | 420 if (FLAG_print_global_handles) isolate_->global_handles()->Print(); |
| 428 if (FLAG_print_handles) PrintHandles(); | 421 if (FLAG_print_handles) PrintHandles(); |
| 429 if (FLAG_gc_verbose) Print(); | 422 if (FLAG_gc_verbose) Print(); |
| 430 if (FLAG_code_stats) ReportCodeStatistics("After GC"); | 423 if (FLAG_code_stats) ReportCodeStatistics("After GC"); |
| 431 #endif | 424 #endif |
| 432 | 425 |
| 433 Counters::alive_after_last_gc.Set(static_cast<int>(SizeOfObjects())); | 426 isolate_->counters()->alive_after_last_gc()->Set( |
| 427 static_cast<int>(SizeOfObjects())); |
| 434 | 428 |
| 435 Counters::symbol_table_capacity.Set(symbol_table()->Capacity()); | 429 isolate_->counters()->symbol_table_capacity()->Set( |
| 436 Counters::number_of_symbols.Set(symbol_table()->NumberOfElements()); | 430 symbol_table()->Capacity()); |
| 431 isolate_->counters()->number_of_symbols()->Set( |
| 432 symbol_table()->NumberOfElements()); |
| 437 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) | 433 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) |
| 438 ReportStatisticsAfterGC(); | 434 ReportStatisticsAfterGC(); |
| 439 #endif | 435 #endif |
| 440 #ifdef ENABLE_DEBUGGER_SUPPORT | 436 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 441 Debug::AfterGarbageCollection(); | 437 isolate_->debug()->AfterGarbageCollection(); |
| 442 #endif | 438 #endif |
| 443 } | 439 } |
| 444 | 440 |
| 445 | 441 |
| 446 void Heap::CollectAllGarbage(bool force_compaction) { | 442 void Heap::CollectAllGarbage(bool force_compaction) { |
| 447 // Since we are ignoring the return value, the exact choice of space does | 443 // Since we are ignoring the return value, the exact choice of space does |
| 448 // not matter, so long as we do not specify NEW_SPACE, which would not | 444 // not matter, so long as we do not specify NEW_SPACE, which would not |
| 449 // cause a full GC. | 445 // cause a full GC. |
| 450 MarkCompactCollector::SetForceCompaction(force_compaction); | 446 mark_compact_collector_.SetForceCompaction(force_compaction); |
| 451 CollectGarbage(OLD_POINTER_SPACE); | 447 CollectGarbage(OLD_POINTER_SPACE); |
| 452 MarkCompactCollector::SetForceCompaction(false); | 448 mark_compact_collector_.SetForceCompaction(false); |
| 453 } | 449 } |
| 454 | 450 |
| 455 | 451 |
| 456 void Heap::CollectAllAvailableGarbage() { | 452 void Heap::CollectAllAvailableGarbage() { |
| 457 // Since we are ignoring the return value, the exact choice of space does | 453 // Since we are ignoring the return value, the exact choice of space does |
| 458 // not matter, so long as we do not specify NEW_SPACE, which would not | 454 // not matter, so long as we do not specify NEW_SPACE, which would not |
| 459 // cause a full GC. | 455 // cause a full GC. |
| 460 MarkCompactCollector::SetForceCompaction(true); | 456 mark_compact_collector()->SetForceCompaction(true); |
| 461 | 457 |
| 462 // Major GC would invoke weak handle callbacks on weakly reachable | 458 // Major GC would invoke weak handle callbacks on weakly reachable |
| 463 // handles, but won't collect weakly reachable objects until next | 459 // handles, but won't collect weakly reachable objects until next |
| 464 // major GC. Therefore if we collect aggressively and weak handle callback | 460 // major GC. Therefore if we collect aggressively and weak handle callback |
| 465 // has been invoked, we rerun major GC to release objects which become | 461 // has been invoked, we rerun major GC to release objects which become |
| 466 // garbage. | 462 // garbage. |
| 467 // Note: as weak callbacks can execute arbitrary code, we cannot | 463 // Note: as weak callbacks can execute arbitrary code, we cannot |
| 468 // hope that eventually there will be no weak callbacks invocations. | 464 // hope that eventually there will be no weak callbacks invocations. |
| 469 // Therefore stop recollecting after several attempts. | 465 // Therefore stop recollecting after several attempts. |
| 470 const int kMaxNumberOfAttempts = 7; | 466 const int kMaxNumberOfAttempts = 7; |
| 471 for (int attempt = 0; attempt < kMaxNumberOfAttempts; attempt++) { | 467 for (int attempt = 0; attempt < kMaxNumberOfAttempts; attempt++) { |
| 472 if (!CollectGarbage(OLD_POINTER_SPACE, MARK_COMPACTOR)) { | 468 if (!CollectGarbage(OLD_POINTER_SPACE, MARK_COMPACTOR)) { |
| 473 break; | 469 break; |
| 474 } | 470 } |
| 475 } | 471 } |
| 476 MarkCompactCollector::SetForceCompaction(false); | 472 mark_compact_collector()->SetForceCompaction(false); |
| 477 } | 473 } |
| 478 | 474 |
| 479 | 475 |
| 480 bool Heap::CollectGarbage(AllocationSpace space, GarbageCollector collector) { | 476 bool Heap::CollectGarbage(AllocationSpace space, GarbageCollector collector) { |
| 481 // The VM is in the GC state until exiting this function. | 477 // The VM is in the GC state until exiting this function. |
| 482 VMState state(GC); | 478 VMState state(isolate_, GC); |
| 483 | 479 |
| 484 #ifdef DEBUG | 480 #ifdef DEBUG |
| 485 // Reset the allocation timeout to the GC interval, but make sure to | 481 // Reset the allocation timeout to the GC interval, but make sure to |
| 486 // allow at least a few allocations after a collection. The reason | 482 // allow at least a few allocations after a collection. The reason |
| 487 // for this is that we have a lot of allocation sequences and we | 483 // for this is that we have a lot of allocation sequences and we |
| 488 // assume that a garbage collection will allow the subsequent | 484 // assume that a garbage collection will allow the subsequent |
| 489 // allocation attempts to go through. | 485 // allocation attempts to go through. |
| 490 allocation_timeout_ = Max(6, FLAG_gc_interval); | 486 allocation_timeout_ = Max(6, FLAG_gc_interval); |
| 491 #endif | 487 #endif |
| 492 | 488 |
| 493 bool next_gc_likely_to_collect_more = false; | 489 bool next_gc_likely_to_collect_more = false; |
| 494 | 490 |
| 495 { GCTracer tracer; | 491 { GCTracer tracer(this); |
| 496 GarbageCollectionPrologue(); | 492 GarbageCollectionPrologue(); |
| 497 // The GC count was incremented in the prologue. Tell the tracer about | 493 // The GC count was incremented in the prologue. Tell the tracer about |
| 498 // it. | 494 // it. |
| 499 tracer.set_gc_count(gc_count_); | 495 tracer.set_gc_count(gc_count_); |
| 500 | 496 |
| 501 // Tell the tracer which collector we've selected. | 497 // Tell the tracer which collector we've selected. |
| 502 tracer.set_collector(collector); | 498 tracer.set_collector(collector); |
| 503 | 499 |
| 504 HistogramTimer* rate = (collector == SCAVENGER) | 500 HistogramTimer* rate = (collector == SCAVENGER) |
| 505 ? &Counters::gc_scavenger | 501 ? isolate_->counters()->gc_scavenger() |
| 506 : &Counters::gc_compactor; | 502 : isolate_->counters()->gc_compactor(); |
| 507 rate->Start(); | 503 rate->Start(); |
| 508 next_gc_likely_to_collect_more = | 504 next_gc_likely_to_collect_more = |
| 509 PerformGarbageCollection(collector, &tracer); | 505 PerformGarbageCollection(collector, &tracer); |
| 510 rate->Stop(); | 506 rate->Stop(); |
| 511 | 507 |
| 512 GarbageCollectionEpilogue(); | 508 GarbageCollectionEpilogue(); |
| 513 } | 509 } |
| 514 | 510 |
| 515 | 511 |
| 516 #ifdef ENABLE_LOGGING_AND_PROFILING | 512 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 517 if (FLAG_log_gc) HeapProfiler::WriteSample(); | 513 if (FLAG_log_gc) HeapProfiler::WriteSample(); |
| 518 #endif | 514 #endif |
| 519 | 515 |
| 520 return next_gc_likely_to_collect_more; | 516 return next_gc_likely_to_collect_more; |
| 521 } | 517 } |
| 522 | 518 |
| 523 | 519 |
| 524 void Heap::PerformScavenge() { | 520 void Heap::PerformScavenge() { |
| 525 GCTracer tracer; | 521 GCTracer tracer(this); |
| 526 PerformGarbageCollection(SCAVENGER, &tracer); | 522 PerformGarbageCollection(SCAVENGER, &tracer); |
| 527 } | 523 } |
| 528 | 524 |
| 529 | 525 |
| 530 #ifdef DEBUG | 526 #ifdef DEBUG |
| 531 // Helper class for verifying the symbol table. | 527 // Helper class for verifying the symbol table. |
| 532 class SymbolTableVerifier : public ObjectVisitor { | 528 class SymbolTableVerifier : public ObjectVisitor { |
| 533 public: | 529 public: |
| 534 SymbolTableVerifier() { } | |
| 535 void VisitPointers(Object** start, Object** end) { | 530 void VisitPointers(Object** start, Object** end) { |
| 536 // Visit all HeapObject pointers in [start, end). | 531 // Visit all HeapObject pointers in [start, end). |
| 537 for (Object** p = start; p < end; p++) { | 532 for (Object** p = start; p < end; p++) { |
| 538 if ((*p)->IsHeapObject()) { | 533 if ((*p)->IsHeapObject()) { |
| 539 // Check that the symbol is actually a symbol. | 534 // Check that the symbol is actually a symbol. |
| 540 ASSERT((*p)->IsNull() || (*p)->IsUndefined() || (*p)->IsSymbol()); | 535 ASSERT((*p)->IsNull() || (*p)->IsUndefined() || (*p)->IsSymbol()); |
| 541 } | 536 } |
| 542 } | 537 } |
| 543 } | 538 } |
| 544 }; | 539 }; |
| 545 #endif // DEBUG | 540 #endif // DEBUG |
| 546 | 541 |
| 547 | 542 |
| 548 static void VerifySymbolTable() { | 543 static void VerifySymbolTable() { |
| 549 #ifdef DEBUG | 544 #ifdef DEBUG |
| 550 SymbolTableVerifier verifier; | 545 SymbolTableVerifier verifier; |
| 551 Heap::symbol_table()->IterateElements(&verifier); | 546 HEAP->symbol_table()->IterateElements(&verifier); |
| 552 #endif // DEBUG | 547 #endif // DEBUG |
| 553 } | 548 } |
| 554 | 549 |
| 555 | 550 |
| 556 void Heap::ReserveSpace( | 551 void Heap::ReserveSpace( |
| 557 int new_space_size, | 552 int new_space_size, |
| 558 int pointer_space_size, | 553 int pointer_space_size, |
| 559 int data_space_size, | 554 int data_space_size, |
| 560 int code_space_size, | 555 int code_space_size, |
| 561 int map_space_size, | 556 int map_space_size, |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 626 Shrink(); | 621 Shrink(); |
| 627 if (new_space_.CommitFromSpaceIfNeeded()) return; | 622 if (new_space_.CommitFromSpaceIfNeeded()) return; |
| 628 | 623 |
| 629 // Committing memory to from space failed again. | 624 // Committing memory to from space failed again. |
| 630 // Memory is exhausted and we will die. | 625 // Memory is exhausted and we will die. |
| 631 V8::FatalProcessOutOfMemory("Committing semi space failed."); | 626 V8::FatalProcessOutOfMemory("Committing semi space failed."); |
| 632 } | 627 } |
| 633 | 628 |
| 634 | 629 |
| 635 void Heap::ClearJSFunctionResultCaches() { | 630 void Heap::ClearJSFunctionResultCaches() { |
| 636 if (Bootstrapper::IsActive()) return; | 631 if (isolate_->bootstrapper()->IsActive()) return; |
| 637 | 632 |
| 638 Object* context = global_contexts_list_; | 633 Object* context = global_contexts_list_; |
| 639 while (!context->IsUndefined()) { | 634 while (!context->IsUndefined()) { |
| 640 // Get the caches for this context: | 635 // Get the caches for this context: |
| 641 FixedArray* caches = | 636 FixedArray* caches = |
| 642 Context::cast(context)->jsfunction_result_caches(); | 637 Context::cast(context)->jsfunction_result_caches(); |
| 643 // Clear the caches: | 638 // Clear the caches: |
| 644 int length = caches->length(); | 639 int length = caches->length(); |
| 645 for (int i = 0; i < length; i++) { | 640 for (int i = 0; i < length; i++) { |
| 646 JSFunctionResultCache::cast(caches->get(i))->Clear(); | 641 JSFunctionResultCache::cast(caches->get(i))->Clear(); |
| 647 } | 642 } |
| 648 // Get the next context: | 643 // Get the next context: |
| 649 context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK); | 644 context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK); |
| 650 } | 645 } |
| 651 } | 646 } |
| 652 | 647 |
| 653 | 648 |
| 649 |
| 654 void Heap::ClearNormalizedMapCaches() { | 650 void Heap::ClearNormalizedMapCaches() { |
| 655 if (Bootstrapper::IsActive()) return; | 651 if (isolate_->bootstrapper()->IsActive()) return; |
| 656 | 652 |
| 657 Object* context = global_contexts_list_; | 653 Object* context = global_contexts_list_; |
| 658 while (!context->IsUndefined()) { | 654 while (!context->IsUndefined()) { |
| 659 Context::cast(context)->normalized_map_cache()->Clear(); | 655 Context::cast(context)->normalized_map_cache()->Clear(); |
| 660 context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK); | 656 context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK); |
| 661 } | 657 } |
| 662 } | 658 } |
| 663 | 659 |
| 664 | 660 |
| 665 #ifdef DEBUG | 661 #ifdef DEBUG |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 702 } | 698 } |
| 703 | 699 |
| 704 survival_rate_ = survival_rate; | 700 survival_rate_ = survival_rate; |
| 705 } | 701 } |
| 706 | 702 |
| 707 bool Heap::PerformGarbageCollection(GarbageCollector collector, | 703 bool Heap::PerformGarbageCollection(GarbageCollector collector, |
| 708 GCTracer* tracer) { | 704 GCTracer* tracer) { |
| 709 bool next_gc_likely_to_collect_more = false; | 705 bool next_gc_likely_to_collect_more = false; |
| 710 | 706 |
| 711 if (collector != SCAVENGER) { | 707 if (collector != SCAVENGER) { |
| 712 PROFILE(CodeMovingGCEvent()); | 708 PROFILE(isolate_, CodeMovingGCEvent()); |
| 713 } | 709 } |
| 714 | 710 |
| 715 VerifySymbolTable(); | 711 VerifySymbolTable(); |
| 716 if (collector == MARK_COMPACTOR && global_gc_prologue_callback_) { | 712 if (collector == MARK_COMPACTOR && global_gc_prologue_callback_) { |
| 717 ASSERT(!allocation_allowed_); | 713 ASSERT(!allocation_allowed_); |
| 718 GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL); | 714 GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL); |
| 719 global_gc_prologue_callback_(); | 715 global_gc_prologue_callback_(); |
| 720 } | 716 } |
| 721 | 717 |
| 722 GCType gc_type = | 718 GCType gc_type = |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 761 | 757 |
| 762 old_gen_exhausted_ = false; | 758 old_gen_exhausted_ = false; |
| 763 } else { | 759 } else { |
| 764 tracer_ = tracer; | 760 tracer_ = tracer; |
| 765 Scavenge(); | 761 Scavenge(); |
| 766 tracer_ = NULL; | 762 tracer_ = NULL; |
| 767 | 763 |
| 768 UpdateSurvivalRateTrend(start_new_space_size); | 764 UpdateSurvivalRateTrend(start_new_space_size); |
| 769 } | 765 } |
| 770 | 766 |
| 771 Counters::objs_since_last_young.Set(0); | 767 isolate_->counters()->objs_since_last_young()->Set(0); |
| 772 | 768 |
| 773 if (collector == MARK_COMPACTOR) { | 769 if (collector == MARK_COMPACTOR) { |
| 774 DisableAssertNoAllocation allow_allocation; | 770 DisableAssertNoAllocation allow_allocation; |
| 775 GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL); | 771 GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL); |
| 776 next_gc_likely_to_collect_more = | 772 next_gc_likely_to_collect_more = |
| 777 GlobalHandles::PostGarbageCollectionProcessing(); | 773 isolate_->global_handles()->PostGarbageCollectionProcessing(); |
| 778 } | 774 } |
| 779 | 775 |
| 780 // Update relocatables. | 776 // Update relocatables. |
| 781 Relocatable::PostGarbageCollectionProcessing(); | 777 Relocatable::PostGarbageCollectionProcessing(); |
| 782 | 778 |
| 783 if (collector == MARK_COMPACTOR) { | 779 if (collector == MARK_COMPACTOR) { |
| 784 // Register the amount of external allocated memory. | 780 // Register the amount of external allocated memory. |
| 785 amount_of_external_allocated_memory_at_last_global_gc_ = | 781 amount_of_external_allocated_memory_at_last_global_gc_ = |
| 786 amount_of_external_allocated_memory_; | 782 amount_of_external_allocated_memory_; |
| 787 } | 783 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 801 global_gc_epilogue_callback_(); | 797 global_gc_epilogue_callback_(); |
| 802 } | 798 } |
| 803 VerifySymbolTable(); | 799 VerifySymbolTable(); |
| 804 | 800 |
| 805 return next_gc_likely_to_collect_more; | 801 return next_gc_likely_to_collect_more; |
| 806 } | 802 } |
| 807 | 803 |
| 808 | 804 |
| 809 void Heap::MarkCompact(GCTracer* tracer) { | 805 void Heap::MarkCompact(GCTracer* tracer) { |
| 810 gc_state_ = MARK_COMPACT; | 806 gc_state_ = MARK_COMPACT; |
| 811 LOG(ResourceEvent("markcompact", "begin")); | 807 LOG(isolate_, ResourceEvent("markcompact", "begin")); |
| 812 | 808 |
| 813 MarkCompactCollector::Prepare(tracer); | 809 mark_compact_collector_.Prepare(tracer); |
| 814 | 810 |
| 815 bool is_compacting = MarkCompactCollector::IsCompacting(); | 811 bool is_compacting = mark_compact_collector_.IsCompacting(); |
| 816 | 812 |
| 817 if (is_compacting) { | 813 if (is_compacting) { |
| 818 mc_count_++; | 814 mc_count_++; |
| 819 } else { | 815 } else { |
| 820 ms_count_++; | 816 ms_count_++; |
| 821 } | 817 } |
| 822 tracer->set_full_gc_count(mc_count_ + ms_count_); | 818 tracer->set_full_gc_count(mc_count_ + ms_count_); |
| 823 | 819 |
| 824 MarkCompactPrologue(is_compacting); | 820 MarkCompactPrologue(is_compacting); |
| 825 | 821 |
| 826 MarkCompactCollector::CollectGarbage(); | 822 is_safe_to_read_maps_ = false; |
| 823 mark_compact_collector_.CollectGarbage(); |
| 824 is_safe_to_read_maps_ = true; |
| 827 | 825 |
| 828 LOG(ResourceEvent("markcompact", "end")); | 826 LOG(isolate_, ResourceEvent("markcompact", "end")); |
| 829 | 827 |
| 830 gc_state_ = NOT_IN_GC; | 828 gc_state_ = NOT_IN_GC; |
| 831 | 829 |
| 832 Shrink(); | 830 Shrink(); |
| 833 | 831 |
| 834 Counters::objs_since_last_full.Set(0); | 832 isolate_->counters()->objs_since_last_full()->Set(0); |
| 835 | 833 |
| 836 contexts_disposed_ = 0; | 834 contexts_disposed_ = 0; |
| 837 } | 835 } |
| 838 | 836 |
| 839 | 837 |
| 840 void Heap::MarkCompactPrologue(bool is_compacting) { | 838 void Heap::MarkCompactPrologue(bool is_compacting) { |
| 841 // At any old GC clear the keyed lookup cache to enable collection of unused | 839 // At any old GC clear the keyed lookup cache to enable collection of unused |
| 842 // maps. | 840 // maps. |
| 843 KeyedLookupCache::Clear(); | 841 isolate_->keyed_lookup_cache()->Clear(); |
| 844 ContextSlotCache::Clear(); | 842 isolate_->context_slot_cache()->Clear(); |
| 845 DescriptorLookupCache::Clear(); | 843 isolate_->descriptor_lookup_cache()->Clear(); |
| 846 | 844 |
| 847 CompilationCache::MarkCompactPrologue(); | 845 isolate_->compilation_cache()->MarkCompactPrologue(); |
| 848 | 846 |
| 849 CompletelyClearInstanceofCache(); | 847 CompletelyClearInstanceofCache(); |
| 850 | 848 |
| 851 if (is_compacting) FlushNumberStringCache(); | 849 if (is_compacting) FlushNumberStringCache(); |
| 852 | 850 |
| 853 ClearNormalizedMapCaches(); | 851 ClearNormalizedMapCaches(); |
| 854 } | 852 } |
| 855 | 853 |
| 856 | 854 |
| 857 Object* Heap::FindCodeObject(Address a) { | 855 Object* Heap::FindCodeObject(Address a) { |
| 858 Object* obj = NULL; // Initialization to please compiler. | 856 Object* obj = NULL; // Initialization to please compiler. |
| 859 { MaybeObject* maybe_obj = code_space_->FindObject(a); | 857 { MaybeObject* maybe_obj = code_space_->FindObject(a); |
| 860 if (!maybe_obj->ToObject(&obj)) { | 858 if (!maybe_obj->ToObject(&obj)) { |
| 861 obj = lo_space_->FindObject(a)->ToObjectUnchecked(); | 859 obj = lo_space_->FindObject(a)->ToObjectUnchecked(); |
| 862 } | 860 } |
| 863 } | 861 } |
| 864 return obj; | 862 return obj; |
| 865 } | 863 } |
| 866 | 864 |
| 867 | 865 |
| 868 // Helper class for copying HeapObjects | 866 // Helper class for copying HeapObjects |
| 869 class ScavengeVisitor: public ObjectVisitor { | 867 class ScavengeVisitor: public ObjectVisitor { |
| 870 public: | 868 public: |
| 869 explicit ScavengeVisitor(Heap* heap) : heap_(heap) {} |
| 871 | 870 |
| 872 void VisitPointer(Object** p) { ScavengePointer(p); } | 871 void VisitPointer(Object** p) { ScavengePointer(p); } |
| 873 | 872 |
| 874 void VisitPointers(Object** start, Object** end) { | 873 void VisitPointers(Object** start, Object** end) { |
| 875 // Copy all HeapObject pointers in [start, end) | 874 // Copy all HeapObject pointers in [start, end) |
| 876 for (Object** p = start; p < end; p++) ScavengePointer(p); | 875 for (Object** p = start; p < end; p++) ScavengePointer(p); |
| 877 } | 876 } |
| 878 | 877 |
| 879 private: | 878 private: |
| 880 void ScavengePointer(Object** p) { | 879 void ScavengePointer(Object** p) { |
| 881 Object* object = *p; | 880 Object* object = *p; |
| 882 if (!Heap::InNewSpace(object)) return; | 881 if (!heap_->InNewSpace(object)) return; |
| 883 Heap::ScavengeObject(reinterpret_cast<HeapObject**>(p), | 882 Heap::ScavengeObject(reinterpret_cast<HeapObject**>(p), |
| 884 reinterpret_cast<HeapObject*>(object)); | 883 reinterpret_cast<HeapObject*>(object)); |
| 885 } | 884 } |
| 885 |
| 886 Heap* heap_; |
| 886 }; | 887 }; |
| 887 | 888 |
| 888 | 889 |
| 889 // A queue of objects promoted during scavenge. Each object is accompanied | |
| 890 // by it's size to avoid dereferencing a map pointer for scanning. | |
| 891 class PromotionQueue { | |
| 892 public: | |
| 893 void Initialize(Address start_address) { | |
| 894 front_ = rear_ = reinterpret_cast<intptr_t*>(start_address); | |
| 895 } | |
| 896 | |
| 897 bool is_empty() { return front_ <= rear_; } | |
| 898 | |
| 899 void insert(HeapObject* target, int size) { | |
| 900 *(--rear_) = reinterpret_cast<intptr_t>(target); | |
| 901 *(--rear_) = size; | |
| 902 // Assert no overflow into live objects. | |
| 903 ASSERT(reinterpret_cast<Address>(rear_) >= Heap::new_space()->top()); | |
| 904 } | |
| 905 | |
| 906 void remove(HeapObject** target, int* size) { | |
| 907 *target = reinterpret_cast<HeapObject*>(*(--front_)); | |
| 908 *size = static_cast<int>(*(--front_)); | |
| 909 // Assert no underflow. | |
| 910 ASSERT(front_ >= rear_); | |
| 911 } | |
| 912 | |
| 913 private: | |
| 914 // The front of the queue is higher in memory than the rear. | |
| 915 intptr_t* front_; | |
| 916 intptr_t* rear_; | |
| 917 }; | |
| 918 | |
| 919 | |
| 920 // Shared state read by the scavenge collector and set by ScavengeObject. | |
| 921 static PromotionQueue promotion_queue; | |
| 922 | |
| 923 | |
| 924 #ifdef DEBUG | 890 #ifdef DEBUG |
| 925 // Visitor class to verify pointers in code or data space do not point into | 891 // Visitor class to verify pointers in code or data space do not point into |
| 926 // new space. | 892 // new space. |
| 927 class VerifyNonPointerSpacePointersVisitor: public ObjectVisitor { | 893 class VerifyNonPointerSpacePointersVisitor: public ObjectVisitor { |
| 928 public: | 894 public: |
| 929 void VisitPointers(Object** start, Object**end) { | 895 void VisitPointers(Object** start, Object**end) { |
| 930 for (Object** current = start; current < end; current++) { | 896 for (Object** current = start; current < end; current++) { |
| 931 if ((*current)->IsHeapObject()) { | 897 if ((*current)->IsHeapObject()) { |
| 932 ASSERT(!Heap::InNewSpace(HeapObject::cast(*current))); | 898 ASSERT(!HEAP->InNewSpace(HeapObject::cast(*current))); |
| 933 } | 899 } |
| 934 } | 900 } |
| 935 } | 901 } |
| 936 }; | 902 }; |
| 937 | 903 |
| 938 | 904 |
| 939 static void VerifyNonPointerSpacePointers() { | 905 static void VerifyNonPointerSpacePointers() { |
| 940 // Verify that there are no pointers to new space in spaces where we | 906 // Verify that there are no pointers to new space in spaces where we |
| 941 // do not expect them. | 907 // do not expect them. |
| 942 VerifyNonPointerSpacePointersVisitor v; | 908 VerifyNonPointerSpacePointersVisitor v; |
| 943 HeapObjectIterator code_it(Heap::code_space()); | 909 HeapObjectIterator code_it(HEAP->code_space()); |
| 944 for (HeapObject* object = code_it.next(); | 910 for (HeapObject* object = code_it.next(); |
| 945 object != NULL; object = code_it.next()) | 911 object != NULL; object = code_it.next()) |
| 946 object->Iterate(&v); | 912 object->Iterate(&v); |
| 947 | 913 |
| 948 HeapObjectIterator data_it(Heap::old_data_space()); | 914 HeapObjectIterator data_it(HEAP->old_data_space()); |
| 949 for (HeapObject* object = data_it.next(); | 915 for (HeapObject* object = data_it.next(); |
| 950 object != NULL; object = data_it.next()) | 916 object != NULL; object = data_it.next()) |
| 951 object->Iterate(&v); | 917 object->Iterate(&v); |
| 952 } | 918 } |
| 953 #endif | 919 #endif |
| 954 | 920 |
| 955 | 921 |
| 956 void Heap::CheckNewSpaceExpansionCriteria() { | 922 void Heap::CheckNewSpaceExpansionCriteria() { |
| 957 if (new_space_.Capacity() < new_space_.MaximumCapacity() && | 923 if (new_space_.Capacity() < new_space_.MaximumCapacity() && |
| 958 survived_since_last_expansion_ > new_space_.Capacity()) { | 924 survived_since_last_expansion_ > new_space_.Capacity()) { |
| 959 // Grow the size of new space if there is room to grow and enough | 925 // Grow the size of new space if there is room to grow and enough |
| 960 // data has survived scavenge since the last expansion. | 926 // data has survived scavenge since the last expansion. |
| 961 new_space_.Grow(); | 927 new_space_.Grow(); |
| 962 survived_since_last_expansion_ = 0; | 928 survived_since_last_expansion_ = 0; |
| 963 } | 929 } |
| 964 } | 930 } |
| 965 | 931 |
| 966 | 932 |
| 967 void Heap::Scavenge() { | 933 void Heap::Scavenge() { |
| 968 #ifdef DEBUG | 934 #ifdef DEBUG |
| 969 if (FLAG_enable_slow_asserts) VerifyNonPointerSpacePointers(); | 935 if (FLAG_enable_slow_asserts) VerifyNonPointerSpacePointers(); |
| 970 #endif | 936 #endif |
| 971 | 937 |
| 972 gc_state_ = SCAVENGE; | 938 gc_state_ = SCAVENGE; |
| 973 | 939 |
| 974 Page::FlipMeaningOfInvalidatedWatermarkFlag(); | 940 Page::FlipMeaningOfInvalidatedWatermarkFlag(this); |
| 975 #ifdef DEBUG | 941 #ifdef DEBUG |
| 976 VerifyPageWatermarkValidity(old_pointer_space_, ALL_VALID); | 942 VerifyPageWatermarkValidity(old_pointer_space_, ALL_VALID); |
| 977 VerifyPageWatermarkValidity(map_space_, ALL_VALID); | 943 VerifyPageWatermarkValidity(map_space_, ALL_VALID); |
| 978 #endif | 944 #endif |
| 979 | 945 |
| 980 // We do not update an allocation watermark of the top page during linear | 946 // We do not update an allocation watermark of the top page during linear |
| 981 // allocation to avoid overhead. So to maintain the watermark invariant | 947 // allocation to avoid overhead. So to maintain the watermark invariant |
| 982 // we have to manually cache the watermark and mark the top page as having an | 948 // we have to manually cache the watermark and mark the top page as having an |
| 983 // invalid watermark. This guarantees that dirty regions iteration will use a | 949 // invalid watermark. This guarantees that dirty regions iteration will use a |
| 984 // correct watermark even if a linear allocation happens. | 950 // correct watermark even if a linear allocation happens. |
| 985 old_pointer_space_->FlushTopPageWatermark(); | 951 old_pointer_space_->FlushTopPageWatermark(); |
| 986 map_space_->FlushTopPageWatermark(); | 952 map_space_->FlushTopPageWatermark(); |
| 987 | 953 |
| 988 // Implements Cheney's copying algorithm | 954 // Implements Cheney's copying algorithm |
| 989 LOG(ResourceEvent("scavenge", "begin")); | 955 LOG(isolate_, ResourceEvent("scavenge", "begin")); |
| 990 | 956 |
| 991 // Clear descriptor cache. | 957 // Clear descriptor cache. |
| 992 DescriptorLookupCache::Clear(); | 958 isolate_->descriptor_lookup_cache()->Clear(); |
| 993 | 959 |
| 994 // Used for updating survived_since_last_expansion_ at function end. | 960 // Used for updating survived_since_last_expansion_ at function end. |
| 995 intptr_t survived_watermark = PromotedSpaceSize(); | 961 intptr_t survived_watermark = PromotedSpaceSize(); |
| 996 | 962 |
| 997 CheckNewSpaceExpansionCriteria(); | 963 CheckNewSpaceExpansionCriteria(); |
| 998 | 964 |
| 999 // Flip the semispaces. After flipping, to space is empty, from space has | 965 // Flip the semispaces. After flipping, to space is empty, from space has |
| 1000 // live objects. | 966 // live objects. |
| 1001 new_space_.Flip(); | 967 new_space_.Flip(); |
| 1002 new_space_.ResetAllocationInfo(); | 968 new_space_.ResetAllocationInfo(); |
| 1003 | 969 |
| 1004 // We need to sweep newly copied objects which can be either in the | 970 // We need to sweep newly copied objects which can be either in the |
| 1005 // to space or promoted to the old generation. For to-space | 971 // to space or promoted to the old generation. For to-space |
| 1006 // objects, we treat the bottom of the to space as a queue. Newly | 972 // objects, we treat the bottom of the to space as a queue. Newly |
| 1007 // copied and unswept objects lie between a 'front' mark and the | 973 // copied and unswept objects lie between a 'front' mark and the |
| 1008 // allocation pointer. | 974 // allocation pointer. |
| 1009 // | 975 // |
| 1010 // Promoted objects can go into various old-generation spaces, and | 976 // Promoted objects can go into various old-generation spaces, and |
| 1011 // can be allocated internally in the spaces (from the free list). | 977 // can be allocated internally in the spaces (from the free list). |
| 1012 // We treat the top of the to space as a queue of addresses of | 978 // We treat the top of the to space as a queue of addresses of |
| 1013 // promoted objects. The addresses of newly promoted and unswept | 979 // promoted objects. The addresses of newly promoted and unswept |
| 1014 // objects lie between a 'front' mark and a 'rear' mark that is | 980 // objects lie between a 'front' mark and a 'rear' mark that is |
| 1015 // updated as a side effect of promoting an object. | 981 // updated as a side effect of promoting an object. |
| 1016 // | 982 // |
| 1017 // There is guaranteed to be enough room at the top of the to space | 983 // There is guaranteed to be enough room at the top of the to space |
| 1018 // for the addresses of promoted objects: every object promoted | 984 // for the addresses of promoted objects: every object promoted |
| 1019 // frees up its size in bytes from the top of the new space, and | 985 // frees up its size in bytes from the top of the new space, and |
| 1020 // objects are at least one pointer in size. | 986 // objects are at least one pointer in size. |
| 1021 Address new_space_front = new_space_.ToSpaceLow(); | 987 Address new_space_front = new_space_.ToSpaceLow(); |
| 1022 promotion_queue.Initialize(new_space_.ToSpaceHigh()); | 988 promotion_queue_.Initialize(new_space_.ToSpaceHigh()); |
| 1023 | 989 |
| 1024 ScavengeVisitor scavenge_visitor; | 990 is_safe_to_read_maps_ = false; |
| 991 ScavengeVisitor scavenge_visitor(this); |
| 1025 // Copy roots. | 992 // Copy roots. |
| 1026 IterateRoots(&scavenge_visitor, VISIT_ALL_IN_SCAVENGE); | 993 IterateRoots(&scavenge_visitor, VISIT_ALL_IN_SCAVENGE); |
| 1027 | 994 |
| 1028 // Copy objects reachable from the old generation. By definition, | 995 // Copy objects reachable from the old generation. By definition, |
| 1029 // there are no intergenerational pointers in code or data spaces. | 996 // there are no intergenerational pointers in code or data spaces. |
| 1030 IterateDirtyRegions(old_pointer_space_, | 997 IterateDirtyRegions(old_pointer_space_, |
| 1031 &IteratePointersInDirtyRegion, | 998 &Heap::IteratePointersInDirtyRegion, |
| 1032 &ScavengePointer, | 999 &ScavengePointer, |
| 1033 WATERMARK_CAN_BE_INVALID); | 1000 WATERMARK_CAN_BE_INVALID); |
| 1034 | 1001 |
| 1035 IterateDirtyRegions(map_space_, | 1002 IterateDirtyRegions(map_space_, |
| 1036 &IteratePointersInDirtyMapsRegion, | 1003 &IteratePointersInDirtyMapsRegion, |
| 1037 &ScavengePointer, | 1004 &ScavengePointer, |
| 1038 WATERMARK_CAN_BE_INVALID); | 1005 WATERMARK_CAN_BE_INVALID); |
| 1039 | 1006 |
| 1040 lo_space_->IterateDirtyRegions(&ScavengePointer); | 1007 lo_space_->IterateDirtyRegions(&ScavengePointer); |
| 1041 | 1008 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1053 | 1020 |
| 1054 // Scavenge object reachable from the global contexts list directly. | 1021 // Scavenge object reachable from the global contexts list directly. |
| 1055 scavenge_visitor.VisitPointer(BitCast<Object**>(&global_contexts_list_)); | 1022 scavenge_visitor.VisitPointer(BitCast<Object**>(&global_contexts_list_)); |
| 1056 | 1023 |
| 1057 new_space_front = DoScavenge(&scavenge_visitor, new_space_front); | 1024 new_space_front = DoScavenge(&scavenge_visitor, new_space_front); |
| 1058 | 1025 |
| 1059 UpdateNewSpaceReferencesInExternalStringTable( | 1026 UpdateNewSpaceReferencesInExternalStringTable( |
| 1060 &UpdateNewSpaceReferenceInExternalStringTableEntry); | 1027 &UpdateNewSpaceReferenceInExternalStringTableEntry); |
| 1061 | 1028 |
| 1062 LiveObjectList::UpdateReferencesForScavengeGC(); | 1029 LiveObjectList::UpdateReferencesForScavengeGC(); |
| 1063 RuntimeProfiler::UpdateSamplesAfterScavenge(); | 1030 isolate()->runtime_profiler()->UpdateSamplesAfterScavenge(); |
| 1064 | 1031 |
| 1065 ASSERT(new_space_front == new_space_.top()); | 1032 ASSERT(new_space_front == new_space_.top()); |
| 1066 | 1033 |
| 1034 is_safe_to_read_maps_ = true; |
| 1035 |
| 1067 // Set age mark. | 1036 // Set age mark. |
| 1068 new_space_.set_age_mark(new_space_.top()); | 1037 new_space_.set_age_mark(new_space_.top()); |
| 1069 | 1038 |
| 1070 // Update how much has survived scavenge. | 1039 // Update how much has survived scavenge. |
| 1071 IncrementYoungSurvivorsCounter(static_cast<int>( | 1040 IncrementYoungSurvivorsCounter(static_cast<int>( |
| 1072 (PromotedSpaceSize() - survived_watermark) + new_space_.Size())); | 1041 (PromotedSpaceSize() - survived_watermark) + new_space_.Size())); |
| 1073 | 1042 |
| 1074 LOG(ResourceEvent("scavenge", "end")); | 1043 LOG(isolate_, ResourceEvent("scavenge", "end")); |
| 1075 | 1044 |
| 1076 gc_state_ = NOT_IN_GC; | 1045 gc_state_ = NOT_IN_GC; |
| 1077 } | 1046 } |
| 1078 | 1047 |
| 1079 | 1048 |
| 1080 String* Heap::UpdateNewSpaceReferenceInExternalStringTableEntry(Object** p) { | 1049 String* Heap::UpdateNewSpaceReferenceInExternalStringTableEntry(Heap* heap, |
| 1050 Object** p) { |
| 1081 MapWord first_word = HeapObject::cast(*p)->map_word(); | 1051 MapWord first_word = HeapObject::cast(*p)->map_word(); |
| 1082 | 1052 |
| 1083 if (!first_word.IsForwardingAddress()) { | 1053 if (!first_word.IsForwardingAddress()) { |
| 1084 // Unreachable external string can be finalized. | 1054 // Unreachable external string can be finalized. |
| 1085 FinalizeExternalString(String::cast(*p)); | 1055 heap->FinalizeExternalString(String::cast(*p)); |
| 1086 return NULL; | 1056 return NULL; |
| 1087 } | 1057 } |
| 1088 | 1058 |
| 1089 // String is still reachable. | 1059 // String is still reachable. |
| 1090 return String::cast(first_word.ToForwardingAddress()); | 1060 return String::cast(first_word.ToForwardingAddress()); |
| 1091 } | 1061 } |
| 1092 | 1062 |
| 1093 | 1063 |
| 1094 void Heap::UpdateNewSpaceReferencesInExternalStringTable( | 1064 void Heap::UpdateNewSpaceReferencesInExternalStringTable( |
| 1095 ExternalStringTableUpdaterCallback updater_func) { | 1065 ExternalStringTableUpdaterCallback updater_func) { |
| 1096 ExternalStringTable::Verify(); | 1066 external_string_table_.Verify(); |
| 1097 | 1067 |
| 1098 if (ExternalStringTable::new_space_strings_.is_empty()) return; | 1068 if (external_string_table_.new_space_strings_.is_empty()) return; |
| 1099 | 1069 |
| 1100 Object** start = &ExternalStringTable::new_space_strings_[0]; | 1070 Object** start = &external_string_table_.new_space_strings_[0]; |
| 1101 Object** end = start + ExternalStringTable::new_space_strings_.length(); | 1071 Object** end = start + external_string_table_.new_space_strings_.length(); |
| 1102 Object** last = start; | 1072 Object** last = start; |
| 1103 | 1073 |
| 1104 for (Object** p = start; p < end; ++p) { | 1074 for (Object** p = start; p < end; ++p) { |
| 1105 ASSERT(Heap::InFromSpace(*p)); | 1075 ASSERT(InFromSpace(*p)); |
| 1106 String* target = updater_func(p); | 1076 String* target = updater_func(this, p); |
| 1107 | 1077 |
| 1108 if (target == NULL) continue; | 1078 if (target == NULL) continue; |
| 1109 | 1079 |
| 1110 ASSERT(target->IsExternalString()); | 1080 ASSERT(target->IsExternalString()); |
| 1111 | 1081 |
| 1112 if (Heap::InNewSpace(target)) { | 1082 if (InNewSpace(target)) { |
| 1113 // String is still in new space. Update the table entry. | 1083 // String is still in new space. Update the table entry. |
| 1114 *last = target; | 1084 *last = target; |
| 1115 ++last; | 1085 ++last; |
| 1116 } else { | 1086 } else { |
| 1117 // String got promoted. Move it to the old string list. | 1087 // String got promoted. Move it to the old string list. |
| 1118 ExternalStringTable::AddOldString(target); | 1088 external_string_table_.AddOldString(target); |
| 1119 } | 1089 } |
| 1120 } | 1090 } |
| 1121 | 1091 |
| 1122 ASSERT(last <= end); | 1092 ASSERT(last <= end); |
| 1123 ExternalStringTable::ShrinkNewStrings(static_cast<int>(last - start)); | 1093 external_string_table_.ShrinkNewStrings(static_cast<int>(last - start)); |
| 1124 } | 1094 } |
| 1125 | 1095 |
| 1126 | 1096 |
| 1127 static Object* ProcessFunctionWeakReferences(Object* function, | 1097 static Object* ProcessFunctionWeakReferences(Heap* heap, |
| 1098 Object* function, |
| 1128 WeakObjectRetainer* retainer) { | 1099 WeakObjectRetainer* retainer) { |
| 1129 Object* head = Heap::undefined_value(); | 1100 Object* head = heap->undefined_value(); |
| 1130 JSFunction* tail = NULL; | 1101 JSFunction* tail = NULL; |
| 1131 Object* candidate = function; | 1102 Object* candidate = function; |
| 1132 while (!candidate->IsUndefined()) { | 1103 while (candidate != heap->undefined_value()) { |
| 1133 // Check whether to keep the candidate in the list. | 1104 // Check whether to keep the candidate in the list. |
| 1134 JSFunction* candidate_function = reinterpret_cast<JSFunction*>(candidate); | 1105 JSFunction* candidate_function = reinterpret_cast<JSFunction*>(candidate); |
| 1135 Object* retain = retainer->RetainAs(candidate); | 1106 Object* retain = retainer->RetainAs(candidate); |
| 1136 if (retain != NULL) { | 1107 if (retain != NULL) { |
| 1137 if (head->IsUndefined()) { | 1108 if (head == heap->undefined_value()) { |
| 1138 // First element in the list. | 1109 // First element in the list. |
| 1139 head = candidate_function; | 1110 head = candidate_function; |
| 1140 } else { | 1111 } else { |
| 1141 // Subsequent elements in the list. | 1112 // Subsequent elements in the list. |
| 1142 ASSERT(tail != NULL); | 1113 ASSERT(tail != NULL); |
| 1143 tail->set_next_function_link(candidate_function); | 1114 tail->set_next_function_link(candidate_function); |
| 1144 } | 1115 } |
| 1145 // Retained function is new tail. | 1116 // Retained function is new tail. |
| 1146 tail = candidate_function; | 1117 tail = candidate_function; |
| 1147 } | 1118 } |
| 1148 // Move to next element in the list. | 1119 // Move to next element in the list. |
| 1149 candidate = candidate_function->next_function_link(); | 1120 candidate = candidate_function->next_function_link(); |
| 1150 } | 1121 } |
| 1151 | 1122 |
| 1152 // Terminate the list if there is one or more elements. | 1123 // Terminate the list if there is one or more elements. |
| 1153 if (tail != NULL) { | 1124 if (tail != NULL) { |
| 1154 tail->set_next_function_link(Heap::undefined_value()); | 1125 tail->set_next_function_link(heap->undefined_value()); |
| 1155 } | 1126 } |
| 1156 | 1127 |
| 1157 return head; | 1128 return head; |
| 1158 } | 1129 } |
| 1159 | 1130 |
| 1160 | 1131 |
| 1161 void Heap::ProcessWeakReferences(WeakObjectRetainer* retainer) { | 1132 void Heap::ProcessWeakReferences(WeakObjectRetainer* retainer) { |
| 1162 Object* head = undefined_value(); | 1133 Object* head = undefined_value(); |
| 1163 Context* tail = NULL; | 1134 Context* tail = NULL; |
| 1164 Object* candidate = global_contexts_list_; | 1135 Object* candidate = global_contexts_list_; |
| 1165 while (!candidate->IsUndefined()) { | 1136 while (candidate != undefined_value()) { |
| 1166 // Check whether to keep the candidate in the list. | 1137 // Check whether to keep the candidate in the list. |
| 1167 Context* candidate_context = reinterpret_cast<Context*>(candidate); | 1138 Context* candidate_context = reinterpret_cast<Context*>(candidate); |
| 1168 Object* retain = retainer->RetainAs(candidate); | 1139 Object* retain = retainer->RetainAs(candidate); |
| 1169 if (retain != NULL) { | 1140 if (retain != NULL) { |
| 1170 if (head->IsUndefined()) { | 1141 if (head == undefined_value()) { |
| 1171 // First element in the list. | 1142 // First element in the list. |
| 1172 head = candidate_context; | 1143 head = candidate_context; |
| 1173 } else { | 1144 } else { |
| 1174 // Subsequent elements in the list. | 1145 // Subsequent elements in the list. |
| 1175 ASSERT(tail != NULL); | 1146 ASSERT(tail != NULL); |
| 1176 tail->set_unchecked(Context::NEXT_CONTEXT_LINK, | 1147 tail->set_unchecked(this, |
| 1148 Context::NEXT_CONTEXT_LINK, |
| 1177 candidate_context, | 1149 candidate_context, |
| 1178 UPDATE_WRITE_BARRIER); | 1150 UPDATE_WRITE_BARRIER); |
| 1179 } | 1151 } |
| 1180 // Retained context is new tail. | 1152 // Retained context is new tail. |
| 1181 tail = candidate_context; | 1153 tail = candidate_context; |
| 1182 | 1154 |
| 1183 // Process the weak list of optimized functions for the context. | 1155 // Process the weak list of optimized functions for the context. |
| 1184 Object* function_list_head = | 1156 Object* function_list_head = |
| 1185 ProcessFunctionWeakReferences( | 1157 ProcessFunctionWeakReferences( |
| 1158 this, |
| 1186 candidate_context->get(Context::OPTIMIZED_FUNCTIONS_LIST), | 1159 candidate_context->get(Context::OPTIMIZED_FUNCTIONS_LIST), |
| 1187 retainer); | 1160 retainer); |
| 1188 candidate_context->set_unchecked(Context::OPTIMIZED_FUNCTIONS_LIST, | 1161 candidate_context->set_unchecked(this, |
| 1162 Context::OPTIMIZED_FUNCTIONS_LIST, |
| 1189 function_list_head, | 1163 function_list_head, |
| 1190 UPDATE_WRITE_BARRIER); | 1164 UPDATE_WRITE_BARRIER); |
| 1191 } | 1165 } |
| 1192 // Move to next element in the list. | 1166 // Move to next element in the list. |
| 1193 candidate = candidate_context->get(Context::NEXT_CONTEXT_LINK); | 1167 candidate = candidate_context->get(Context::NEXT_CONTEXT_LINK); |
| 1194 } | 1168 } |
| 1195 | 1169 |
| 1196 // Terminate the list if there is one or more elements. | 1170 // Terminate the list if there is one or more elements. |
| 1197 if (tail != NULL) { | 1171 if (tail != NULL) { |
| 1198 tail->set_unchecked(Context::NEXT_CONTEXT_LINK, | 1172 tail->set_unchecked(this, |
| 1173 Context::NEXT_CONTEXT_LINK, |
| 1199 Heap::undefined_value(), | 1174 Heap::undefined_value(), |
| 1200 UPDATE_WRITE_BARRIER); | 1175 UPDATE_WRITE_BARRIER); |
| 1201 } | 1176 } |
| 1202 | 1177 |
| 1203 // Update the head of the list of contexts. | 1178 // Update the head of the list of contexts. |
| 1204 Heap::global_contexts_list_ = head; | 1179 global_contexts_list_ = head; |
| 1205 } | 1180 } |
| 1206 | 1181 |
| 1207 | 1182 |
| 1208 class NewSpaceScavenger : public StaticNewSpaceVisitor<NewSpaceScavenger> { | 1183 class NewSpaceScavenger : public StaticNewSpaceVisitor<NewSpaceScavenger> { |
| 1209 public: | 1184 public: |
| 1210 static inline void VisitPointer(Object** p) { | 1185 static inline void VisitPointer(Heap* heap, Object** p) { |
| 1211 Object* object = *p; | 1186 Object* object = *p; |
| 1212 if (!Heap::InNewSpace(object)) return; | 1187 if (!heap->InNewSpace(object)) return; |
| 1213 Heap::ScavengeObject(reinterpret_cast<HeapObject**>(p), | 1188 Heap::ScavengeObject(reinterpret_cast<HeapObject**>(p), |
| 1214 reinterpret_cast<HeapObject*>(object)); | 1189 reinterpret_cast<HeapObject*>(object)); |
| 1215 } | 1190 } |
| 1216 }; | 1191 }; |
| 1217 | 1192 |
| 1218 | 1193 |
| 1219 Address Heap::DoScavenge(ObjectVisitor* scavenge_visitor, | 1194 Address Heap::DoScavenge(ObjectVisitor* scavenge_visitor, |
| 1220 Address new_space_front) { | 1195 Address new_space_front) { |
| 1221 do { | 1196 do { |
| 1222 ASSERT(new_space_front <= new_space_.top()); | 1197 ASSERT(new_space_front <= new_space_.top()); |
| 1223 | 1198 |
| 1224 // The addresses new_space_front and new_space_.top() define a | 1199 // The addresses new_space_front and new_space_.top() define a |
| 1225 // queue of unprocessed copied objects. Process them until the | 1200 // queue of unprocessed copied objects. Process them until the |
| 1226 // queue is empty. | 1201 // queue is empty. |
| 1227 while (new_space_front < new_space_.top()) { | 1202 while (new_space_front < new_space_.top()) { |
| 1228 HeapObject* object = HeapObject::FromAddress(new_space_front); | 1203 HeapObject* object = HeapObject::FromAddress(new_space_front); |
| 1229 new_space_front += NewSpaceScavenger::IterateBody(object->map(), object); | 1204 new_space_front += NewSpaceScavenger::IterateBody(object->map(), object); |
| 1230 } | 1205 } |
| 1231 | 1206 |
| 1232 // Promote and process all the to-be-promoted objects. | 1207 // Promote and process all the to-be-promoted objects. |
| 1233 while (!promotion_queue.is_empty()) { | 1208 while (!promotion_queue_.is_empty()) { |
| 1234 HeapObject* target; | 1209 HeapObject* target; |
| 1235 int size; | 1210 int size; |
| 1236 promotion_queue.remove(&target, &size); | 1211 promotion_queue_.remove(&target, &size); |
| 1237 | 1212 |
| 1238 // Promoted object might be already partially visited | 1213 // Promoted object might be already partially visited |
| 1239 // during dirty regions iteration. Thus we search specificly | 1214 // during dirty regions iteration. Thus we search specificly |
| 1240 // for pointers to from semispace instead of looking for pointers | 1215 // for pointers to from semispace instead of looking for pointers |
| 1241 // to new space. | 1216 // to new space. |
| 1242 ASSERT(!target->IsMap()); | 1217 ASSERT(!target->IsMap()); |
| 1243 IterateAndMarkPointersToFromSpace(target->address(), | 1218 IterateAndMarkPointersToFromSpace(target->address(), |
| 1244 target->address() + size, | 1219 target->address() + size, |
| 1245 &ScavengePointer); | 1220 &ScavengePointer); |
| 1246 } | 1221 } |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1296 static inline void Scavenge(Map* map, HeapObject** slot, HeapObject* obj) { | 1271 static inline void Scavenge(Map* map, HeapObject** slot, HeapObject* obj) { |
| 1297 table_.GetVisitor(map)(map, slot, obj); | 1272 table_.GetVisitor(map)(map, slot, obj); |
| 1298 } | 1273 } |
| 1299 | 1274 |
| 1300 | 1275 |
| 1301 private: | 1276 private: |
| 1302 enum ObjectContents { DATA_OBJECT, POINTER_OBJECT }; | 1277 enum ObjectContents { DATA_OBJECT, POINTER_OBJECT }; |
| 1303 enum SizeRestriction { SMALL, UNKNOWN_SIZE }; | 1278 enum SizeRestriction { SMALL, UNKNOWN_SIZE }; |
| 1304 | 1279 |
| 1305 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) | 1280 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) |
| 1306 static void RecordCopiedObject(HeapObject* obj) { | 1281 static void RecordCopiedObject(Heap* heap, HeapObject* obj) { |
| 1307 bool should_record = false; | 1282 bool should_record = false; |
| 1308 #ifdef DEBUG | 1283 #ifdef DEBUG |
| 1309 should_record = FLAG_heap_stats; | 1284 should_record = FLAG_heap_stats; |
| 1310 #endif | 1285 #endif |
| 1311 #ifdef ENABLE_LOGGING_AND_PROFILING | 1286 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 1312 should_record = should_record || FLAG_log_gc; | 1287 should_record = should_record || FLAG_log_gc; |
| 1313 #endif | 1288 #endif |
| 1314 if (should_record) { | 1289 if (should_record) { |
| 1315 if (Heap::new_space()->Contains(obj)) { | 1290 if (heap->new_space()->Contains(obj)) { |
| 1316 Heap::new_space()->RecordAllocation(obj); | 1291 heap->new_space()->RecordAllocation(obj); |
| 1317 } else { | 1292 } else { |
| 1318 Heap::new_space()->RecordPromotion(obj); | 1293 heap->new_space()->RecordPromotion(obj); |
| 1319 } | 1294 } |
| 1320 } | 1295 } |
| 1321 } | 1296 } |
| 1322 #endif // defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) | 1297 #endif // defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) |
| 1323 | 1298 |
| 1324 // Helper function used by CopyObject to copy a source object to an | 1299 // Helper function used by CopyObject to copy a source object to an |
| 1325 // allocated target object and update the forwarding pointer in the source | 1300 // allocated target object and update the forwarding pointer in the source |
| 1326 // object. Returns the target object. | 1301 // object. Returns the target object. |
| 1327 INLINE(static HeapObject* MigrateObject(HeapObject* source, | 1302 INLINE(static HeapObject* MigrateObject(Heap* heap, |
| 1303 HeapObject* source, |
| 1328 HeapObject* target, | 1304 HeapObject* target, |
| 1329 int size)) { | 1305 int size)) { |
| 1330 // Copy the content of source to target. | 1306 // Copy the content of source to target. |
| 1331 Heap::CopyBlock(target->address(), source->address(), size); | 1307 heap->CopyBlock(target->address(), source->address(), size); |
| 1332 | 1308 |
| 1333 // Set the forwarding address. | 1309 // Set the forwarding address. |
| 1334 source->set_map_word(MapWord::FromForwardingAddress(target)); | 1310 source->set_map_word(MapWord::FromForwardingAddress(target)); |
| 1335 | 1311 |
| 1336 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) | 1312 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) |
| 1337 // Update NewSpace stats if necessary. | 1313 // Update NewSpace stats if necessary. |
| 1338 RecordCopiedObject(target); | 1314 RecordCopiedObject(heap, target); |
| 1339 #endif | 1315 #endif |
| 1340 HEAP_PROFILE(ObjectMoveEvent(source->address(), target->address())); | 1316 HEAP_PROFILE(heap, ObjectMoveEvent(source->address(), target->address())); |
| 1341 #if defined(ENABLE_LOGGING_AND_PROFILING) | 1317 #if defined(ENABLE_LOGGING_AND_PROFILING) |
| 1342 if (Logger::is_logging() || CpuProfiler::is_profiling()) { | 1318 Isolate* isolate = heap->isolate(); |
| 1319 if (isolate->logger()->is_logging() || |
| 1320 isolate->cpu_profiler()->is_profiling()) { |
| 1343 if (target->IsSharedFunctionInfo()) { | 1321 if (target->IsSharedFunctionInfo()) { |
| 1344 PROFILE(SharedFunctionInfoMoveEvent( | 1322 PROFILE(isolate, SharedFunctionInfoMoveEvent( |
| 1345 source->address(), target->address())); | 1323 source->address(), target->address())); |
| 1346 } | 1324 } |
| 1347 } | 1325 } |
| 1348 #endif | 1326 #endif |
| 1349 return target; | 1327 return target; |
| 1350 } | 1328 } |
| 1351 | 1329 |
| 1352 | 1330 |
| 1353 template<ObjectContents object_contents, SizeRestriction size_restriction> | 1331 template<ObjectContents object_contents, SizeRestriction size_restriction> |
| 1354 static inline void EvacuateObject(Map* map, | 1332 static inline void EvacuateObject(Map* map, |
| 1355 HeapObject** slot, | 1333 HeapObject** slot, |
| 1356 HeapObject* object, | 1334 HeapObject* object, |
| 1357 int object_size) { | 1335 int object_size) { |
| 1358 ASSERT((size_restriction != SMALL) || | 1336 ASSERT((size_restriction != SMALL) || |
| 1359 (object_size <= Page::kMaxHeapObjectSize)); | 1337 (object_size <= Page::kMaxHeapObjectSize)); |
| 1360 ASSERT(object->Size() == object_size); | 1338 ASSERT(object->Size() == object_size); |
| 1361 | 1339 |
| 1362 if (Heap::ShouldBePromoted(object->address(), object_size)) { | 1340 Heap* heap = map->heap(); |
| 1341 if (heap->ShouldBePromoted(object->address(), object_size)) { |
| 1363 MaybeObject* maybe_result; | 1342 MaybeObject* maybe_result; |
| 1364 | 1343 |
| 1365 if ((size_restriction != SMALL) && | 1344 if ((size_restriction != SMALL) && |
| 1366 (object_size > Page::kMaxHeapObjectSize)) { | 1345 (object_size > Page::kMaxHeapObjectSize)) { |
| 1367 maybe_result = Heap::lo_space()->AllocateRawFixedArray(object_size); | 1346 maybe_result = heap->lo_space()->AllocateRawFixedArray(object_size); |
| 1368 } else { | 1347 } else { |
| 1369 if (object_contents == DATA_OBJECT) { | 1348 if (object_contents == DATA_OBJECT) { |
| 1370 maybe_result = Heap::old_data_space()->AllocateRaw(object_size); | 1349 maybe_result = heap->old_data_space()->AllocateRaw(object_size); |
| 1371 } else { | 1350 } else { |
| 1372 maybe_result = Heap::old_pointer_space()->AllocateRaw(object_size); | 1351 maybe_result = heap->old_pointer_space()->AllocateRaw(object_size); |
| 1373 } | 1352 } |
| 1374 } | 1353 } |
| 1375 | 1354 |
| 1376 Object* result = NULL; // Initialization to please compiler. | 1355 Object* result = NULL; // Initialization to please compiler. |
| 1377 if (maybe_result->ToObject(&result)) { | 1356 if (maybe_result->ToObject(&result)) { |
| 1378 HeapObject* target = HeapObject::cast(result); | 1357 HeapObject* target = HeapObject::cast(result); |
| 1379 *slot = MigrateObject(object, target, object_size); | 1358 *slot = MigrateObject(heap, object , target, object_size); |
| 1380 | 1359 |
| 1381 if (object_contents == POINTER_OBJECT) { | 1360 if (object_contents == POINTER_OBJECT) { |
| 1382 promotion_queue.insert(target, object_size); | 1361 heap->promotion_queue()->insert(target, object_size); |
| 1383 } | 1362 } |
| 1384 | 1363 |
| 1385 Heap::tracer()->increment_promoted_objects_size(object_size); | 1364 heap->tracer()->increment_promoted_objects_size(object_size); |
| 1386 return; | 1365 return; |
| 1387 } | 1366 } |
| 1388 } | 1367 } |
| 1389 Object* result = | 1368 Object* result = |
| 1390 Heap::new_space()->AllocateRaw(object_size)->ToObjectUnchecked(); | 1369 heap->new_space()->AllocateRaw(object_size)->ToObjectUnchecked(); |
| 1391 *slot = MigrateObject(object, HeapObject::cast(result), object_size); | 1370 *slot = MigrateObject(heap, object, HeapObject::cast(result), object_size); |
| 1392 return; | 1371 return; |
| 1393 } | 1372 } |
| 1394 | 1373 |
| 1395 | 1374 |
| 1396 static inline void EvacuateFixedArray(Map* map, | 1375 static inline void EvacuateFixedArray(Map* map, |
| 1397 HeapObject** slot, | 1376 HeapObject** slot, |
| 1398 HeapObject* object) { | 1377 HeapObject* object) { |
| 1399 int object_size = FixedArray::BodyDescriptor::SizeOf(map, object); | 1378 int object_size = FixedArray::BodyDescriptor::SizeOf(map, object); |
| 1400 EvacuateObject<POINTER_OBJECT, UNKNOWN_SIZE>(map, | 1379 EvacuateObject<POINTER_OBJECT, UNKNOWN_SIZE>(map, |
| 1401 slot, | 1380 slot, |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1432 | 1411 |
| 1433 static inline bool IsShortcutCandidate(int type) { | 1412 static inline bool IsShortcutCandidate(int type) { |
| 1434 return ((type & kShortcutTypeMask) == kShortcutTypeTag); | 1413 return ((type & kShortcutTypeMask) == kShortcutTypeTag); |
| 1435 } | 1414 } |
| 1436 | 1415 |
| 1437 static inline void EvacuateShortcutCandidate(Map* map, | 1416 static inline void EvacuateShortcutCandidate(Map* map, |
| 1438 HeapObject** slot, | 1417 HeapObject** slot, |
| 1439 HeapObject* object) { | 1418 HeapObject* object) { |
| 1440 ASSERT(IsShortcutCandidate(map->instance_type())); | 1419 ASSERT(IsShortcutCandidate(map->instance_type())); |
| 1441 | 1420 |
| 1442 if (ConsString::cast(object)->unchecked_second() == Heap::empty_string()) { | 1421 if (ConsString::cast(object)->unchecked_second() == |
| 1422 map->heap()->empty_string()) { |
| 1443 HeapObject* first = | 1423 HeapObject* first = |
| 1444 HeapObject::cast(ConsString::cast(object)->unchecked_first()); | 1424 HeapObject::cast(ConsString::cast(object)->unchecked_first()); |
| 1445 | 1425 |
| 1446 *slot = first; | 1426 *slot = first; |
| 1447 | 1427 |
| 1448 if (!Heap::InNewSpace(first)) { | 1428 if (!map->heap()->InNewSpace(first)) { |
| 1449 object->set_map_word(MapWord::FromForwardingAddress(first)); | 1429 object->set_map_word(MapWord::FromForwardingAddress(first)); |
| 1450 return; | 1430 return; |
| 1451 } | 1431 } |
| 1452 | 1432 |
| 1453 MapWord first_word = first->map_word(); | 1433 MapWord first_word = first->map_word(); |
| 1454 if (first_word.IsForwardingAddress()) { | 1434 if (first_word.IsForwardingAddress()) { |
| 1455 HeapObject* target = first_word.ToForwardingAddress(); | 1435 HeapObject* target = first_word.ToForwardingAddress(); |
| 1456 | 1436 |
| 1457 *slot = target; | 1437 *slot = target; |
| 1458 object->set_map_word(MapWord::FromForwardingAddress(target)); | 1438 object->set_map_word(MapWord::FromForwardingAddress(target)); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1489 typedef void (*Callback)(Map* map, HeapObject** slot, HeapObject* object); | 1469 typedef void (*Callback)(Map* map, HeapObject** slot, HeapObject* object); |
| 1490 | 1470 |
| 1491 static VisitorDispatchTable<Callback> table_; | 1471 static VisitorDispatchTable<Callback> table_; |
| 1492 }; | 1472 }; |
| 1493 | 1473 |
| 1494 | 1474 |
| 1495 VisitorDispatchTable<ScavengingVisitor::Callback> ScavengingVisitor::table_; | 1475 VisitorDispatchTable<ScavengingVisitor::Callback> ScavengingVisitor::table_; |
| 1496 | 1476 |
| 1497 | 1477 |
| 1498 void Heap::ScavengeObjectSlow(HeapObject** p, HeapObject* object) { | 1478 void Heap::ScavengeObjectSlow(HeapObject** p, HeapObject* object) { |
| 1499 ASSERT(InFromSpace(object)); | 1479 ASSERT(HEAP->InFromSpace(object)); |
| 1500 MapWord first_word = object->map_word(); | 1480 MapWord first_word = object->map_word(); |
| 1501 ASSERT(!first_word.IsForwardingAddress()); | 1481 ASSERT(!first_word.IsForwardingAddress()); |
| 1502 Map* map = first_word.ToMap(); | 1482 Map* map = first_word.ToMap(); |
| 1503 ScavengingVisitor::Scavenge(map, p, object); | 1483 ScavengingVisitor::Scavenge(map, p, object); |
| 1504 } | 1484 } |
| 1505 | 1485 |
| 1506 | 1486 |
| 1507 void Heap::ScavengePointer(HeapObject** p) { | |
| 1508 ScavengeObject(p, *p); | |
| 1509 } | |
| 1510 | |
| 1511 | |
| 1512 MaybeObject* Heap::AllocatePartialMap(InstanceType instance_type, | 1487 MaybeObject* Heap::AllocatePartialMap(InstanceType instance_type, |
| 1513 int instance_size) { | 1488 int instance_size) { |
| 1514 Object* result; | 1489 Object* result; |
| 1515 { MaybeObject* maybe_result = AllocateRawMap(); | 1490 { MaybeObject* maybe_result = AllocateRawMap(); |
| 1516 if (!maybe_result->ToObject(&result)) return maybe_result; | 1491 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 1517 } | 1492 } |
| 1518 | 1493 |
| 1519 // Map::cast cannot be used due to uninitialized map field. | 1494 // Map::cast cannot be used due to uninitialized map field. |
| 1520 reinterpret_cast<Map*>(result)->set_map(raw_unchecked_meta_map()); | 1495 reinterpret_cast<Map*>(result)->set_map(raw_unchecked_meta_map()); |
| 1521 reinterpret_cast<Map*>(result)->set_instance_type(instance_type); | 1496 reinterpret_cast<Map*>(result)->set_instance_type(instance_type); |
| 1522 reinterpret_cast<Map*>(result)->set_instance_size(instance_size); | 1497 reinterpret_cast<Map*>(result)->set_instance_size(instance_size); |
| 1523 reinterpret_cast<Map*>(result)-> | 1498 reinterpret_cast<Map*>(result)->set_visitor_id( |
| 1524 set_visitor_id( | 1499 StaticVisitorBase::GetVisitorId(instance_type, instance_size)); |
| 1525 StaticVisitorBase::GetVisitorId(instance_type, instance_size)); | |
| 1526 reinterpret_cast<Map*>(result)->set_inobject_properties(0); | 1500 reinterpret_cast<Map*>(result)->set_inobject_properties(0); |
| 1527 reinterpret_cast<Map*>(result)->set_pre_allocated_property_fields(0); | 1501 reinterpret_cast<Map*>(result)->set_pre_allocated_property_fields(0); |
| 1528 reinterpret_cast<Map*>(result)->set_unused_property_fields(0); | 1502 reinterpret_cast<Map*>(result)->set_unused_property_fields(0); |
| 1529 reinterpret_cast<Map*>(result)->set_bit_field(0); | 1503 reinterpret_cast<Map*>(result)->set_bit_field(0); |
| 1530 reinterpret_cast<Map*>(result)->set_bit_field2(0); | 1504 reinterpret_cast<Map*>(result)->set_bit_field2(0); |
| 1531 return result; | 1505 return result; |
| 1532 } | 1506 } |
| 1533 | 1507 |
| 1534 | 1508 |
| 1535 MaybeObject* Heap::AllocateMap(InstanceType instance_type, int instance_size) { | 1509 MaybeObject* Heap::AllocateMap(InstanceType instance_type, int instance_size) { |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1624 // Allocate the empty array. | 1598 // Allocate the empty array. |
| 1625 { MaybeObject* maybe_obj = AllocateEmptyFixedArray(); | 1599 { MaybeObject* maybe_obj = AllocateEmptyFixedArray(); |
| 1626 if (!maybe_obj->ToObject(&obj)) return false; | 1600 if (!maybe_obj->ToObject(&obj)) return false; |
| 1627 } | 1601 } |
| 1628 set_empty_fixed_array(FixedArray::cast(obj)); | 1602 set_empty_fixed_array(FixedArray::cast(obj)); |
| 1629 | 1603 |
| 1630 { MaybeObject* maybe_obj = Allocate(oddball_map(), OLD_DATA_SPACE); | 1604 { MaybeObject* maybe_obj = Allocate(oddball_map(), OLD_DATA_SPACE); |
| 1631 if (!maybe_obj->ToObject(&obj)) return false; | 1605 if (!maybe_obj->ToObject(&obj)) return false; |
| 1632 } | 1606 } |
| 1633 set_null_value(obj); | 1607 set_null_value(obj); |
| 1608 Oddball::cast(obj)->set_kind(Oddball::kNull); |
| 1634 | 1609 |
| 1635 // Allocate the empty descriptor array. | 1610 // Allocate the empty descriptor array. |
| 1636 { MaybeObject* maybe_obj = AllocateEmptyFixedArray(); | 1611 { MaybeObject* maybe_obj = AllocateEmptyFixedArray(); |
| 1637 if (!maybe_obj->ToObject(&obj)) return false; | 1612 if (!maybe_obj->ToObject(&obj)) return false; |
| 1638 } | 1613 } |
| 1639 set_empty_descriptor_array(DescriptorArray::cast(obj)); | 1614 set_empty_descriptor_array(DescriptorArray::cast(obj)); |
| 1640 | 1615 |
| 1641 // Fix the instance_descriptors for the existing maps. | 1616 // Fix the instance_descriptors for the existing maps. |
| 1642 meta_map()->set_instance_descriptors(empty_descriptor_array()); | 1617 meta_map()->set_instance_descriptors(empty_descriptor_array()); |
| 1643 meta_map()->set_code_cache(empty_fixed_array()); | 1618 meta_map()->set_code_cache(empty_fixed_array()); |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1815 if (!maybe_obj->ToObject(&obj)) return false; | 1790 if (!maybe_obj->ToObject(&obj)) return false; |
| 1816 } | 1791 } |
| 1817 set_shared_function_info_map(Map::cast(obj)); | 1792 set_shared_function_info_map(Map::cast(obj)); |
| 1818 | 1793 |
| 1819 { MaybeObject* maybe_obj = AllocateMap(JS_MESSAGE_OBJECT_TYPE, | 1794 { MaybeObject* maybe_obj = AllocateMap(JS_MESSAGE_OBJECT_TYPE, |
| 1820 JSMessageObject::kSize); | 1795 JSMessageObject::kSize); |
| 1821 if (!maybe_obj->ToObject(&obj)) return false; | 1796 if (!maybe_obj->ToObject(&obj)) return false; |
| 1822 } | 1797 } |
| 1823 set_message_object_map(Map::cast(obj)); | 1798 set_message_object_map(Map::cast(obj)); |
| 1824 | 1799 |
| 1825 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array())); | 1800 ASSERT(!InNewSpace(empty_fixed_array())); |
| 1826 return true; | 1801 return true; |
| 1827 } | 1802 } |
| 1828 | 1803 |
| 1829 | 1804 |
| 1830 MaybeObject* Heap::AllocateHeapNumber(double value, PretenureFlag pretenure) { | 1805 MaybeObject* Heap::AllocateHeapNumber(double value, PretenureFlag pretenure) { |
| 1831 // Statically ensure that it is safe to allocate heap numbers in paged | 1806 // Statically ensure that it is safe to allocate heap numbers in paged |
| 1832 // spaces. | 1807 // spaces. |
| 1833 STATIC_ASSERT(HeapNumber::kSize <= Page::kMaxHeapObjectSize); | 1808 STATIC_ASSERT(HeapNumber::kSize <= Page::kMaxHeapObjectSize); |
| 1834 AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE; | 1809 AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE; |
| 1835 | 1810 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1868 { MaybeObject* maybe_result = AllocateRawCell(); | 1843 { MaybeObject* maybe_result = AllocateRawCell(); |
| 1869 if (!maybe_result->ToObject(&result)) return maybe_result; | 1844 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 1870 } | 1845 } |
| 1871 HeapObject::cast(result)->set_map(global_property_cell_map()); | 1846 HeapObject::cast(result)->set_map(global_property_cell_map()); |
| 1872 JSGlobalPropertyCell::cast(result)->set_value(value); | 1847 JSGlobalPropertyCell::cast(result)->set_value(value); |
| 1873 return result; | 1848 return result; |
| 1874 } | 1849 } |
| 1875 | 1850 |
| 1876 | 1851 |
| 1877 MaybeObject* Heap::CreateOddball(const char* to_string, | 1852 MaybeObject* Heap::CreateOddball(const char* to_string, |
| 1878 Object* to_number) { | 1853 Object* to_number, |
| 1854 byte kind) { |
| 1879 Object* result; | 1855 Object* result; |
| 1880 { MaybeObject* maybe_result = Allocate(oddball_map(), OLD_DATA_SPACE); | 1856 { MaybeObject* maybe_result = Allocate(oddball_map(), OLD_DATA_SPACE); |
| 1881 if (!maybe_result->ToObject(&result)) return maybe_result; | 1857 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 1882 } | 1858 } |
| 1883 return Oddball::cast(result)->Initialize(to_string, to_number); | 1859 return Oddball::cast(result)->Initialize(to_string, to_number, kind); |
| 1884 } | 1860 } |
| 1885 | 1861 |
| 1886 | 1862 |
| 1887 bool Heap::CreateApiObjects() { | 1863 bool Heap::CreateApiObjects() { |
| 1888 Object* obj; | 1864 Object* obj; |
| 1889 | 1865 |
| 1890 { MaybeObject* maybe_obj = AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); | 1866 { MaybeObject* maybe_obj = AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); |
| 1891 if (!maybe_obj->ToObject(&obj)) return false; | 1867 if (!maybe_obj->ToObject(&obj)) return false; |
| 1892 } | 1868 } |
| 1893 set_neander_map(Map::cast(obj)); | 1869 set_neander_map(Map::cast(obj)); |
| 1894 | 1870 |
| 1895 { MaybeObject* maybe_obj = Heap::AllocateJSObjectFromMap(neander_map()); | 1871 { MaybeObject* maybe_obj = AllocateJSObjectFromMap(neander_map()); |
| 1896 if (!maybe_obj->ToObject(&obj)) return false; | 1872 if (!maybe_obj->ToObject(&obj)) return false; |
| 1897 } | 1873 } |
| 1898 Object* elements; | 1874 Object* elements; |
| 1899 { MaybeObject* maybe_elements = AllocateFixedArray(2); | 1875 { MaybeObject* maybe_elements = AllocateFixedArray(2); |
| 1900 if (!maybe_elements->ToObject(&elements)) return false; | 1876 if (!maybe_elements->ToObject(&elements)) return false; |
| 1901 } | 1877 } |
| 1902 FixedArray::cast(elements)->set(0, Smi::FromInt(0)); | 1878 FixedArray::cast(elements)->set(0, Smi::FromInt(0)); |
| 1903 JSObject::cast(obj)->set_elements(FixedArray::cast(elements)); | 1879 JSObject::cast(obj)->set_elements(FixedArray::cast(elements)); |
| 1904 set_message_listeners(JSObject::cast(obj)); | 1880 set_message_listeners(JSObject::cast(obj)); |
| 1905 | 1881 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1950 | 1926 |
| 1951 { MaybeObject* maybe_obj = AllocateHeapNumber(OS::nan_value(), TENURED); | 1927 { MaybeObject* maybe_obj = AllocateHeapNumber(OS::nan_value(), TENURED); |
| 1952 if (!maybe_obj->ToObject(&obj)) return false; | 1928 if (!maybe_obj->ToObject(&obj)) return false; |
| 1953 } | 1929 } |
| 1954 set_nan_value(obj); | 1930 set_nan_value(obj); |
| 1955 | 1931 |
| 1956 { MaybeObject* maybe_obj = Allocate(oddball_map(), OLD_DATA_SPACE); | 1932 { MaybeObject* maybe_obj = Allocate(oddball_map(), OLD_DATA_SPACE); |
| 1957 if (!maybe_obj->ToObject(&obj)) return false; | 1933 if (!maybe_obj->ToObject(&obj)) return false; |
| 1958 } | 1934 } |
| 1959 set_undefined_value(obj); | 1935 set_undefined_value(obj); |
| 1936 Oddball::cast(obj)->set_kind(Oddball::kUndefined); |
| 1960 ASSERT(!InNewSpace(undefined_value())); | 1937 ASSERT(!InNewSpace(undefined_value())); |
| 1961 | 1938 |
| 1962 // Allocate initial symbol table. | 1939 // Allocate initial symbol table. |
| 1963 { MaybeObject* maybe_obj = SymbolTable::Allocate(kInitialSymbolTableSize); | 1940 { MaybeObject* maybe_obj = SymbolTable::Allocate(kInitialSymbolTableSize); |
| 1964 if (!maybe_obj->ToObject(&obj)) return false; | 1941 if (!maybe_obj->ToObject(&obj)) return false; |
| 1965 } | 1942 } |
| 1966 // Don't use set_symbol_table() due to asserts. | 1943 // Don't use set_symbol_table() due to asserts. |
| 1967 roots_[kSymbolTableRootIndex] = obj; | 1944 roots_[kSymbolTableRootIndex] = obj; |
| 1968 | 1945 |
| 1969 // Assign the print strings for oddballs after creating symboltable. | 1946 // Assign the print strings for oddballs after creating symboltable. |
| 1970 Object* symbol; | 1947 Object* symbol; |
| 1971 { MaybeObject* maybe_symbol = LookupAsciiSymbol("undefined"); | 1948 { MaybeObject* maybe_symbol = LookupAsciiSymbol("undefined"); |
| 1972 if (!maybe_symbol->ToObject(&symbol)) return false; | 1949 if (!maybe_symbol->ToObject(&symbol)) return false; |
| 1973 } | 1950 } |
| 1974 Oddball::cast(undefined_value())->set_to_string(String::cast(symbol)); | 1951 Oddball::cast(undefined_value())->set_to_string(String::cast(symbol)); |
| 1975 Oddball::cast(undefined_value())->set_to_number(nan_value()); | 1952 Oddball::cast(undefined_value())->set_to_number(nan_value()); |
| 1976 | 1953 |
| 1977 // Allocate the null_value | 1954 // Allocate the null_value |
| 1978 { MaybeObject* maybe_obj = | 1955 { MaybeObject* maybe_obj = |
| 1979 Oddball::cast(null_value())->Initialize("null", Smi::FromInt(0)); | 1956 Oddball::cast(null_value())->Initialize("null", |
| 1957 Smi::FromInt(0), |
| 1958 Oddball::kNull); |
| 1980 if (!maybe_obj->ToObject(&obj)) return false; | 1959 if (!maybe_obj->ToObject(&obj)) return false; |
| 1981 } | 1960 } |
| 1982 | 1961 |
| 1983 { MaybeObject* maybe_obj = CreateOddball("true", Smi::FromInt(1)); | 1962 { MaybeObject* maybe_obj = CreateOddball("true", |
| 1963 Smi::FromInt(1), |
| 1964 Oddball::kTrue); |
| 1984 if (!maybe_obj->ToObject(&obj)) return false; | 1965 if (!maybe_obj->ToObject(&obj)) return false; |
| 1985 } | 1966 } |
| 1986 set_true_value(obj); | 1967 set_true_value(obj); |
| 1987 | 1968 |
| 1988 { MaybeObject* maybe_obj = CreateOddball("false", Smi::FromInt(0)); | 1969 { MaybeObject* maybe_obj = CreateOddball("false", |
| 1970 Smi::FromInt(0), |
| 1971 Oddball::kFalse); |
| 1989 if (!maybe_obj->ToObject(&obj)) return false; | 1972 if (!maybe_obj->ToObject(&obj)) return false; |
| 1990 } | 1973 } |
| 1991 set_false_value(obj); | 1974 set_false_value(obj); |
| 1992 | 1975 |
| 1993 { MaybeObject* maybe_obj = CreateOddball("hole", Smi::FromInt(-1)); | 1976 { MaybeObject* maybe_obj = CreateOddball("hole", |
| 1977 Smi::FromInt(-1), |
| 1978 Oddball::kTheHole); |
| 1994 if (!maybe_obj->ToObject(&obj)) return false; | 1979 if (!maybe_obj->ToObject(&obj)) return false; |
| 1995 } | 1980 } |
| 1996 set_the_hole_value(obj); | 1981 set_the_hole_value(obj); |
| 1997 | 1982 |
| 1998 { MaybeObject* maybe_obj = CreateOddball("arguments_marker", | 1983 { MaybeObject* maybe_obj = CreateOddball("arguments_marker", |
| 1999 Smi::FromInt(-4)); | 1984 Smi::FromInt(-4), |
| 1985 Oddball::kArgumentMarker); |
| 2000 if (!maybe_obj->ToObject(&obj)) return false; | 1986 if (!maybe_obj->ToObject(&obj)) return false; |
| 2001 } | 1987 } |
| 2002 set_arguments_marker(obj); | 1988 set_arguments_marker(obj); |
| 2003 | 1989 |
| 2004 { MaybeObject* maybe_obj = | 1990 { MaybeObject* maybe_obj = CreateOddball("no_interceptor_result_sentinel", |
| 2005 CreateOddball("no_interceptor_result_sentinel", Smi::FromInt(-2)); | 1991 Smi::FromInt(-2), |
| 1992 Oddball::kOther); |
| 2006 if (!maybe_obj->ToObject(&obj)) return false; | 1993 if (!maybe_obj->ToObject(&obj)) return false; |
| 2007 } | 1994 } |
| 2008 set_no_interceptor_result_sentinel(obj); | 1995 set_no_interceptor_result_sentinel(obj); |
| 2009 | 1996 |
| 2010 { MaybeObject* maybe_obj = | 1997 { MaybeObject* maybe_obj = CreateOddball("termination_exception", |
| 2011 CreateOddball("termination_exception", Smi::FromInt(-3)); | 1998 Smi::FromInt(-3), |
| 1999 Oddball::kOther); |
| 2012 if (!maybe_obj->ToObject(&obj)) return false; | 2000 if (!maybe_obj->ToObject(&obj)) return false; |
| 2013 } | 2001 } |
| 2014 set_termination_exception(obj); | 2002 set_termination_exception(obj); |
| 2015 | 2003 |
| 2016 // Allocate the empty string. | 2004 // Allocate the empty string. |
| 2017 { MaybeObject* maybe_obj = AllocateRawAsciiString(0, TENURED); | 2005 { MaybeObject* maybe_obj = AllocateRawAsciiString(0, TENURED); |
| 2018 if (!maybe_obj->ToObject(&obj)) return false; | 2006 if (!maybe_obj->ToObject(&obj)) return false; |
| 2019 } | 2007 } |
| 2020 set_empty_string(String::cast(obj)); | 2008 set_empty_string(String::cast(obj)); |
| 2021 | 2009 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2063 set_instanceof_cache_function(Smi::FromInt(0)); | 2051 set_instanceof_cache_function(Smi::FromInt(0)); |
| 2064 set_instanceof_cache_map(Smi::FromInt(0)); | 2052 set_instanceof_cache_map(Smi::FromInt(0)); |
| 2065 set_instanceof_cache_answer(Smi::FromInt(0)); | 2053 set_instanceof_cache_answer(Smi::FromInt(0)); |
| 2066 | 2054 |
| 2067 CreateFixedStubs(); | 2055 CreateFixedStubs(); |
| 2068 | 2056 |
| 2069 // Allocate the dictionary of intrinsic function names. | 2057 // Allocate the dictionary of intrinsic function names. |
| 2070 { MaybeObject* maybe_obj = StringDictionary::Allocate(Runtime::kNumFunctions); | 2058 { MaybeObject* maybe_obj = StringDictionary::Allocate(Runtime::kNumFunctions); |
| 2071 if (!maybe_obj->ToObject(&obj)) return false; | 2059 if (!maybe_obj->ToObject(&obj)) return false; |
| 2072 } | 2060 } |
| 2073 { MaybeObject* maybe_obj = Runtime::InitializeIntrinsicFunctionNames(obj); | 2061 { MaybeObject* maybe_obj = Runtime::InitializeIntrinsicFunctionNames(this, |
| 2062 obj); |
| 2074 if (!maybe_obj->ToObject(&obj)) return false; | 2063 if (!maybe_obj->ToObject(&obj)) return false; |
| 2075 } | 2064 } |
| 2076 set_intrinsic_function_names(StringDictionary::cast(obj)); | 2065 set_intrinsic_function_names(StringDictionary::cast(obj)); |
| 2077 | 2066 |
| 2078 if (InitializeNumberStringCache()->IsFailure()) return false; | 2067 if (InitializeNumberStringCache()->IsFailure()) return false; |
| 2079 | 2068 |
| 2080 // Allocate cache for single character ASCII strings. | 2069 // Allocate cache for single character ASCII strings. |
| 2081 { MaybeObject* maybe_obj = | 2070 { MaybeObject* maybe_obj = |
| 2082 AllocateFixedArray(String::kMaxAsciiCharCode + 1, TENURED); | 2071 AllocateFixedArray(String::kMaxAsciiCharCode + 1, TENURED); |
| 2083 if (!maybe_obj->ToObject(&obj)) return false; | 2072 if (!maybe_obj->ToObject(&obj)) return false; |
| 2084 } | 2073 } |
| 2085 set_single_character_string_cache(FixedArray::cast(obj)); | 2074 set_single_character_string_cache(FixedArray::cast(obj)); |
| 2086 | 2075 |
| 2087 // Allocate cache for external strings pointing to native source code. | 2076 // Allocate cache for external strings pointing to native source code. |
| 2088 { MaybeObject* maybe_obj = AllocateFixedArray(Natives::GetBuiltinsCount()); | 2077 { MaybeObject* maybe_obj = AllocateFixedArray(Natives::GetBuiltinsCount()); |
| 2089 if (!maybe_obj->ToObject(&obj)) return false; | 2078 if (!maybe_obj->ToObject(&obj)) return false; |
| 2090 } | 2079 } |
| 2091 set_natives_source_cache(FixedArray::cast(obj)); | 2080 set_natives_source_cache(FixedArray::cast(obj)); |
| 2092 | 2081 |
| 2093 // Handling of script id generation is in Factory::NewScript. | 2082 // Handling of script id generation is in FACTORY->NewScript. |
| 2094 set_last_script_id(undefined_value()); | 2083 set_last_script_id(undefined_value()); |
| 2095 | 2084 |
| 2096 // Initialize keyed lookup cache. | 2085 // Initialize keyed lookup cache. |
| 2097 KeyedLookupCache::Clear(); | 2086 isolate_->keyed_lookup_cache()->Clear(); |
| 2098 | 2087 |
| 2099 // Initialize context slot cache. | 2088 // Initialize context slot cache. |
| 2100 ContextSlotCache::Clear(); | 2089 isolate_->context_slot_cache()->Clear(); |
| 2101 | 2090 |
| 2102 // Initialize descriptor cache. | 2091 // Initialize descriptor cache. |
| 2103 DescriptorLookupCache::Clear(); | 2092 isolate_->descriptor_lookup_cache()->Clear(); |
| 2104 | 2093 |
| 2105 // Initialize compilation cache. | 2094 // Initialize compilation cache. |
| 2106 CompilationCache::Clear(); | 2095 isolate_->compilation_cache()->Clear(); |
| 2107 | 2096 |
| 2108 return true; | 2097 return true; |
| 2109 } | 2098 } |
| 2110 | 2099 |
| 2111 | 2100 |
| 2112 MaybeObject* Heap::InitializeNumberStringCache() { | 2101 MaybeObject* Heap::InitializeNumberStringCache() { |
| 2113 // Compute the size of the number string cache based on the max heap size. | 2102 // Compute the size of the number string cache based on the max heap size. |
| 2114 // max_semispace_size_ == 512 KB => number_string_cache_size = 32. | 2103 // max_semispace_size_ == 512 KB => number_string_cache_size = 32. |
| 2115 // max_semispace_size_ == 8 MB => number_string_cache_size = 16KB. | 2104 // max_semispace_size_ == 8 MB => number_string_cache_size = 16KB. |
| 2116 int number_string_cache_size = max_semispace_size_ / 512; | 2105 int number_string_cache_size = max_semispace_size_ / 512; |
| 2117 number_string_cache_size = Max(32, Min(16*KB, number_string_cache_size)); | 2106 number_string_cache_size = Max(32, Min(16*KB, number_string_cache_size)); |
| 2118 Object* obj; | 2107 Object* obj; |
| 2119 MaybeObject* maybe_obj = | 2108 MaybeObject* maybe_obj = |
| 2120 AllocateFixedArray(number_string_cache_size * 2, TENURED); | 2109 AllocateFixedArray(number_string_cache_size * 2, TENURED); |
| 2121 if (maybe_obj->ToObject(&obj)) set_number_string_cache(FixedArray::cast(obj)); | 2110 if (maybe_obj->ToObject(&obj)) set_number_string_cache(FixedArray::cast(obj)); |
| 2122 return maybe_obj; | 2111 return maybe_obj; |
| 2123 } | 2112 } |
| 2124 | 2113 |
| 2125 | 2114 |
| 2126 void Heap::FlushNumberStringCache() { | 2115 void Heap::FlushNumberStringCache() { |
| 2127 // Flush the number to string cache. | 2116 // Flush the number to string cache. |
| 2128 int len = number_string_cache()->length(); | 2117 int len = number_string_cache()->length(); |
| 2129 for (int i = 0; i < len; i++) { | 2118 for (int i = 0; i < len; i++) { |
| 2130 number_string_cache()->set_undefined(i); | 2119 number_string_cache()->set_undefined(this, i); |
| 2131 } | 2120 } |
| 2132 } | 2121 } |
| 2133 | 2122 |
| 2134 | 2123 |
| 2135 static inline int double_get_hash(double d) { | 2124 static inline int double_get_hash(double d) { |
| 2136 DoubleRepresentation rep(d); | 2125 DoubleRepresentation rep(d); |
| 2137 return static_cast<int>(rep.bits) ^ static_cast<int>(rep.bits >> 32); | 2126 return static_cast<int>(rep.bits) ^ static_cast<int>(rep.bits >> 32); |
| 2138 } | 2127 } |
| 2139 | 2128 |
| 2140 | 2129 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2172 } else { | 2161 } else { |
| 2173 hash = double_get_hash(number->Number()) & mask; | 2162 hash = double_get_hash(number->Number()) & mask; |
| 2174 number_string_cache()->set(hash * 2, number); | 2163 number_string_cache()->set(hash * 2, number); |
| 2175 } | 2164 } |
| 2176 number_string_cache()->set(hash * 2 + 1, string); | 2165 number_string_cache()->set(hash * 2 + 1, string); |
| 2177 } | 2166 } |
| 2178 | 2167 |
| 2179 | 2168 |
| 2180 MaybeObject* Heap::NumberToString(Object* number, | 2169 MaybeObject* Heap::NumberToString(Object* number, |
| 2181 bool check_number_string_cache) { | 2170 bool check_number_string_cache) { |
| 2182 Counters::number_to_string_runtime.Increment(); | 2171 isolate_->counters()->number_to_string_runtime()->Increment(); |
| 2183 if (check_number_string_cache) { | 2172 if (check_number_string_cache) { |
| 2184 Object* cached = GetNumberStringCache(number); | 2173 Object* cached = GetNumberStringCache(number); |
| 2185 if (cached != undefined_value()) { | 2174 if (cached != undefined_value()) { |
| 2186 return cached; | 2175 return cached; |
| 2187 } | 2176 } |
| 2188 } | 2177 } |
| 2189 | 2178 |
| 2190 char arr[100]; | 2179 char arr[100]; |
| 2191 Vector<char> buffer(arr, ARRAY_SIZE(arr)); | 2180 Vector<char> buffer(arr, ARRAY_SIZE(arr)); |
| 2192 const char* str; | 2181 const char* str; |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2275 | 2264 |
| 2276 MaybeObject* Heap::AllocateSharedFunctionInfo(Object* name) { | 2265 MaybeObject* Heap::AllocateSharedFunctionInfo(Object* name) { |
| 2277 Object* result; | 2266 Object* result; |
| 2278 { MaybeObject* maybe_result = | 2267 { MaybeObject* maybe_result = |
| 2279 Allocate(shared_function_info_map(), OLD_POINTER_SPACE); | 2268 Allocate(shared_function_info_map(), OLD_POINTER_SPACE); |
| 2280 if (!maybe_result->ToObject(&result)) return maybe_result; | 2269 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 2281 } | 2270 } |
| 2282 | 2271 |
| 2283 SharedFunctionInfo* share = SharedFunctionInfo::cast(result); | 2272 SharedFunctionInfo* share = SharedFunctionInfo::cast(result); |
| 2284 share->set_name(name); | 2273 share->set_name(name); |
| 2285 Code* illegal = Builtins::builtin(Builtins::Illegal); | 2274 Code* illegal = isolate_->builtins()->builtin(Builtins::Illegal); |
| 2286 share->set_code(illegal); | 2275 share->set_code(illegal); |
| 2287 share->set_scope_info(SerializedScopeInfo::Empty()); | 2276 share->set_scope_info(SerializedScopeInfo::Empty()); |
| 2288 Code* construct_stub = Builtins::builtin(Builtins::JSConstructStubGeneric); | 2277 Code* construct_stub = isolate_->builtins()->builtin( |
| 2278 Builtins::JSConstructStubGeneric); |
| 2289 share->set_construct_stub(construct_stub); | 2279 share->set_construct_stub(construct_stub); |
| 2290 share->set_expected_nof_properties(0); | 2280 share->set_expected_nof_properties(0); |
| 2291 share->set_length(0); | 2281 share->set_length(0); |
| 2292 share->set_formal_parameter_count(0); | 2282 share->set_formal_parameter_count(0); |
| 2293 share->set_instance_class_name(Object_symbol()); | 2283 share->set_instance_class_name(Object_symbol()); |
| 2294 share->set_function_data(undefined_value()); | 2284 share->set_function_data(undefined_value()); |
| 2295 share->set_script(undefined_value()); | 2285 share->set_script(undefined_value()); |
| 2296 share->set_start_position_and_type(0); | 2286 share->set_start_position_and_type(0); |
| 2297 share->set_debug_info(undefined_value()); | 2287 share->set_debug_info(undefined_value()); |
| 2298 share->set_inferred_name(empty_string()); | 2288 share->set_inferred_name(empty_string()); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2336 | 2326 |
| 2337 | 2327 |
| 2338 // Returns true for a character in a range. Both limits are inclusive. | 2328 // Returns true for a character in a range. Both limits are inclusive. |
| 2339 static inline bool Between(uint32_t character, uint32_t from, uint32_t to) { | 2329 static inline bool Between(uint32_t character, uint32_t from, uint32_t to) { |
| 2340 // This makes uses of the the unsigned wraparound. | 2330 // This makes uses of the the unsigned wraparound. |
| 2341 return character - from <= to - from; | 2331 return character - from <= to - from; |
| 2342 } | 2332 } |
| 2343 | 2333 |
| 2344 | 2334 |
| 2345 MUST_USE_RESULT static inline MaybeObject* MakeOrFindTwoCharacterString( | 2335 MUST_USE_RESULT static inline MaybeObject* MakeOrFindTwoCharacterString( |
| 2336 Heap* heap, |
| 2346 uint32_t c1, | 2337 uint32_t c1, |
| 2347 uint32_t c2) { | 2338 uint32_t c2) { |
| 2348 String* symbol; | 2339 String* symbol; |
| 2349 // Numeric strings have a different hash algorithm not known by | 2340 // Numeric strings have a different hash algorithm not known by |
| 2350 // LookupTwoCharsSymbolIfExists, so we skip this step for such strings. | 2341 // LookupTwoCharsSymbolIfExists, so we skip this step for such strings. |
| 2351 if ((!Between(c1, '0', '9') || !Between(c2, '0', '9')) && | 2342 if ((!Between(c1, '0', '9') || !Between(c2, '0', '9')) && |
| 2352 Heap::symbol_table()->LookupTwoCharsSymbolIfExists(c1, c2, &symbol)) { | 2343 heap->symbol_table()->LookupTwoCharsSymbolIfExists(c1, c2, &symbol)) { |
| 2353 return symbol; | 2344 return symbol; |
| 2354 // Now we know the length is 2, we might as well make use of that fact | 2345 // Now we know the length is 2, we might as well make use of that fact |
| 2355 // when building the new string. | 2346 // when building the new string. |
| 2356 } else if ((c1 | c2) <= String::kMaxAsciiCharCodeU) { // We can do this | 2347 } else if ((c1 | c2) <= String::kMaxAsciiCharCodeU) { // We can do this |
| 2357 ASSERT(IsPowerOf2(String::kMaxAsciiCharCodeU + 1)); // because of this. | 2348 ASSERT(IsPowerOf2(String::kMaxAsciiCharCodeU + 1)); // because of this. |
| 2358 Object* result; | 2349 Object* result; |
| 2359 { MaybeObject* maybe_result = Heap::AllocateRawAsciiString(2); | 2350 { MaybeObject* maybe_result = heap->AllocateRawAsciiString(2); |
| 2360 if (!maybe_result->ToObject(&result)) return maybe_result; | 2351 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 2361 } | 2352 } |
| 2362 char* dest = SeqAsciiString::cast(result)->GetChars(); | 2353 char* dest = SeqAsciiString::cast(result)->GetChars(); |
| 2363 dest[0] = c1; | 2354 dest[0] = c1; |
| 2364 dest[1] = c2; | 2355 dest[1] = c2; |
| 2365 return result; | 2356 return result; |
| 2366 } else { | 2357 } else { |
| 2367 Object* result; | 2358 Object* result; |
| 2368 { MaybeObject* maybe_result = Heap::AllocateRawTwoByteString(2); | 2359 { MaybeObject* maybe_result = heap->AllocateRawTwoByteString(2); |
| 2369 if (!maybe_result->ToObject(&result)) return maybe_result; | 2360 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 2370 } | 2361 } |
| 2371 uc16* dest = SeqTwoByteString::cast(result)->GetChars(); | 2362 uc16* dest = SeqTwoByteString::cast(result)->GetChars(); |
| 2372 dest[0] = c1; | 2363 dest[0] = c1; |
| 2373 dest[1] = c2; | 2364 dest[1] = c2; |
| 2374 return result; | 2365 return result; |
| 2375 } | 2366 } |
| 2376 } | 2367 } |
| 2377 | 2368 |
| 2378 | 2369 |
| 2379 MaybeObject* Heap::AllocateConsString(String* first, String* second) { | 2370 MaybeObject* Heap::AllocateConsString(String* first, String* second) { |
| 2380 int first_length = first->length(); | 2371 int first_length = first->length(); |
| 2381 if (first_length == 0) { | 2372 if (first_length == 0) { |
| 2382 return second; | 2373 return second; |
| 2383 } | 2374 } |
| 2384 | 2375 |
| 2385 int second_length = second->length(); | 2376 int second_length = second->length(); |
| 2386 if (second_length == 0) { | 2377 if (second_length == 0) { |
| 2387 return first; | 2378 return first; |
| 2388 } | 2379 } |
| 2389 | 2380 |
| 2390 int length = first_length + second_length; | 2381 int length = first_length + second_length; |
| 2391 | 2382 |
| 2392 // Optimization for 2-byte strings often used as keys in a decompression | 2383 // Optimization for 2-byte strings often used as keys in a decompression |
| 2393 // dictionary. Check whether we already have the string in the symbol | 2384 // dictionary. Check whether we already have the string in the symbol |
| 2394 // table to prevent creation of many unneccesary strings. | 2385 // table to prevent creation of many unneccesary strings. |
| 2395 if (length == 2) { | 2386 if (length == 2) { |
| 2396 unsigned c1 = first->Get(0); | 2387 unsigned c1 = first->Get(0); |
| 2397 unsigned c2 = second->Get(0); | 2388 unsigned c2 = second->Get(0); |
| 2398 return MakeOrFindTwoCharacterString(c1, c2); | 2389 return MakeOrFindTwoCharacterString(this, c1, c2); |
| 2399 } | 2390 } |
| 2400 | 2391 |
| 2401 bool first_is_ascii = first->IsAsciiRepresentation(); | 2392 bool first_is_ascii = first->IsAsciiRepresentation(); |
| 2402 bool second_is_ascii = second->IsAsciiRepresentation(); | 2393 bool second_is_ascii = second->IsAsciiRepresentation(); |
| 2403 bool is_ascii = first_is_ascii && second_is_ascii; | 2394 bool is_ascii = first_is_ascii && second_is_ascii; |
| 2404 | 2395 |
| 2405 // Make sure that an out of memory exception is thrown if the length | 2396 // Make sure that an out of memory exception is thrown if the length |
| 2406 // of the new cons string is too large. | 2397 // of the new cons string is too large. |
| 2407 if (length > String::kMaxLength || length < 0) { | 2398 if (length > String::kMaxLength || length < 0) { |
| 2408 Top::context()->mark_out_of_memory(); | 2399 isolate()->context()->mark_out_of_memory(); |
| 2409 return Failure::OutOfMemoryException(); | 2400 return Failure::OutOfMemoryException(); |
| 2410 } | 2401 } |
| 2411 | 2402 |
| 2412 bool is_ascii_data_in_two_byte_string = false; | 2403 bool is_ascii_data_in_two_byte_string = false; |
| 2413 if (!is_ascii) { | 2404 if (!is_ascii) { |
| 2414 // At least one of the strings uses two-byte representation so we | 2405 // At least one of the strings uses two-byte representation so we |
| 2415 // can't use the fast case code for short ascii strings below, but | 2406 // can't use the fast case code for short ascii strings below, but |
| 2416 // we can try to save memory if all chars actually fit in ascii. | 2407 // we can try to save memory if all chars actually fit in ascii. |
| 2417 is_ascii_data_in_two_byte_string = | 2408 is_ascii_data_in_two_byte_string = |
| 2418 first->HasOnlyAsciiChars() && second->HasOnlyAsciiChars(); | 2409 first->HasOnlyAsciiChars() && second->HasOnlyAsciiChars(); |
| 2419 if (is_ascii_data_in_two_byte_string) { | 2410 if (is_ascii_data_in_two_byte_string) { |
| 2420 Counters::string_add_runtime_ext_to_ascii.Increment(); | 2411 isolate_->counters()->string_add_runtime_ext_to_ascii()->Increment(); |
| 2421 } | 2412 } |
| 2422 } | 2413 } |
| 2423 | 2414 |
| 2424 // If the resulting string is small make a flat string. | 2415 // If the resulting string is small make a flat string. |
| 2425 if (length < String::kMinNonFlatLength) { | 2416 if (length < String::kMinNonFlatLength) { |
| 2426 ASSERT(first->IsFlat()); | 2417 ASSERT(first->IsFlat()); |
| 2427 ASSERT(second->IsFlat()); | 2418 ASSERT(second->IsFlat()); |
| 2428 if (is_ascii) { | 2419 if (is_ascii) { |
| 2429 Object* result; | 2420 Object* result; |
| 2430 { MaybeObject* maybe_result = AllocateRawAsciiString(length); | 2421 { MaybeObject* maybe_result = AllocateRawAsciiString(length); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2451 } else { | 2442 } else { |
| 2452 if (is_ascii_data_in_two_byte_string) { | 2443 if (is_ascii_data_in_two_byte_string) { |
| 2453 Object* result; | 2444 Object* result; |
| 2454 { MaybeObject* maybe_result = AllocateRawAsciiString(length); | 2445 { MaybeObject* maybe_result = AllocateRawAsciiString(length); |
| 2455 if (!maybe_result->ToObject(&result)) return maybe_result; | 2446 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 2456 } | 2447 } |
| 2457 // Copy the characters into the new object. | 2448 // Copy the characters into the new object. |
| 2458 char* dest = SeqAsciiString::cast(result)->GetChars(); | 2449 char* dest = SeqAsciiString::cast(result)->GetChars(); |
| 2459 String::WriteToFlat(first, dest, 0, first_length); | 2450 String::WriteToFlat(first, dest, 0, first_length); |
| 2460 String::WriteToFlat(second, dest + first_length, 0, second_length); | 2451 String::WriteToFlat(second, dest + first_length, 0, second_length); |
| 2452 isolate_->counters()->string_add_runtime_ext_to_ascii()->Increment(); |
| 2461 return result; | 2453 return result; |
| 2462 } | 2454 } |
| 2463 | 2455 |
| 2464 Object* result; | 2456 Object* result; |
| 2465 { MaybeObject* maybe_result = AllocateRawTwoByteString(length); | 2457 { MaybeObject* maybe_result = AllocateRawTwoByteString(length); |
| 2466 if (!maybe_result->ToObject(&result)) return maybe_result; | 2458 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 2467 } | 2459 } |
| 2468 // Copy the characters into the new object. | 2460 // Copy the characters into the new object. |
| 2469 uc16* dest = SeqTwoByteString::cast(result)->GetChars(); | 2461 uc16* dest = SeqTwoByteString::cast(result)->GetChars(); |
| 2470 String::WriteToFlat(first, dest, 0, first_length); | 2462 String::WriteToFlat(first, dest, 0, first_length); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 2492 } | 2484 } |
| 2493 | 2485 |
| 2494 | 2486 |
| 2495 MaybeObject* Heap::AllocateSubString(String* buffer, | 2487 MaybeObject* Heap::AllocateSubString(String* buffer, |
| 2496 int start, | 2488 int start, |
| 2497 int end, | 2489 int end, |
| 2498 PretenureFlag pretenure) { | 2490 PretenureFlag pretenure) { |
| 2499 int length = end - start; | 2491 int length = end - start; |
| 2500 | 2492 |
| 2501 if (length == 1) { | 2493 if (length == 1) { |
| 2502 return Heap::LookupSingleCharacterStringFromCode( | 2494 return LookupSingleCharacterStringFromCode(buffer->Get(start)); |
| 2503 buffer->Get(start)); | |
| 2504 } else if (length == 2) { | 2495 } else if (length == 2) { |
| 2505 // Optimization for 2-byte strings often used as keys in a decompression | 2496 // Optimization for 2-byte strings often used as keys in a decompression |
| 2506 // dictionary. Check whether we already have the string in the symbol | 2497 // dictionary. Check whether we already have the string in the symbol |
| 2507 // table to prevent creation of many unneccesary strings. | 2498 // table to prevent creation of many unneccesary strings. |
| 2508 unsigned c1 = buffer->Get(start); | 2499 unsigned c1 = buffer->Get(start); |
| 2509 unsigned c2 = buffer->Get(start + 1); | 2500 unsigned c2 = buffer->Get(start + 1); |
| 2510 return MakeOrFindTwoCharacterString(c1, c2); | 2501 return MakeOrFindTwoCharacterString(this, c1, c2); |
| 2511 } | 2502 } |
| 2512 | 2503 |
| 2513 // Make an attempt to flatten the buffer to reduce access time. | 2504 // Make an attempt to flatten the buffer to reduce access time. |
| 2514 buffer = buffer->TryFlattenGetString(); | 2505 buffer = buffer->TryFlattenGetString(); |
| 2515 | 2506 |
| 2516 Object* result; | 2507 Object* result; |
| 2517 { MaybeObject* maybe_result = buffer->IsAsciiRepresentation() | 2508 { MaybeObject* maybe_result = buffer->IsAsciiRepresentation() |
| 2518 ? AllocateRawAsciiString(length, pretenure ) | 2509 ? AllocateRawAsciiString(length, pretenure ) |
| 2519 : AllocateRawTwoByteString(length, pretenure); | 2510 : AllocateRawTwoByteString(length, pretenure); |
| 2520 if (!maybe_result->ToObject(&result)) return maybe_result; | 2511 if (!maybe_result->ToObject(&result)) return maybe_result; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2532 } | 2523 } |
| 2533 | 2524 |
| 2534 return result; | 2525 return result; |
| 2535 } | 2526 } |
| 2536 | 2527 |
| 2537 | 2528 |
| 2538 MaybeObject* Heap::AllocateExternalStringFromAscii( | 2529 MaybeObject* Heap::AllocateExternalStringFromAscii( |
| 2539 ExternalAsciiString::Resource* resource) { | 2530 ExternalAsciiString::Resource* resource) { |
| 2540 size_t length = resource->length(); | 2531 size_t length = resource->length(); |
| 2541 if (length > static_cast<size_t>(String::kMaxLength)) { | 2532 if (length > static_cast<size_t>(String::kMaxLength)) { |
| 2542 Top::context()->mark_out_of_memory(); | 2533 isolate()->context()->mark_out_of_memory(); |
| 2543 return Failure::OutOfMemoryException(); | 2534 return Failure::OutOfMemoryException(); |
| 2544 } | 2535 } |
| 2545 | 2536 |
| 2546 Map* map = external_ascii_string_map(); | 2537 Map* map = external_ascii_string_map(); |
| 2547 Object* result; | 2538 Object* result; |
| 2548 { MaybeObject* maybe_result = Allocate(map, NEW_SPACE); | 2539 { MaybeObject* maybe_result = Allocate(map, NEW_SPACE); |
| 2549 if (!maybe_result->ToObject(&result)) return maybe_result; | 2540 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 2550 } | 2541 } |
| 2551 | 2542 |
| 2552 ExternalAsciiString* external_string = ExternalAsciiString::cast(result); | 2543 ExternalAsciiString* external_string = ExternalAsciiString::cast(result); |
| 2553 external_string->set_length(static_cast<int>(length)); | 2544 external_string->set_length(static_cast<int>(length)); |
| 2554 external_string->set_hash_field(String::kEmptyHashField); | 2545 external_string->set_hash_field(String::kEmptyHashField); |
| 2555 external_string->set_resource(resource); | 2546 external_string->set_resource(resource); |
| 2556 | 2547 |
| 2557 return result; | 2548 return result; |
| 2558 } | 2549 } |
| 2559 | 2550 |
| 2560 | 2551 |
| 2561 MaybeObject* Heap::AllocateExternalStringFromTwoByte( | 2552 MaybeObject* Heap::AllocateExternalStringFromTwoByte( |
| 2562 ExternalTwoByteString::Resource* resource) { | 2553 ExternalTwoByteString::Resource* resource) { |
| 2563 size_t length = resource->length(); | 2554 size_t length = resource->length(); |
| 2564 if (length > static_cast<size_t>(String::kMaxLength)) { | 2555 if (length > static_cast<size_t>(String::kMaxLength)) { |
| 2565 Top::context()->mark_out_of_memory(); | 2556 isolate()->context()->mark_out_of_memory(); |
| 2566 return Failure::OutOfMemoryException(); | 2557 return Failure::OutOfMemoryException(); |
| 2567 } | 2558 } |
| 2568 | 2559 |
| 2569 // For small strings we check whether the resource contains only | 2560 // For small strings we check whether the resource contains only |
| 2570 // ASCII characters. If yes, we use a different string map. | 2561 // ASCII characters. If yes, we use a different string map. |
| 2571 static const size_t kAsciiCheckLengthLimit = 32; | 2562 static const size_t kAsciiCheckLengthLimit = 32; |
| 2572 bool is_ascii = length <= kAsciiCheckLengthLimit && | 2563 bool is_ascii = length <= kAsciiCheckLengthLimit && |
| 2573 String::IsAscii(resource->data(), static_cast<int>(length)); | 2564 String::IsAscii(resource->data(), static_cast<int>(length)); |
| 2574 Map* map = is_ascii ? | 2565 Map* map = is_ascii ? |
| 2575 Heap::external_string_with_ascii_data_map() : Heap::external_string_map(); | 2566 external_string_with_ascii_data_map() : external_string_map(); |
| 2576 Object* result; | 2567 Object* result; |
| 2577 { MaybeObject* maybe_result = Allocate(map, NEW_SPACE); | 2568 { MaybeObject* maybe_result = Allocate(map, NEW_SPACE); |
| 2578 if (!maybe_result->ToObject(&result)) return maybe_result; | 2569 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 2579 } | 2570 } |
| 2580 | 2571 |
| 2581 ExternalTwoByteString* external_string = ExternalTwoByteString::cast(result); | 2572 ExternalTwoByteString* external_string = ExternalTwoByteString::cast(result); |
| 2582 external_string->set_length(static_cast<int>(length)); | 2573 external_string->set_length(static_cast<int>(length)); |
| 2583 external_string->set_hash_field(String::kEmptyHashField); | 2574 external_string->set_hash_field(String::kEmptyHashField); |
| 2584 external_string->set_resource(resource); | 2575 external_string->set_resource(resource); |
| 2585 | 2576 |
| 2586 return result; | 2577 return result; |
| 2587 } | 2578 } |
| 2588 | 2579 |
| 2589 | 2580 |
| 2590 MaybeObject* Heap::LookupSingleCharacterStringFromCode(uint16_t code) { | 2581 MaybeObject* Heap::LookupSingleCharacterStringFromCode(uint16_t code) { |
| 2591 if (code <= String::kMaxAsciiCharCode) { | 2582 if (code <= String::kMaxAsciiCharCode) { |
| 2592 Object* value = Heap::single_character_string_cache()->get(code); | 2583 Object* value = single_character_string_cache()->get(code); |
| 2593 if (value != Heap::undefined_value()) return value; | 2584 if (value != undefined_value()) return value; |
| 2594 | 2585 |
| 2595 char buffer[1]; | 2586 char buffer[1]; |
| 2596 buffer[0] = static_cast<char>(code); | 2587 buffer[0] = static_cast<char>(code); |
| 2597 Object* result; | 2588 Object* result; |
| 2598 MaybeObject* maybe_result = LookupSymbol(Vector<const char>(buffer, 1)); | 2589 MaybeObject* maybe_result = LookupSymbol(Vector<const char>(buffer, 1)); |
| 2599 | 2590 |
| 2600 if (!maybe_result->ToObject(&result)) return maybe_result; | 2591 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 2601 Heap::single_character_string_cache()->set(code, result); | 2592 single_character_string_cache()->set(code, result); |
| 2602 return result; | 2593 return result; |
| 2603 } | 2594 } |
| 2604 | 2595 |
| 2605 Object* result; | 2596 Object* result; |
| 2606 { MaybeObject* maybe_result = Heap::AllocateRawTwoByteString(1); | 2597 { MaybeObject* maybe_result = AllocateRawTwoByteString(1); |
| 2607 if (!maybe_result->ToObject(&result)) return maybe_result; | 2598 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 2608 } | 2599 } |
| 2609 String* answer = String::cast(result); | 2600 String* answer = String::cast(result); |
| 2610 answer->Set(0, code); | 2601 answer->Set(0, code); |
| 2611 return answer; | 2602 return answer; |
| 2612 } | 2603 } |
| 2613 | 2604 |
| 2614 | 2605 |
| 2615 MaybeObject* Heap::AllocateByteArray(int length, PretenureFlag pretenure) { | 2606 MaybeObject* Heap::AllocateByteArray(int length, PretenureFlag pretenure) { |
| 2616 if (length < 0 || length > ByteArray::kMaxLength) { | 2607 if (length < 0 || length > ByteArray::kMaxLength) { |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2710 } else { | 2701 } else { |
| 2711 maybe_result = code_space_->AllocateRaw(obj_size); | 2702 maybe_result = code_space_->AllocateRaw(obj_size); |
| 2712 } | 2703 } |
| 2713 | 2704 |
| 2714 Object* result; | 2705 Object* result; |
| 2715 if (!maybe_result->ToObject(&result)) return maybe_result; | 2706 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 2716 | 2707 |
| 2717 // Initialize the object | 2708 // Initialize the object |
| 2718 HeapObject::cast(result)->set_map(code_map()); | 2709 HeapObject::cast(result)->set_map(code_map()); |
| 2719 Code* code = Code::cast(result); | 2710 Code* code = Code::cast(result); |
| 2720 ASSERT(!CodeRange::exists() || CodeRange::contains(code->address())); | 2711 ASSERT(!isolate_->code_range()->exists() || |
| 2712 isolate_->code_range()->contains(code->address())); |
| 2721 code->set_instruction_size(desc.instr_size); | 2713 code->set_instruction_size(desc.instr_size); |
| 2722 code->set_relocation_info(ByteArray::cast(reloc_info)); | 2714 code->set_relocation_info(ByteArray::cast(reloc_info)); |
| 2723 code->set_flags(flags); | 2715 code->set_flags(flags); |
| 2724 if (code->is_call_stub() || code->is_keyed_call_stub()) { | 2716 if (code->is_call_stub() || code->is_keyed_call_stub()) { |
| 2725 code->set_check_type(RECEIVER_MAP_CHECK); | 2717 code->set_check_type(RECEIVER_MAP_CHECK); |
| 2726 } | 2718 } |
| 2727 code->set_deoptimization_data(empty_fixed_array()); | 2719 code->set_deoptimization_data(empty_fixed_array()); |
| 2728 // Allow self references to created code object by patching the handle to | 2720 // Allow self references to created code object by patching the handle to |
| 2729 // point to the newly allocated Code object. | 2721 // point to the newly allocated Code object. |
| 2730 if (!self_reference.is_null()) { | 2722 if (!self_reference.is_null()) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 2756 | 2748 |
| 2757 Object* result; | 2749 Object* result; |
| 2758 if (!maybe_result->ToObject(&result)) return maybe_result; | 2750 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 2759 | 2751 |
| 2760 // Copy code object. | 2752 // Copy code object. |
| 2761 Address old_addr = code->address(); | 2753 Address old_addr = code->address(); |
| 2762 Address new_addr = reinterpret_cast<HeapObject*>(result)->address(); | 2754 Address new_addr = reinterpret_cast<HeapObject*>(result)->address(); |
| 2763 CopyBlock(new_addr, old_addr, obj_size); | 2755 CopyBlock(new_addr, old_addr, obj_size); |
| 2764 // Relocate the copy. | 2756 // Relocate the copy. |
| 2765 Code* new_code = Code::cast(result); | 2757 Code* new_code = Code::cast(result); |
| 2766 ASSERT(!CodeRange::exists() || CodeRange::contains(code->address())); | 2758 ASSERT(!isolate_->code_range()->exists() || |
| 2759 isolate_->code_range()->contains(code->address())); |
| 2767 new_code->Relocate(new_addr - old_addr); | 2760 new_code->Relocate(new_addr - old_addr); |
| 2768 return new_code; | 2761 return new_code; |
| 2769 } | 2762 } |
| 2770 | 2763 |
| 2771 | 2764 |
| 2772 MaybeObject* Heap::CopyCode(Code* code, Vector<byte> reloc_info) { | 2765 MaybeObject* Heap::CopyCode(Code* code, Vector<byte> reloc_info) { |
| 2773 // Allocate ByteArray before the Code object, so that we do not risk | 2766 // Allocate ByteArray before the Code object, so that we do not risk |
| 2774 // leaving uninitialized Code object (and breaking the heap). | 2767 // leaving uninitialized Code object (and breaking the heap). |
| 2775 Object* reloc_info_array; | 2768 Object* reloc_info_array; |
| 2776 { MaybeObject* maybe_reloc_info_array = | 2769 { MaybeObject* maybe_reloc_info_array = |
| (...skipping 28 matching lines...) Expand all Loading... |
| 2805 // Copy header and instructions. | 2798 // Copy header and instructions. |
| 2806 memcpy(new_addr, old_addr, relocation_offset); | 2799 memcpy(new_addr, old_addr, relocation_offset); |
| 2807 | 2800 |
| 2808 Code* new_code = Code::cast(result); | 2801 Code* new_code = Code::cast(result); |
| 2809 new_code->set_relocation_info(ByteArray::cast(reloc_info_array)); | 2802 new_code->set_relocation_info(ByteArray::cast(reloc_info_array)); |
| 2810 | 2803 |
| 2811 // Copy patched rinfo. | 2804 // Copy patched rinfo. |
| 2812 memcpy(new_code->relocation_start(), reloc_info.start(), reloc_info.length()); | 2805 memcpy(new_code->relocation_start(), reloc_info.start(), reloc_info.length()); |
| 2813 | 2806 |
| 2814 // Relocate the copy. | 2807 // Relocate the copy. |
| 2815 ASSERT(!CodeRange::exists() || CodeRange::contains(code->address())); | 2808 ASSERT(!isolate_->code_range()->exists() || |
| 2809 isolate_->code_range()->contains(code->address())); |
| 2816 new_code->Relocate(new_addr - old_addr); | 2810 new_code->Relocate(new_addr - old_addr); |
| 2817 | 2811 |
| 2818 #ifdef DEBUG | 2812 #ifdef DEBUG |
| 2819 code->Verify(); | 2813 code->Verify(); |
| 2820 #endif | 2814 #endif |
| 2821 return new_code; | 2815 return new_code; |
| 2822 } | 2816 } |
| 2823 | 2817 |
| 2824 | 2818 |
| 2825 MaybeObject* Heap::Allocate(Map* map, AllocationSpace space) { | 2819 MaybeObject* Heap::Allocate(Map* map, AllocationSpace space) { |
| 2826 ASSERT(gc_state_ == NOT_IN_GC); | 2820 ASSERT(gc_state_ == NOT_IN_GC); |
| 2827 ASSERT(map->instance_type() != MAP_TYPE); | 2821 ASSERT(map->instance_type() != MAP_TYPE); |
| 2828 // If allocation failures are disallowed, we may allocate in a different | 2822 // If allocation failures are disallowed, we may allocate in a different |
| 2829 // space when new space is full and the object is not a large object. | 2823 // space when new space is full and the object is not a large object. |
| 2830 AllocationSpace retry_space = | 2824 AllocationSpace retry_space = |
| 2831 (space != NEW_SPACE) ? space : TargetSpaceId(map->instance_type()); | 2825 (space != NEW_SPACE) ? space : TargetSpaceId(map->instance_type()); |
| 2832 Object* result; | 2826 Object* result; |
| 2833 { MaybeObject* maybe_result = | 2827 { MaybeObject* maybe_result = |
| 2834 AllocateRaw(map->instance_size(), space, retry_space); | 2828 AllocateRaw(map->instance_size(), space, retry_space); |
| 2835 if (!maybe_result->ToObject(&result)) return maybe_result; | 2829 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 2836 } | 2830 } |
| 2837 HeapObject::cast(result)->set_map(map); | 2831 HeapObject::cast(result)->set_map(map); |
| 2838 #ifdef ENABLE_LOGGING_AND_PROFILING | 2832 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 2839 ProducerHeapProfile::RecordJSObjectAllocation(result); | 2833 isolate_->producer_heap_profile()->RecordJSObjectAllocation(result); |
| 2840 #endif | 2834 #endif |
| 2841 return result; | 2835 return result; |
| 2842 } | 2836 } |
| 2843 | 2837 |
| 2844 | 2838 |
| 2845 MaybeObject* Heap::InitializeFunction(JSFunction* function, | 2839 MaybeObject* Heap::InitializeFunction(JSFunction* function, |
| 2846 SharedFunctionInfo* shared, | 2840 SharedFunctionInfo* shared, |
| 2847 Object* prototype) { | 2841 Object* prototype) { |
| 2848 ASSERT(!prototype->IsMap()); | 2842 ASSERT(!prototype->IsMap()); |
| 2849 function->initialize_properties(); | 2843 function->initialize_properties(); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2897 MaybeObject* Heap::AllocateArgumentsObject(Object* callee, int length) { | 2891 MaybeObject* Heap::AllocateArgumentsObject(Object* callee, int length) { |
| 2898 // To get fast allocation and map sharing for arguments objects we | 2892 // To get fast allocation and map sharing for arguments objects we |
| 2899 // allocate them based on an arguments boilerplate. | 2893 // allocate them based on an arguments boilerplate. |
| 2900 | 2894 |
| 2901 JSObject* boilerplate; | 2895 JSObject* boilerplate; |
| 2902 int arguments_object_size; | 2896 int arguments_object_size; |
| 2903 bool strict_mode_callee = callee->IsJSFunction() && | 2897 bool strict_mode_callee = callee->IsJSFunction() && |
| 2904 JSFunction::cast(callee)->shared()->strict_mode(); | 2898 JSFunction::cast(callee)->shared()->strict_mode(); |
| 2905 if (strict_mode_callee) { | 2899 if (strict_mode_callee) { |
| 2906 boilerplate = | 2900 boilerplate = |
| 2907 Top::context()->global_context()->strict_mode_arguments_boilerplate(); | 2901 isolate()->context()->global_context()-> |
| 2902 strict_mode_arguments_boilerplate(); |
| 2908 arguments_object_size = kArgumentsObjectSizeStrict; | 2903 arguments_object_size = kArgumentsObjectSizeStrict; |
| 2909 } else { | 2904 } else { |
| 2910 boilerplate = Top::context()->global_context()->arguments_boilerplate(); | 2905 boilerplate = |
| 2906 isolate()->context()->global_context()->arguments_boilerplate(); |
| 2911 arguments_object_size = kArgumentsObjectSize; | 2907 arguments_object_size = kArgumentsObjectSize; |
| 2912 } | 2908 } |
| 2913 | 2909 |
| 2914 // This calls Copy directly rather than using Heap::AllocateRaw so we | 2910 // This calls Copy directly rather than using Heap::AllocateRaw so we |
| 2915 // duplicate the check here. | 2911 // duplicate the check here. |
| 2916 ASSERT(allocation_allowed_ && gc_state_ == NOT_IN_GC); | 2912 ASSERT(allocation_allowed_ && gc_state_ == NOT_IN_GC); |
| 2917 | 2913 |
| 2918 // Check that the size of the boilerplate matches our | 2914 // Check that the size of the boilerplate matches our |
| 2919 // expectations. The ArgumentsAccessStub::GenerateNewObject relies | 2915 // expectations. The ArgumentsAccessStub::GenerateNewObject relies |
| 2920 // on the size being a known constant. | 2916 // on the size being a known constant. |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2967 | 2963 |
| 2968 | 2964 |
| 2969 MaybeObject* Heap::AllocateInitialMap(JSFunction* fun) { | 2965 MaybeObject* Heap::AllocateInitialMap(JSFunction* fun) { |
| 2970 ASSERT(!fun->has_initial_map()); | 2966 ASSERT(!fun->has_initial_map()); |
| 2971 | 2967 |
| 2972 // First create a new map with the size and number of in-object properties | 2968 // First create a new map with the size and number of in-object properties |
| 2973 // suggested by the function. | 2969 // suggested by the function. |
| 2974 int instance_size = fun->shared()->CalculateInstanceSize(); | 2970 int instance_size = fun->shared()->CalculateInstanceSize(); |
| 2975 int in_object_properties = fun->shared()->CalculateInObjectProperties(); | 2971 int in_object_properties = fun->shared()->CalculateInObjectProperties(); |
| 2976 Object* map_obj; | 2972 Object* map_obj; |
| 2977 { MaybeObject* maybe_map_obj = | 2973 { MaybeObject* maybe_map_obj = AllocateMap(JS_OBJECT_TYPE, instance_size); |
| 2978 Heap::AllocateMap(JS_OBJECT_TYPE, instance_size); | |
| 2979 if (!maybe_map_obj->ToObject(&map_obj)) return maybe_map_obj; | 2974 if (!maybe_map_obj->ToObject(&map_obj)) return maybe_map_obj; |
| 2980 } | 2975 } |
| 2981 | 2976 |
| 2982 // Fetch or allocate prototype. | 2977 // Fetch or allocate prototype. |
| 2983 Object* prototype; | 2978 Object* prototype; |
| 2984 if (fun->has_instance_prototype()) { | 2979 if (fun->has_instance_prototype()) { |
| 2985 prototype = fun->instance_prototype(); | 2980 prototype = fun->instance_prototype(); |
| 2986 } else { | 2981 } else { |
| 2987 { MaybeObject* maybe_prototype = AllocateFunctionPrototype(fun); | 2982 { MaybeObject* maybe_prototype = AllocateFunctionPrototype(fun); |
| 2988 if (!maybe_prototype->ToObject(&prototype)) return maybe_prototype; | 2983 if (!maybe_prototype->ToObject(&prototype)) return maybe_prototype; |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3164 | 3159 |
| 3165 // The global object might be created from an object template with accessors. | 3160 // The global object might be created from an object template with accessors. |
| 3166 // Fill these accessors into the dictionary. | 3161 // Fill these accessors into the dictionary. |
| 3167 DescriptorArray* descs = map->instance_descriptors(); | 3162 DescriptorArray* descs = map->instance_descriptors(); |
| 3168 for (int i = 0; i < descs->number_of_descriptors(); i++) { | 3163 for (int i = 0; i < descs->number_of_descriptors(); i++) { |
| 3169 PropertyDetails details = descs->GetDetails(i); | 3164 PropertyDetails details = descs->GetDetails(i); |
| 3170 ASSERT(details.type() == CALLBACKS); // Only accessors are expected. | 3165 ASSERT(details.type() == CALLBACKS); // Only accessors are expected. |
| 3171 PropertyDetails d = | 3166 PropertyDetails d = |
| 3172 PropertyDetails(details.attributes(), CALLBACKS, details.index()); | 3167 PropertyDetails(details.attributes(), CALLBACKS, details.index()); |
| 3173 Object* value = descs->GetCallbacksObject(i); | 3168 Object* value = descs->GetCallbacksObject(i); |
| 3174 { MaybeObject* maybe_value = Heap::AllocateJSGlobalPropertyCell(value); | 3169 { MaybeObject* maybe_value = AllocateJSGlobalPropertyCell(value); |
| 3175 if (!maybe_value->ToObject(&value)) return maybe_value; | 3170 if (!maybe_value->ToObject(&value)) return maybe_value; |
| 3176 } | 3171 } |
| 3177 | 3172 |
| 3178 Object* result; | 3173 Object* result; |
| 3179 { MaybeObject* maybe_result = dictionary->Add(descs->GetKey(i), value, d); | 3174 { MaybeObject* maybe_result = dictionary->Add(descs->GetKey(i), value, d); |
| 3180 if (!maybe_result->ToObject(&result)) return maybe_result; | 3175 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 3181 } | 3176 } |
| 3182 dictionary = StringDictionary::cast(result); | 3177 dictionary = StringDictionary::cast(result); |
| 3183 } | 3178 } |
| 3184 | 3179 |
| 3185 // Allocate the global object and initialize it with the backing store. | 3180 // Allocate the global object and initialize it with the backing store. |
| 3186 { MaybeObject* maybe_obj = Allocate(map, OLD_POINTER_SPACE); | 3181 { MaybeObject* maybe_obj = Allocate(map, OLD_POINTER_SPACE); |
| 3187 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 3182 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 3188 } | 3183 } |
| 3189 JSObject* global = JSObject::cast(obj); | 3184 JSObject* global = JSObject::cast(obj); |
| 3190 InitializeJSObjectFromMap(global, dictionary, map); | 3185 InitializeJSObjectFromMap(global, dictionary, map); |
| 3191 | 3186 |
| 3192 // Create a new map for the global object. | 3187 // Create a new map for the global object. |
| 3193 { MaybeObject* maybe_obj = map->CopyDropDescriptors(); | 3188 { MaybeObject* maybe_obj = map->CopyDropDescriptors(); |
| 3194 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 3189 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 3195 } | 3190 } |
| 3196 Map* new_map = Map::cast(obj); | 3191 Map* new_map = Map::cast(obj); |
| 3197 | 3192 |
| 3198 // Setup the global object as a normalized object. | 3193 // Setup the global object as a normalized object. |
| 3199 global->set_map(new_map); | 3194 global->set_map(new_map); |
| 3200 global->map()->set_instance_descriptors(Heap::empty_descriptor_array()); | 3195 global->map()->set_instance_descriptors(empty_descriptor_array()); |
| 3201 global->set_properties(dictionary); | 3196 global->set_properties(dictionary); |
| 3202 | 3197 |
| 3203 // Make sure result is a global object with properties in dictionary. | 3198 // Make sure result is a global object with properties in dictionary. |
| 3204 ASSERT(global->IsGlobalObject()); | 3199 ASSERT(global->IsGlobalObject()); |
| 3205 ASSERT(!global->HasFastProperties()); | 3200 ASSERT(!global->HasFastProperties()); |
| 3206 return global; | 3201 return global; |
| 3207 } | 3202 } |
| 3208 | 3203 |
| 3209 | 3204 |
| 3210 MaybeObject* Heap::CopyJSObject(JSObject* source) { | 3205 MaybeObject* Heap::CopyJSObject(JSObject* source) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 3229 source->address(), | 3224 source->address(), |
| 3230 object_size); | 3225 object_size); |
| 3231 // Update write barrier for all fields that lie beyond the header. | 3226 // Update write barrier for all fields that lie beyond the header. |
| 3232 RecordWrites(clone_address, | 3227 RecordWrites(clone_address, |
| 3233 JSObject::kHeaderSize, | 3228 JSObject::kHeaderSize, |
| 3234 (object_size - JSObject::kHeaderSize) / kPointerSize); | 3229 (object_size - JSObject::kHeaderSize) / kPointerSize); |
| 3235 } else { | 3230 } else { |
| 3236 { MaybeObject* maybe_clone = new_space_.AllocateRaw(object_size); | 3231 { MaybeObject* maybe_clone = new_space_.AllocateRaw(object_size); |
| 3237 if (!maybe_clone->ToObject(&clone)) return maybe_clone; | 3232 if (!maybe_clone->ToObject(&clone)) return maybe_clone; |
| 3238 } | 3233 } |
| 3239 ASSERT(Heap::InNewSpace(clone)); | 3234 ASSERT(InNewSpace(clone)); |
| 3240 // Since we know the clone is allocated in new space, we can copy | 3235 // Since we know the clone is allocated in new space, we can copy |
| 3241 // the contents without worrying about updating the write barrier. | 3236 // the contents without worrying about updating the write barrier. |
| 3242 CopyBlock(HeapObject::cast(clone)->address(), | 3237 CopyBlock(HeapObject::cast(clone)->address(), |
| 3243 source->address(), | 3238 source->address(), |
| 3244 object_size); | 3239 object_size); |
| 3245 } | 3240 } |
| 3246 | 3241 |
| 3247 FixedArray* elements = FixedArray::cast(source->elements()); | 3242 FixedArray* elements = FixedArray::cast(source->elements()); |
| 3248 FixedArray* properties = FixedArray::cast(source->properties()); | 3243 FixedArray* properties = FixedArray::cast(source->properties()); |
| 3249 // Update elements if necessary. | 3244 // Update elements if necessary. |
| 3250 if (elements->length() > 0) { | 3245 if (elements->length() > 0) { |
| 3251 Object* elem; | 3246 Object* elem; |
| 3252 { MaybeObject* maybe_elem = | 3247 { MaybeObject* maybe_elem = |
| 3253 (elements->map() == fixed_cow_array_map()) ? | 3248 (elements->map() == fixed_cow_array_map()) ? |
| 3254 elements : CopyFixedArray(elements); | 3249 elements : CopyFixedArray(elements); |
| 3255 if (!maybe_elem->ToObject(&elem)) return maybe_elem; | 3250 if (!maybe_elem->ToObject(&elem)) return maybe_elem; |
| 3256 } | 3251 } |
| 3257 JSObject::cast(clone)->set_elements(FixedArray::cast(elem)); | 3252 JSObject::cast(clone)->set_elements(FixedArray::cast(elem)); |
| 3258 } | 3253 } |
| 3259 // Update properties if necessary. | 3254 // Update properties if necessary. |
| 3260 if (properties->length() > 0) { | 3255 if (properties->length() > 0) { |
| 3261 Object* prop; | 3256 Object* prop; |
| 3262 { MaybeObject* maybe_prop = CopyFixedArray(properties); | 3257 { MaybeObject* maybe_prop = CopyFixedArray(properties); |
| 3263 if (!maybe_prop->ToObject(&prop)) return maybe_prop; | 3258 if (!maybe_prop->ToObject(&prop)) return maybe_prop; |
| 3264 } | 3259 } |
| 3265 JSObject::cast(clone)->set_properties(FixedArray::cast(prop)); | 3260 JSObject::cast(clone)->set_properties(FixedArray::cast(prop)); |
| 3266 } | 3261 } |
| 3267 // Return the new clone. | 3262 // Return the new clone. |
| 3268 #ifdef ENABLE_LOGGING_AND_PROFILING | 3263 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 3269 ProducerHeapProfile::RecordJSObjectAllocation(clone); | 3264 isolate_->producer_heap_profile()->RecordJSObjectAllocation(clone); |
| 3270 #endif | 3265 #endif |
| 3271 return clone; | 3266 return clone; |
| 3272 } | 3267 } |
| 3273 | 3268 |
| 3274 | 3269 |
| 3275 MaybeObject* Heap::ReinitializeJSGlobalProxy(JSFunction* constructor, | 3270 MaybeObject* Heap::ReinitializeJSGlobalProxy(JSFunction* constructor, |
| 3276 JSGlobalProxy* object) { | 3271 JSGlobalProxy* object) { |
| 3277 ASSERT(constructor->has_initial_map()); | 3272 ASSERT(constructor->has_initial_map()); |
| 3278 Map* map = constructor->initial_map(); | 3273 Map* map = constructor->initial_map(); |
| 3279 | 3274 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3315 } | 3310 } |
| 3316 | 3311 |
| 3317 | 3312 |
| 3318 MaybeObject* Heap::AllocateStringFromUtf8Slow(Vector<const char> string, | 3313 MaybeObject* Heap::AllocateStringFromUtf8Slow(Vector<const char> string, |
| 3319 PretenureFlag pretenure) { | 3314 PretenureFlag pretenure) { |
| 3320 // V8 only supports characters in the Basic Multilingual Plane. | 3315 // V8 only supports characters in the Basic Multilingual Plane. |
| 3321 const uc32 kMaxSupportedChar = 0xFFFF; | 3316 const uc32 kMaxSupportedChar = 0xFFFF; |
| 3322 // Count the number of characters in the UTF-8 string and check if | 3317 // Count the number of characters in the UTF-8 string and check if |
| 3323 // it is an ASCII string. | 3318 // it is an ASCII string. |
| 3324 Access<ScannerConstants::Utf8Decoder> | 3319 Access<ScannerConstants::Utf8Decoder> |
| 3325 decoder(ScannerConstants::utf8_decoder()); | 3320 decoder(isolate_->scanner_constants()->utf8_decoder()); |
| 3326 decoder->Reset(string.start(), string.length()); | 3321 decoder->Reset(string.start(), string.length()); |
| 3327 int chars = 0; | 3322 int chars = 0; |
| 3328 while (decoder->has_more()) { | 3323 while (decoder->has_more()) { |
| 3329 decoder->GetNext(); | 3324 decoder->GetNext(); |
| 3330 chars++; | 3325 chars++; |
| 3331 } | 3326 } |
| 3332 | 3327 |
| 3333 Object* result; | 3328 Object* result; |
| 3334 { MaybeObject* maybe_result = AllocateRawTwoByteString(chars, pretenure); | 3329 { MaybeObject* maybe_result = AllocateRawTwoByteString(chars, pretenure); |
| 3335 if (!maybe_result->ToObject(&result)) return maybe_result; | 3330 if (!maybe_result->ToObject(&result)) return maybe_result; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3368 return result; | 3363 return result; |
| 3369 } | 3364 } |
| 3370 | 3365 |
| 3371 | 3366 |
| 3372 Map* Heap::SymbolMapForString(String* string) { | 3367 Map* Heap::SymbolMapForString(String* string) { |
| 3373 // If the string is in new space it cannot be used as a symbol. | 3368 // If the string is in new space it cannot be used as a symbol. |
| 3374 if (InNewSpace(string)) return NULL; | 3369 if (InNewSpace(string)) return NULL; |
| 3375 | 3370 |
| 3376 // Find the corresponding symbol map for strings. | 3371 // Find the corresponding symbol map for strings. |
| 3377 Map* map = string->map(); | 3372 Map* map = string->map(); |
| 3378 if (map == ascii_string_map()) return ascii_symbol_map(); | 3373 if (map == ascii_string_map()) { |
| 3379 if (map == string_map()) return symbol_map(); | 3374 return ascii_symbol_map(); |
| 3380 if (map == cons_string_map()) return cons_symbol_map(); | 3375 } |
| 3381 if (map == cons_ascii_string_map()) return cons_ascii_symbol_map(); | 3376 if (map == string_map()) { |
| 3382 if (map == external_string_map()) return external_symbol_map(); | 3377 return symbol_map(); |
| 3383 if (map == external_ascii_string_map()) return external_ascii_symbol_map(); | 3378 } |
| 3379 if (map == cons_string_map()) { |
| 3380 return cons_symbol_map(); |
| 3381 } |
| 3382 if (map == cons_ascii_string_map()) { |
| 3383 return cons_ascii_symbol_map(); |
| 3384 } |
| 3385 if (map == external_string_map()) { |
| 3386 return external_symbol_map(); |
| 3387 } |
| 3388 if (map == external_ascii_string_map()) { |
| 3389 return external_ascii_symbol_map(); |
| 3390 } |
| 3384 if (map == external_string_with_ascii_data_map()) { | 3391 if (map == external_string_with_ascii_data_map()) { |
| 3385 return external_symbol_with_ascii_data_map(); | 3392 return external_symbol_with_ascii_data_map(); |
| 3386 } | 3393 } |
| 3387 | 3394 |
| 3388 // No match found. | 3395 // No match found. |
| 3389 return NULL; | 3396 return NULL; |
| 3390 } | 3397 } |
| 3391 | 3398 |
| 3392 | 3399 |
| 3393 MaybeObject* Heap::AllocateInternalSymbol(unibrow::CharacterStream* buffer, | 3400 MaybeObject* Heap::AllocateInternalSymbol(unibrow::CharacterStream* buffer, |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3547 : lo_space_->AllocateRawFixedArray(size); | 3554 : lo_space_->AllocateRawFixedArray(size); |
| 3548 } | 3555 } |
| 3549 | 3556 |
| 3550 | 3557 |
| 3551 MaybeObject* Heap::CopyFixedArrayWithMap(FixedArray* src, Map* map) { | 3558 MaybeObject* Heap::CopyFixedArrayWithMap(FixedArray* src, Map* map) { |
| 3552 int len = src->length(); | 3559 int len = src->length(); |
| 3553 Object* obj; | 3560 Object* obj; |
| 3554 { MaybeObject* maybe_obj = AllocateRawFixedArray(len); | 3561 { MaybeObject* maybe_obj = AllocateRawFixedArray(len); |
| 3555 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 3562 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 3556 } | 3563 } |
| 3557 if (Heap::InNewSpace(obj)) { | 3564 if (InNewSpace(obj)) { |
| 3558 HeapObject* dst = HeapObject::cast(obj); | 3565 HeapObject* dst = HeapObject::cast(obj); |
| 3559 dst->set_map(map); | 3566 dst->set_map(map); |
| 3560 CopyBlock(dst->address() + kPointerSize, | 3567 CopyBlock(dst->address() + kPointerSize, |
| 3561 src->address() + kPointerSize, | 3568 src->address() + kPointerSize, |
| 3562 FixedArray::SizeFor(len) - kPointerSize); | 3569 FixedArray::SizeFor(len) - kPointerSize); |
| 3563 return obj; | 3570 return obj; |
| 3564 } | 3571 } |
| 3565 HeapObject::cast(obj)->set_map(map); | 3572 HeapObject::cast(obj)->set_map(map); |
| 3566 FixedArray* result = FixedArray::cast(obj); | 3573 FixedArray* result = FixedArray::cast(obj); |
| 3567 result->set_length(len); | 3574 result->set_length(len); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 3579 if (length == 0) return empty_fixed_array(); | 3586 if (length == 0) return empty_fixed_array(); |
| 3580 Object* result; | 3587 Object* result; |
| 3581 { MaybeObject* maybe_result = AllocateRawFixedArray(length); | 3588 { MaybeObject* maybe_result = AllocateRawFixedArray(length); |
| 3582 if (!maybe_result->ToObject(&result)) return maybe_result; | 3589 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 3583 } | 3590 } |
| 3584 // Initialize header. | 3591 // Initialize header. |
| 3585 FixedArray* array = reinterpret_cast<FixedArray*>(result); | 3592 FixedArray* array = reinterpret_cast<FixedArray*>(result); |
| 3586 array->set_map(fixed_array_map()); | 3593 array->set_map(fixed_array_map()); |
| 3587 array->set_length(length); | 3594 array->set_length(length); |
| 3588 // Initialize body. | 3595 // Initialize body. |
| 3589 ASSERT(!Heap::InNewSpace(undefined_value())); | 3596 ASSERT(!InNewSpace(undefined_value())); |
| 3590 MemsetPointer(array->data_start(), undefined_value(), length); | 3597 MemsetPointer(array->data_start(), undefined_value(), length); |
| 3591 return result; | 3598 return result; |
| 3592 } | 3599 } |
| 3593 | 3600 |
| 3594 | 3601 |
| 3595 MaybeObject* Heap::AllocateRawFixedArray(int length, PretenureFlag pretenure) { | 3602 MaybeObject* Heap::AllocateRawFixedArray(int length, PretenureFlag pretenure) { |
| 3596 if (length < 0 || length > FixedArray::kMaxLength) { | 3603 if (length < 0 || length > FixedArray::kMaxLength) { |
| 3597 return Failure::OutOfMemoryException(); | 3604 return Failure::OutOfMemoryException(); |
| 3598 } | 3605 } |
| 3599 | 3606 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 3610 } | 3617 } |
| 3611 | 3618 |
| 3612 AllocationSpace retry_space = | 3619 AllocationSpace retry_space = |
| 3613 (size <= MaxObjectSizeInPagedSpace()) ? OLD_POINTER_SPACE : LO_SPACE; | 3620 (size <= MaxObjectSizeInPagedSpace()) ? OLD_POINTER_SPACE : LO_SPACE; |
| 3614 | 3621 |
| 3615 return AllocateRaw(size, space, retry_space); | 3622 return AllocateRaw(size, space, retry_space); |
| 3616 } | 3623 } |
| 3617 | 3624 |
| 3618 | 3625 |
| 3619 MUST_USE_RESULT static MaybeObject* AllocateFixedArrayWithFiller( | 3626 MUST_USE_RESULT static MaybeObject* AllocateFixedArrayWithFiller( |
| 3627 Heap* heap, |
| 3620 int length, | 3628 int length, |
| 3621 PretenureFlag pretenure, | 3629 PretenureFlag pretenure, |
| 3622 Object* filler) { | 3630 Object* filler) { |
| 3623 ASSERT(length >= 0); | 3631 ASSERT(length >= 0); |
| 3624 ASSERT(Heap::empty_fixed_array()->IsFixedArray()); | 3632 ASSERT(heap->empty_fixed_array()->IsFixedArray()); |
| 3625 if (length == 0) return Heap::empty_fixed_array(); | 3633 if (length == 0) return heap->empty_fixed_array(); |
| 3626 | 3634 |
| 3627 ASSERT(!Heap::InNewSpace(filler)); | 3635 ASSERT(!heap->InNewSpace(filler)); |
| 3628 Object* result; | 3636 Object* result; |
| 3629 { MaybeObject* maybe_result = Heap::AllocateRawFixedArray(length, pretenure); | 3637 { MaybeObject* maybe_result = heap->AllocateRawFixedArray(length, pretenure); |
| 3630 if (!maybe_result->ToObject(&result)) return maybe_result; | 3638 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 3631 } | 3639 } |
| 3632 | 3640 |
| 3633 HeapObject::cast(result)->set_map(Heap::fixed_array_map()); | 3641 HeapObject::cast(result)->set_map(heap->fixed_array_map()); |
| 3634 FixedArray* array = FixedArray::cast(result); | 3642 FixedArray* array = FixedArray::cast(result); |
| 3635 array->set_length(length); | 3643 array->set_length(length); |
| 3636 MemsetPointer(array->data_start(), filler, length); | 3644 MemsetPointer(array->data_start(), filler, length); |
| 3637 return array; | 3645 return array; |
| 3638 } | 3646 } |
| 3639 | 3647 |
| 3640 | 3648 |
| 3641 MaybeObject* Heap::AllocateFixedArray(int length, PretenureFlag pretenure) { | 3649 MaybeObject* Heap::AllocateFixedArray(int length, PretenureFlag pretenure) { |
| 3642 return AllocateFixedArrayWithFiller(length, pretenure, undefined_value()); | 3650 return AllocateFixedArrayWithFiller(this, |
| 3651 length, |
| 3652 pretenure, |
| 3653 undefined_value()); |
| 3643 } | 3654 } |
| 3644 | 3655 |
| 3645 | 3656 |
| 3646 MaybeObject* Heap::AllocateFixedArrayWithHoles(int length, | 3657 MaybeObject* Heap::AllocateFixedArrayWithHoles(int length, |
| 3647 PretenureFlag pretenure) { | 3658 PretenureFlag pretenure) { |
| 3648 return AllocateFixedArrayWithFiller(length, pretenure, the_hole_value()); | 3659 return AllocateFixedArrayWithFiller(this, |
| 3660 length, |
| 3661 pretenure, |
| 3662 the_hole_value()); |
| 3649 } | 3663 } |
| 3650 | 3664 |
| 3651 | 3665 |
| 3652 MaybeObject* Heap::AllocateUninitializedFixedArray(int length) { | 3666 MaybeObject* Heap::AllocateUninitializedFixedArray(int length) { |
| 3653 if (length == 0) return empty_fixed_array(); | 3667 if (length == 0) return empty_fixed_array(); |
| 3654 | 3668 |
| 3655 Object* obj; | 3669 Object* obj; |
| 3656 { MaybeObject* maybe_obj = AllocateRawFixedArray(length); | 3670 { MaybeObject* maybe_obj = AllocateRawFixedArray(length); |
| 3657 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 3671 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 3658 } | 3672 } |
| 3659 | 3673 |
| 3660 reinterpret_cast<FixedArray*>(obj)->set_map(fixed_array_map()); | 3674 reinterpret_cast<FixedArray*>(obj)->set_map(fixed_array_map()); |
| 3661 FixedArray::cast(obj)->set_length(length); | 3675 FixedArray::cast(obj)->set_length(length); |
| 3662 return obj; | 3676 return obj; |
| 3663 } | 3677 } |
| 3664 | 3678 |
| 3665 | 3679 |
| 3666 MaybeObject* Heap::AllocateHashTable(int length, PretenureFlag pretenure) { | 3680 MaybeObject* Heap::AllocateHashTable(int length, PretenureFlag pretenure) { |
| 3667 Object* result; | 3681 Object* result; |
| 3668 { MaybeObject* maybe_result = Heap::AllocateFixedArray(length, pretenure); | 3682 { MaybeObject* maybe_result = AllocateFixedArray(length, pretenure); |
| 3669 if (!maybe_result->ToObject(&result)) return maybe_result; | 3683 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 3670 } | 3684 } |
| 3671 reinterpret_cast<HeapObject*>(result)->set_map(hash_table_map()); | 3685 reinterpret_cast<HeapObject*>(result)->set_map(hash_table_map()); |
| 3672 ASSERT(result->IsHashTable()); | 3686 ASSERT(result->IsHashTable()); |
| 3673 return result; | 3687 return result; |
| 3674 } | 3688 } |
| 3675 | 3689 |
| 3676 | 3690 |
| 3677 MaybeObject* Heap::AllocateGlobalContext() { | 3691 MaybeObject* Heap::AllocateGlobalContext() { |
| 3678 Object* result; | 3692 Object* result; |
| 3679 { MaybeObject* maybe_result = | 3693 { MaybeObject* maybe_result = |
| 3680 Heap::AllocateFixedArray(Context::GLOBAL_CONTEXT_SLOTS); | 3694 AllocateFixedArray(Context::GLOBAL_CONTEXT_SLOTS); |
| 3681 if (!maybe_result->ToObject(&result)) return maybe_result; | 3695 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 3682 } | 3696 } |
| 3683 Context* context = reinterpret_cast<Context*>(result); | 3697 Context* context = reinterpret_cast<Context*>(result); |
| 3684 context->set_map(global_context_map()); | 3698 context->set_map(global_context_map()); |
| 3685 ASSERT(context->IsGlobalContext()); | 3699 ASSERT(context->IsGlobalContext()); |
| 3686 ASSERT(result->IsContext()); | 3700 ASSERT(result->IsContext()); |
| 3687 return result; | 3701 return result; |
| 3688 } | 3702 } |
| 3689 | 3703 |
| 3690 | 3704 |
| 3691 MaybeObject* Heap::AllocateFunctionContext(int length, JSFunction* function) { | 3705 MaybeObject* Heap::AllocateFunctionContext(int length, JSFunction* function) { |
| 3692 ASSERT(length >= Context::MIN_CONTEXT_SLOTS); | 3706 ASSERT(length >= Context::MIN_CONTEXT_SLOTS); |
| 3693 Object* result; | 3707 Object* result; |
| 3694 { MaybeObject* maybe_result = Heap::AllocateFixedArray(length); | 3708 { MaybeObject* maybe_result = AllocateFixedArray(length); |
| 3695 if (!maybe_result->ToObject(&result)) return maybe_result; | 3709 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 3696 } | 3710 } |
| 3697 Context* context = reinterpret_cast<Context*>(result); | 3711 Context* context = reinterpret_cast<Context*>(result); |
| 3698 context->set_map(context_map()); | 3712 context->set_map(context_map()); |
| 3699 context->set_closure(function); | 3713 context->set_closure(function); |
| 3700 context->set_fcontext(context); | 3714 context->set_fcontext(context); |
| 3701 context->set_previous(NULL); | 3715 context->set_previous(NULL); |
| 3702 context->set_extension(NULL); | 3716 context->set_extension(NULL); |
| 3703 context->set_global(function->context()->global()); | 3717 context->set_global(function->context()->global()); |
| 3704 ASSERT(!context->IsGlobalContext()); | 3718 ASSERT(!context->IsGlobalContext()); |
| 3705 ASSERT(context->is_function_context()); | 3719 ASSERT(context->is_function_context()); |
| 3706 ASSERT(result->IsContext()); | 3720 ASSERT(result->IsContext()); |
| 3707 return result; | 3721 return result; |
| 3708 } | 3722 } |
| 3709 | 3723 |
| 3710 | 3724 |
| 3711 MaybeObject* Heap::AllocateWithContext(Context* previous, | 3725 MaybeObject* Heap::AllocateWithContext(Context* previous, |
| 3712 JSObject* extension, | 3726 JSObject* extension, |
| 3713 bool is_catch_context) { | 3727 bool is_catch_context) { |
| 3714 Object* result; | 3728 Object* result; |
| 3715 { MaybeObject* maybe_result = | 3729 { MaybeObject* maybe_result = AllocateFixedArray(Context::MIN_CONTEXT_SLOTS); |
| 3716 Heap::AllocateFixedArray(Context::MIN_CONTEXT_SLOTS); | |
| 3717 if (!maybe_result->ToObject(&result)) return maybe_result; | 3730 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 3718 } | 3731 } |
| 3719 Context* context = reinterpret_cast<Context*>(result); | 3732 Context* context = reinterpret_cast<Context*>(result); |
| 3720 context->set_map(is_catch_context ? catch_context_map() : context_map()); | 3733 context->set_map(is_catch_context ? catch_context_map() : |
| 3734 context_map()); |
| 3721 context->set_closure(previous->closure()); | 3735 context->set_closure(previous->closure()); |
| 3722 context->set_fcontext(previous->fcontext()); | 3736 context->set_fcontext(previous->fcontext()); |
| 3723 context->set_previous(previous); | 3737 context->set_previous(previous); |
| 3724 context->set_extension(extension); | 3738 context->set_extension(extension); |
| 3725 context->set_global(previous->global()); | 3739 context->set_global(previous->global()); |
| 3726 ASSERT(!context->IsGlobalContext()); | 3740 ASSERT(!context->IsGlobalContext()); |
| 3727 ASSERT(!context->is_function_context()); | 3741 ASSERT(!context->is_function_context()); |
| 3728 ASSERT(result->IsContext()); | 3742 ASSERT(result->IsContext()); |
| 3729 return result; | 3743 return result; |
| 3730 } | 3744 } |
| 3731 | 3745 |
| 3732 | 3746 |
| 3733 MaybeObject* Heap::AllocateStruct(InstanceType type) { | 3747 MaybeObject* Heap::AllocateStruct(InstanceType type) { |
| 3734 Map* map; | 3748 Map* map; |
| 3735 switch (type) { | 3749 switch (type) { |
| 3736 #define MAKE_CASE(NAME, Name, name) case NAME##_TYPE: map = name##_map(); break; | 3750 #define MAKE_CASE(NAME, Name, name) \ |
| 3751 case NAME##_TYPE: map = name##_map(); break; |
| 3737 STRUCT_LIST(MAKE_CASE) | 3752 STRUCT_LIST(MAKE_CASE) |
| 3738 #undef MAKE_CASE | 3753 #undef MAKE_CASE |
| 3739 default: | 3754 default: |
| 3740 UNREACHABLE(); | 3755 UNREACHABLE(); |
| 3741 return Failure::InternalError(); | 3756 return Failure::InternalError(); |
| 3742 } | 3757 } |
| 3743 int size = map->instance_size(); | 3758 int size = map->instance_size(); |
| 3744 AllocationSpace space = | 3759 AllocationSpace space = |
| 3745 (size > MaxObjectSizeInPagedSpace()) ? LO_SPACE : OLD_POINTER_SPACE; | 3760 (size > MaxObjectSizeInPagedSpace()) ? LO_SPACE : OLD_POINTER_SPACE; |
| 3746 Object* result; | 3761 Object* result; |
| 3747 { MaybeObject* maybe_result = Heap::Allocate(map, space); | 3762 { MaybeObject* maybe_result = Allocate(map, space); |
| 3748 if (!maybe_result->ToObject(&result)) return maybe_result; | 3763 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 3749 } | 3764 } |
| 3750 Struct::cast(result)->InitializeBody(size); | 3765 Struct::cast(result)->InitializeBody(size); |
| 3751 return result; | 3766 return result; |
| 3752 } | 3767 } |
| 3753 | 3768 |
| 3754 | 3769 |
| 3755 bool Heap::IdleNotification() { | 3770 bool Heap::IdleNotification() { |
| 3756 static const int kIdlesBeforeScavenge = 4; | 3771 static const int kIdlesBeforeScavenge = 4; |
| 3757 static const int kIdlesBeforeMarkSweep = 7; | 3772 static const int kIdlesBeforeMarkSweep = 7; |
| 3758 static const int kIdlesBeforeMarkCompact = 8; | 3773 static const int kIdlesBeforeMarkCompact = 8; |
| 3759 static const int kMaxIdleCount = kIdlesBeforeMarkCompact + 1; | 3774 static const int kMaxIdleCount = kIdlesBeforeMarkCompact + 1; |
| 3760 static const unsigned int kGCsBetweenCleanup = 4; | 3775 static const unsigned int kGCsBetweenCleanup = 4; |
| 3761 static int number_idle_notifications = 0; | 3776 |
| 3762 static unsigned int last_gc_count = gc_count_; | 3777 if (!last_idle_notification_gc_count_init_) { |
| 3778 last_idle_notification_gc_count_ = gc_count_; |
| 3779 last_idle_notification_gc_count_init_ = true; |
| 3780 } |
| 3763 | 3781 |
| 3764 bool uncommit = true; | 3782 bool uncommit = true; |
| 3765 bool finished = false; | 3783 bool finished = false; |
| 3766 | 3784 |
| 3767 // Reset the number of idle notifications received when a number of | 3785 // Reset the number of idle notifications received when a number of |
| 3768 // GCs have taken place. This allows another round of cleanup based | 3786 // GCs have taken place. This allows another round of cleanup based |
| 3769 // on idle notifications if enough work has been carried out to | 3787 // on idle notifications if enough work has been carried out to |
| 3770 // provoke a number of garbage collections. | 3788 // provoke a number of garbage collections. |
| 3771 if (gc_count_ - last_gc_count < kGCsBetweenCleanup) { | 3789 if (gc_count_ - last_idle_notification_gc_count_ < kGCsBetweenCleanup) { |
| 3772 number_idle_notifications = | 3790 number_idle_notifications_ = |
| 3773 Min(number_idle_notifications + 1, kMaxIdleCount); | 3791 Min(number_idle_notifications_ + 1, kMaxIdleCount); |
| 3774 } else { | 3792 } else { |
| 3775 number_idle_notifications = 0; | 3793 number_idle_notifications_ = 0; |
| 3776 last_gc_count = gc_count_; | 3794 last_idle_notification_gc_count_ = gc_count_; |
| 3777 } | 3795 } |
| 3778 | 3796 |
| 3779 if (number_idle_notifications == kIdlesBeforeScavenge) { | 3797 if (number_idle_notifications_ == kIdlesBeforeScavenge) { |
| 3780 if (contexts_disposed_ > 0) { | 3798 if (contexts_disposed_ > 0) { |
| 3781 HistogramTimerScope scope(&Counters::gc_context); | 3799 HistogramTimerScope scope(isolate_->counters()->gc_context()); |
| 3782 CollectAllGarbage(false); | 3800 CollectAllGarbage(false); |
| 3783 } else { | 3801 } else { |
| 3784 CollectGarbage(NEW_SPACE); | 3802 CollectGarbage(NEW_SPACE); |
| 3785 } | 3803 } |
| 3786 new_space_.Shrink(); | 3804 new_space_.Shrink(); |
| 3787 last_gc_count = gc_count_; | 3805 last_idle_notification_gc_count_ = gc_count_; |
| 3788 } else if (number_idle_notifications == kIdlesBeforeMarkSweep) { | 3806 } else if (number_idle_notifications_ == kIdlesBeforeMarkSweep) { |
| 3789 // Before doing the mark-sweep collections we clear the | 3807 // Before doing the mark-sweep collections we clear the |
| 3790 // compilation cache to avoid hanging on to source code and | 3808 // compilation cache to avoid hanging on to source code and |
| 3791 // generated code for cached functions. | 3809 // generated code for cached functions. |
| 3792 CompilationCache::Clear(); | 3810 isolate_->compilation_cache()->Clear(); |
| 3793 | 3811 |
| 3794 CollectAllGarbage(false); | 3812 CollectAllGarbage(false); |
| 3795 new_space_.Shrink(); | 3813 new_space_.Shrink(); |
| 3796 last_gc_count = gc_count_; | 3814 last_idle_notification_gc_count_ = gc_count_; |
| 3797 | 3815 |
| 3798 } else if (number_idle_notifications == kIdlesBeforeMarkCompact) { | 3816 } else if (number_idle_notifications_ == kIdlesBeforeMarkCompact) { |
| 3799 CollectAllGarbage(true); | 3817 CollectAllGarbage(true); |
| 3800 new_space_.Shrink(); | 3818 new_space_.Shrink(); |
| 3801 last_gc_count = gc_count_; | 3819 last_idle_notification_gc_count_ = gc_count_; |
| 3820 number_idle_notifications_ = 0; |
| 3802 finished = true; | 3821 finished = true; |
| 3803 | |
| 3804 } else if (contexts_disposed_ > 0) { | 3822 } else if (contexts_disposed_ > 0) { |
| 3805 if (FLAG_expose_gc) { | 3823 if (FLAG_expose_gc) { |
| 3806 contexts_disposed_ = 0; | 3824 contexts_disposed_ = 0; |
| 3807 } else { | 3825 } else { |
| 3808 HistogramTimerScope scope(&Counters::gc_context); | 3826 HistogramTimerScope scope(isolate_->counters()->gc_context()); |
| 3809 CollectAllGarbage(false); | 3827 CollectAllGarbage(false); |
| 3810 last_gc_count = gc_count_; | 3828 last_idle_notification_gc_count_ = gc_count_; |
| 3811 } | 3829 } |
| 3812 // If this is the first idle notification, we reset the | 3830 // If this is the first idle notification, we reset the |
| 3813 // notification count to avoid letting idle notifications for | 3831 // notification count to avoid letting idle notifications for |
| 3814 // context disposal garbage collections start a potentially too | 3832 // context disposal garbage collections start a potentially too |
| 3815 // aggressive idle GC cycle. | 3833 // aggressive idle GC cycle. |
| 3816 if (number_idle_notifications <= 1) { | 3834 if (number_idle_notifications_ <= 1) { |
| 3817 number_idle_notifications = 0; | 3835 number_idle_notifications_ = 0; |
| 3818 uncommit = false; | 3836 uncommit = false; |
| 3819 } | 3837 } |
| 3820 } else if (number_idle_notifications > kIdlesBeforeMarkCompact) { | 3838 } else if (number_idle_notifications_ > kIdlesBeforeMarkCompact) { |
| 3821 // If we have received more than kIdlesBeforeMarkCompact idle | 3839 // If we have received more than kIdlesBeforeMarkCompact idle |
| 3822 // notifications we do not perform any cleanup because we don't | 3840 // notifications we do not perform any cleanup because we don't |
| 3823 // expect to gain much by doing so. | 3841 // expect to gain much by doing so. |
| 3824 finished = true; | 3842 finished = true; |
| 3825 } | 3843 } |
| 3826 | 3844 |
| 3827 // Make sure that we have no pending context disposals and | 3845 // Make sure that we have no pending context disposals and |
| 3828 // conditionally uncommit from space. | 3846 // conditionally uncommit from space. |
| 3829 ASSERT(contexts_disposed_ == 0); | 3847 ASSERT(contexts_disposed_ == 0); |
| 3830 if (uncommit) Heap::UncommitFromSpace(); | 3848 if (uncommit) UncommitFromSpace(); |
| 3831 return finished; | 3849 return finished; |
| 3832 } | 3850 } |
| 3833 | 3851 |
| 3834 | 3852 |
| 3835 #ifdef DEBUG | 3853 #ifdef DEBUG |
| 3836 | 3854 |
| 3837 void Heap::Print() { | 3855 void Heap::Print() { |
| 3838 if (!HasBeenSetup()) return; | 3856 if (!HasBeenSetup()) return; |
| 3839 Top::PrintStack(); | 3857 isolate()->PrintStack(); |
| 3840 AllSpaces spaces; | 3858 AllSpaces spaces; |
| 3841 for (Space* space = spaces.next(); space != NULL; space = spaces.next()) | 3859 for (Space* space = spaces.next(); space != NULL; space = spaces.next()) |
| 3842 space->Print(); | 3860 space->Print(); |
| 3843 } | 3861 } |
| 3844 | 3862 |
| 3845 | 3863 |
| 3846 void Heap::ReportCodeStatistics(const char* title) { | 3864 void Heap::ReportCodeStatistics(const char* title) { |
| 3847 PrintF(">>>>>> Code Stats (%s) >>>>>>\n", title); | 3865 PrintF(">>>>>> Code Stats (%s) >>>>>>\n", title); |
| 3848 PagedSpace::ResetCodeStatistics(); | 3866 PagedSpace::ResetCodeStatistics(); |
| 3849 // We do not look for code in new space, map space, or old space. If code | 3867 // We do not look for code in new space, map space, or old space. If code |
| (...skipping 12 matching lines...) Expand all Loading... |
| 3862 PrintF(">>>>>> =============== %s (%d) =============== >>>>>>\n", | 3880 PrintF(">>>>>> =============== %s (%d) =============== >>>>>>\n", |
| 3863 title, gc_count_); | 3881 title, gc_count_); |
| 3864 PrintF("mark-compact GC : %d\n", mc_count_); | 3882 PrintF("mark-compact GC : %d\n", mc_count_); |
| 3865 PrintF("old_gen_promotion_limit_ %" V8_PTR_PREFIX "d\n", | 3883 PrintF("old_gen_promotion_limit_ %" V8_PTR_PREFIX "d\n", |
| 3866 old_gen_promotion_limit_); | 3884 old_gen_promotion_limit_); |
| 3867 PrintF("old_gen_allocation_limit_ %" V8_PTR_PREFIX "d\n", | 3885 PrintF("old_gen_allocation_limit_ %" V8_PTR_PREFIX "d\n", |
| 3868 old_gen_allocation_limit_); | 3886 old_gen_allocation_limit_); |
| 3869 | 3887 |
| 3870 PrintF("\n"); | 3888 PrintF("\n"); |
| 3871 PrintF("Number of handles : %d\n", HandleScope::NumberOfHandles()); | 3889 PrintF("Number of handles : %d\n", HandleScope::NumberOfHandles()); |
| 3872 GlobalHandles::PrintStats(); | 3890 isolate_->global_handles()->PrintStats(); |
| 3873 PrintF("\n"); | 3891 PrintF("\n"); |
| 3874 | 3892 |
| 3875 PrintF("Heap statistics : "); | 3893 PrintF("Heap statistics : "); |
| 3876 MemoryAllocator::ReportStatistics(); | 3894 isolate_->memory_allocator()->ReportStatistics(); |
| 3877 PrintF("To space : "); | 3895 PrintF("To space : "); |
| 3878 new_space_.ReportStatistics(); | 3896 new_space_.ReportStatistics(); |
| 3879 PrintF("Old pointer space : "); | 3897 PrintF("Old pointer space : "); |
| 3880 old_pointer_space_->ReportStatistics(); | 3898 old_pointer_space_->ReportStatistics(); |
| 3881 PrintF("Old data space : "); | 3899 PrintF("Old data space : "); |
| 3882 old_data_space_->ReportStatistics(); | 3900 old_data_space_->ReportStatistics(); |
| 3883 PrintF("Code space : "); | 3901 PrintF("Code space : "); |
| 3884 code_space_->ReportStatistics(); | 3902 code_space_->ReportStatistics(); |
| 3885 PrintF("Map space : "); | 3903 PrintF("Map space : "); |
| 3886 map_space_->ReportStatistics(); | 3904 map_space_->ReportStatistics(); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3949 static void VerifyPointersUnderWatermark( | 3967 static void VerifyPointersUnderWatermark( |
| 3950 PagedSpace* space, | 3968 PagedSpace* space, |
| 3951 DirtyRegionCallback visit_dirty_region) { | 3969 DirtyRegionCallback visit_dirty_region) { |
| 3952 PageIterator it(space, PageIterator::PAGES_IN_USE); | 3970 PageIterator it(space, PageIterator::PAGES_IN_USE); |
| 3953 | 3971 |
| 3954 while (it.has_next()) { | 3972 while (it.has_next()) { |
| 3955 Page* page = it.next(); | 3973 Page* page = it.next(); |
| 3956 Address start = page->ObjectAreaStart(); | 3974 Address start = page->ObjectAreaStart(); |
| 3957 Address end = page->AllocationWatermark(); | 3975 Address end = page->AllocationWatermark(); |
| 3958 | 3976 |
| 3959 Heap::IterateDirtyRegions(Page::kAllRegionsDirtyMarks, | 3977 HEAP->IterateDirtyRegions(Page::kAllRegionsDirtyMarks, |
| 3960 start, | 3978 start, |
| 3961 end, | 3979 end, |
| 3962 visit_dirty_region, | 3980 visit_dirty_region, |
| 3963 &DummyScavengePointer); | 3981 &DummyScavengePointer); |
| 3964 } | 3982 } |
| 3965 } | 3983 } |
| 3966 | 3984 |
| 3967 | 3985 |
| 3968 static void VerifyPointersUnderWatermark(LargeObjectSpace* space) { | 3986 static void VerifyPointersUnderWatermark(LargeObjectSpace* space) { |
| 3969 LargeObjectIterator it(space); | 3987 LargeObjectIterator it(space); |
| 3970 for (HeapObject* object = it.next(); object != NULL; object = it.next()) { | 3988 for (HeapObject* object = it.next(); object != NULL; object = it.next()) { |
| 3971 if (object->IsFixedArray()) { | 3989 if (object->IsFixedArray()) { |
| 3972 Address slot_address = object->address(); | 3990 Address slot_address = object->address(); |
| 3973 Address end = object->address() + object->Size(); | 3991 Address end = object->address() + object->Size(); |
| 3974 | 3992 |
| 3975 while (slot_address < end) { | 3993 while (slot_address < end) { |
| 3976 HeapObject** slot = reinterpret_cast<HeapObject**>(slot_address); | 3994 HeapObject** slot = reinterpret_cast<HeapObject**>(slot_address); |
| 3977 // When we are not in GC the Heap::InNewSpace() predicate | 3995 // When we are not in GC the Heap::InNewSpace() predicate |
| 3978 // checks that pointers which satisfy predicate point into | 3996 // checks that pointers which satisfy predicate point into |
| 3979 // the active semispace. | 3997 // the active semispace. |
| 3980 Heap::InNewSpace(*slot); | 3998 HEAP->InNewSpace(*slot); |
| 3981 slot_address += kPointerSize; | 3999 slot_address += kPointerSize; |
| 3982 } | 4000 } |
| 3983 } | 4001 } |
| 3984 } | 4002 } |
| 3985 } | 4003 } |
| 3986 | 4004 |
| 3987 | 4005 |
| 3988 void Heap::Verify() { | 4006 void Heap::Verify() { |
| 3989 ASSERT(HasBeenSetup()); | 4007 ASSERT(HasBeenSetup()); |
| 3990 | 4008 |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4091 ASSERT(reinterpret_cast<Object*>(kFromSpaceZapValue)->IsFailure()); | 4109 ASSERT(reinterpret_cast<Object*>(kFromSpaceZapValue)->IsFailure()); |
| 4092 for (Address a = new_space_.FromSpaceLow(); | 4110 for (Address a = new_space_.FromSpaceLow(); |
| 4093 a < new_space_.FromSpaceHigh(); | 4111 a < new_space_.FromSpaceHigh(); |
| 4094 a += kPointerSize) { | 4112 a += kPointerSize) { |
| 4095 Memory::Address_at(a) = kFromSpaceZapValue; | 4113 Memory::Address_at(a) = kFromSpaceZapValue; |
| 4096 } | 4114 } |
| 4097 } | 4115 } |
| 4098 #endif // DEBUG | 4116 #endif // DEBUG |
| 4099 | 4117 |
| 4100 | 4118 |
| 4101 bool Heap::IteratePointersInDirtyRegion(Address start, | 4119 bool Heap::IteratePointersInDirtyRegion(Heap* heap, |
| 4120 Address start, |
| 4102 Address end, | 4121 Address end, |
| 4103 ObjectSlotCallback copy_object_func) { | 4122 ObjectSlotCallback copy_object_func) { |
| 4104 Address slot_address = start; | 4123 Address slot_address = start; |
| 4105 bool pointers_to_new_space_found = false; | 4124 bool pointers_to_new_space_found = false; |
| 4106 | 4125 |
| 4107 while (slot_address < end) { | 4126 while (slot_address < end) { |
| 4108 Object** slot = reinterpret_cast<Object**>(slot_address); | 4127 Object** slot = reinterpret_cast<Object**>(slot_address); |
| 4109 if (Heap::InNewSpace(*slot)) { | 4128 if (heap->InNewSpace(*slot)) { |
| 4110 ASSERT((*slot)->IsHeapObject()); | 4129 ASSERT((*slot)->IsHeapObject()); |
| 4111 copy_object_func(reinterpret_cast<HeapObject**>(slot)); | 4130 copy_object_func(reinterpret_cast<HeapObject**>(slot)); |
| 4112 if (Heap::InNewSpace(*slot)) { | 4131 if (heap->InNewSpace(*slot)) { |
| 4113 ASSERT((*slot)->IsHeapObject()); | 4132 ASSERT((*slot)->IsHeapObject()); |
| 4114 pointers_to_new_space_found = true; | 4133 pointers_to_new_space_found = true; |
| 4115 } | 4134 } |
| 4116 } | 4135 } |
| 4117 slot_address += kPointerSize; | 4136 slot_address += kPointerSize; |
| 4118 } | 4137 } |
| 4119 return pointers_to_new_space_found; | 4138 return pointers_to_new_space_found; |
| 4120 } | 4139 } |
| 4121 | 4140 |
| 4122 | 4141 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 4136 | 4155 |
| 4137 static bool IteratePointersInDirtyMaps(Address start, | 4156 static bool IteratePointersInDirtyMaps(Address start, |
| 4138 Address end, | 4157 Address end, |
| 4139 ObjectSlotCallback copy_object_func) { | 4158 ObjectSlotCallback copy_object_func) { |
| 4140 ASSERT(MapStartAlign(start) == start); | 4159 ASSERT(MapStartAlign(start) == start); |
| 4141 ASSERT(MapEndAlign(end) == end); | 4160 ASSERT(MapEndAlign(end) == end); |
| 4142 | 4161 |
| 4143 Address map_address = start; | 4162 Address map_address = start; |
| 4144 bool pointers_to_new_space_found = false; | 4163 bool pointers_to_new_space_found = false; |
| 4145 | 4164 |
| 4165 Heap* heap = HEAP; |
| 4146 while (map_address < end) { | 4166 while (map_address < end) { |
| 4147 ASSERT(!Heap::InNewSpace(Memory::Object_at(map_address))); | 4167 ASSERT(!heap->InNewSpace(Memory::Object_at(map_address))); |
| 4148 ASSERT(Memory::Object_at(map_address)->IsMap()); | 4168 ASSERT(Memory::Object_at(map_address)->IsMap()); |
| 4149 | 4169 |
| 4150 Address pointer_fields_start = map_address + Map::kPointerFieldsBeginOffset; | 4170 Address pointer_fields_start = map_address + Map::kPointerFieldsBeginOffset; |
| 4151 Address pointer_fields_end = map_address + Map::kPointerFieldsEndOffset; | 4171 Address pointer_fields_end = map_address + Map::kPointerFieldsEndOffset; |
| 4152 | 4172 |
| 4153 if (Heap::IteratePointersInDirtyRegion(pointer_fields_start, | 4173 if (Heap::IteratePointersInDirtyRegion(heap, |
| 4174 pointer_fields_start, |
| 4154 pointer_fields_end, | 4175 pointer_fields_end, |
| 4155 copy_object_func)) { | 4176 copy_object_func)) { |
| 4156 pointers_to_new_space_found = true; | 4177 pointers_to_new_space_found = true; |
| 4157 } | 4178 } |
| 4158 | 4179 |
| 4159 map_address += Map::kSize; | 4180 map_address += Map::kSize; |
| 4160 } | 4181 } |
| 4161 | 4182 |
| 4162 return pointers_to_new_space_found; | 4183 return pointers_to_new_space_found; |
| 4163 } | 4184 } |
| 4164 | 4185 |
| 4165 | 4186 |
| 4166 bool Heap::IteratePointersInDirtyMapsRegion( | 4187 bool Heap::IteratePointersInDirtyMapsRegion( |
| 4188 Heap* heap, |
| 4167 Address start, | 4189 Address start, |
| 4168 Address end, | 4190 Address end, |
| 4169 ObjectSlotCallback copy_object_func) { | 4191 ObjectSlotCallback copy_object_func) { |
| 4170 Address map_aligned_start = MapStartAlign(start); | 4192 Address map_aligned_start = MapStartAlign(start); |
| 4171 Address map_aligned_end = MapEndAlign(end); | 4193 Address map_aligned_end = MapEndAlign(end); |
| 4172 | 4194 |
| 4173 bool contains_pointers_to_new_space = false; | 4195 bool contains_pointers_to_new_space = false; |
| 4174 | 4196 |
| 4175 if (map_aligned_start != start) { | 4197 if (map_aligned_start != start) { |
| 4176 Address prev_map = map_aligned_start - Map::kSize; | 4198 Address prev_map = map_aligned_start - Map::kSize; |
| 4177 ASSERT(Memory::Object_at(prev_map)->IsMap()); | 4199 ASSERT(Memory::Object_at(prev_map)->IsMap()); |
| 4178 | 4200 |
| 4179 Address pointer_fields_start = | 4201 Address pointer_fields_start = |
| 4180 Max(start, prev_map + Map::kPointerFieldsBeginOffset); | 4202 Max(start, prev_map + Map::kPointerFieldsBeginOffset); |
| 4181 | 4203 |
| 4182 Address pointer_fields_end = | 4204 Address pointer_fields_end = |
| 4183 Min(prev_map + Map::kPointerFieldsEndOffset, end); | 4205 Min(prev_map + Map::kPointerFieldsEndOffset, end); |
| 4184 | 4206 |
| 4185 contains_pointers_to_new_space = | 4207 contains_pointers_to_new_space = |
| 4186 IteratePointersInDirtyRegion(pointer_fields_start, | 4208 IteratePointersInDirtyRegion(heap, |
| 4209 pointer_fields_start, |
| 4187 pointer_fields_end, | 4210 pointer_fields_end, |
| 4188 copy_object_func) | 4211 copy_object_func) |
| 4189 || contains_pointers_to_new_space; | 4212 || contains_pointers_to_new_space; |
| 4190 } | 4213 } |
| 4191 | 4214 |
| 4192 contains_pointers_to_new_space = | 4215 contains_pointers_to_new_space = |
| 4193 IteratePointersInDirtyMaps(map_aligned_start, | 4216 IteratePointersInDirtyMaps(map_aligned_start, |
| 4194 map_aligned_end, | 4217 map_aligned_end, |
| 4195 copy_object_func) | 4218 copy_object_func) |
| 4196 || contains_pointers_to_new_space; | 4219 || contains_pointers_to_new_space; |
| 4197 | 4220 |
| 4198 if (map_aligned_end != end) { | 4221 if (map_aligned_end != end) { |
| 4199 ASSERT(Memory::Object_at(map_aligned_end)->IsMap()); | 4222 ASSERT(Memory::Object_at(map_aligned_end)->IsMap()); |
| 4200 | 4223 |
| 4201 Address pointer_fields_start = | 4224 Address pointer_fields_start = |
| 4202 map_aligned_end + Map::kPointerFieldsBeginOffset; | 4225 map_aligned_end + Map::kPointerFieldsBeginOffset; |
| 4203 | 4226 |
| 4204 Address pointer_fields_end = | 4227 Address pointer_fields_end = |
| 4205 Min(end, map_aligned_end + Map::kPointerFieldsEndOffset); | 4228 Min(end, map_aligned_end + Map::kPointerFieldsEndOffset); |
| 4206 | 4229 |
| 4207 contains_pointers_to_new_space = | 4230 contains_pointers_to_new_space = |
| 4208 IteratePointersInDirtyRegion(pointer_fields_start, | 4231 IteratePointersInDirtyRegion(heap, |
| 4232 pointer_fields_start, |
| 4209 pointer_fields_end, | 4233 pointer_fields_end, |
| 4210 copy_object_func) | 4234 copy_object_func) |
| 4211 || contains_pointers_to_new_space; | 4235 || contains_pointers_to_new_space; |
| 4212 } | 4236 } |
| 4213 | 4237 |
| 4214 return contains_pointers_to_new_space; | 4238 return contains_pointers_to_new_space; |
| 4215 } | 4239 } |
| 4216 | 4240 |
| 4217 | 4241 |
| 4218 void Heap::IterateAndMarkPointersToFromSpace(Address start, | 4242 void Heap::IterateAndMarkPointersToFromSpace(Address start, |
| 4219 Address end, | 4243 Address end, |
| 4220 ObjectSlotCallback callback) { | 4244 ObjectSlotCallback callback) { |
| 4221 Address slot_address = start; | 4245 Address slot_address = start; |
| 4222 Page* page = Page::FromAddress(start); | 4246 Page* page = Page::FromAddress(start); |
| 4223 | 4247 |
| 4224 uint32_t marks = page->GetRegionMarks(); | 4248 uint32_t marks = page->GetRegionMarks(); |
| 4225 | 4249 |
| 4226 while (slot_address < end) { | 4250 while (slot_address < end) { |
| 4227 Object** slot = reinterpret_cast<Object**>(slot_address); | 4251 Object** slot = reinterpret_cast<Object**>(slot_address); |
| 4228 if (Heap::InFromSpace(*slot)) { | 4252 if (InFromSpace(*slot)) { |
| 4229 ASSERT((*slot)->IsHeapObject()); | 4253 ASSERT((*slot)->IsHeapObject()); |
| 4230 callback(reinterpret_cast<HeapObject**>(slot)); | 4254 callback(reinterpret_cast<HeapObject**>(slot)); |
| 4231 if (Heap::InNewSpace(*slot)) { | 4255 if (InNewSpace(*slot)) { |
| 4232 ASSERT((*slot)->IsHeapObject()); | 4256 ASSERT((*slot)->IsHeapObject()); |
| 4233 marks |= page->GetRegionMaskForAddress(slot_address); | 4257 marks |= page->GetRegionMaskForAddress(slot_address); |
| 4234 } | 4258 } |
| 4235 } | 4259 } |
| 4236 slot_address += kPointerSize; | 4260 slot_address += kPointerSize; |
| 4237 } | 4261 } |
| 4238 | 4262 |
| 4239 page->SetRegionMarks(marks); | 4263 page->SetRegionMarks(marks); |
| 4240 } | 4264 } |
| 4241 | 4265 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 4260 // area_start by Page::kRegionSize. | 4284 // area_start by Page::kRegionSize. |
| 4261 Address second_region = | 4285 Address second_region = |
| 4262 reinterpret_cast<Address>( | 4286 reinterpret_cast<Address>( |
| 4263 reinterpret_cast<intptr_t>(area_start + Page::kRegionSize) & | 4287 reinterpret_cast<intptr_t>(area_start + Page::kRegionSize) & |
| 4264 ~Page::kRegionAlignmentMask); | 4288 ~Page::kRegionAlignmentMask); |
| 4265 | 4289 |
| 4266 // Next region might be beyond area_end. | 4290 // Next region might be beyond area_end. |
| 4267 Address region_end = Min(second_region, area_end); | 4291 Address region_end = Min(second_region, area_end); |
| 4268 | 4292 |
| 4269 if (marks & mask) { | 4293 if (marks & mask) { |
| 4270 if (visit_dirty_region(region_start, region_end, copy_object_func)) { | 4294 if (visit_dirty_region(this, region_start, region_end, copy_object_func)) { |
| 4271 newmarks |= mask; | 4295 newmarks |= mask; |
| 4272 } | 4296 } |
| 4273 } | 4297 } |
| 4274 mask <<= 1; | 4298 mask <<= 1; |
| 4275 | 4299 |
| 4276 // Iterate subsequent regions which fully lay inside [area_start, area_end[. | 4300 // Iterate subsequent regions which fully lay inside [area_start, area_end[. |
| 4277 region_start = region_end; | 4301 region_start = region_end; |
| 4278 region_end = region_start + Page::kRegionSize; | 4302 region_end = region_start + Page::kRegionSize; |
| 4279 | 4303 |
| 4280 while (region_end <= area_end) { | 4304 while (region_end <= area_end) { |
| 4281 if (marks & mask) { | 4305 if (marks & mask) { |
| 4282 if (visit_dirty_region(region_start, region_end, copy_object_func)) { | 4306 if (visit_dirty_region(this, |
| 4307 region_start, |
| 4308 region_end, |
| 4309 copy_object_func)) { |
| 4283 newmarks |= mask; | 4310 newmarks |= mask; |
| 4284 } | 4311 } |
| 4285 } | 4312 } |
| 4286 | 4313 |
| 4287 region_start = region_end; | 4314 region_start = region_end; |
| 4288 region_end = region_start + Page::kRegionSize; | 4315 region_end = region_start + Page::kRegionSize; |
| 4289 | 4316 |
| 4290 mask <<= 1; | 4317 mask <<= 1; |
| 4291 } | 4318 } |
| 4292 | 4319 |
| 4293 if (region_start != area_end) { | 4320 if (region_start != area_end) { |
| 4294 // A small piece of area left uniterated because area_end does not coincide | 4321 // A small piece of area left uniterated because area_end does not coincide |
| 4295 // with region end. Check whether region covering last part of area is | 4322 // with region end. Check whether region covering last part of area is |
| 4296 // dirty. | 4323 // dirty. |
| 4297 if (marks & mask) { | 4324 if (marks & mask) { |
| 4298 if (visit_dirty_region(region_start, area_end, copy_object_func)) { | 4325 if (visit_dirty_region(this, region_start, area_end, copy_object_func)) { |
| 4299 newmarks |= mask; | 4326 newmarks |= mask; |
| 4300 } | 4327 } |
| 4301 } | 4328 } |
| 4302 } | 4329 } |
| 4303 | 4330 |
| 4304 return newmarks; | 4331 return newmarks; |
| 4305 } | 4332 } |
| 4306 | 4333 |
| 4307 | 4334 |
| 4308 | 4335 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4354 IterateStrongRoots(v, mode); | 4381 IterateStrongRoots(v, mode); |
| 4355 IterateWeakRoots(v, mode); | 4382 IterateWeakRoots(v, mode); |
| 4356 } | 4383 } |
| 4357 | 4384 |
| 4358 | 4385 |
| 4359 void Heap::IterateWeakRoots(ObjectVisitor* v, VisitMode mode) { | 4386 void Heap::IterateWeakRoots(ObjectVisitor* v, VisitMode mode) { |
| 4360 v->VisitPointer(reinterpret_cast<Object**>(&roots_[kSymbolTableRootIndex])); | 4387 v->VisitPointer(reinterpret_cast<Object**>(&roots_[kSymbolTableRootIndex])); |
| 4361 v->Synchronize("symbol_table"); | 4388 v->Synchronize("symbol_table"); |
| 4362 if (mode != VISIT_ALL_IN_SCAVENGE) { | 4389 if (mode != VISIT_ALL_IN_SCAVENGE) { |
| 4363 // Scavenge collections have special processing for this. | 4390 // Scavenge collections have special processing for this. |
| 4364 ExternalStringTable::Iterate(v); | 4391 external_string_table_.Iterate(v); |
| 4365 } | 4392 } |
| 4366 v->Synchronize("external_string_table"); | 4393 v->Synchronize("external_string_table"); |
| 4367 } | 4394 } |
| 4368 | 4395 |
| 4369 | 4396 |
| 4370 void Heap::IterateStrongRoots(ObjectVisitor* v, VisitMode mode) { | 4397 void Heap::IterateStrongRoots(ObjectVisitor* v, VisitMode mode) { |
| 4371 v->VisitPointers(&roots_[0], &roots_[kStrongRootListLength]); | 4398 v->VisitPointers(&roots_[0], &roots_[kStrongRootListLength]); |
| 4372 v->Synchronize("strong_root_list"); | 4399 v->Synchronize("strong_root_list"); |
| 4373 | 4400 |
| 4374 v->VisitPointer(BitCast<Object**>(&hidden_symbol_)); | 4401 v->VisitPointer(BitCast<Object**>(&hidden_symbol_)); |
| 4375 v->Synchronize("symbol"); | 4402 v->Synchronize("symbol"); |
| 4376 | 4403 |
| 4377 Bootstrapper::Iterate(v); | 4404 isolate_->bootstrapper()->Iterate(v); |
| 4378 v->Synchronize("bootstrapper"); | 4405 v->Synchronize("bootstrapper"); |
| 4379 Top::Iterate(v); | 4406 isolate_->Iterate(v); |
| 4380 v->Synchronize("top"); | 4407 v->Synchronize("top"); |
| 4381 Relocatable::Iterate(v); | 4408 Relocatable::Iterate(v); |
| 4382 v->Synchronize("relocatable"); | 4409 v->Synchronize("relocatable"); |
| 4383 | 4410 |
| 4384 #ifdef ENABLE_DEBUGGER_SUPPORT | 4411 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 4385 Debug::Iterate(v); | 4412 isolate_->debug()->Iterate(v); |
| 4386 #endif | 4413 #endif |
| 4387 v->Synchronize("debug"); | 4414 v->Synchronize("debug"); |
| 4388 CompilationCache::Iterate(v); | 4415 isolate_->compilation_cache()->Iterate(v); |
| 4389 v->Synchronize("compilationcache"); | 4416 v->Synchronize("compilationcache"); |
| 4390 | 4417 |
| 4391 // Iterate over local handles in handle scopes. | 4418 // Iterate over local handles in handle scopes. |
| 4392 HandleScopeImplementer::Iterate(v); | 4419 isolate_->handle_scope_implementer()->Iterate(v); |
| 4393 v->Synchronize("handlescope"); | 4420 v->Synchronize("handlescope"); |
| 4394 | 4421 |
| 4395 // Iterate over the builtin code objects and code stubs in the | 4422 // Iterate over the builtin code objects and code stubs in the |
| 4396 // heap. Note that it is not necessary to iterate over code objects | 4423 // heap. Note that it is not necessary to iterate over code objects |
| 4397 // on scavenge collections. | 4424 // on scavenge collections. |
| 4398 if (mode != VISIT_ALL_IN_SCAVENGE) { | 4425 if (mode != VISIT_ALL_IN_SCAVENGE) { |
| 4399 Builtins::IterateBuiltins(v); | 4426 isolate_->builtins()->IterateBuiltins(v); |
| 4400 } | 4427 } |
| 4401 v->Synchronize("builtins"); | 4428 v->Synchronize("builtins"); |
| 4402 | 4429 |
| 4403 // Iterate over global handles. | 4430 // Iterate over global handles. |
| 4404 if (mode == VISIT_ONLY_STRONG) { | 4431 if (mode == VISIT_ONLY_STRONG) { |
| 4405 GlobalHandles::IterateStrongRoots(v); | 4432 isolate_->global_handles()->IterateStrongRoots(v); |
| 4406 } else { | 4433 } else { |
| 4407 GlobalHandles::IterateAllRoots(v); | 4434 isolate_->global_handles()->IterateAllRoots(v); |
| 4408 } | 4435 } |
| 4409 v->Synchronize("globalhandles"); | 4436 v->Synchronize("globalhandles"); |
| 4410 | 4437 |
| 4411 // Iterate over pointers being held by inactive threads. | 4438 // Iterate over pointers being held by inactive threads. |
| 4412 ThreadManager::Iterate(v); | 4439 isolate_->thread_manager()->Iterate(v); |
| 4413 v->Synchronize("threadmanager"); | 4440 v->Synchronize("threadmanager"); |
| 4414 | 4441 |
| 4415 // Iterate over the pointers the Serialization/Deserialization code is | 4442 // Iterate over the pointers the Serialization/Deserialization code is |
| 4416 // holding. | 4443 // holding. |
| 4417 // During garbage collection this keeps the partial snapshot cache alive. | 4444 // During garbage collection this keeps the partial snapshot cache alive. |
| 4418 // During deserialization of the startup snapshot this creates the partial | 4445 // During deserialization of the startup snapshot this creates the partial |
| 4419 // snapshot cache and deserializes the objects it refers to. During | 4446 // snapshot cache and deserializes the objects it refers to. During |
| 4420 // serialization this does nothing, since the partial snapshot cache is | 4447 // serialization this does nothing, since the partial snapshot cache is |
| 4421 // empty. However the next thing we do is create the partial snapshot, | 4448 // empty. However the next thing we do is create the partial snapshot, |
| 4422 // filling up the partial snapshot cache with objects it needs as we go. | 4449 // filling up the partial snapshot cache with objects it needs as we go. |
| 4423 SerializerDeserializer::Iterate(v); | 4450 SerializerDeserializer::Iterate(v); |
| 4424 // We don't do a v->Synchronize call here, because in debug mode that will | 4451 // We don't do a v->Synchronize call here, because in debug mode that will |
| 4425 // output a flag to the snapshot. However at this point the serializer and | 4452 // output a flag to the snapshot. However at this point the serializer and |
| 4426 // deserializer are deliberately a little unsynchronized (see above) so the | 4453 // deserializer are deliberately a little unsynchronized (see above) so the |
| 4427 // checking of the sync flag in the snapshot would fail. | 4454 // checking of the sync flag in the snapshot would fail. |
| 4428 } | 4455 } |
| 4429 | 4456 |
| 4430 | 4457 |
| 4431 // Flag is set when the heap has been configured. The heap can be repeatedly | |
| 4432 // configured through the API until it is setup. | |
| 4433 static bool heap_configured = false; | |
| 4434 | |
| 4435 // TODO(1236194): Since the heap size is configurable on the command line | 4458 // TODO(1236194): Since the heap size is configurable on the command line |
| 4436 // and through the API, we should gracefully handle the case that the heap | 4459 // and through the API, we should gracefully handle the case that the heap |
| 4437 // size is not big enough to fit all the initial objects. | 4460 // size is not big enough to fit all the initial objects. |
| 4438 bool Heap::ConfigureHeap(int max_semispace_size, | 4461 bool Heap::ConfigureHeap(int max_semispace_size, |
| 4439 int max_old_gen_size, | 4462 int max_old_gen_size, |
| 4440 int max_executable_size) { | 4463 int max_executable_size) { |
| 4441 if (HasBeenSetup()) return false; | 4464 if (HasBeenSetup()) return false; |
| 4442 | 4465 |
| 4443 if (max_semispace_size > 0) max_semispace_size_ = max_semispace_size; | 4466 if (max_semispace_size > 0) max_semispace_size_ = max_semispace_size; |
| 4444 | 4467 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 4471 // The new space size must be a power of two to support single-bit testing | 4494 // The new space size must be a power of two to support single-bit testing |
| 4472 // for containment. | 4495 // for containment. |
| 4473 max_semispace_size_ = RoundUpToPowerOf2(max_semispace_size_); | 4496 max_semispace_size_ = RoundUpToPowerOf2(max_semispace_size_); |
| 4474 reserved_semispace_size_ = RoundUpToPowerOf2(reserved_semispace_size_); | 4497 reserved_semispace_size_ = RoundUpToPowerOf2(reserved_semispace_size_); |
| 4475 initial_semispace_size_ = Min(initial_semispace_size_, max_semispace_size_); | 4498 initial_semispace_size_ = Min(initial_semispace_size_, max_semispace_size_); |
| 4476 external_allocation_limit_ = 10 * max_semispace_size_; | 4499 external_allocation_limit_ = 10 * max_semispace_size_; |
| 4477 | 4500 |
| 4478 // The old generation is paged. | 4501 // The old generation is paged. |
| 4479 max_old_generation_size_ = RoundUp(max_old_generation_size_, Page::kPageSize); | 4502 max_old_generation_size_ = RoundUp(max_old_generation_size_, Page::kPageSize); |
| 4480 | 4503 |
| 4481 heap_configured = true; | 4504 configured_ = true; |
| 4482 return true; | 4505 return true; |
| 4483 } | 4506 } |
| 4484 | 4507 |
| 4485 | 4508 |
| 4486 bool Heap::ConfigureHeapDefault() { | 4509 bool Heap::ConfigureHeapDefault() { |
| 4487 return ConfigureHeap(FLAG_max_new_space_size / 2 * KB, | 4510 return ConfigureHeap(FLAG_max_new_space_size / 2 * KB, |
| 4488 FLAG_max_old_space_size * MB, | 4511 FLAG_max_old_space_size * MB, |
| 4489 FLAG_max_executable_size * MB); | 4512 FLAG_max_executable_size * MB); |
| 4490 } | 4513 } |
| 4491 | 4514 |
| 4492 | 4515 |
| 4493 void Heap::RecordStats(HeapStats* stats, bool take_snapshot) { | 4516 void Heap::RecordStats(HeapStats* stats, bool take_snapshot) { |
| 4494 *stats->start_marker = HeapStats::kStartMarker; | 4517 *stats->start_marker = HeapStats::kStartMarker; |
| 4495 *stats->end_marker = HeapStats::kEndMarker; | 4518 *stats->end_marker = HeapStats::kEndMarker; |
| 4496 *stats->new_space_size = new_space_.SizeAsInt(); | 4519 *stats->new_space_size = new_space_.SizeAsInt(); |
| 4497 *stats->new_space_capacity = static_cast<int>(new_space_.Capacity()); | 4520 *stats->new_space_capacity = static_cast<int>(new_space_.Capacity()); |
| 4498 *stats->old_pointer_space_size = old_pointer_space_->Size(); | 4521 *stats->old_pointer_space_size = old_pointer_space_->Size(); |
| 4499 *stats->old_pointer_space_capacity = old_pointer_space_->Capacity(); | 4522 *stats->old_pointer_space_capacity = old_pointer_space_->Capacity(); |
| 4500 *stats->old_data_space_size = old_data_space_->Size(); | 4523 *stats->old_data_space_size = old_data_space_->Size(); |
| 4501 *stats->old_data_space_capacity = old_data_space_->Capacity(); | 4524 *stats->old_data_space_capacity = old_data_space_->Capacity(); |
| 4502 *stats->code_space_size = code_space_->Size(); | 4525 *stats->code_space_size = code_space_->Size(); |
| 4503 *stats->code_space_capacity = code_space_->Capacity(); | 4526 *stats->code_space_capacity = code_space_->Capacity(); |
| 4504 *stats->map_space_size = map_space_->Size(); | 4527 *stats->map_space_size = map_space_->Size(); |
| 4505 *stats->map_space_capacity = map_space_->Capacity(); | 4528 *stats->map_space_capacity = map_space_->Capacity(); |
| 4506 *stats->cell_space_size = cell_space_->Size(); | 4529 *stats->cell_space_size = cell_space_->Size(); |
| 4507 *stats->cell_space_capacity = cell_space_->Capacity(); | 4530 *stats->cell_space_capacity = cell_space_->Capacity(); |
| 4508 *stats->lo_space_size = lo_space_->Size(); | 4531 *stats->lo_space_size = lo_space_->Size(); |
| 4509 GlobalHandles::RecordStats(stats); | 4532 isolate_->global_handles()->RecordStats(stats); |
| 4510 *stats->memory_allocator_size = MemoryAllocator::Size(); | 4533 *stats->memory_allocator_size = isolate()->memory_allocator()->Size(); |
| 4511 *stats->memory_allocator_capacity = | 4534 *stats->memory_allocator_capacity = |
| 4512 MemoryAllocator::Size() + MemoryAllocator::Available(); | 4535 isolate()->memory_allocator()->Size() + |
| 4536 isolate()->memory_allocator()->Available(); |
| 4513 *stats->os_error = OS::GetLastError(); | 4537 *stats->os_error = OS::GetLastError(); |
| 4538 isolate()->memory_allocator()->Available(); |
| 4514 if (take_snapshot) { | 4539 if (take_snapshot) { |
| 4515 HeapIterator iterator(HeapIterator::kFilterFreeListNodes); | 4540 HeapIterator iterator(HeapIterator::kFilterFreeListNodes); |
| 4516 for (HeapObject* obj = iterator.next(); | 4541 for (HeapObject* obj = iterator.next(); |
| 4517 obj != NULL; | 4542 obj != NULL; |
| 4518 obj = iterator.next()) { | 4543 obj = iterator.next()) { |
| 4519 InstanceType type = obj->map()->instance_type(); | 4544 InstanceType type = obj->map()->instance_type(); |
| 4520 ASSERT(0 <= type && type <= LAST_TYPE); | 4545 ASSERT(0 <= type && type <= LAST_TYPE); |
| 4521 stats->objects_per_type[type]++; | 4546 stats->objects_per_type[type]++; |
| 4522 stats->size_per_type[type] += obj->Size(); | 4547 stats->size_per_type[type] += obj->Size(); |
| 4523 } | 4548 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 4535 } | 4560 } |
| 4536 | 4561 |
| 4537 | 4562 |
| 4538 int Heap::PromotedExternalMemorySize() { | 4563 int Heap::PromotedExternalMemorySize() { |
| 4539 if (amount_of_external_allocated_memory_ | 4564 if (amount_of_external_allocated_memory_ |
| 4540 <= amount_of_external_allocated_memory_at_last_global_gc_) return 0; | 4565 <= amount_of_external_allocated_memory_at_last_global_gc_) return 0; |
| 4541 return amount_of_external_allocated_memory_ | 4566 return amount_of_external_allocated_memory_ |
| 4542 - amount_of_external_allocated_memory_at_last_global_gc_; | 4567 - amount_of_external_allocated_memory_at_last_global_gc_; |
| 4543 } | 4568 } |
| 4544 | 4569 |
| 4570 #ifdef DEBUG |
| 4571 |
| 4572 // Tags 0, 1, and 3 are used. Use 2 for marking visited HeapObject. |
| 4573 static const int kMarkTag = 2; |
| 4574 |
| 4575 |
| 4576 class HeapDebugUtils { |
| 4577 public: |
| 4578 explicit HeapDebugUtils(Heap* heap) |
| 4579 : search_for_any_global_(false), |
| 4580 search_target_(NULL), |
| 4581 found_target_(false), |
| 4582 object_stack_(20), |
| 4583 heap_(heap) { |
| 4584 } |
| 4585 |
| 4586 class MarkObjectVisitor : public ObjectVisitor { |
| 4587 public: |
| 4588 explicit MarkObjectVisitor(HeapDebugUtils* utils) : utils_(utils) { } |
| 4589 |
| 4590 void VisitPointers(Object** start, Object** end) { |
| 4591 // Copy all HeapObject pointers in [start, end) |
| 4592 for (Object** p = start; p < end; p++) { |
| 4593 if ((*p)->IsHeapObject()) |
| 4594 utils_->MarkObjectRecursively(p); |
| 4595 } |
| 4596 } |
| 4597 |
| 4598 HeapDebugUtils* utils_; |
| 4599 }; |
| 4600 |
| 4601 void MarkObjectRecursively(Object** p) { |
| 4602 if (!(*p)->IsHeapObject()) return; |
| 4603 |
| 4604 HeapObject* obj = HeapObject::cast(*p); |
| 4605 |
| 4606 Object* map = obj->map(); |
| 4607 |
| 4608 if (!map->IsHeapObject()) return; // visited before |
| 4609 |
| 4610 if (found_target_) return; // stop if target found |
| 4611 object_stack_.Add(obj); |
| 4612 if ((search_for_any_global_ && obj->IsJSGlobalObject()) || |
| 4613 (!search_for_any_global_ && (obj == search_target_))) { |
| 4614 found_target_ = true; |
| 4615 return; |
| 4616 } |
| 4617 |
| 4618 // not visited yet |
| 4619 Map* map_p = reinterpret_cast<Map*>(HeapObject::cast(map)); |
| 4620 |
| 4621 Address map_addr = map_p->address(); |
| 4622 |
| 4623 obj->set_map(reinterpret_cast<Map*>(map_addr + kMarkTag)); |
| 4624 |
| 4625 MarkObjectRecursively(&map); |
| 4626 |
| 4627 MarkObjectVisitor mark_visitor(this); |
| 4628 |
| 4629 obj->IterateBody(map_p->instance_type(), obj->SizeFromMap(map_p), |
| 4630 &mark_visitor); |
| 4631 |
| 4632 if (!found_target_) // don't pop if found the target |
| 4633 object_stack_.RemoveLast(); |
| 4634 } |
| 4635 |
| 4636 |
| 4637 class UnmarkObjectVisitor : public ObjectVisitor { |
| 4638 public: |
| 4639 explicit UnmarkObjectVisitor(HeapDebugUtils* utils) : utils_(utils) { } |
| 4640 |
| 4641 void VisitPointers(Object** start, Object** end) { |
| 4642 // Copy all HeapObject pointers in [start, end) |
| 4643 for (Object** p = start; p < end; p++) { |
| 4644 if ((*p)->IsHeapObject()) |
| 4645 utils_->UnmarkObjectRecursively(p); |
| 4646 } |
| 4647 } |
| 4648 |
| 4649 HeapDebugUtils* utils_; |
| 4650 }; |
| 4651 |
| 4652 |
| 4653 void UnmarkObjectRecursively(Object** p) { |
| 4654 if (!(*p)->IsHeapObject()) return; |
| 4655 |
| 4656 HeapObject* obj = HeapObject::cast(*p); |
| 4657 |
| 4658 Object* map = obj->map(); |
| 4659 |
| 4660 if (map->IsHeapObject()) return; // unmarked already |
| 4661 |
| 4662 Address map_addr = reinterpret_cast<Address>(map); |
| 4663 |
| 4664 map_addr -= kMarkTag; |
| 4665 |
| 4666 ASSERT_TAG_ALIGNED(map_addr); |
| 4667 |
| 4668 HeapObject* map_p = HeapObject::FromAddress(map_addr); |
| 4669 |
| 4670 obj->set_map(reinterpret_cast<Map*>(map_p)); |
| 4671 |
| 4672 UnmarkObjectRecursively(reinterpret_cast<Object**>(&map_p)); |
| 4673 |
| 4674 UnmarkObjectVisitor unmark_visitor(this); |
| 4675 |
| 4676 obj->IterateBody(Map::cast(map_p)->instance_type(), |
| 4677 obj->SizeFromMap(Map::cast(map_p)), |
| 4678 &unmark_visitor); |
| 4679 } |
| 4680 |
| 4681 |
| 4682 void MarkRootObjectRecursively(Object** root) { |
| 4683 if (search_for_any_global_) { |
| 4684 ASSERT(search_target_ == NULL); |
| 4685 } else { |
| 4686 ASSERT(search_target_->IsHeapObject()); |
| 4687 } |
| 4688 found_target_ = false; |
| 4689 object_stack_.Clear(); |
| 4690 |
| 4691 MarkObjectRecursively(root); |
| 4692 UnmarkObjectRecursively(root); |
| 4693 |
| 4694 if (found_target_) { |
| 4695 PrintF("=====================================\n"); |
| 4696 PrintF("==== Path to object ====\n"); |
| 4697 PrintF("=====================================\n\n"); |
| 4698 |
| 4699 ASSERT(!object_stack_.is_empty()); |
| 4700 for (int i = 0; i < object_stack_.length(); i++) { |
| 4701 if (i > 0) PrintF("\n |\n |\n V\n\n"); |
| 4702 Object* obj = object_stack_[i]; |
| 4703 obj->Print(); |
| 4704 } |
| 4705 PrintF("=====================================\n"); |
| 4706 } |
| 4707 } |
| 4708 |
| 4709 // Helper class for visiting HeapObjects recursively. |
| 4710 class MarkRootVisitor: public ObjectVisitor { |
| 4711 public: |
| 4712 explicit MarkRootVisitor(HeapDebugUtils* utils) : utils_(utils) { } |
| 4713 |
| 4714 void VisitPointers(Object** start, Object** end) { |
| 4715 // Visit all HeapObject pointers in [start, end) |
| 4716 for (Object** p = start; p < end; p++) { |
| 4717 if ((*p)->IsHeapObject()) |
| 4718 utils_->MarkRootObjectRecursively(p); |
| 4719 } |
| 4720 } |
| 4721 |
| 4722 HeapDebugUtils* utils_; |
| 4723 }; |
| 4724 |
| 4725 bool search_for_any_global_; |
| 4726 Object* search_target_; |
| 4727 bool found_target_; |
| 4728 List<Object*> object_stack_; |
| 4729 Heap* heap_; |
| 4730 |
| 4731 friend class Heap; |
| 4732 }; |
| 4733 |
| 4734 #endif |
| 4545 | 4735 |
| 4546 bool Heap::Setup(bool create_heap_objects) { | 4736 bool Heap::Setup(bool create_heap_objects) { |
| 4737 #ifdef DEBUG |
| 4738 debug_utils_ = new HeapDebugUtils(this); |
| 4739 #endif |
| 4740 |
| 4547 // Initialize heap spaces and initial maps and objects. Whenever something | 4741 // Initialize heap spaces and initial maps and objects. Whenever something |
| 4548 // goes wrong, just return false. The caller should check the results and | 4742 // goes wrong, just return false. The caller should check the results and |
| 4549 // call Heap::TearDown() to release allocated memory. | 4743 // call Heap::TearDown() to release allocated memory. |
| 4550 // | 4744 // |
| 4551 // If the heap is not yet configured (eg, through the API), configure it. | 4745 // If the heap is not yet configured (eg, through the API), configure it. |
| 4552 // Configuration is based on the flags new-space-size (really the semispace | 4746 // Configuration is based on the flags new-space-size (really the semispace |
| 4553 // size) and old-space-size if set or the initial values of semispace_size_ | 4747 // size) and old-space-size if set or the initial values of semispace_size_ |
| 4554 // and old_generation_size_ otherwise. | 4748 // and old_generation_size_ otherwise. |
| 4555 if (!heap_configured) { | 4749 if (!configured_) { |
| 4556 if (!ConfigureHeapDefault()) return false; | 4750 if (!ConfigureHeapDefault()) return false; |
| 4557 } | 4751 } |
| 4558 | 4752 |
| 4559 ScavengingVisitor::Initialize(); | 4753 gc_initializer_mutex->Lock(); |
| 4560 NewSpaceScavenger::Initialize(); | 4754 static bool initialized_gc = false; |
| 4561 MarkCompactCollector::Initialize(); | 4755 if (!initialized_gc) { |
| 4756 initialized_gc = true; |
| 4757 ScavengingVisitor::Initialize(); |
| 4758 NewSpaceScavenger::Initialize(); |
| 4759 MarkCompactCollector::Initialize(); |
| 4760 } |
| 4761 gc_initializer_mutex->Unlock(); |
| 4562 | 4762 |
| 4563 MarkMapPointersAsEncoded(false); | 4763 MarkMapPointersAsEncoded(false); |
| 4564 | 4764 |
| 4565 // Setup memory allocator and reserve a chunk of memory for new | 4765 // Setup memory allocator and reserve a chunk of memory for new |
| 4566 // space. The chunk is double the size of the requested reserved | 4766 // space. The chunk is double the size of the requested reserved |
| 4567 // new space size to ensure that we can find a pair of semispaces that | 4767 // new space size to ensure that we can find a pair of semispaces that |
| 4568 // are contiguous and aligned to their size. | 4768 // are contiguous and aligned to their size. |
| 4569 if (!MemoryAllocator::Setup(MaxReserved(), MaxExecutableSize())) return false; | 4769 if (!isolate_->memory_allocator()->Setup(MaxReserved(), MaxExecutableSize())) |
| 4770 return false; |
| 4570 void* chunk = | 4771 void* chunk = |
| 4571 MemoryAllocator::ReserveInitialChunk(4 * reserved_semispace_size_); | 4772 isolate_->memory_allocator()->ReserveInitialChunk( |
| 4773 4 * reserved_semispace_size_); |
| 4572 if (chunk == NULL) return false; | 4774 if (chunk == NULL) return false; |
| 4573 | 4775 |
| 4574 // Align the pair of semispaces to their size, which must be a power | 4776 // Align the pair of semispaces to their size, which must be a power |
| 4575 // of 2. | 4777 // of 2. |
| 4576 Address new_space_start = | 4778 Address new_space_start = |
| 4577 RoundUp(reinterpret_cast<byte*>(chunk), 2 * reserved_semispace_size_); | 4779 RoundUp(reinterpret_cast<byte*>(chunk), 2 * reserved_semispace_size_); |
| 4578 if (!new_space_.Setup(new_space_start, 2 * reserved_semispace_size_)) { | 4780 if (!new_space_.Setup(new_space_start, 2 * reserved_semispace_size_)) { |
| 4579 return false; | 4781 return false; |
| 4580 } | 4782 } |
| 4581 | 4783 |
| 4582 // Initialize old pointer space. | 4784 // Initialize old pointer space. |
| 4583 old_pointer_space_ = | 4785 old_pointer_space_ = |
| 4584 new OldSpace(max_old_generation_size_, OLD_POINTER_SPACE, NOT_EXECUTABLE); | 4786 new OldSpace(this, |
| 4787 max_old_generation_size_, |
| 4788 OLD_POINTER_SPACE, |
| 4789 NOT_EXECUTABLE); |
| 4585 if (old_pointer_space_ == NULL) return false; | 4790 if (old_pointer_space_ == NULL) return false; |
| 4586 if (!old_pointer_space_->Setup(NULL, 0)) return false; | 4791 if (!old_pointer_space_->Setup(NULL, 0)) return false; |
| 4587 | 4792 |
| 4588 // Initialize old data space. | 4793 // Initialize old data space. |
| 4589 old_data_space_ = | 4794 old_data_space_ = |
| 4590 new OldSpace(max_old_generation_size_, OLD_DATA_SPACE, NOT_EXECUTABLE); | 4795 new OldSpace(this, |
| 4796 max_old_generation_size_, |
| 4797 OLD_DATA_SPACE, |
| 4798 NOT_EXECUTABLE); |
| 4591 if (old_data_space_ == NULL) return false; | 4799 if (old_data_space_ == NULL) return false; |
| 4592 if (!old_data_space_->Setup(NULL, 0)) return false; | 4800 if (!old_data_space_->Setup(NULL, 0)) return false; |
| 4593 | 4801 |
| 4594 // Initialize the code space, set its maximum capacity to the old | 4802 // Initialize the code space, set its maximum capacity to the old |
| 4595 // generation size. It needs executable memory. | 4803 // generation size. It needs executable memory. |
| 4596 // On 64-bit platform(s), we put all code objects in a 2 GB range of | 4804 // On 64-bit platform(s), we put all code objects in a 2 GB range of |
| 4597 // virtual address space, so that they can call each other with near calls. | 4805 // virtual address space, so that they can call each other with near calls. |
| 4598 if (code_range_size_ > 0) { | 4806 if (code_range_size_ > 0) { |
| 4599 if (!CodeRange::Setup(code_range_size_)) { | 4807 if (!isolate_->code_range()->Setup(code_range_size_)) { |
| 4600 return false; | 4808 return false; |
| 4601 } | 4809 } |
| 4602 } | 4810 } |
| 4603 | 4811 |
| 4604 code_space_ = | 4812 code_space_ = |
| 4605 new OldSpace(max_old_generation_size_, CODE_SPACE, EXECUTABLE); | 4813 new OldSpace(this, max_old_generation_size_, CODE_SPACE, EXECUTABLE); |
| 4606 if (code_space_ == NULL) return false; | 4814 if (code_space_ == NULL) return false; |
| 4607 if (!code_space_->Setup(NULL, 0)) return false; | 4815 if (!code_space_->Setup(NULL, 0)) return false; |
| 4608 | 4816 |
| 4609 // Initialize map space. | 4817 // Initialize map space. |
| 4610 map_space_ = new MapSpace(FLAG_use_big_map_space | 4818 map_space_ = new MapSpace(this, FLAG_use_big_map_space |
| 4611 ? max_old_generation_size_ | 4819 ? max_old_generation_size_ |
| 4612 : MapSpace::kMaxMapPageIndex * Page::kPageSize, | 4820 : MapSpace::kMaxMapPageIndex * Page::kPageSize, |
| 4613 FLAG_max_map_space_pages, | 4821 FLAG_max_map_space_pages, |
| 4614 MAP_SPACE); | 4822 MAP_SPACE); |
| 4615 if (map_space_ == NULL) return false; | 4823 if (map_space_ == NULL) return false; |
| 4616 if (!map_space_->Setup(NULL, 0)) return false; | 4824 if (!map_space_->Setup(NULL, 0)) return false; |
| 4617 | 4825 |
| 4618 // Initialize global property cell space. | 4826 // Initialize global property cell space. |
| 4619 cell_space_ = new CellSpace(max_old_generation_size_, CELL_SPACE); | 4827 cell_space_ = new CellSpace(this, max_old_generation_size_, CELL_SPACE); |
| 4620 if (cell_space_ == NULL) return false; | 4828 if (cell_space_ == NULL) return false; |
| 4621 if (!cell_space_->Setup(NULL, 0)) return false; | 4829 if (!cell_space_->Setup(NULL, 0)) return false; |
| 4622 | 4830 |
| 4623 // The large object code space may contain code or data. We set the memory | 4831 // The large object code space may contain code or data. We set the memory |
| 4624 // to be non-executable here for safety, but this means we need to enable it | 4832 // to be non-executable here for safety, but this means we need to enable it |
| 4625 // explicitly when allocating large code objects. | 4833 // explicitly when allocating large code objects. |
| 4626 lo_space_ = new LargeObjectSpace(LO_SPACE); | 4834 lo_space_ = new LargeObjectSpace(this, LO_SPACE); |
| 4627 if (lo_space_ == NULL) return false; | 4835 if (lo_space_ == NULL) return false; |
| 4628 if (!lo_space_->Setup()) return false; | 4836 if (!lo_space_->Setup()) return false; |
| 4629 | 4837 |
| 4630 if (create_heap_objects) { | 4838 if (create_heap_objects) { |
| 4631 // Create initial maps. | 4839 // Create initial maps. |
| 4632 if (!CreateInitialMaps()) return false; | 4840 if (!CreateInitialMaps()) return false; |
| 4633 if (!CreateApiObjects()) return false; | 4841 if (!CreateApiObjects()) return false; |
| 4634 | 4842 |
| 4635 // Create initial objects | 4843 // Create initial objects |
| 4636 if (!CreateInitialObjects()) return false; | 4844 if (!CreateInitialObjects()) return false; |
| 4637 | 4845 |
| 4638 global_contexts_list_ = undefined_value(); | 4846 global_contexts_list_ = undefined_value(); |
| 4639 } | 4847 } |
| 4640 | 4848 |
| 4641 LOG(IntPtrTEvent("heap-capacity", Capacity())); | 4849 LOG(isolate_, IntPtrTEvent("heap-capacity", Capacity())); |
| 4642 LOG(IntPtrTEvent("heap-available", Available())); | 4850 LOG(isolate_, IntPtrTEvent("heap-available", Available())); |
| 4643 | 4851 |
| 4644 #ifdef ENABLE_LOGGING_AND_PROFILING | 4852 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 4645 // This should be called only after initial objects have been created. | 4853 // This should be called only after initial objects have been created. |
| 4646 ProducerHeapProfile::Setup(); | 4854 isolate_->producer_heap_profile()->Setup(); |
| 4647 #endif | 4855 #endif |
| 4648 | 4856 |
| 4649 return true; | 4857 return true; |
| 4650 } | 4858 } |
| 4651 | 4859 |
| 4652 | 4860 |
| 4653 void Heap::SetStackLimits() { | 4861 void Heap::SetStackLimits() { |
| 4862 ASSERT(isolate_ != NULL); |
| 4863 ASSERT(isolate_ == isolate()); |
| 4654 // On 64 bit machines, pointers are generally out of range of Smis. We write | 4864 // On 64 bit machines, pointers are generally out of range of Smis. We write |
| 4655 // something that looks like an out of range Smi to the GC. | 4865 // something that looks like an out of range Smi to the GC. |
| 4656 | 4866 |
| 4657 // Set up the special root array entries containing the stack limits. | 4867 // Set up the special root array entries containing the stack limits. |
| 4658 // These are actually addresses, but the tag makes the GC ignore it. | 4868 // These are actually addresses, but the tag makes the GC ignore it. |
| 4659 roots_[kStackLimitRootIndex] = | 4869 roots_[kStackLimitRootIndex] = |
| 4660 reinterpret_cast<Object*>( | 4870 reinterpret_cast<Object*>( |
| 4661 (StackGuard::jslimit() & ~kSmiTagMask) | kSmiTag); | 4871 (isolate_->stack_guard()->jslimit() & ~kSmiTagMask) | kSmiTag); |
| 4662 roots_[kRealStackLimitRootIndex] = | 4872 roots_[kRealStackLimitRootIndex] = |
| 4663 reinterpret_cast<Object*>( | 4873 reinterpret_cast<Object*>( |
| 4664 (StackGuard::real_jslimit() & ~kSmiTagMask) | kSmiTag); | 4874 (isolate_->stack_guard()->real_jslimit() & ~kSmiTagMask) | kSmiTag); |
| 4665 } | 4875 } |
| 4666 | 4876 |
| 4667 | 4877 |
| 4668 void Heap::TearDown() { | 4878 void Heap::TearDown() { |
| 4669 if (FLAG_print_cumulative_gc_stat) { | 4879 if (FLAG_print_cumulative_gc_stat) { |
| 4670 PrintF("\n\n"); | 4880 PrintF("\n\n"); |
| 4671 PrintF("gc_count=%d ", gc_count_); | 4881 PrintF("gc_count=%d ", gc_count_); |
| 4672 PrintF("mark_sweep_count=%d ", ms_count_); | 4882 PrintF("mark_sweep_count=%d ", ms_count_); |
| 4673 PrintF("mark_compact_count=%d ", mc_count_); | 4883 PrintF("mark_compact_count=%d ", mc_count_); |
| 4674 PrintF("max_gc_pause=%d ", GCTracer::get_max_gc_pause()); | 4884 PrintF("max_gc_pause=%d ", get_max_gc_pause()); |
| 4675 PrintF("min_in_mutator=%d ", GCTracer::get_min_in_mutator()); | 4885 PrintF("min_in_mutator=%d ", get_min_in_mutator()); |
| 4676 PrintF("max_alive_after_gc=%" V8_PTR_PREFIX "d ", | 4886 PrintF("max_alive_after_gc=%" V8_PTR_PREFIX "d ", |
| 4677 GCTracer::get_max_alive_after_gc()); | 4887 get_max_alive_after_gc()); |
| 4678 PrintF("\n\n"); | 4888 PrintF("\n\n"); |
| 4679 } | 4889 } |
| 4680 | 4890 |
| 4681 GlobalHandles::TearDown(); | 4891 isolate_->global_handles()->TearDown(); |
| 4682 | 4892 |
| 4683 ExternalStringTable::TearDown(); | 4893 external_string_table_.TearDown(); |
| 4684 | 4894 |
| 4685 new_space_.TearDown(); | 4895 new_space_.TearDown(); |
| 4686 | 4896 |
| 4687 if (old_pointer_space_ != NULL) { | 4897 if (old_pointer_space_ != NULL) { |
| 4688 old_pointer_space_->TearDown(); | 4898 old_pointer_space_->TearDown(); |
| 4689 delete old_pointer_space_; | 4899 delete old_pointer_space_; |
| 4690 old_pointer_space_ = NULL; | 4900 old_pointer_space_ = NULL; |
| 4691 } | 4901 } |
| 4692 | 4902 |
| 4693 if (old_data_space_ != NULL) { | 4903 if (old_data_space_ != NULL) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 4713 delete cell_space_; | 4923 delete cell_space_; |
| 4714 cell_space_ = NULL; | 4924 cell_space_ = NULL; |
| 4715 } | 4925 } |
| 4716 | 4926 |
| 4717 if (lo_space_ != NULL) { | 4927 if (lo_space_ != NULL) { |
| 4718 lo_space_->TearDown(); | 4928 lo_space_->TearDown(); |
| 4719 delete lo_space_; | 4929 delete lo_space_; |
| 4720 lo_space_ = NULL; | 4930 lo_space_ = NULL; |
| 4721 } | 4931 } |
| 4722 | 4932 |
| 4723 MemoryAllocator::TearDown(); | 4933 isolate_->memory_allocator()->TearDown(); |
| 4934 |
| 4935 #ifdef DEBUG |
| 4936 delete debug_utils_; |
| 4937 debug_utils_ = NULL; |
| 4938 #endif |
| 4724 } | 4939 } |
| 4725 | 4940 |
| 4726 | 4941 |
| 4727 void Heap::Shrink() { | 4942 void Heap::Shrink() { |
| 4728 // Try to shrink all paged spaces. | 4943 // Try to shrink all paged spaces. |
| 4729 PagedSpaces spaces; | 4944 PagedSpaces spaces; |
| 4730 for (PagedSpace* space = spaces.next(); space != NULL; space = spaces.next()) | 4945 for (PagedSpace* space = spaces.next(); space != NULL; space = spaces.next()) |
| 4731 space->Shrink(); | 4946 space->Shrink(); |
| 4732 } | 4947 } |
| 4733 | 4948 |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4802 for (Object** p = start; p < end; p++) | 5017 for (Object** p = start; p < end; p++) |
| 4803 PrintF(" handle %p to %p\n", | 5018 PrintF(" handle %p to %p\n", |
| 4804 reinterpret_cast<void*>(p), | 5019 reinterpret_cast<void*>(p), |
| 4805 reinterpret_cast<void*>(*p)); | 5020 reinterpret_cast<void*>(*p)); |
| 4806 } | 5021 } |
| 4807 }; | 5022 }; |
| 4808 | 5023 |
| 4809 void Heap::PrintHandles() { | 5024 void Heap::PrintHandles() { |
| 4810 PrintF("Handles:\n"); | 5025 PrintF("Handles:\n"); |
| 4811 PrintHandleVisitor v; | 5026 PrintHandleVisitor v; |
| 4812 HandleScopeImplementer::Iterate(&v); | 5027 isolate_->handle_scope_implementer()->Iterate(&v); |
| 4813 } | 5028 } |
| 4814 | 5029 |
| 4815 #endif | 5030 #endif |
| 4816 | 5031 |
| 4817 | 5032 |
| 4818 Space* AllSpaces::next() { | 5033 Space* AllSpaces::next() { |
| 4819 switch (counter_++) { | 5034 switch (counter_++) { |
| 4820 case NEW_SPACE: | 5035 case NEW_SPACE: |
| 4821 return Heap::new_space(); | 5036 return HEAP->new_space(); |
| 4822 case OLD_POINTER_SPACE: | 5037 case OLD_POINTER_SPACE: |
| 4823 return Heap::old_pointer_space(); | 5038 return HEAP->old_pointer_space(); |
| 4824 case OLD_DATA_SPACE: | 5039 case OLD_DATA_SPACE: |
| 4825 return Heap::old_data_space(); | 5040 return HEAP->old_data_space(); |
| 4826 case CODE_SPACE: | 5041 case CODE_SPACE: |
| 4827 return Heap::code_space(); | 5042 return HEAP->code_space(); |
| 4828 case MAP_SPACE: | 5043 case MAP_SPACE: |
| 4829 return Heap::map_space(); | 5044 return HEAP->map_space(); |
| 4830 case CELL_SPACE: | 5045 case CELL_SPACE: |
| 4831 return Heap::cell_space(); | 5046 return HEAP->cell_space(); |
| 4832 case LO_SPACE: | 5047 case LO_SPACE: |
| 4833 return Heap::lo_space(); | 5048 return HEAP->lo_space(); |
| 4834 default: | 5049 default: |
| 4835 return NULL; | 5050 return NULL; |
| 4836 } | 5051 } |
| 4837 } | 5052 } |
| 4838 | 5053 |
| 4839 | 5054 |
| 4840 PagedSpace* PagedSpaces::next() { | 5055 PagedSpace* PagedSpaces::next() { |
| 4841 switch (counter_++) { | 5056 switch (counter_++) { |
| 4842 case OLD_POINTER_SPACE: | 5057 case OLD_POINTER_SPACE: |
| 4843 return Heap::old_pointer_space(); | 5058 return HEAP->old_pointer_space(); |
| 4844 case OLD_DATA_SPACE: | 5059 case OLD_DATA_SPACE: |
| 4845 return Heap::old_data_space(); | 5060 return HEAP->old_data_space(); |
| 4846 case CODE_SPACE: | 5061 case CODE_SPACE: |
| 4847 return Heap::code_space(); | 5062 return HEAP->code_space(); |
| 4848 case MAP_SPACE: | 5063 case MAP_SPACE: |
| 4849 return Heap::map_space(); | 5064 return HEAP->map_space(); |
| 4850 case CELL_SPACE: | 5065 case CELL_SPACE: |
| 4851 return Heap::cell_space(); | 5066 return HEAP->cell_space(); |
| 4852 default: | 5067 default: |
| 4853 return NULL; | 5068 return NULL; |
| 4854 } | 5069 } |
| 4855 } | 5070 } |
| 4856 | 5071 |
| 4857 | 5072 |
| 4858 | 5073 |
| 4859 OldSpace* OldSpaces::next() { | 5074 OldSpace* OldSpaces::next() { |
| 4860 switch (counter_++) { | 5075 switch (counter_++) { |
| 4861 case OLD_POINTER_SPACE: | 5076 case OLD_POINTER_SPACE: |
| 4862 return Heap::old_pointer_space(); | 5077 return HEAP->old_pointer_space(); |
| 4863 case OLD_DATA_SPACE: | 5078 case OLD_DATA_SPACE: |
| 4864 return Heap::old_data_space(); | 5079 return HEAP->old_data_space(); |
| 4865 case CODE_SPACE: | 5080 case CODE_SPACE: |
| 4866 return Heap::code_space(); | 5081 return HEAP->code_space(); |
| 4867 default: | 5082 default: |
| 4868 return NULL; | 5083 return NULL; |
| 4869 } | 5084 } |
| 4870 } | 5085 } |
| 4871 | 5086 |
| 4872 | 5087 |
| 4873 SpaceIterator::SpaceIterator() | 5088 SpaceIterator::SpaceIterator() |
| 4874 : current_space_(FIRST_SPACE), | 5089 : current_space_(FIRST_SPACE), |
| 4875 iterator_(NULL), | 5090 iterator_(NULL), |
| 4876 size_func_(NULL) { | 5091 size_func_(NULL) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4911 return CreateIterator(); | 5126 return CreateIterator(); |
| 4912 } | 5127 } |
| 4913 | 5128 |
| 4914 | 5129 |
| 4915 // Create an iterator for the space to iterate. | 5130 // Create an iterator for the space to iterate. |
| 4916 ObjectIterator* SpaceIterator::CreateIterator() { | 5131 ObjectIterator* SpaceIterator::CreateIterator() { |
| 4917 ASSERT(iterator_ == NULL); | 5132 ASSERT(iterator_ == NULL); |
| 4918 | 5133 |
| 4919 switch (current_space_) { | 5134 switch (current_space_) { |
| 4920 case NEW_SPACE: | 5135 case NEW_SPACE: |
| 4921 iterator_ = new SemiSpaceIterator(Heap::new_space(), size_func_); | 5136 iterator_ = new SemiSpaceIterator(HEAP->new_space(), size_func_); |
| 4922 break; | 5137 break; |
| 4923 case OLD_POINTER_SPACE: | 5138 case OLD_POINTER_SPACE: |
| 4924 iterator_ = new HeapObjectIterator(Heap::old_pointer_space(), size_func_); | 5139 iterator_ = new HeapObjectIterator(HEAP->old_pointer_space(), size_func_); |
| 4925 break; | 5140 break; |
| 4926 case OLD_DATA_SPACE: | 5141 case OLD_DATA_SPACE: |
| 4927 iterator_ = new HeapObjectIterator(Heap::old_data_space(), size_func_); | 5142 iterator_ = new HeapObjectIterator(HEAP->old_data_space(), size_func_); |
| 4928 break; | 5143 break; |
| 4929 case CODE_SPACE: | 5144 case CODE_SPACE: |
| 4930 iterator_ = new HeapObjectIterator(Heap::code_space(), size_func_); | 5145 iterator_ = new HeapObjectIterator(HEAP->code_space(), size_func_); |
| 4931 break; | 5146 break; |
| 4932 case MAP_SPACE: | 5147 case MAP_SPACE: |
| 4933 iterator_ = new HeapObjectIterator(Heap::map_space(), size_func_); | 5148 iterator_ = new HeapObjectIterator(HEAP->map_space(), size_func_); |
| 4934 break; | 5149 break; |
| 4935 case CELL_SPACE: | 5150 case CELL_SPACE: |
| 4936 iterator_ = new HeapObjectIterator(Heap::cell_space(), size_func_); | 5151 iterator_ = new HeapObjectIterator(HEAP->cell_space(), size_func_); |
| 4937 break; | 5152 break; |
| 4938 case LO_SPACE: | 5153 case LO_SPACE: |
| 4939 iterator_ = new LargeObjectIterator(Heap::lo_space(), size_func_); | 5154 iterator_ = new LargeObjectIterator(HEAP->lo_space(), size_func_); |
| 4940 break; | 5155 break; |
| 4941 } | 5156 } |
| 4942 | 5157 |
| 4943 // Return the newly allocated iterator; | 5158 // Return the newly allocated iterator; |
| 4944 ASSERT(iterator_ != NULL); | 5159 ASSERT(iterator_ != NULL); |
| 4945 return iterator_; | 5160 return iterator_; |
| 4946 } | 5161 } |
| 4947 | 5162 |
| 4948 | 5163 |
| 4949 class HeapObjectsFilter { | 5164 class HeapObjectsFilter { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 4963 if (object->IsMarked()) { | 5178 if (object->IsMarked()) { |
| 4964 object->ClearMark(); | 5179 object->ClearMark(); |
| 4965 return true; | 5180 return true; |
| 4966 } else { | 5181 } else { |
| 4967 return false; | 5182 return false; |
| 4968 } | 5183 } |
| 4969 } | 5184 } |
| 4970 | 5185 |
| 4971 private: | 5186 private: |
| 4972 void MarkFreeListNodes() { | 5187 void MarkFreeListNodes() { |
| 4973 Heap::old_pointer_space()->MarkFreeListNodes(); | 5188 Heap* heap = HEAP; |
| 4974 Heap::old_data_space()->MarkFreeListNodes(); | 5189 heap->old_pointer_space()->MarkFreeListNodes(); |
| 4975 MarkCodeSpaceFreeListNodes(); | 5190 heap->old_data_space()->MarkFreeListNodes(); |
| 4976 Heap::map_space()->MarkFreeListNodes(); | 5191 MarkCodeSpaceFreeListNodes(heap); |
| 4977 Heap::cell_space()->MarkFreeListNodes(); | 5192 heap->map_space()->MarkFreeListNodes(); |
| 5193 heap->cell_space()->MarkFreeListNodes(); |
| 4978 } | 5194 } |
| 4979 | 5195 |
| 4980 void MarkCodeSpaceFreeListNodes() { | 5196 void MarkCodeSpaceFreeListNodes(Heap* heap) { |
| 4981 // For code space, using FreeListNode::IsFreeListNode is OK. | 5197 // For code space, using FreeListNode::IsFreeListNode is OK. |
| 4982 HeapObjectIterator iter(Heap::code_space()); | 5198 HeapObjectIterator iter(heap->code_space()); |
| 4983 for (HeapObject* obj = iter.next_object(); | 5199 for (HeapObject* obj = iter.next_object(); |
| 4984 obj != NULL; | 5200 obj != NULL; |
| 4985 obj = iter.next_object()) { | 5201 obj = iter.next_object()) { |
| 4986 if (FreeListNode::IsFreeListNode(obj)) obj->SetMark(); | 5202 if (FreeListNode::IsFreeListNode(obj)) obj->SetMark(); |
| 4987 } | 5203 } |
| 4988 } | 5204 } |
| 4989 | 5205 |
| 4990 AssertNoAllocation no_alloc; | 5206 AssertNoAllocation no_alloc; |
| 4991 }; | 5207 }; |
| 4992 | 5208 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5034 }; | 5250 }; |
| 5035 | 5251 |
| 5036 void MarkUnreachableObjects() { | 5252 void MarkUnreachableObjects() { |
| 5037 HeapIterator iterator; | 5253 HeapIterator iterator; |
| 5038 for (HeapObject* obj = iterator.next(); | 5254 for (HeapObject* obj = iterator.next(); |
| 5039 obj != NULL; | 5255 obj != NULL; |
| 5040 obj = iterator.next()) { | 5256 obj = iterator.next()) { |
| 5041 obj->SetMark(); | 5257 obj->SetMark(); |
| 5042 } | 5258 } |
| 5043 UnmarkingVisitor visitor; | 5259 UnmarkingVisitor visitor; |
| 5044 Heap::IterateRoots(&visitor, VISIT_ALL); | 5260 HEAP->IterateRoots(&visitor, VISIT_ALL); |
| 5045 while (visitor.can_process()) | 5261 while (visitor.can_process()) |
| 5046 visitor.ProcessNext(); | 5262 visitor.ProcessNext(); |
| 5047 } | 5263 } |
| 5048 | 5264 |
| 5049 AssertNoAllocation no_alloc; | 5265 AssertNoAllocation no_alloc; |
| 5050 }; | 5266 }; |
| 5051 | 5267 |
| 5052 | 5268 |
| 5053 HeapIterator::HeapIterator() | 5269 HeapIterator::HeapIterator() |
| 5054 : filtering_(HeapIterator::kNoFiltering), | 5270 : filtering_(HeapIterator::kNoFiltering), |
| (...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5337 OldSpaces spaces; | 5553 OldSpaces spaces; |
| 5338 for (OldSpace* space = spaces.next(); | 5554 for (OldSpace* space = spaces.next(); |
| 5339 space != NULL; | 5555 space != NULL; |
| 5340 space = spaces.next()) { | 5556 space = spaces.next()) { |
| 5341 holes_size += space->Waste() + space->AvailableFree(); | 5557 holes_size += space->Waste() + space->AvailableFree(); |
| 5342 } | 5558 } |
| 5343 return holes_size; | 5559 return holes_size; |
| 5344 } | 5560 } |
| 5345 | 5561 |
| 5346 | 5562 |
| 5347 GCTracer::GCTracer() | 5563 GCTracer::GCTracer(Heap* heap) |
| 5348 : start_time_(0.0), | 5564 : start_time_(0.0), |
| 5349 start_size_(0), | 5565 start_size_(0), |
| 5350 gc_count_(0), | 5566 gc_count_(0), |
| 5351 full_gc_count_(0), | 5567 full_gc_count_(0), |
| 5352 is_compacting_(false), | 5568 is_compacting_(false), |
| 5353 marked_count_(0), | 5569 marked_count_(0), |
| 5354 allocated_since_last_gc_(0), | 5570 allocated_since_last_gc_(0), |
| 5355 spent_in_mutator_(0), | 5571 spent_in_mutator_(0), |
| 5356 promoted_objects_size_(0) { | 5572 promoted_objects_size_(0), |
| 5573 heap_(heap) { |
| 5357 // These two fields reflect the state of the previous full collection. | 5574 // These two fields reflect the state of the previous full collection. |
| 5358 // Set them before they are changed by the collector. | 5575 // Set them before they are changed by the collector. |
| 5359 previous_has_compacted_ = MarkCompactCollector::HasCompacted(); | 5576 previous_has_compacted_ = heap_->mark_compact_collector_.HasCompacted(); |
| 5360 previous_marked_count_ = MarkCompactCollector::previous_marked_count(); | 5577 previous_marked_count_ = |
| 5578 heap_->mark_compact_collector_.previous_marked_count(); |
| 5361 if (!FLAG_trace_gc && !FLAG_print_cumulative_gc_stat) return; | 5579 if (!FLAG_trace_gc && !FLAG_print_cumulative_gc_stat) return; |
| 5362 start_time_ = OS::TimeCurrentMillis(); | 5580 start_time_ = OS::TimeCurrentMillis(); |
| 5363 start_size_ = Heap::SizeOfObjects(); | 5581 start_size_ = heap_->SizeOfObjects(); |
| 5364 | 5582 |
| 5365 for (int i = 0; i < Scope::kNumberOfScopes; i++) { | 5583 for (int i = 0; i < Scope::kNumberOfScopes; i++) { |
| 5366 scopes_[i] = 0; | 5584 scopes_[i] = 0; |
| 5367 } | 5585 } |
| 5368 | 5586 |
| 5369 in_free_list_or_wasted_before_gc_ = CountTotalHolesSize(); | 5587 in_free_list_or_wasted_before_gc_ = CountTotalHolesSize(); |
| 5370 | 5588 |
| 5371 allocated_since_last_gc_ = Heap::SizeOfObjects() - alive_after_last_gc_; | 5589 allocated_since_last_gc_ = |
| 5590 heap_->SizeOfObjects() - heap_->alive_after_last_gc_; |
| 5372 | 5591 |
| 5373 if (last_gc_end_timestamp_ > 0) { | 5592 if (heap_->last_gc_end_timestamp_ > 0) { |
| 5374 spent_in_mutator_ = Max(start_time_ - last_gc_end_timestamp_, 0.0); | 5593 spent_in_mutator_ = Max(start_time_ - heap_->last_gc_end_timestamp_, 0.0); |
| 5375 } | 5594 } |
| 5376 } | 5595 } |
| 5377 | 5596 |
| 5378 | 5597 |
| 5379 GCTracer::~GCTracer() { | 5598 GCTracer::~GCTracer() { |
| 5380 // Printf ONE line iff flag is set. | 5599 // Printf ONE line iff flag is set. |
| 5381 if (!FLAG_trace_gc && !FLAG_print_cumulative_gc_stat) return; | 5600 if (!FLAG_trace_gc && !FLAG_print_cumulative_gc_stat) return; |
| 5382 | 5601 |
| 5383 bool first_gc = (last_gc_end_timestamp_ == 0); | 5602 bool first_gc = (heap_->last_gc_end_timestamp_ == 0); |
| 5384 | 5603 |
| 5385 alive_after_last_gc_ = Heap::SizeOfObjects(); | 5604 heap_->alive_after_last_gc_ = heap_->SizeOfObjects(); |
| 5386 last_gc_end_timestamp_ = OS::TimeCurrentMillis(); | 5605 heap_->last_gc_end_timestamp_ = OS::TimeCurrentMillis(); |
| 5387 | 5606 |
| 5388 int time = static_cast<int>(last_gc_end_timestamp_ - start_time_); | 5607 int time = static_cast<int>(heap_->last_gc_end_timestamp_ - start_time_); |
| 5389 | 5608 |
| 5390 // Update cumulative GC statistics if required. | 5609 // Update cumulative GC statistics if required. |
| 5391 if (FLAG_print_cumulative_gc_stat) { | 5610 if (FLAG_print_cumulative_gc_stat) { |
| 5392 max_gc_pause_ = Max(max_gc_pause_, time); | 5611 heap_->max_gc_pause_ = Max(heap_->max_gc_pause_, time); |
| 5393 max_alive_after_gc_ = Max(max_alive_after_gc_, alive_after_last_gc_); | 5612 heap_->max_alive_after_gc_ = Max(heap_->max_alive_after_gc_, |
| 5613 heap_->alive_after_last_gc_); |
| 5394 if (!first_gc) { | 5614 if (!first_gc) { |
| 5395 min_in_mutator_ = Min(min_in_mutator_, | 5615 heap_->min_in_mutator_ = Min(heap_->min_in_mutator_, |
| 5396 static_cast<int>(spent_in_mutator_)); | 5616 static_cast<int>(spent_in_mutator_)); |
| 5397 } | 5617 } |
| 5398 } | 5618 } |
| 5399 | 5619 |
| 5400 if (!FLAG_trace_gc_nvp) { | 5620 if (!FLAG_trace_gc_nvp) { |
| 5401 int external_time = static_cast<int>(scopes_[Scope::EXTERNAL]); | 5621 int external_time = static_cast<int>(scopes_[Scope::EXTERNAL]); |
| 5402 | 5622 |
| 5403 PrintF("%s %.1f -> %.1f MB, ", | 5623 PrintF("%s %.1f -> %.1f MB, ", |
| 5404 CollectorString(), | 5624 CollectorString(), |
| 5405 static_cast<double>(start_size_) / MB, | 5625 static_cast<double>(start_size_) / MB, |
| 5406 SizeOfHeapObjects()); | 5626 SizeOfHeapObjects()); |
| 5407 | 5627 |
| 5408 if (external_time > 0) PrintF("%d / ", external_time); | 5628 if (external_time > 0) PrintF("%d / ", external_time); |
| 5409 PrintF("%d ms.\n", time); | 5629 PrintF("%d ms.\n", time); |
| 5410 } else { | 5630 } else { |
| 5411 PrintF("pause=%d ", time); | 5631 PrintF("pause=%d ", time); |
| 5412 PrintF("mutator=%d ", | 5632 PrintF("mutator=%d ", |
| 5413 static_cast<int>(spent_in_mutator_)); | 5633 static_cast<int>(spent_in_mutator_)); |
| 5414 | 5634 |
| 5415 PrintF("gc="); | 5635 PrintF("gc="); |
| 5416 switch (collector_) { | 5636 switch (collector_) { |
| 5417 case SCAVENGER: | 5637 case SCAVENGER: |
| 5418 PrintF("s"); | 5638 PrintF("s"); |
| 5419 break; | 5639 break; |
| 5420 case MARK_COMPACTOR: | 5640 case MARK_COMPACTOR: |
| 5421 PrintF(MarkCompactCollector::HasCompacted() ? "mc" : "ms"); | 5641 PrintF("%s", |
| 5642 heap_->mark_compact_collector_.HasCompacted() ? "mc" : "ms"); |
| 5422 break; | 5643 break; |
| 5423 default: | 5644 default: |
| 5424 UNREACHABLE(); | 5645 UNREACHABLE(); |
| 5425 } | 5646 } |
| 5426 PrintF(" "); | 5647 PrintF(" "); |
| 5427 | 5648 |
| 5428 PrintF("external=%d ", static_cast<int>(scopes_[Scope::EXTERNAL])); | 5649 PrintF("external=%d ", static_cast<int>(scopes_[Scope::EXTERNAL])); |
| 5429 PrintF("mark=%d ", static_cast<int>(scopes_[Scope::MC_MARK])); | 5650 PrintF("mark=%d ", static_cast<int>(scopes_[Scope::MC_MARK])); |
| 5430 PrintF("sweep=%d ", static_cast<int>(scopes_[Scope::MC_SWEEP])); | 5651 PrintF("sweep=%d ", static_cast<int>(scopes_[Scope::MC_SWEEP])); |
| 5431 PrintF("sweepns=%d ", static_cast<int>(scopes_[Scope::MC_SWEEP_NEWSPACE])); | 5652 PrintF("sweepns=%d ", static_cast<int>(scopes_[Scope::MC_SWEEP_NEWSPACE])); |
| 5432 PrintF("compact=%d ", static_cast<int>(scopes_[Scope::MC_COMPACT])); | 5653 PrintF("compact=%d ", static_cast<int>(scopes_[Scope::MC_COMPACT])); |
| 5433 | 5654 |
| 5434 PrintF("total_size_before=%" V8_PTR_PREFIX "d ", start_size_); | 5655 PrintF("total_size_before=%" V8_PTR_PREFIX "d ", start_size_); |
| 5435 PrintF("total_size_after=%" V8_PTR_PREFIX "d ", Heap::SizeOfObjects()); | 5656 PrintF("total_size_after=%" V8_PTR_PREFIX "d ", heap_->SizeOfObjects()); |
| 5436 PrintF("holes_size_before=%" V8_PTR_PREFIX "d ", | 5657 PrintF("holes_size_before=%" V8_PTR_PREFIX "d ", |
| 5437 in_free_list_or_wasted_before_gc_); | 5658 in_free_list_or_wasted_before_gc_); |
| 5438 PrintF("holes_size_after=%" V8_PTR_PREFIX "d ", CountTotalHolesSize()); | 5659 PrintF("holes_size_after=%" V8_PTR_PREFIX "d ", CountTotalHolesSize()); |
| 5439 | 5660 |
| 5440 PrintF("allocated=%" V8_PTR_PREFIX "d ", allocated_since_last_gc_); | 5661 PrintF("allocated=%" V8_PTR_PREFIX "d ", allocated_since_last_gc_); |
| 5441 PrintF("promoted=%" V8_PTR_PREFIX "d ", promoted_objects_size_); | 5662 PrintF("promoted=%" V8_PTR_PREFIX "d ", promoted_objects_size_); |
| 5442 | 5663 |
| 5443 PrintF("\n"); | 5664 PrintF("\n"); |
| 5444 } | 5665 } |
| 5445 | 5666 |
| 5446 #if defined(ENABLE_LOGGING_AND_PROFILING) | 5667 #if defined(ENABLE_LOGGING_AND_PROFILING) |
| 5447 Heap::PrintShortHeapStatistics(); | 5668 heap_->PrintShortHeapStatistics(); |
| 5448 #endif | 5669 #endif |
| 5449 } | 5670 } |
| 5450 | 5671 |
| 5451 | 5672 |
| 5452 const char* GCTracer::CollectorString() { | 5673 const char* GCTracer::CollectorString() { |
| 5453 switch (collector_) { | 5674 switch (collector_) { |
| 5454 case SCAVENGER: | 5675 case SCAVENGER: |
| 5455 return "Scavenge"; | 5676 return "Scavenge"; |
| 5456 case MARK_COMPACTOR: | 5677 case MARK_COMPACTOR: |
| 5457 return MarkCompactCollector::HasCompacted() ? "Mark-compact" | 5678 return heap_->mark_compact_collector_.HasCompacted() ? "Mark-compact" |
| 5458 : "Mark-sweep"; | 5679 : "Mark-sweep"; |
| 5459 } | 5680 } |
| 5460 return "Unknown GC"; | 5681 return "Unknown GC"; |
| 5461 } | 5682 } |
| 5462 | 5683 |
| 5463 | 5684 |
| 5464 int KeyedLookupCache::Hash(Map* map, String* name) { | 5685 int KeyedLookupCache::Hash(Map* map, String* name) { |
| 5465 // Uses only lower 32 bits if pointers are larger. | 5686 // Uses only lower 32 bits if pointers are larger. |
| 5466 uintptr_t addr_hash = | 5687 uintptr_t addr_hash = |
| 5467 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(map)) >> kMapHashShift; | 5688 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(map)) >> kMapHashShift; |
| 5468 return static_cast<uint32_t>((addr_hash ^ name->Hash()) & kCapacityMask); | 5689 return static_cast<uint32_t>((addr_hash ^ name->Hash()) & kCapacityMask); |
| 5469 } | 5690 } |
| 5470 | 5691 |
| 5471 | 5692 |
| 5472 int KeyedLookupCache::Lookup(Map* map, String* name) { | 5693 int KeyedLookupCache::Lookup(Map* map, String* name) { |
| 5473 int index = Hash(map, name); | 5694 int index = Hash(map, name); |
| 5474 Key& key = keys_[index]; | 5695 Key& key = keys_[index]; |
| 5475 if ((key.map == map) && key.name->Equals(name)) { | 5696 if ((key.map == map) && key.name->Equals(name)) { |
| 5476 return field_offsets_[index]; | 5697 return field_offsets_[index]; |
| 5477 } | 5698 } |
| 5478 return -1; | 5699 return kNotFound; |
| 5479 } | 5700 } |
| 5480 | 5701 |
| 5481 | 5702 |
| 5482 void KeyedLookupCache::Update(Map* map, String* name, int field_offset) { | 5703 void KeyedLookupCache::Update(Map* map, String* name, int field_offset) { |
| 5483 String* symbol; | 5704 String* symbol; |
| 5484 if (Heap::LookupSymbolIfExists(name, &symbol)) { | 5705 if (HEAP->LookupSymbolIfExists(name, &symbol)) { |
| 5485 int index = Hash(map, symbol); | 5706 int index = Hash(map, symbol); |
| 5486 Key& key = keys_[index]; | 5707 Key& key = keys_[index]; |
| 5487 key.map = map; | 5708 key.map = map; |
| 5488 key.name = symbol; | 5709 key.name = symbol; |
| 5489 field_offsets_[index] = field_offset; | 5710 field_offsets_[index] = field_offset; |
| 5490 } | 5711 } |
| 5491 } | 5712 } |
| 5492 | 5713 |
| 5493 | 5714 |
| 5494 void KeyedLookupCache::Clear() { | 5715 void KeyedLookupCache::Clear() { |
| 5495 for (int index = 0; index < kLength; index++) keys_[index].map = NULL; | 5716 for (int index = 0; index < kLength; index++) keys_[index].map = NULL; |
| 5496 } | 5717 } |
| 5497 | 5718 |
| 5498 | 5719 |
| 5499 KeyedLookupCache::Key KeyedLookupCache::keys_[KeyedLookupCache::kLength]; | |
| 5500 | |
| 5501 | |
| 5502 int KeyedLookupCache::field_offsets_[KeyedLookupCache::kLength]; | |
| 5503 | |
| 5504 | |
| 5505 void DescriptorLookupCache::Clear() { | 5720 void DescriptorLookupCache::Clear() { |
| 5506 for (int index = 0; index < kLength; index++) keys_[index].array = NULL; | 5721 for (int index = 0; index < kLength; index++) keys_[index].array = NULL; |
| 5507 } | 5722 } |
| 5508 | 5723 |
| 5509 | 5724 |
| 5510 DescriptorLookupCache::Key | |
| 5511 DescriptorLookupCache::keys_[DescriptorLookupCache::kLength]; | |
| 5512 | |
| 5513 int DescriptorLookupCache::results_[DescriptorLookupCache::kLength]; | |
| 5514 | |
| 5515 | |
| 5516 #ifdef DEBUG | 5725 #ifdef DEBUG |
| 5517 void Heap::GarbageCollectionGreedyCheck() { | 5726 void Heap::GarbageCollectionGreedyCheck() { |
| 5518 ASSERT(FLAG_gc_greedy); | 5727 ASSERT(FLAG_gc_greedy); |
| 5519 if (Bootstrapper::IsActive()) return; | 5728 if (isolate_->bootstrapper()->IsActive()) return; |
| 5520 if (disallow_allocation_failure()) return; | 5729 if (disallow_allocation_failure()) return; |
| 5521 CollectGarbage(NEW_SPACE); | 5730 CollectGarbage(NEW_SPACE); |
| 5522 } | 5731 } |
| 5523 #endif | 5732 #endif |
| 5524 | 5733 |
| 5525 | 5734 |
| 5526 TranscendentalCache::TranscendentalCache(TranscendentalCache::Type t) | 5735 TranscendentalCache::SubCache::SubCache(Type t) |
| 5527 : type_(t) { | 5736 : type_(t), |
| 5737 isolate_(Isolate::Current()) { |
| 5528 uint32_t in0 = 0xffffffffu; // Bit-pattern for a NaN that isn't | 5738 uint32_t in0 = 0xffffffffu; // Bit-pattern for a NaN that isn't |
| 5529 uint32_t in1 = 0xffffffffu; // generated by the FPU. | 5739 uint32_t in1 = 0xffffffffu; // generated by the FPU. |
| 5530 for (int i = 0; i < kCacheSize; i++) { | 5740 for (int i = 0; i < kCacheSize; i++) { |
| 5531 elements_[i].in[0] = in0; | 5741 elements_[i].in[0] = in0; |
| 5532 elements_[i].in[1] = in1; | 5742 elements_[i].in[1] = in1; |
| 5533 elements_[i].output = NULL; | 5743 elements_[i].output = NULL; |
| 5534 } | 5744 } |
| 5535 } | 5745 } |
| 5536 | 5746 |
| 5537 | 5747 |
| 5538 TranscendentalCache* TranscendentalCache::caches_[kNumberOfCaches]; | |
| 5539 | |
| 5540 | |
| 5541 void TranscendentalCache::Clear() { | 5748 void TranscendentalCache::Clear() { |
| 5542 for (int i = 0; i < kNumberOfCaches; i++) { | 5749 for (int i = 0; i < kNumberOfCaches; i++) { |
| 5543 if (caches_[i] != NULL) { | 5750 if (caches_[i] != NULL) { |
| 5544 delete caches_[i]; | 5751 delete caches_[i]; |
| 5545 caches_[i] = NULL; | 5752 caches_[i] = NULL; |
| 5546 } | 5753 } |
| 5547 } | 5754 } |
| 5548 } | 5755 } |
| 5549 | 5756 |
| 5550 | 5757 |
| 5551 void ExternalStringTable::CleanUp() { | 5758 void ExternalStringTable::CleanUp() { |
| 5552 int last = 0; | 5759 int last = 0; |
| 5553 for (int i = 0; i < new_space_strings_.length(); ++i) { | 5760 for (int i = 0; i < new_space_strings_.length(); ++i) { |
| 5554 if (new_space_strings_[i] == Heap::raw_unchecked_null_value()) continue; | 5761 if (new_space_strings_[i] == heap_->raw_unchecked_null_value()) continue; |
| 5555 if (Heap::InNewSpace(new_space_strings_[i])) { | 5762 if (heap_->InNewSpace(new_space_strings_[i])) { |
| 5556 new_space_strings_[last++] = new_space_strings_[i]; | 5763 new_space_strings_[last++] = new_space_strings_[i]; |
| 5557 } else { | 5764 } else { |
| 5558 old_space_strings_.Add(new_space_strings_[i]); | 5765 old_space_strings_.Add(new_space_strings_[i]); |
| 5559 } | 5766 } |
| 5560 } | 5767 } |
| 5561 new_space_strings_.Rewind(last); | 5768 new_space_strings_.Rewind(last); |
| 5562 last = 0; | 5769 last = 0; |
| 5563 for (int i = 0; i < old_space_strings_.length(); ++i) { | 5770 for (int i = 0; i < old_space_strings_.length(); ++i) { |
| 5564 if (old_space_strings_[i] == Heap::raw_unchecked_null_value()) continue; | 5771 if (old_space_strings_[i] == heap_->raw_unchecked_null_value()) continue; |
| 5565 ASSERT(!Heap::InNewSpace(old_space_strings_[i])); | 5772 ASSERT(!heap_->InNewSpace(old_space_strings_[i])); |
| 5566 old_space_strings_[last++] = old_space_strings_[i]; | 5773 old_space_strings_[last++] = old_space_strings_[i]; |
| 5567 } | 5774 } |
| 5568 old_space_strings_.Rewind(last); | 5775 old_space_strings_.Rewind(last); |
| 5569 Verify(); | 5776 Verify(); |
| 5570 } | 5777 } |
| 5571 | 5778 |
| 5572 | 5779 |
| 5573 void ExternalStringTable::TearDown() { | 5780 void ExternalStringTable::TearDown() { |
| 5574 new_space_strings_.Free(); | 5781 new_space_strings_.Free(); |
| 5575 old_space_strings_.Free(); | 5782 old_space_strings_.Free(); |
| 5576 } | 5783 } |
| 5577 | 5784 |
| 5578 | 5785 |
| 5579 List<Object*> ExternalStringTable::new_space_strings_; | |
| 5580 List<Object*> ExternalStringTable::old_space_strings_; | |
| 5581 | |
| 5582 } } // namespace v8::internal | 5786 } } // namespace v8::internal |
| OLD | NEW |