| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 60 #include "regexp-macro-assembler.h" | 60 #include "regexp-macro-assembler.h" |
| 61 #include "mips/regexp-macro-assembler-mips.h" | 61 #include "mips/regexp-macro-assembler-mips.h" |
| 62 #endif | 62 #endif |
| 63 | 63 |
| 64 namespace v8 { | 64 namespace v8 { |
| 65 namespace internal { | 65 namespace internal { |
| 66 | 66 |
| 67 | 67 |
| 68 Heap::Heap() | 68 Heap::Heap() |
| 69 : isolate_(NULL), | 69 : isolate_(NULL), |
| 70 code_range_size_(kIs64BitArch ? 512 * MB : 0), |
| 70 // semispace_size_ should be a power of 2 and old_generation_size_ should be | 71 // semispace_size_ should be a power of 2 and old_generation_size_ should be |
| 71 // a multiple of Page::kPageSize. | 72 // a multiple of Page::kPageSize. |
| 72 #if V8_TARGET_ARCH_X64 | 73 reserved_semispace_size_(8 * (kPointerSize / 4) * MB), |
| 73 #define LUMP_OF_MEMORY (2 * MB) | 74 max_semispace_size_(8 * (kPointerSize / 4) * MB), |
| 74 code_range_size_(512*MB), | |
| 75 #else | |
| 76 #define LUMP_OF_MEMORY MB | |
| 77 code_range_size_(0), | |
| 78 #endif | |
| 79 #if defined(ANDROID) || V8_TARGET_ARCH_MIPS | |
| 80 reserved_semispace_size_(4 * Max(LUMP_OF_MEMORY, Page::kPageSize)), | |
| 81 max_semispace_size_(4 * Max(LUMP_OF_MEMORY, Page::kPageSize)), | |
| 82 initial_semispace_size_(Page::kPageSize), | 75 initial_semispace_size_(Page::kPageSize), |
| 83 max_old_generation_size_(192*MB), | 76 max_old_generation_size_(700ul * (kPointerSize / 4) * MB), |
| 84 max_executable_size_(max_old_generation_size_), | 77 max_executable_size_(256ul * (kPointerSize / 4) * MB), |
| 85 #else | |
| 86 reserved_semispace_size_(8 * Max(LUMP_OF_MEMORY, Page::kPageSize)), | |
| 87 max_semispace_size_(8 * Max(LUMP_OF_MEMORY, Page::kPageSize)), | |
| 88 initial_semispace_size_(Page::kPageSize), | |
| 89 max_old_generation_size_(700ul * LUMP_OF_MEMORY), | |
| 90 max_executable_size_(256l * LUMP_OF_MEMORY), | |
| 91 #endif | |
| 92 | |
| 93 // Variables set based on semispace_size_ and old_generation_size_ in | 78 // Variables set based on semispace_size_ and old_generation_size_ in |
| 94 // ConfigureHeap (survived_since_last_expansion_, external_allocation_limit_) | 79 // ConfigureHeap (survived_since_last_expansion_, external_allocation_limit_) |
| 95 // Will be 4 * reserved_semispace_size_ to ensure that young | 80 // Will be 4 * reserved_semispace_size_ to ensure that young |
| 96 // generation can be aligned to its size. | 81 // generation can be aligned to its size. |
| 97 survived_since_last_expansion_(0), | 82 survived_since_last_expansion_(0), |
| 98 sweep_generation_(0), | 83 sweep_generation_(0), |
| 99 always_allocate_scope_depth_(0), | 84 always_allocate_scope_depth_(0), |
| 100 linear_allocation_scope_depth_(0), | 85 linear_allocation_scope_depth_(0), |
| 101 contexts_disposed_(0), | 86 contexts_disposed_(0), |
| 102 global_ic_age_(0), | 87 global_ic_age_(0), |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 163 configured_(false), | 148 configured_(false), |
| 164 chunks_queued_for_free_(NULL), | 149 chunks_queued_for_free_(NULL), |
| 165 relocation_mutex_(NULL) { | 150 relocation_mutex_(NULL) { |
| 166 // Allow build-time customization of the max semispace size. Building | 151 // Allow build-time customization of the max semispace size. Building |
| 167 // V8 with snapshots and a non-default max semispace size is much | 152 // V8 with snapshots and a non-default max semispace size is much |
| 168 // easier if you can define it as part of the build environment. | 153 // easier if you can define it as part of the build environment. |
| 169 #if defined(V8_MAX_SEMISPACE_SIZE) | 154 #if defined(V8_MAX_SEMISPACE_SIZE) |
| 170 max_semispace_size_ = reserved_semispace_size_ = V8_MAX_SEMISPACE_SIZE; | 155 max_semispace_size_ = reserved_semispace_size_ = V8_MAX_SEMISPACE_SIZE; |
| 171 #endif | 156 #endif |
| 172 | 157 |
| 158 // Ensure old_generation_size_ is a multiple of kPageSize. |
| 159 ASSERT(MB >= Page::kPageSize); |
| 160 |
| 173 intptr_t max_virtual = OS::MaxVirtualMemory(); | 161 intptr_t max_virtual = OS::MaxVirtualMemory(); |
| 174 | 162 |
| 175 if (max_virtual > 0) { | 163 if (max_virtual > 0) { |
| 176 if (code_range_size_ > 0) { | 164 if (code_range_size_ > 0) { |
| 177 // Reserve no more than 1/8 of the memory for the code range. | 165 // Reserve no more than 1/8 of the memory for the code range. |
| 178 code_range_size_ = Min(code_range_size_, max_virtual >> 3); | 166 code_range_size_ = Min(code_range_size_, max_virtual >> 3); |
| 179 } | 167 } |
| 180 } | 168 } |
| 181 | 169 |
| 182 memset(roots_, 0, sizeof(roots_[0]) * kRootListLength); | 170 memset(roots_, 0, sizeof(roots_[0]) * kRootListLength); |
| (...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 601 // not matter, so long as we do not specify NEW_SPACE, which would not | 589 // not matter, so long as we do not specify NEW_SPACE, which would not |
| 602 // cause a full GC. | 590 // cause a full GC. |
| 603 // Major GC would invoke weak handle callbacks on weakly reachable | 591 // Major GC would invoke weak handle callbacks on weakly reachable |
| 604 // handles, but won't collect weakly reachable objects until next | 592 // handles, but won't collect weakly reachable objects until next |
| 605 // major GC. Therefore if we collect aggressively and weak handle callback | 593 // major GC. Therefore if we collect aggressively and weak handle callback |
| 606 // has been invoked, we rerun major GC to release objects which become | 594 // has been invoked, we rerun major GC to release objects which become |
| 607 // garbage. | 595 // garbage. |
| 608 // Note: as weak callbacks can execute arbitrary code, we cannot | 596 // Note: as weak callbacks can execute arbitrary code, we cannot |
| 609 // hope that eventually there will be no weak callbacks invocations. | 597 // hope that eventually there will be no weak callbacks invocations. |
| 610 // Therefore stop recollecting after several attempts. | 598 // Therefore stop recollecting after several attempts. |
| 599 if (FLAG_concurrent_recompilation) { |
| 600 // The optimizing compiler may be unnecessarily holding on to memory. |
| 601 DisallowHeapAllocation no_recursive_gc; |
| 602 isolate()->optimizing_compiler_thread()->Flush(); |
| 603 } |
| 611 mark_compact_collector()->SetFlags(kMakeHeapIterableMask | | 604 mark_compact_collector()->SetFlags(kMakeHeapIterableMask | |
| 612 kReduceMemoryFootprintMask); | 605 kReduceMemoryFootprintMask); |
| 613 isolate_->compilation_cache()->Clear(); | 606 isolate_->compilation_cache()->Clear(); |
| 614 const int kMaxNumberOfAttempts = 7; | 607 const int kMaxNumberOfAttempts = 7; |
| 615 const int kMinNumberOfAttempts = 2; | 608 const int kMinNumberOfAttempts = 2; |
| 616 for (int attempt = 0; attempt < kMaxNumberOfAttempts; attempt++) { | 609 for (int attempt = 0; attempt < kMaxNumberOfAttempts; attempt++) { |
| 617 if (!CollectGarbage(OLD_POINTER_SPACE, MARK_COMPACTOR, gc_reason, NULL) && | 610 if (!CollectGarbage(OLD_POINTER_SPACE, MARK_COMPACTOR, gc_reason, NULL) && |
| 618 attempt + 1 >= kMinNumberOfAttempts) { | 611 attempt + 1 >= kMinNumberOfAttempts) { |
| 619 break; | 612 break; |
| 620 } | 613 } |
| (...skipping 4712 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5333 reinterpret_cast<FixedArray*>(result)->set_length(0); | 5326 reinterpret_cast<FixedArray*>(result)->set_length(0); |
| 5334 return result; | 5327 return result; |
| 5335 } | 5328 } |
| 5336 | 5329 |
| 5337 | 5330 |
| 5338 MaybeObject* Heap::AllocateEmptyExternalArray(ExternalArrayType array_type) { | 5331 MaybeObject* Heap::AllocateEmptyExternalArray(ExternalArrayType array_type) { |
| 5339 return AllocateExternalArray(0, array_type, NULL, TENURED); | 5332 return AllocateExternalArray(0, array_type, NULL, TENURED); |
| 5340 } | 5333 } |
| 5341 | 5334 |
| 5342 | 5335 |
| 5343 MaybeObject* Heap::AllocateRawFixedArray(int length) { | |
| 5344 if (length < 0 || length > FixedArray::kMaxLength) { | |
| 5345 return Failure::OutOfMemoryException(0xd); | |
| 5346 } | |
| 5347 ASSERT(length > 0); | |
| 5348 // Use the general function if we're forced to always allocate. | |
| 5349 if (always_allocate()) return AllocateFixedArray(length, TENURED); | |
| 5350 // Allocate the raw data for a fixed array. | |
| 5351 int size = FixedArray::SizeFor(length); | |
| 5352 return size <= Page::kMaxNonCodeHeapObjectSize | |
| 5353 ? new_space_.AllocateRaw(size) | |
| 5354 : lo_space_->AllocateRaw(size, NOT_EXECUTABLE); | |
| 5355 } | |
| 5356 | |
| 5357 | |
| 5358 MaybeObject* Heap::CopyFixedArrayWithMap(FixedArray* src, Map* map) { | 5336 MaybeObject* Heap::CopyFixedArrayWithMap(FixedArray* src, Map* map) { |
| 5359 int len = src->length(); | 5337 int len = src->length(); |
| 5360 Object* obj; | 5338 Object* obj; |
| 5361 { MaybeObject* maybe_obj = AllocateRawFixedArray(len); | 5339 { MaybeObject* maybe_obj = AllocateRawFixedArray(len, NOT_TENURED); |
| 5362 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 5340 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 5363 } | 5341 } |
| 5364 if (InNewSpace(obj)) { | 5342 if (InNewSpace(obj)) { |
| 5365 HeapObject* dst = HeapObject::cast(obj); | 5343 HeapObject* dst = HeapObject::cast(obj); |
| 5366 dst->set_map_no_write_barrier(map); | 5344 dst->set_map_no_write_barrier(map); |
| 5367 CopyBlock(dst->address() + kPointerSize, | 5345 CopyBlock(dst->address() + kPointerSize, |
| 5368 src->address() + kPointerSize, | 5346 src->address() + kPointerSize, |
| 5369 FixedArray::SizeFor(len) - kPointerSize); | 5347 FixedArray::SizeFor(len) - kPointerSize); |
| 5370 return obj; | 5348 return obj; |
| 5371 } | 5349 } |
| (...skipping 30 matching lines...) Expand all Loading... |
| 5402 if (length < 0 || length > FixedArray::kMaxLength) { | 5380 if (length < 0 || length > FixedArray::kMaxLength) { |
| 5403 return Failure::OutOfMemoryException(0xe); | 5381 return Failure::OutOfMemoryException(0xe); |
| 5404 } | 5382 } |
| 5405 int size = FixedArray::SizeFor(length); | 5383 int size = FixedArray::SizeFor(length); |
| 5406 AllocationSpace space = SelectSpace(size, OLD_POINTER_SPACE, pretenure); | 5384 AllocationSpace space = SelectSpace(size, OLD_POINTER_SPACE, pretenure); |
| 5407 | 5385 |
| 5408 return AllocateRaw(size, space, OLD_POINTER_SPACE); | 5386 return AllocateRaw(size, space, OLD_POINTER_SPACE); |
| 5409 } | 5387 } |
| 5410 | 5388 |
| 5411 | 5389 |
| 5412 MUST_USE_RESULT static MaybeObject* AllocateFixedArrayWithFiller( | 5390 MaybeObject* Heap::AllocateFixedArrayWithFiller(int length, |
| 5413 Heap* heap, | 5391 PretenureFlag pretenure, |
| 5414 int length, | 5392 Object* filler) { |
| 5415 PretenureFlag pretenure, | |
| 5416 Object* filler) { | |
| 5417 ASSERT(length >= 0); | 5393 ASSERT(length >= 0); |
| 5418 ASSERT(heap->empty_fixed_array()->IsFixedArray()); | 5394 ASSERT(empty_fixed_array()->IsFixedArray()); |
| 5419 if (length == 0) return heap->empty_fixed_array(); | 5395 if (length == 0) return empty_fixed_array(); |
| 5420 | 5396 |
| 5421 ASSERT(!heap->InNewSpace(filler)); | 5397 ASSERT(!InNewSpace(filler)); |
| 5422 Object* result; | 5398 Object* result; |
| 5423 { MaybeObject* maybe_result = heap->AllocateRawFixedArray(length, pretenure); | 5399 { MaybeObject* maybe_result = AllocateRawFixedArray(length, pretenure); |
| 5424 if (!maybe_result->ToObject(&result)) return maybe_result; | 5400 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 5425 } | 5401 } |
| 5426 | 5402 |
| 5427 HeapObject::cast(result)->set_map_no_write_barrier(heap->fixed_array_map()); | 5403 HeapObject::cast(result)->set_map_no_write_barrier(fixed_array_map()); |
| 5428 FixedArray* array = FixedArray::cast(result); | 5404 FixedArray* array = FixedArray::cast(result); |
| 5429 array->set_length(length); | 5405 array->set_length(length); |
| 5430 MemsetPointer(array->data_start(), filler, length); | 5406 MemsetPointer(array->data_start(), filler, length); |
| 5431 return array; | 5407 return array; |
| 5432 } | 5408 } |
| 5433 | 5409 |
| 5434 | 5410 |
| 5435 MaybeObject* Heap::AllocateFixedArray(int length, PretenureFlag pretenure) { | 5411 MaybeObject* Heap::AllocateFixedArray(int length, PretenureFlag pretenure) { |
| 5436 return AllocateFixedArrayWithFiller(this, | 5412 return AllocateFixedArrayWithFiller(length, pretenure, undefined_value()); |
| 5437 length, | |
| 5438 pretenure, | |
| 5439 undefined_value()); | |
| 5440 } | 5413 } |
| 5441 | 5414 |
| 5442 | 5415 |
| 5443 MaybeObject* Heap::AllocateFixedArrayWithHoles(int length, | 5416 MaybeObject* Heap::AllocateFixedArrayWithHoles(int length, |
| 5444 PretenureFlag pretenure) { | 5417 PretenureFlag pretenure) { |
| 5445 return AllocateFixedArrayWithFiller(this, | 5418 return AllocateFixedArrayWithFiller(length, pretenure, the_hole_value()); |
| 5446 length, | |
| 5447 pretenure, | |
| 5448 the_hole_value()); | |
| 5449 } | 5419 } |
| 5450 | 5420 |
| 5451 | 5421 |
| 5452 MaybeObject* Heap::AllocateUninitializedFixedArray(int length) { | 5422 MaybeObject* Heap::AllocateUninitializedFixedArray(int length) { |
| 5453 if (length == 0) return empty_fixed_array(); | 5423 if (length == 0) return empty_fixed_array(); |
| 5454 | 5424 |
| 5455 Object* obj; | 5425 Object* obj; |
| 5456 { MaybeObject* maybe_obj = AllocateRawFixedArray(length); | 5426 { MaybeObject* maybe_obj = AllocateRawFixedArray(length, NOT_TENURED); |
| 5457 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 5427 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 5458 } | 5428 } |
| 5459 | 5429 |
| 5460 reinterpret_cast<FixedArray*>(obj)->set_map_no_write_barrier( | 5430 reinterpret_cast<FixedArray*>(obj)->set_map_no_write_barrier( |
| 5461 fixed_array_map()); | 5431 fixed_array_map()); |
| 5462 FixedArray::cast(obj)->set_length(length); | 5432 FixedArray::cast(obj)->set_length(length); |
| 5463 return obj; | 5433 return obj; |
| 5464 } | 5434 } |
| 5465 | 5435 |
| 5466 | 5436 |
| (...skipping 2433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7900 if (FLAG_concurrent_recompilation) { | 7870 if (FLAG_concurrent_recompilation) { |
| 7901 heap_->relocation_mutex_->Lock(); | 7871 heap_->relocation_mutex_->Lock(); |
| 7902 #ifdef DEBUG | 7872 #ifdef DEBUG |
| 7903 heap_->relocation_mutex_locked_by_optimizer_thread_ = | 7873 heap_->relocation_mutex_locked_by_optimizer_thread_ = |
| 7904 heap_->isolate()->optimizing_compiler_thread()->IsOptimizerThread(); | 7874 heap_->isolate()->optimizing_compiler_thread()->IsOptimizerThread(); |
| 7905 #endif // DEBUG | 7875 #endif // DEBUG |
| 7906 } | 7876 } |
| 7907 } | 7877 } |
| 7908 | 7878 |
| 7909 } } // namespace v8::internal | 7879 } } // namespace v8::internal |
| OLD | NEW |