| 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 565 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 576 #undef UPDATE_COUNTERS_FOR_SPACE | 576 #undef UPDATE_COUNTERS_FOR_SPACE |
| 577 #undef UPDATE_FRAGMENTATION_FOR_SPACE | 577 #undef UPDATE_FRAGMENTATION_FOR_SPACE |
| 578 #undef UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE | 578 #undef UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE |
| 579 | 579 |
| 580 #if defined(DEBUG) | 580 #if defined(DEBUG) |
| 581 ReportStatisticsAfterGC(); | 581 ReportStatisticsAfterGC(); |
| 582 #endif // DEBUG | 582 #endif // DEBUG |
| 583 #ifdef ENABLE_DEBUGGER_SUPPORT | 583 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 584 isolate_->debug()->AfterGarbageCollection(); | 584 isolate_->debug()->AfterGarbageCollection(); |
| 585 #endif // ENABLE_DEBUGGER_SUPPORT | 585 #endif // ENABLE_DEBUGGER_SUPPORT |
| 586 | |
| 587 error_object_list_.DeferredFormatStackTrace(isolate()); | |
| 588 } | 586 } |
| 589 | 587 |
| 590 | 588 |
| 591 void Heap::CollectAllGarbage(int flags, const char* gc_reason) { | 589 void Heap::CollectAllGarbage(int flags, const char* gc_reason) { |
| 592 // Since we are ignoring the return value, the exact choice of space does | 590 // Since we are ignoring the return value, the exact choice of space does |
| 593 // not matter, so long as we do not specify NEW_SPACE, which would not | 591 // not matter, so long as we do not specify NEW_SPACE, which would not |
| 594 // cause a full GC. | 592 // cause a full GC. |
| 595 mark_compact_collector_.SetFlags(flags); | 593 mark_compact_collector_.SetFlags(flags); |
| 596 CollectGarbage(OLD_POINTER_SPACE, gc_reason); | 594 CollectGarbage(OLD_POINTER_SPACE, gc_reason); |
| 597 mark_compact_collector_.SetFlags(kNoGCFlags); | 595 mark_compact_collector_.SetFlags(kNoGCFlags); |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 698 incremental_marking()->IsStopped() && | 696 incremental_marking()->IsStopped() && |
| 699 incremental_marking()->WorthActivating() && | 697 incremental_marking()->WorthActivating() && |
| 700 NextGCIsLikelyToBeFull()) { | 698 NextGCIsLikelyToBeFull()) { |
| 701 incremental_marking()->Start(); | 699 incremental_marking()->Start(); |
| 702 } | 700 } |
| 703 | 701 |
| 704 return next_gc_likely_to_collect_more; | 702 return next_gc_likely_to_collect_more; |
| 705 } | 703 } |
| 706 | 704 |
| 707 | 705 |
| 706 int Heap::NotifyContextDisposed() { |
| 707 if (FLAG_parallel_recompilation) { |
| 708 // Flush the queued recompilation tasks. |
| 709 isolate()->optimizing_compiler_thread()->Flush(); |
| 710 } |
| 711 flush_monomorphic_ics_ = true; |
| 712 return ++contexts_disposed_; |
| 713 } |
| 714 |
| 715 |
| 708 void Heap::PerformScavenge() { | 716 void Heap::PerformScavenge() { |
| 709 GCTracer tracer(this, NULL, NULL); | 717 GCTracer tracer(this, NULL, NULL); |
| 710 if (incremental_marking()->IsStopped()) { | 718 if (incremental_marking()->IsStopped()) { |
| 711 PerformGarbageCollection(SCAVENGER, &tracer); | 719 PerformGarbageCollection(SCAVENGER, &tracer); |
| 712 } else { | 720 } else { |
| 713 PerformGarbageCollection(MARK_COMPACTOR, &tracer); | 721 PerformGarbageCollection(MARK_COMPACTOR, &tracer); |
| 714 } | 722 } |
| 715 } | 723 } |
| 716 | 724 |
| 717 | 725 |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 915 VerifyStringTable(); | 923 VerifyStringTable(); |
| 916 } | 924 } |
| 917 #endif | 925 #endif |
| 918 | 926 |
| 919 GCType gc_type = | 927 GCType gc_type = |
| 920 collector == MARK_COMPACTOR ? kGCTypeMarkSweepCompact : kGCTypeScavenge; | 928 collector == MARK_COMPACTOR ? kGCTypeMarkSweepCompact : kGCTypeScavenge; |
| 921 | 929 |
| 922 { | 930 { |
| 923 GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL); | 931 GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL); |
| 924 VMState<EXTERNAL> state(isolate_); | 932 VMState<EXTERNAL> state(isolate_); |
| 933 HandleScope handle_scope(isolate_); |
| 925 CallGCPrologueCallbacks(gc_type, kNoGCCallbackFlags); | 934 CallGCPrologueCallbacks(gc_type, kNoGCCallbackFlags); |
| 926 } | 935 } |
| 927 | 936 |
| 928 EnsureFromSpaceIsCommitted(); | 937 EnsureFromSpaceIsCommitted(); |
| 929 | 938 |
| 930 int start_new_space_size = Heap::new_space()->SizeAsInt(); | 939 int start_new_space_size = Heap::new_space()->SizeAsInt(); |
| 931 | 940 |
| 932 if (IsHighSurvivalRate()) { | 941 if (IsHighSurvivalRate()) { |
| 933 // We speed up the incremental marker if it is running so that it | 942 // We speed up the incremental marker if it is running so that it |
| 934 // does not fall behind the rate of promotion, which would cause a | 943 // does not fall behind the rate of promotion, which would cause a |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1020 | 1029 |
| 1021 if (collector == MARK_COMPACTOR) { | 1030 if (collector == MARK_COMPACTOR) { |
| 1022 // Register the amount of external allocated memory. | 1031 // Register the amount of external allocated memory. |
| 1023 amount_of_external_allocated_memory_at_last_global_gc_ = | 1032 amount_of_external_allocated_memory_at_last_global_gc_ = |
| 1024 amount_of_external_allocated_memory_; | 1033 amount_of_external_allocated_memory_; |
| 1025 } | 1034 } |
| 1026 | 1035 |
| 1027 { | 1036 { |
| 1028 GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL); | 1037 GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL); |
| 1029 VMState<EXTERNAL> state(isolate_); | 1038 VMState<EXTERNAL> state(isolate_); |
| 1039 HandleScope handle_scope(isolate_); |
| 1030 CallGCEpilogueCallbacks(gc_type); | 1040 CallGCEpilogueCallbacks(gc_type); |
| 1031 } | 1041 } |
| 1032 | 1042 |
| 1033 #ifdef VERIFY_HEAP | 1043 #ifdef VERIFY_HEAP |
| 1034 if (FLAG_verify_heap) { | 1044 if (FLAG_verify_heap) { |
| 1035 VerifyStringTable(); | 1045 VerifyStringTable(); |
| 1036 } | 1046 } |
| 1037 #endif | 1047 #endif |
| 1038 | 1048 |
| 1039 return next_gc_likely_to_collect_more; | 1049 return next_gc_likely_to_collect_more; |
| (...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1421 | 1431 |
| 1422 isolate_->global_handles()->IdentifyNewSpaceWeakIndependentHandles( | 1432 isolate_->global_handles()->IdentifyNewSpaceWeakIndependentHandles( |
| 1423 &IsUnscavengedHeapObject); | 1433 &IsUnscavengedHeapObject); |
| 1424 isolate_->global_handles()->IterateNewSpaceWeakIndependentRoots( | 1434 isolate_->global_handles()->IterateNewSpaceWeakIndependentRoots( |
| 1425 &scavenge_visitor); | 1435 &scavenge_visitor); |
| 1426 new_space_front = DoScavenge(&scavenge_visitor, new_space_front); | 1436 new_space_front = DoScavenge(&scavenge_visitor, new_space_front); |
| 1427 | 1437 |
| 1428 UpdateNewSpaceReferencesInExternalStringTable( | 1438 UpdateNewSpaceReferencesInExternalStringTable( |
| 1429 &UpdateNewSpaceReferenceInExternalStringTableEntry); | 1439 &UpdateNewSpaceReferenceInExternalStringTableEntry); |
| 1430 | 1440 |
| 1431 error_object_list_.UpdateReferencesInNewSpace(this); | |
| 1432 | |
| 1433 promotion_queue_.Destroy(); | 1441 promotion_queue_.Destroy(); |
| 1434 | 1442 |
| 1435 if (!FLAG_watch_ic_patching) { | 1443 if (!FLAG_watch_ic_patching) { |
| 1436 isolate()->runtime_profiler()->UpdateSamplesAfterScavenge(); | 1444 isolate()->runtime_profiler()->UpdateSamplesAfterScavenge(); |
| 1437 } | 1445 } |
| 1438 incremental_marking()->UpdateMarkingDequeAfterScavenge(); | 1446 incremental_marking()->UpdateMarkingDequeAfterScavenge(); |
| 1439 | 1447 |
| 1440 ScavengeWeakObjectRetainer weak_object_retainer(this); | 1448 ScavengeWeakObjectRetainer weak_object_retainer(this); |
| 1441 ProcessWeakReferences(&weak_object_retainer); | 1449 ProcessWeakReferences(&weak_object_retainer); |
| 1442 | 1450 |
| (...skipping 1770 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3213 if (!maybe_obj->ToObject(&obj)) return false; | 3221 if (!maybe_obj->ToObject(&obj)) return false; |
| 3214 } | 3222 } |
| 3215 SeededNumberDictionary::cast(obj)->set_requires_slow_elements(); | 3223 SeededNumberDictionary::cast(obj)->set_requires_slow_elements(); |
| 3216 set_empty_slow_element_dictionary(SeededNumberDictionary::cast(obj)); | 3224 set_empty_slow_element_dictionary(SeededNumberDictionary::cast(obj)); |
| 3217 | 3225 |
| 3218 { MaybeObject* maybe_obj = AllocateSymbol(); | 3226 { MaybeObject* maybe_obj = AllocateSymbol(); |
| 3219 if (!maybe_obj->ToObject(&obj)) return false; | 3227 if (!maybe_obj->ToObject(&obj)) return false; |
| 3220 } | 3228 } |
| 3221 set_observed_symbol(Symbol::cast(obj)); | 3229 set_observed_symbol(Symbol::cast(obj)); |
| 3222 | 3230 |
| 3231 set_i18n_template_one(the_hole_value()); |
| 3232 set_i18n_template_two(the_hole_value()); |
| 3233 |
| 3223 // Handling of script id generation is in Factory::NewScript. | 3234 // Handling of script id generation is in Factory::NewScript. |
| 3224 set_last_script_id(Smi::FromInt(v8::Script::kNoScriptId)); | 3235 set_last_script_id(Smi::FromInt(v8::Script::kNoScriptId)); |
| 3225 | 3236 |
| 3226 // Initialize keyed lookup cache. | 3237 // Initialize keyed lookup cache. |
| 3227 isolate_->keyed_lookup_cache()->Clear(); | 3238 isolate_->keyed_lookup_cache()->Clear(); |
| 3228 | 3239 |
| 3229 // Initialize context slot cache. | 3240 // Initialize context slot cache. |
| 3230 isolate_->context_slot_cache()->Clear(); | 3241 isolate_->context_slot_cache()->Clear(); |
| 3231 | 3242 |
| 3232 // Initialize descriptor cache. | 3243 // Initialize descriptor cache. |
| (...skipping 2118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5351 template | 5362 template |
| 5352 MaybeObject* Heap::AllocateInternalizedStringImpl<false>( | 5363 MaybeObject* Heap::AllocateInternalizedStringImpl<false>( |
| 5353 Vector<const char>, int, uint32_t); | 5364 Vector<const char>, int, uint32_t); |
| 5354 | 5365 |
| 5355 | 5366 |
| 5356 MaybeObject* Heap::AllocateRawOneByteString(int length, | 5367 MaybeObject* Heap::AllocateRawOneByteString(int length, |
| 5357 PretenureFlag pretenure) { | 5368 PretenureFlag pretenure) { |
| 5358 if (length < 0 || length > SeqOneByteString::kMaxLength) { | 5369 if (length < 0 || length > SeqOneByteString::kMaxLength) { |
| 5359 return Failure::OutOfMemoryException(0xb); | 5370 return Failure::OutOfMemoryException(0xb); |
| 5360 } | 5371 } |
| 5361 | |
| 5362 int size = SeqOneByteString::SizeFor(length); | 5372 int size = SeqOneByteString::SizeFor(length); |
| 5363 ASSERT(size <= SeqOneByteString::kMaxSize); | 5373 ASSERT(size <= SeqOneByteString::kMaxSize); |
| 5364 | |
| 5365 AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE; | 5374 AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE; |
| 5366 AllocationSpace retry_space = OLD_DATA_SPACE; | 5375 AllocationSpace retry_space = OLD_DATA_SPACE; |
| 5367 | 5376 |
| 5368 if (space == NEW_SPACE) { | 5377 if (size > Page::kMaxNonCodeHeapObjectSize) { |
| 5369 if (size > kMaxObjectSizeInNewSpace) { | 5378 // Allocate in large object space, retry space will be ignored. |
| 5370 // Allocate in large object space, retry space will be ignored. | |
| 5371 space = LO_SPACE; | |
| 5372 } else if (size > Page::kMaxNonCodeHeapObjectSize) { | |
| 5373 // Allocate in new space, retry in large object space. | |
| 5374 retry_space = LO_SPACE; | |
| 5375 } | |
| 5376 } else if (space == OLD_DATA_SPACE && | |
| 5377 size > Page::kMaxNonCodeHeapObjectSize) { | |
| 5378 space = LO_SPACE; | 5379 space = LO_SPACE; |
| 5379 } | 5380 } |
| 5381 |
| 5380 Object* result; | 5382 Object* result; |
| 5381 { MaybeObject* maybe_result = AllocateRaw(size, space, retry_space); | 5383 { MaybeObject* maybe_result = AllocateRaw(size, space, retry_space); |
| 5382 if (!maybe_result->ToObject(&result)) return maybe_result; | 5384 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 5383 } | 5385 } |
| 5384 | 5386 |
| 5385 // Partially initialize the object. | 5387 // Partially initialize the object. |
| 5386 HeapObject::cast(result)->set_map_no_write_barrier(ascii_string_map()); | 5388 HeapObject::cast(result)->set_map_no_write_barrier(ascii_string_map()); |
| 5387 String::cast(result)->set_length(length); | 5389 String::cast(result)->set_length(length); |
| 5388 String::cast(result)->set_hash_field(String::kEmptyHashField); | 5390 String::cast(result)->set_hash_field(String::kEmptyHashField); |
| 5389 ASSERT_EQ(size, HeapObject::cast(result)->Size()); | 5391 ASSERT_EQ(size, HeapObject::cast(result)->Size()); |
| 5390 | 5392 |
| 5391 return result; | 5393 return result; |
| 5392 } | 5394 } |
| 5393 | 5395 |
| 5394 | 5396 |
| 5395 MaybeObject* Heap::AllocateRawTwoByteString(int length, | 5397 MaybeObject* Heap::AllocateRawTwoByteString(int length, |
| 5396 PretenureFlag pretenure) { | 5398 PretenureFlag pretenure) { |
| 5397 if (length < 0 || length > SeqTwoByteString::kMaxLength) { | 5399 if (length < 0 || length > SeqTwoByteString::kMaxLength) { |
| 5398 return Failure::OutOfMemoryException(0xc); | 5400 return Failure::OutOfMemoryException(0xc); |
| 5399 } | 5401 } |
| 5400 int size = SeqTwoByteString::SizeFor(length); | 5402 int size = SeqTwoByteString::SizeFor(length); |
| 5401 ASSERT(size <= SeqTwoByteString::kMaxSize); | 5403 ASSERT(size <= SeqTwoByteString::kMaxSize); |
| 5402 AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE; | 5404 AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE; |
| 5403 AllocationSpace retry_space = OLD_DATA_SPACE; | 5405 AllocationSpace retry_space = OLD_DATA_SPACE; |
| 5404 | 5406 |
| 5405 if (space == NEW_SPACE) { | 5407 if (size > Page::kMaxNonCodeHeapObjectSize) { |
| 5406 if (size > kMaxObjectSizeInNewSpace) { | 5408 // Allocate in large object space, retry space will be ignored. |
| 5407 // Allocate in large object space, retry space will be ignored. | |
| 5408 space = LO_SPACE; | |
| 5409 } else if (size > Page::kMaxNonCodeHeapObjectSize) { | |
| 5410 // Allocate in new space, retry in large object space. | |
| 5411 retry_space = LO_SPACE; | |
| 5412 } | |
| 5413 } else if (space == OLD_DATA_SPACE && | |
| 5414 size > Page::kMaxNonCodeHeapObjectSize) { | |
| 5415 space = LO_SPACE; | 5409 space = LO_SPACE; |
| 5416 } | 5410 } |
| 5411 |
| 5417 Object* result; | 5412 Object* result; |
| 5418 { MaybeObject* maybe_result = AllocateRaw(size, space, retry_space); | 5413 { MaybeObject* maybe_result = AllocateRaw(size, space, retry_space); |
| 5419 if (!maybe_result->ToObject(&result)) return maybe_result; | 5414 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 5420 } | 5415 } |
| 5421 | 5416 |
| 5422 // Partially initialize the object. | 5417 // Partially initialize the object. |
| 5423 HeapObject::cast(result)->set_map_no_write_barrier(string_map()); | 5418 HeapObject::cast(result)->set_map_no_write_barrier(string_map()); |
| 5424 String::cast(result)->set_length(length); | 5419 String::cast(result)->set_length(length); |
| 5425 String::cast(result)->set_hash_field(String::kEmptyHashField); | 5420 String::cast(result)->set_hash_field(String::kEmptyHashField); |
| 5426 ASSERT_EQ(size, HeapObject::cast(result)->Size()); | 5421 ASSERT_EQ(size, HeapObject::cast(result)->Size()); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5480 | 5475 |
| 5481 MaybeObject* Heap::AllocateRawFixedArray(int length) { | 5476 MaybeObject* Heap::AllocateRawFixedArray(int length) { |
| 5482 if (length < 0 || length > FixedArray::kMaxLength) { | 5477 if (length < 0 || length > FixedArray::kMaxLength) { |
| 5483 return Failure::OutOfMemoryException(0xd); | 5478 return Failure::OutOfMemoryException(0xd); |
| 5484 } | 5479 } |
| 5485 ASSERT(length > 0); | 5480 ASSERT(length > 0); |
| 5486 // Use the general function if we're forced to always allocate. | 5481 // Use the general function if we're forced to always allocate. |
| 5487 if (always_allocate()) return AllocateFixedArray(length, TENURED); | 5482 if (always_allocate()) return AllocateFixedArray(length, TENURED); |
| 5488 // Allocate the raw data for a fixed array. | 5483 // Allocate the raw data for a fixed array. |
| 5489 int size = FixedArray::SizeFor(length); | 5484 int size = FixedArray::SizeFor(length); |
| 5490 return size <= kMaxObjectSizeInNewSpace | 5485 return size <= Page::kMaxNonCodeHeapObjectSize |
| 5491 ? new_space_.AllocateRaw(size) | 5486 ? new_space_.AllocateRaw(size) |
| 5492 : lo_space_->AllocateRaw(size, NOT_EXECUTABLE); | 5487 : lo_space_->AllocateRaw(size, NOT_EXECUTABLE); |
| 5493 } | 5488 } |
| 5494 | 5489 |
| 5495 | 5490 |
| 5496 MaybeObject* Heap::CopyFixedArrayWithMap(FixedArray* src, Map* map) { | 5491 MaybeObject* Heap::CopyFixedArrayWithMap(FixedArray* src, Map* map) { |
| 5497 int len = src->length(); | 5492 int len = src->length(); |
| 5498 Object* obj; | 5493 Object* obj; |
| 5499 { MaybeObject* maybe_obj = AllocateRawFixedArray(len); | 5494 { MaybeObject* maybe_obj = AllocateRawFixedArray(len); |
| 5500 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 5495 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5551 ASSERT(!InNewSpace(undefined_value())); | 5546 ASSERT(!InNewSpace(undefined_value())); |
| 5552 MemsetPointer(array->data_start(), undefined_value(), length); | 5547 MemsetPointer(array->data_start(), undefined_value(), length); |
| 5553 return result; | 5548 return result; |
| 5554 } | 5549 } |
| 5555 | 5550 |
| 5556 | 5551 |
| 5557 MaybeObject* Heap::AllocateRawFixedArray(int length, PretenureFlag pretenure) { | 5552 MaybeObject* Heap::AllocateRawFixedArray(int length, PretenureFlag pretenure) { |
| 5558 if (length < 0 || length > FixedArray::kMaxLength) { | 5553 if (length < 0 || length > FixedArray::kMaxLength) { |
| 5559 return Failure::OutOfMemoryException(0xe); | 5554 return Failure::OutOfMemoryException(0xe); |
| 5560 } | 5555 } |
| 5561 | 5556 int size = FixedArray::SizeFor(length); |
| 5562 AllocationSpace space = | 5557 AllocationSpace space = |
| 5563 (pretenure == TENURED) ? OLD_POINTER_SPACE : NEW_SPACE; | 5558 (pretenure == TENURED) ? OLD_POINTER_SPACE : NEW_SPACE; |
| 5564 int size = FixedArray::SizeFor(length); | 5559 AllocationSpace retry_space = OLD_POINTER_SPACE; |
| 5565 if (space == NEW_SPACE && size > kMaxObjectSizeInNewSpace) { | 5560 |
| 5566 // Too big for new space. | 5561 if (size > Page::kMaxNonCodeHeapObjectSize) { |
| 5567 space = LO_SPACE; | 5562 // Allocate in large object space, retry space will be ignored. |
| 5568 } else if (space == OLD_POINTER_SPACE && | |
| 5569 size > Page::kMaxNonCodeHeapObjectSize) { | |
| 5570 // Too big for old pointer space. | |
| 5571 space = LO_SPACE; | 5563 space = LO_SPACE; |
| 5572 } | 5564 } |
| 5573 | 5565 |
| 5574 AllocationSpace retry_space = | |
| 5575 (size <= Page::kMaxNonCodeHeapObjectSize) ? OLD_POINTER_SPACE : LO_SPACE; | |
| 5576 | |
| 5577 return AllocateRaw(size, space, retry_space); | 5566 return AllocateRaw(size, space, retry_space); |
| 5578 } | 5567 } |
| 5579 | 5568 |
| 5580 | 5569 |
| 5581 MUST_USE_RESULT static MaybeObject* AllocateFixedArrayWithFiller( | 5570 MUST_USE_RESULT static MaybeObject* AllocateFixedArrayWithFiller( |
| 5582 Heap* heap, | 5571 Heap* heap, |
| 5583 int length, | 5572 int length, |
| 5584 PretenureFlag pretenure, | 5573 PretenureFlag pretenure, |
| 5585 Object* filler) { | 5574 Object* filler) { |
| 5586 ASSERT(length >= 0); | 5575 ASSERT(length >= 0); |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5684 elements->set_length(length); | 5673 elements->set_length(length); |
| 5685 return elements; | 5674 return elements; |
| 5686 } | 5675 } |
| 5687 | 5676 |
| 5688 | 5677 |
| 5689 MaybeObject* Heap::AllocateRawFixedDoubleArray(int length, | 5678 MaybeObject* Heap::AllocateRawFixedDoubleArray(int length, |
| 5690 PretenureFlag pretenure) { | 5679 PretenureFlag pretenure) { |
| 5691 if (length < 0 || length > FixedDoubleArray::kMaxLength) { | 5680 if (length < 0 || length > FixedDoubleArray::kMaxLength) { |
| 5692 return Failure::OutOfMemoryException(0xf); | 5681 return Failure::OutOfMemoryException(0xf); |
| 5693 } | 5682 } |
| 5694 | |
| 5695 AllocationSpace space = | |
| 5696 (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE; | |
| 5697 int size = FixedDoubleArray::SizeFor(length); | 5683 int size = FixedDoubleArray::SizeFor(length); |
| 5684 AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE; |
| 5685 AllocationSpace retry_space = OLD_DATA_SPACE; |
| 5698 | 5686 |
| 5699 #ifndef V8_HOST_ARCH_64_BIT | 5687 #ifndef V8_HOST_ARCH_64_BIT |
| 5700 size += kPointerSize; | 5688 size += kPointerSize; |
| 5701 #endif | 5689 #endif |
| 5702 | 5690 |
| 5703 if (space == NEW_SPACE && size > kMaxObjectSizeInNewSpace) { | 5691 if (size > Page::kMaxNonCodeHeapObjectSize) { |
| 5704 // Too big for new space. | 5692 // Allocate in large object space, retry space will be ignored. |
| 5705 space = LO_SPACE; | |
| 5706 } else if (space == OLD_DATA_SPACE && | |
| 5707 size > Page::kMaxNonCodeHeapObjectSize) { | |
| 5708 // Too big for old data space. | |
| 5709 space = LO_SPACE; | 5693 space = LO_SPACE; |
| 5710 } | 5694 } |
| 5711 | 5695 |
| 5712 AllocationSpace retry_space = | |
| 5713 (size <= Page::kMaxNonCodeHeapObjectSize) ? OLD_DATA_SPACE : LO_SPACE; | |
| 5714 | |
| 5715 HeapObject* object; | 5696 HeapObject* object; |
| 5716 { MaybeObject* maybe_object = AllocateRaw(size, space, retry_space); | 5697 { MaybeObject* maybe_object = AllocateRaw(size, space, retry_space); |
| 5717 if (!maybe_object->To<HeapObject>(&object)) return maybe_object; | 5698 if (!maybe_object->To<HeapObject>(&object)) return maybe_object; |
| 5718 } | 5699 } |
| 5719 | 5700 |
| 5720 return EnsureDoubleAligned(this, object, size); | 5701 return EnsureDoubleAligned(this, object, size); |
| 5721 } | 5702 } |
| 5722 | 5703 |
| 5723 | 5704 |
| 5724 MaybeObject* Heap::AllocateHashTable(int length, PretenureFlag pretenure) { | 5705 MaybeObject* Heap::AllocateHashTable(int length, PretenureFlag pretenure) { |
| (...skipping 848 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6573 } | 6554 } |
| 6574 | 6555 |
| 6575 | 6556 |
| 6576 void Heap::IterateWeakRoots(ObjectVisitor* v, VisitMode mode) { | 6557 void Heap::IterateWeakRoots(ObjectVisitor* v, VisitMode mode) { |
| 6577 v->VisitPointer(reinterpret_cast<Object**>(&roots_[kStringTableRootIndex])); | 6558 v->VisitPointer(reinterpret_cast<Object**>(&roots_[kStringTableRootIndex])); |
| 6578 v->Synchronize(VisitorSynchronization::kStringTable); | 6559 v->Synchronize(VisitorSynchronization::kStringTable); |
| 6579 if (mode != VISIT_ALL_IN_SCAVENGE && | 6560 if (mode != VISIT_ALL_IN_SCAVENGE && |
| 6580 mode != VISIT_ALL_IN_SWEEP_NEWSPACE) { | 6561 mode != VISIT_ALL_IN_SWEEP_NEWSPACE) { |
| 6581 // Scavenge collections have special processing for this. | 6562 // Scavenge collections have special processing for this. |
| 6582 external_string_table_.Iterate(v); | 6563 external_string_table_.Iterate(v); |
| 6583 error_object_list_.Iterate(v); | |
| 6584 } | 6564 } |
| 6585 v->Synchronize(VisitorSynchronization::kExternalStringsTable); | 6565 v->Synchronize(VisitorSynchronization::kExternalStringsTable); |
| 6586 } | 6566 } |
| 6587 | 6567 |
| 6588 | 6568 |
| 6589 void Heap::IterateStrongRoots(ObjectVisitor* v, VisitMode mode) { | 6569 void Heap::IterateStrongRoots(ObjectVisitor* v, VisitMode mode) { |
| 6590 v->VisitPointers(&roots_[0], &roots_[kStrongRootListLength]); | 6570 v->VisitPointers(&roots_[0], &roots_[kStrongRootListLength]); |
| 6591 v->Synchronize(VisitorSynchronization::kStrongRootList); | 6571 v->Synchronize(VisitorSynchronization::kStrongRootList); |
| 6592 | 6572 |
| 6593 v->VisitPointer(BitCast<Object**>(&hidden_string_)); | 6573 v->VisitPointer(BitCast<Object**>(&hidden_string_)); |
| (...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6973 PrintF("total_sweeping_time=%.1f ", sweeping_time()); | 6953 PrintF("total_sweeping_time=%.1f ", sweeping_time()); |
| 6974 PrintF("\n\n"); | 6954 PrintF("\n\n"); |
| 6975 } | 6955 } |
| 6976 | 6956 |
| 6977 TearDownArrayBuffers(); | 6957 TearDownArrayBuffers(); |
| 6978 | 6958 |
| 6979 isolate_->global_handles()->TearDown(); | 6959 isolate_->global_handles()->TearDown(); |
| 6980 | 6960 |
| 6981 external_string_table_.TearDown(); | 6961 external_string_table_.TearDown(); |
| 6982 | 6962 |
| 6983 error_object_list_.TearDown(); | |
| 6984 | |
| 6985 new_space_.TearDown(); | 6963 new_space_.TearDown(); |
| 6986 | 6964 |
| 6987 if (old_pointer_space_ != NULL) { | 6965 if (old_pointer_space_ != NULL) { |
| 6988 old_pointer_space_->TearDown(); | 6966 old_pointer_space_->TearDown(); |
| 6989 delete old_pointer_space_; | 6967 delete old_pointer_space_; |
| 6990 old_pointer_space_ = NULL; | 6968 old_pointer_space_ = NULL; |
| 6991 } | 6969 } |
| 6992 | 6970 |
| 6993 if (old_data_space_ != NULL) { | 6971 if (old_data_space_ != NULL) { |
| 6994 old_data_space_->TearDown(); | 6972 old_data_space_->TearDown(); |
| (...skipping 932 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7927 #endif | 7905 #endif |
| 7928 } | 7906 } |
| 7929 | 7907 |
| 7930 | 7908 |
| 7931 void ExternalStringTable::TearDown() { | 7909 void ExternalStringTable::TearDown() { |
| 7932 new_space_strings_.Free(); | 7910 new_space_strings_.Free(); |
| 7933 old_space_strings_.Free(); | 7911 old_space_strings_.Free(); |
| 7934 } | 7912 } |
| 7935 | 7913 |
| 7936 | 7914 |
| 7937 // Update all references. | |
| 7938 void ErrorObjectList::UpdateReferences() { | |
| 7939 for (int i = 0; i < list_.length(); i++) { | |
| 7940 HeapObject* object = HeapObject::cast(list_[i]); | |
| 7941 MapWord first_word = object->map_word(); | |
| 7942 if (first_word.IsForwardingAddress()) { | |
| 7943 list_[i] = first_word.ToForwardingAddress(); | |
| 7944 } | |
| 7945 } | |
| 7946 } | |
| 7947 | |
| 7948 | |
| 7949 // Unforwarded objects in new space are dead and removed from the list. | |
| 7950 void ErrorObjectList::UpdateReferencesInNewSpace(Heap* heap) { | |
| 7951 if (list_.is_empty()) return; | |
| 7952 if (!nested_) { | |
| 7953 int write_index = 0; | |
| 7954 for (int i = 0; i < list_.length(); i++) { | |
| 7955 MapWord first_word = HeapObject::cast(list_[i])->map_word(); | |
| 7956 if (first_word.IsForwardingAddress()) { | |
| 7957 list_[write_index++] = first_word.ToForwardingAddress(); | |
| 7958 } | |
| 7959 } | |
| 7960 list_.Rewind(write_index); | |
| 7961 } else { | |
| 7962 // If a GC is triggered during DeferredFormatStackTrace, we do not move | |
| 7963 // objects in the list, just remove dead ones, as to not confuse the | |
| 7964 // loop in DeferredFormatStackTrace. | |
| 7965 for (int i = 0; i < list_.length(); i++) { | |
| 7966 MapWord first_word = HeapObject::cast(list_[i])->map_word(); | |
| 7967 list_[i] = first_word.IsForwardingAddress() | |
| 7968 ? first_word.ToForwardingAddress() | |
| 7969 : heap->the_hole_value(); | |
| 7970 } | |
| 7971 } | |
| 7972 } | |
| 7973 | |
| 7974 | |
| 7975 void ErrorObjectList::DeferredFormatStackTrace(Isolate* isolate) { | |
| 7976 // If formatting the stack trace causes a GC, this method will be | |
| 7977 // recursively called. In that case, skip the recursive call, since | |
| 7978 // the loop modifies the list while iterating over it. | |
| 7979 if (nested_ || list_.is_empty() || isolate->has_pending_exception()) return; | |
| 7980 nested_ = true; | |
| 7981 HandleScope scope(isolate); | |
| 7982 Handle<String> stack_key = isolate->factory()->stack_string(); | |
| 7983 int write_index = 0; | |
| 7984 int budget = kBudgetPerGC; | |
| 7985 for (int i = 0; i < list_.length(); i++) { | |
| 7986 Object* object = list_[i]; | |
| 7987 JSFunction* getter_fun; | |
| 7988 | |
| 7989 { DisallowHeapAllocation no_gc; | |
| 7990 // Skip possible holes in the list. | |
| 7991 if (object->IsTheHole()) continue; | |
| 7992 if (isolate->heap()->InNewSpace(object) || budget == 0) { | |
| 7993 list_[write_index++] = object; | |
| 7994 continue; | |
| 7995 } | |
| 7996 | |
| 7997 // Check whether the stack property is backed by the original getter. | |
| 7998 LookupResult lookup(isolate); | |
| 7999 JSObject::cast(object)->LocalLookupRealNamedProperty(*stack_key, &lookup); | |
| 8000 if (!lookup.IsFound() || lookup.type() != CALLBACKS) continue; | |
| 8001 Object* callback = lookup.GetCallbackObject(); | |
| 8002 if (!callback->IsAccessorPair()) continue; | |
| 8003 Object* getter_obj = AccessorPair::cast(callback)->getter(); | |
| 8004 if (!getter_obj->IsJSFunction()) continue; | |
| 8005 getter_fun = JSFunction::cast(getter_obj); | |
| 8006 String* key = isolate->heap()->hidden_stack_trace_string(); | |
| 8007 Object* value = getter_fun->GetHiddenProperty(key); | |
| 8008 if (key != value) continue; | |
| 8009 } | |
| 8010 | |
| 8011 budget--; | |
| 8012 HandleScope scope(isolate); | |
| 8013 bool has_exception = false; | |
| 8014 #ifdef DEBUG | |
| 8015 Handle<Map> map(HeapObject::cast(object)->map(), isolate); | |
| 8016 #endif | |
| 8017 Handle<Object> object_handle(object, isolate); | |
| 8018 Handle<Object> getter_handle(getter_fun, isolate); | |
| 8019 Execution::Call(getter_handle, object_handle, 0, NULL, &has_exception); | |
| 8020 ASSERT(*map == HeapObject::cast(*object_handle)->map()); | |
| 8021 if (has_exception) { | |
| 8022 // Hit an exception (most likely a stack overflow). | |
| 8023 // Wrap up this pass and retry after another GC. | |
| 8024 isolate->clear_pending_exception(); | |
| 8025 // We use the handle since calling the getter might have caused a GC. | |
| 8026 list_[write_index++] = *object_handle; | |
| 8027 budget = 0; | |
| 8028 } | |
| 8029 } | |
| 8030 list_.Rewind(write_index); | |
| 8031 list_.Trim(); | |
| 8032 nested_ = false; | |
| 8033 } | |
| 8034 | |
| 8035 | |
| 8036 void ErrorObjectList::RemoveUnmarked(Heap* heap) { | |
| 8037 for (int i = 0; i < list_.length(); i++) { | |
| 8038 HeapObject* object = HeapObject::cast(list_[i]); | |
| 8039 if (!Marking::MarkBitFrom(object).Get()) { | |
| 8040 list_[i] = heap->the_hole_value(); | |
| 8041 } | |
| 8042 } | |
| 8043 } | |
| 8044 | |
| 8045 | |
| 8046 void ErrorObjectList::TearDown() { | |
| 8047 list_.Free(); | |
| 8048 } | |
| 8049 | |
| 8050 | |
| 8051 void Heap::QueueMemoryChunkForFree(MemoryChunk* chunk) { | 7915 void Heap::QueueMemoryChunkForFree(MemoryChunk* chunk) { |
| 8052 chunk->set_next_chunk(chunks_queued_for_free_); | 7916 chunk->set_next_chunk(chunks_queued_for_free_); |
| 8053 chunks_queued_for_free_ = chunk; | 7917 chunks_queued_for_free_ = chunk; |
| 8054 } | 7918 } |
| 8055 | 7919 |
| 8056 | 7920 |
| 8057 void Heap::FreeQueuedChunks() { | 7921 void Heap::FreeQueuedChunks() { |
| 8058 if (chunks_queued_for_free_ == NULL) return; | 7922 if (chunks_queued_for_free_ == NULL) return; |
| 8059 MemoryChunk* next; | 7923 MemoryChunk* next; |
| 8060 MemoryChunk* chunk; | 7924 MemoryChunk* chunk; |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8180 if (FLAG_parallel_recompilation) { | 8044 if (FLAG_parallel_recompilation) { |
| 8181 heap_->relocation_mutex_->Lock(); | 8045 heap_->relocation_mutex_->Lock(); |
| 8182 #ifdef DEBUG | 8046 #ifdef DEBUG |
| 8183 heap_->relocation_mutex_locked_by_optimizer_thread_ = | 8047 heap_->relocation_mutex_locked_by_optimizer_thread_ = |
| 8184 heap_->isolate()->optimizing_compiler_thread()->IsOptimizerThread(); | 8048 heap_->isolate()->optimizing_compiler_thread()->IsOptimizerThread(); |
| 8185 #endif // DEBUG | 8049 #endif // DEBUG |
| 8186 } | 8050 } |
| 8187 } | 8051 } |
| 8188 | 8052 |
| 8189 } } // namespace v8::internal | 8053 } } // namespace v8::internal |
| OLD | NEW |