| 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 386 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 397 if (FLAG_log_gc) new_space_.ReportStatistics(); | 397 if (FLAG_log_gc) new_space_.ReportStatistics(); |
| 398 #endif // DEBUG | 398 #endif // DEBUG |
| 399 } | 399 } |
| 400 | 400 |
| 401 | 401 |
| 402 void Heap::GarbageCollectionPrologue() { | 402 void Heap::GarbageCollectionPrologue() { |
| 403 isolate_->transcendental_cache()->Clear(); | 403 isolate_->transcendental_cache()->Clear(); |
| 404 ClearJSFunctionResultCaches(); | 404 ClearJSFunctionResultCaches(); |
| 405 gc_count_++; | 405 gc_count_++; |
| 406 unflattened_strings_length_ = 0; | 406 unflattened_strings_length_ = 0; |
| 407 |
| 408 #ifdef VERIFY_HEAP |
| 409 if (FLAG_verify_heap) { |
| 410 Verify(); |
| 411 } |
| 412 #endif |
| 413 |
| 407 #ifdef DEBUG | 414 #ifdef DEBUG |
| 408 ASSERT(allocation_allowed_ && gc_state_ == NOT_IN_GC); | 415 ASSERT(allocation_allowed_ && gc_state_ == NOT_IN_GC); |
| 409 allow_allocation(false); | 416 allow_allocation(false); |
| 410 | 417 |
| 411 if (FLAG_verify_heap) { | 418 if (FLAG_gc_verbose) Print(); |
| 412 Verify(); | |
| 413 } | |
| 414 | 419 |
| 415 if (FLAG_gc_verbose) Print(); | |
| 416 #endif // DEBUG | |
| 417 | |
| 418 #if defined(DEBUG) | |
| 419 ReportStatisticsBeforeGC(); | 420 ReportStatisticsBeforeGC(); |
| 420 #endif // DEBUG | 421 #endif // DEBUG |
| 421 | 422 |
| 422 LiveObjectList::GCPrologue(); | 423 LiveObjectList::GCPrologue(); |
| 423 store_buffer()->GCPrologue(); | 424 store_buffer()->GCPrologue(); |
| 424 } | 425 } |
| 425 | 426 |
| 426 | 427 |
| 427 intptr_t Heap::SizeOfObjects() { | 428 intptr_t Heap::SizeOfObjects() { |
| 428 intptr_t total = 0; | 429 intptr_t total = 0; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 440 space != NULL; | 441 space != NULL; |
| 441 space = spaces.next()) { | 442 space = spaces.next()) { |
| 442 space->RepairFreeListsAfterBoot(); | 443 space->RepairFreeListsAfterBoot(); |
| 443 } | 444 } |
| 444 } | 445 } |
| 445 | 446 |
| 446 | 447 |
| 447 void Heap::GarbageCollectionEpilogue() { | 448 void Heap::GarbageCollectionEpilogue() { |
| 448 store_buffer()->GCEpilogue(); | 449 store_buffer()->GCEpilogue(); |
| 449 LiveObjectList::GCEpilogue(); | 450 LiveObjectList::GCEpilogue(); |
| 450 #ifdef DEBUG | |
| 451 allow_allocation(true); | |
| 452 ZapFromSpace(); | |
| 453 | 451 |
| 452 // In release mode, we only zap the from space under heap verification. |
| 453 if (Heap::ShouldZapGarbage()) { |
| 454 ZapFromSpace(); |
| 455 } |
| 456 |
| 457 #ifdef VERIFY_HEAP |
| 454 if (FLAG_verify_heap) { | 458 if (FLAG_verify_heap) { |
| 455 Verify(); | 459 Verify(); |
| 456 } | 460 } |
| 461 #endif |
| 457 | 462 |
| 463 #ifdef DEBUG |
| 464 allow_allocation(true); |
| 458 if (FLAG_print_global_handles) isolate_->global_handles()->Print(); | 465 if (FLAG_print_global_handles) isolate_->global_handles()->Print(); |
| 459 if (FLAG_print_handles) PrintHandles(); | 466 if (FLAG_print_handles) PrintHandles(); |
| 460 if (FLAG_gc_verbose) Print(); | 467 if (FLAG_gc_verbose) Print(); |
| 461 if (FLAG_code_stats) ReportCodeStatistics("After GC"); | 468 if (FLAG_code_stats) ReportCodeStatistics("After GC"); |
| 462 #endif | 469 #endif |
| 463 | 470 |
| 464 isolate_->counters()->alive_after_last_gc()->Set( | 471 isolate_->counters()->alive_after_last_gc()->Set( |
| 465 static_cast<int>(SizeOfObjects())); | 472 static_cast<int>(SizeOfObjects())); |
| 466 | 473 |
| 467 isolate_->counters()->symbol_table_capacity()->Set( | 474 isolate_->counters()->symbol_table_capacity()->Set( |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 644 void Heap::PerformScavenge() { | 651 void Heap::PerformScavenge() { |
| 645 GCTracer tracer(this, NULL, NULL); | 652 GCTracer tracer(this, NULL, NULL); |
| 646 if (incremental_marking()->IsStopped()) { | 653 if (incremental_marking()->IsStopped()) { |
| 647 PerformGarbageCollection(SCAVENGER, &tracer); | 654 PerformGarbageCollection(SCAVENGER, &tracer); |
| 648 } else { | 655 } else { |
| 649 PerformGarbageCollection(MARK_COMPACTOR, &tracer); | 656 PerformGarbageCollection(MARK_COMPACTOR, &tracer); |
| 650 } | 657 } |
| 651 } | 658 } |
| 652 | 659 |
| 653 | 660 |
| 654 #ifdef DEBUG | 661 #ifdef VERIFY_HEAP |
| 655 // Helper class for verifying the symbol table. | 662 // Helper class for verifying the symbol table. |
| 656 class SymbolTableVerifier : public ObjectVisitor { | 663 class SymbolTableVerifier : public ObjectVisitor { |
| 657 public: | 664 public: |
| 658 void VisitPointers(Object** start, Object** end) { | 665 void VisitPointers(Object** start, Object** end) { |
| 659 // Visit all HeapObject pointers in [start, end). | 666 // Visit all HeapObject pointers in [start, end). |
| 660 for (Object** p = start; p < end; p++) { | 667 for (Object** p = start; p < end; p++) { |
| 661 if ((*p)->IsHeapObject()) { | 668 if ((*p)->IsHeapObject()) { |
| 662 // Check that the symbol is actually a symbol. | 669 // Check that the symbol is actually a symbol. |
| 663 ASSERT((*p)->IsTheHole() || (*p)->IsUndefined() || (*p)->IsSymbol()); | 670 CHECK((*p)->IsTheHole() || (*p)->IsUndefined() || (*p)->IsSymbol()); |
| 664 } | 671 } |
| 665 } | 672 } |
| 666 } | 673 } |
| 667 }; | 674 }; |
| 668 #endif // DEBUG | |
| 669 | 675 |
| 670 | 676 |
| 671 static void VerifySymbolTable() { | 677 static void VerifySymbolTable() { |
| 672 #ifdef DEBUG | |
| 673 SymbolTableVerifier verifier; | 678 SymbolTableVerifier verifier; |
| 674 HEAP->symbol_table()->IterateElements(&verifier); | 679 HEAP->symbol_table()->IterateElements(&verifier); |
| 675 #endif // DEBUG | |
| 676 } | 680 } |
| 681 #endif // VERIFY_HEAP |
| 677 | 682 |
| 678 | 683 |
| 679 static bool AbortIncrementalMarkingAndCollectGarbage( | 684 static bool AbortIncrementalMarkingAndCollectGarbage( |
| 680 Heap* heap, | 685 Heap* heap, |
| 681 AllocationSpace space, | 686 AllocationSpace space, |
| 682 const char* gc_reason = NULL) { | 687 const char* gc_reason = NULL) { |
| 683 heap->mark_compact_collector()->SetFlags(Heap::kAbortIncrementalMarkingMask); | 688 heap->mark_compact_collector()->SetFlags(Heap::kAbortIncrementalMarkingMask); |
| 684 bool result = heap->CollectGarbage(space, gc_reason); | 689 bool result = heap->CollectGarbage(space, gc_reason); |
| 685 heap->mark_compact_collector()->SetFlags(Heap::kNoGCFlags); | 690 heap->mark_compact_collector()->SetFlags(Heap::kNoGCFlags); |
| 686 return result; | 691 return result; |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 823 } | 828 } |
| 824 | 829 |
| 825 bool Heap::PerformGarbageCollection(GarbageCollector collector, | 830 bool Heap::PerformGarbageCollection(GarbageCollector collector, |
| 826 GCTracer* tracer) { | 831 GCTracer* tracer) { |
| 827 bool next_gc_likely_to_collect_more = false; | 832 bool next_gc_likely_to_collect_more = false; |
| 828 | 833 |
| 829 if (collector != SCAVENGER) { | 834 if (collector != SCAVENGER) { |
| 830 PROFILE(isolate_, CodeMovingGCEvent()); | 835 PROFILE(isolate_, CodeMovingGCEvent()); |
| 831 } | 836 } |
| 832 | 837 |
| 838 #ifdef VERIFY_HEAP |
| 833 if (FLAG_verify_heap) { | 839 if (FLAG_verify_heap) { |
| 834 VerifySymbolTable(); | 840 VerifySymbolTable(); |
| 835 } | 841 } |
| 842 #endif |
| 843 |
| 836 if (collector == MARK_COMPACTOR && global_gc_prologue_callback_) { | 844 if (collector == MARK_COMPACTOR && global_gc_prologue_callback_) { |
| 837 ASSERT(!allocation_allowed_); | 845 ASSERT(!allocation_allowed_); |
| 838 GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL); | 846 GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL); |
| 839 global_gc_prologue_callback_(); | 847 global_gc_prologue_callback_(); |
| 840 } | 848 } |
| 841 | 849 |
| 842 GCType gc_type = | 850 GCType gc_type = |
| 843 collector == MARK_COMPACTOR ? kGCTypeMarkSweepCompact : kGCTypeScavenge; | 851 collector == MARK_COMPACTOR ? kGCTypeMarkSweepCompact : kGCTypeScavenge; |
| 844 | 852 |
| 845 for (int i = 0; i < gc_prologue_callbacks_.length(); ++i) { | 853 for (int i = 0; i < gc_prologue_callbacks_.length(); ++i) { |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 952 if (gc_type & gc_epilogue_callbacks_[i].gc_type) { | 960 if (gc_type & gc_epilogue_callbacks_[i].gc_type) { |
| 953 gc_epilogue_callbacks_[i].callback(gc_type, callback_flags); | 961 gc_epilogue_callbacks_[i].callback(gc_type, callback_flags); |
| 954 } | 962 } |
| 955 } | 963 } |
| 956 | 964 |
| 957 if (collector == MARK_COMPACTOR && global_gc_epilogue_callback_) { | 965 if (collector == MARK_COMPACTOR && global_gc_epilogue_callback_) { |
| 958 ASSERT(!allocation_allowed_); | 966 ASSERT(!allocation_allowed_); |
| 959 GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL); | 967 GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL); |
| 960 global_gc_epilogue_callback_(); | 968 global_gc_epilogue_callback_(); |
| 961 } | 969 } |
| 970 |
| 971 #ifdef VERIFY_HEAP |
| 962 if (FLAG_verify_heap) { | 972 if (FLAG_verify_heap) { |
| 963 VerifySymbolTable(); | 973 VerifySymbolTable(); |
| 964 } | 974 } |
| 975 #endif |
| 965 | 976 |
| 966 return next_gc_likely_to_collect_more; | 977 return next_gc_likely_to_collect_more; |
| 967 } | 978 } |
| 968 | 979 |
| 969 | 980 |
| 970 void Heap::MarkCompact(GCTracer* tracer) { | 981 void Heap::MarkCompact(GCTracer* tracer) { |
| 971 gc_state_ = MARK_COMPACT; | 982 gc_state_ = MARK_COMPACT; |
| 972 LOG(isolate_, ResourceEvent("markcompact", "begin")); | 983 LOG(isolate_, ResourceEvent("markcompact", "begin")); |
| 973 | 984 |
| 974 mark_compact_collector_.Prepare(tracer); | 985 mark_compact_collector_.Prepare(tracer); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1037 Object* object = *p; | 1048 Object* object = *p; |
| 1038 if (!heap_->InNewSpace(object)) return; | 1049 if (!heap_->InNewSpace(object)) return; |
| 1039 Heap::ScavengeObject(reinterpret_cast<HeapObject**>(p), | 1050 Heap::ScavengeObject(reinterpret_cast<HeapObject**>(p), |
| 1040 reinterpret_cast<HeapObject*>(object)); | 1051 reinterpret_cast<HeapObject*>(object)); |
| 1041 } | 1052 } |
| 1042 | 1053 |
| 1043 Heap* heap_; | 1054 Heap* heap_; |
| 1044 }; | 1055 }; |
| 1045 | 1056 |
| 1046 | 1057 |
| 1047 #ifdef DEBUG | 1058 #ifdef VERIFY_HEAP |
| 1048 // Visitor class to verify pointers in code or data space do not point into | 1059 // Visitor class to verify pointers in code or data space do not point into |
| 1049 // new space. | 1060 // new space. |
| 1050 class VerifyNonPointerSpacePointersVisitor: public ObjectVisitor { | 1061 class VerifyNonPointerSpacePointersVisitor: public ObjectVisitor { |
| 1051 public: | 1062 public: |
| 1052 void VisitPointers(Object** start, Object**end) { | 1063 void VisitPointers(Object** start, Object**end) { |
| 1053 for (Object** current = start; current < end; current++) { | 1064 for (Object** current = start; current < end; current++) { |
| 1054 if ((*current)->IsHeapObject()) { | 1065 if ((*current)->IsHeapObject()) { |
| 1055 ASSERT(!HEAP->InNewSpace(HeapObject::cast(*current))); | 1066 CHECK(!HEAP->InNewSpace(HeapObject::cast(*current))); |
| 1056 } | 1067 } |
| 1057 } | 1068 } |
| 1058 } | 1069 } |
| 1059 }; | 1070 }; |
| 1060 | 1071 |
| 1061 | 1072 |
| 1062 static void VerifyNonPointerSpacePointers() { | 1073 static void VerifyNonPointerSpacePointers() { |
| 1063 // Verify that there are no pointers to new space in spaces where we | 1074 // Verify that there are no pointers to new space in spaces where we |
| 1064 // do not expect them. | 1075 // do not expect them. |
| 1065 VerifyNonPointerSpacePointersVisitor v; | 1076 VerifyNonPointerSpacePointersVisitor v; |
| 1066 HeapObjectIterator code_it(HEAP->code_space()); | 1077 HeapObjectIterator code_it(HEAP->code_space()); |
| 1067 for (HeapObject* object = code_it.Next(); | 1078 for (HeapObject* object = code_it.Next(); |
| 1068 object != NULL; object = code_it.Next()) | 1079 object != NULL; object = code_it.Next()) |
| 1069 object->Iterate(&v); | 1080 object->Iterate(&v); |
| 1070 | 1081 |
| 1071 // The old data space was normally swept conservatively so that the iterator | 1082 // The old data space was normally swept conservatively so that the iterator |
| 1072 // doesn't work, so we normally skip the next bit. | 1083 // doesn't work, so we normally skip the next bit. |
| 1073 if (!HEAP->old_data_space()->was_swept_conservatively()) { | 1084 if (!HEAP->old_data_space()->was_swept_conservatively()) { |
| 1074 HeapObjectIterator data_it(HEAP->old_data_space()); | 1085 HeapObjectIterator data_it(HEAP->old_data_space()); |
| 1075 for (HeapObject* object = data_it.Next(); | 1086 for (HeapObject* object = data_it.Next(); |
| 1076 object != NULL; object = data_it.Next()) | 1087 object != NULL; object = data_it.Next()) |
| 1077 object->Iterate(&v); | 1088 object->Iterate(&v); |
| 1078 } | 1089 } |
| 1079 } | 1090 } |
| 1080 #endif | 1091 #endif // VERIFY_HEAP |
| 1081 | 1092 |
| 1082 | 1093 |
| 1083 void Heap::CheckNewSpaceExpansionCriteria() { | 1094 void Heap::CheckNewSpaceExpansionCriteria() { |
| 1084 if (new_space_.Capacity() < new_space_.MaximumCapacity() && | 1095 if (new_space_.Capacity() < new_space_.MaximumCapacity() && |
| 1085 survived_since_last_expansion_ > new_space_.Capacity() && | 1096 survived_since_last_expansion_ > new_space_.Capacity() && |
| 1086 !new_space_high_promotion_mode_active_) { | 1097 !new_space_high_promotion_mode_active_) { |
| 1087 // Grow the size of new space if there is room to grow, enough data | 1098 // Grow the size of new space if there is room to grow, enough data |
| 1088 // has survived scavenge since the last expansion and we are not in | 1099 // has survived scavenge since the last expansion and we are not in |
| 1089 // high promotion mode. | 1100 // high promotion mode. |
| 1090 new_space_.Grow(); | 1101 new_space_.Grow(); |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1209 return NULL; | 1220 return NULL; |
| 1210 } | 1221 } |
| 1211 | 1222 |
| 1212 private: | 1223 private: |
| 1213 Heap* heap_; | 1224 Heap* heap_; |
| 1214 }; | 1225 }; |
| 1215 | 1226 |
| 1216 | 1227 |
| 1217 void Heap::Scavenge() { | 1228 void Heap::Scavenge() { |
| 1218 RelocationLock relocation_lock(this); | 1229 RelocationLock relocation_lock(this); |
| 1219 #ifdef DEBUG | 1230 |
| 1231 #ifdef VERIFY_HEAP |
| 1220 if (FLAG_verify_heap) VerifyNonPointerSpacePointers(); | 1232 if (FLAG_verify_heap) VerifyNonPointerSpacePointers(); |
| 1221 #endif | 1233 #endif |
| 1222 | 1234 |
| 1223 gc_state_ = SCAVENGE; | 1235 gc_state_ = SCAVENGE; |
| 1224 | 1236 |
| 1225 // Implements Cheney's copying algorithm | 1237 // Implements Cheney's copying algorithm |
| 1226 LOG(isolate_, ResourceEvent("scavenge", "begin")); | 1238 LOG(isolate_, ResourceEvent("scavenge", "begin")); |
| 1227 | 1239 |
| 1228 // Clear descriptor cache. | 1240 // Clear descriptor cache. |
| 1229 isolate_->descriptor_lookup_cache()->Clear(); | 1241 isolate_->descriptor_lookup_cache()->Clear(); |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1346 return NULL; | 1358 return NULL; |
| 1347 } | 1359 } |
| 1348 | 1360 |
| 1349 // String is still reachable. | 1361 // String is still reachable. |
| 1350 return String::cast(first_word.ToForwardingAddress()); | 1362 return String::cast(first_word.ToForwardingAddress()); |
| 1351 } | 1363 } |
| 1352 | 1364 |
| 1353 | 1365 |
| 1354 void Heap::UpdateNewSpaceReferencesInExternalStringTable( | 1366 void Heap::UpdateNewSpaceReferencesInExternalStringTable( |
| 1355 ExternalStringTableUpdaterCallback updater_func) { | 1367 ExternalStringTableUpdaterCallback updater_func) { |
| 1368 #ifdef VERIFY_HEAP |
| 1356 if (FLAG_verify_heap) { | 1369 if (FLAG_verify_heap) { |
| 1357 external_string_table_.Verify(); | 1370 external_string_table_.Verify(); |
| 1358 } | 1371 } |
| 1372 #endif |
| 1359 | 1373 |
| 1360 if (external_string_table_.new_space_strings_.is_empty()) return; | 1374 if (external_string_table_.new_space_strings_.is_empty()) return; |
| 1361 | 1375 |
| 1362 Object** start = &external_string_table_.new_space_strings_[0]; | 1376 Object** start = &external_string_table_.new_space_strings_[0]; |
| 1363 Object** end = start + external_string_table_.new_space_strings_.length(); | 1377 Object** end = start + external_string_table_.new_space_strings_.length(); |
| 1364 Object** last = start; | 1378 Object** last = start; |
| 1365 | 1379 |
| 1366 for (Object** p = start; p < end; ++p) { | 1380 for (Object** p = start; p < end; ++p) { |
| 1367 ASSERT(InFromSpace(*p)); | 1381 ASSERT(InFromSpace(*p)); |
| 1368 String* target = updater_func(this, p); | 1382 String* target = updater_func(this, p); |
| (...skipping 2002 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3371 String::WriteToFlat(buffer, dest, start, end); | 3385 String::WriteToFlat(buffer, dest, start, end); |
| 3372 } else { | 3386 } else { |
| 3373 ASSERT(string_result->IsTwoByteRepresentation()); | 3387 ASSERT(string_result->IsTwoByteRepresentation()); |
| 3374 uc16* dest = SeqTwoByteString::cast(string_result)->GetChars(); | 3388 uc16* dest = SeqTwoByteString::cast(string_result)->GetChars(); |
| 3375 String::WriteToFlat(buffer, dest, start, end); | 3389 String::WriteToFlat(buffer, dest, start, end); |
| 3376 } | 3390 } |
| 3377 return result; | 3391 return result; |
| 3378 } | 3392 } |
| 3379 | 3393 |
| 3380 ASSERT(buffer->IsFlat()); | 3394 ASSERT(buffer->IsFlat()); |
| 3381 #if DEBUG | 3395 #if VERIFY_HEAP |
| 3382 if (FLAG_verify_heap) { | 3396 if (FLAG_verify_heap) { |
| 3383 buffer->StringVerify(); | 3397 buffer->StringVerify(); |
| 3384 } | 3398 } |
| 3385 #endif | 3399 #endif |
| 3386 | 3400 |
| 3387 Object* result; | 3401 Object* result; |
| 3388 // When slicing an indirect string we use its encoding for a newly created | 3402 // When slicing an indirect string we use its encoding for a newly created |
| 3389 // slice and don't check the encoding of the underlying string. This is safe | 3403 // slice and don't check the encoding of the underlying string. This is safe |
| 3390 // even if the encodings are different because of externalization. If an | 3404 // even if the encodings are different because of externalization. If an |
| 3391 // indirect ASCII string is pointing to a two-byte string, the two-byte char | 3405 // indirect ASCII string is pointing to a two-byte string, the two-byte char |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3635 if (!self_reference.is_null()) { | 3649 if (!self_reference.is_null()) { |
| 3636 *(self_reference.location()) = code; | 3650 *(self_reference.location()) = code; |
| 3637 } | 3651 } |
| 3638 // Migrate generated code. | 3652 // Migrate generated code. |
| 3639 // The generated code can contain Object** values (typically from handles) | 3653 // The generated code can contain Object** values (typically from handles) |
| 3640 // that are dereferenced during the copy to point directly to the actual heap | 3654 // that are dereferenced during the copy to point directly to the actual heap |
| 3641 // objects. These pointers can include references to the code object itself, | 3655 // objects. These pointers can include references to the code object itself, |
| 3642 // through the self_reference parameter. | 3656 // through the self_reference parameter. |
| 3643 code->CopyFrom(desc); | 3657 code->CopyFrom(desc); |
| 3644 | 3658 |
| 3645 #ifdef DEBUG | 3659 #ifdef VERIFY_HEAP |
| 3646 if (FLAG_verify_heap) { | 3660 if (FLAG_verify_heap) { |
| 3647 code->Verify(); | 3661 code->Verify(); |
| 3648 } | 3662 } |
| 3649 #endif | 3663 #endif |
| 3650 return code; | 3664 return code; |
| 3651 } | 3665 } |
| 3652 | 3666 |
| 3653 | 3667 |
| 3654 MaybeObject* Heap::CopyCode(Code* code) { | 3668 MaybeObject* Heap::CopyCode(Code* code) { |
| 3655 // Allocate an object the same size as the code object. | 3669 // Allocate an object the same size as the code object. |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3717 new_code->set_relocation_info(ByteArray::cast(reloc_info_array)); | 3731 new_code->set_relocation_info(ByteArray::cast(reloc_info_array)); |
| 3718 | 3732 |
| 3719 // Copy patched rinfo. | 3733 // Copy patched rinfo. |
| 3720 memcpy(new_code->relocation_start(), reloc_info.start(), reloc_info.length()); | 3734 memcpy(new_code->relocation_start(), reloc_info.start(), reloc_info.length()); |
| 3721 | 3735 |
| 3722 // Relocate the copy. | 3736 // Relocate the copy. |
| 3723 ASSERT(!isolate_->code_range()->exists() || | 3737 ASSERT(!isolate_->code_range()->exists() || |
| 3724 isolate_->code_range()->contains(code->address())); | 3738 isolate_->code_range()->contains(code->address())); |
| 3725 new_code->Relocate(new_addr - old_addr); | 3739 new_code->Relocate(new_addr - old_addr); |
| 3726 | 3740 |
| 3727 #ifdef DEBUG | 3741 #ifdef VERIFY_HEAP |
| 3728 if (FLAG_verify_heap) { | 3742 if (FLAG_verify_heap) { |
| 3729 code->Verify(); | 3743 code->Verify(); |
| 3730 } | 3744 } |
| 3731 #endif | 3745 #endif |
| 3732 return new_code; | 3746 return new_code; |
| 3733 } | 3747 } |
| 3734 | 3748 |
| 3735 | 3749 |
| 3736 MaybeObject* Heap::Allocate(Map* map, AllocationSpace space) { | 3750 MaybeObject* Heap::Allocate(Map* map, AllocationSpace space) { |
| 3737 ASSERT(gc_state_ == NOT_IN_GC); | 3751 ASSERT(gc_state_ == NOT_IN_GC); |
| (...skipping 852 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4590 { MaybeObject* maybe_result = AllocateRaw(size, space, retry_space); | 4604 { MaybeObject* maybe_result = AllocateRaw(size, space, retry_space); |
| 4591 if (!maybe_result->ToObject(&result)) return maybe_result; | 4605 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 4592 } | 4606 } |
| 4593 | 4607 |
| 4594 // Partially initialize the object. | 4608 // Partially initialize the object. |
| 4595 HeapObject::cast(result)->set_map_no_write_barrier(ascii_string_map()); | 4609 HeapObject::cast(result)->set_map_no_write_barrier(ascii_string_map()); |
| 4596 String::cast(result)->set_length(length); | 4610 String::cast(result)->set_length(length); |
| 4597 String::cast(result)->set_hash_field(String::kEmptyHashField); | 4611 String::cast(result)->set_hash_field(String::kEmptyHashField); |
| 4598 ASSERT_EQ(size, HeapObject::cast(result)->Size()); | 4612 ASSERT_EQ(size, HeapObject::cast(result)->Size()); |
| 4599 | 4613 |
| 4600 #ifdef DEBUG | 4614 #ifdef VERIFY_HEAP |
| 4601 if (FLAG_verify_heap) { | 4615 if (FLAG_verify_heap) { |
| 4602 // Initialize string's content to ensure ASCII-ness (character range 0-127) | 4616 // Initialize string's content to ensure ASCII-ness (character range 0-127) |
| 4603 // as required when verifying the heap. | 4617 // as required when verifying the heap. |
| 4604 char* dest = SeqAsciiString::cast(result)->GetChars(); | 4618 char* dest = SeqAsciiString::cast(result)->GetChars(); |
| 4605 memset(dest, 0x0F, length * kCharSize); | 4619 memset(dest, 0x0F, length * kCharSize); |
| 4606 } | 4620 } |
| 4607 #endif // DEBUG | 4621 #endif |
| 4608 | 4622 |
| 4609 return result; | 4623 return result; |
| 4610 } | 4624 } |
| 4611 | 4625 |
| 4612 | 4626 |
| 4613 MaybeObject* Heap::AllocateRawTwoByteString(int length, | 4627 MaybeObject* Heap::AllocateRawTwoByteString(int length, |
| 4614 PretenureFlag pretenure) { | 4628 PretenureFlag pretenure) { |
| 4615 if (length < 0 || length > SeqTwoByteString::kMaxLength) { | 4629 if (length < 0 || length > SeqTwoByteString::kMaxLength) { |
| 4616 return Failure::OutOfMemoryException(); | 4630 return Failure::OutOfMemoryException(); |
| 4617 } | 4631 } |
| (...skipping 769 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5387 case CELL_SPACE: | 5401 case CELL_SPACE: |
| 5388 return cell_space_->Contains(addr); | 5402 return cell_space_->Contains(addr); |
| 5389 case LO_SPACE: | 5403 case LO_SPACE: |
| 5390 return lo_space_->SlowContains(addr); | 5404 return lo_space_->SlowContains(addr); |
| 5391 } | 5405 } |
| 5392 | 5406 |
| 5393 return false; | 5407 return false; |
| 5394 } | 5408 } |
| 5395 | 5409 |
| 5396 | 5410 |
| 5397 #ifdef DEBUG | 5411 #ifdef VERIFY_HEAP |
| 5398 void Heap::Verify() { | 5412 void Heap::Verify() { |
| 5399 ASSERT(HasBeenSetUp()); | 5413 CHECK(HasBeenSetUp()); |
| 5400 | 5414 |
| 5401 store_buffer()->Verify(); | 5415 store_buffer()->Verify(); |
| 5402 | 5416 |
| 5403 VerifyPointersVisitor visitor; | 5417 VerifyPointersVisitor visitor; |
| 5404 IterateRoots(&visitor, VISIT_ONLY_STRONG); | 5418 IterateRoots(&visitor, VISIT_ONLY_STRONG); |
| 5405 | 5419 |
| 5406 new_space_.Verify(); | 5420 new_space_.Verify(); |
| 5407 | 5421 |
| 5408 old_pointer_space_->Verify(&visitor); | 5422 old_pointer_space_->Verify(&visitor); |
| 5409 map_space_->Verify(&visitor); | 5423 map_space_->Verify(&visitor); |
| 5410 | 5424 |
| 5411 VerifyPointersVisitor no_dirty_regions_visitor; | 5425 VerifyPointersVisitor no_dirty_regions_visitor; |
| 5412 old_data_space_->Verify(&no_dirty_regions_visitor); | 5426 old_data_space_->Verify(&no_dirty_regions_visitor); |
| 5413 code_space_->Verify(&no_dirty_regions_visitor); | 5427 code_space_->Verify(&no_dirty_regions_visitor); |
| 5414 cell_space_->Verify(&no_dirty_regions_visitor); | 5428 cell_space_->Verify(&no_dirty_regions_visitor); |
| 5415 | 5429 |
| 5416 lo_space_->Verify(); | 5430 lo_space_->Verify(); |
| 5417 } | 5431 } |
| 5418 | 5432 #endif |
| 5419 | |
| 5420 #endif // DEBUG | |
| 5421 | 5433 |
| 5422 | 5434 |
| 5423 MaybeObject* Heap::LookupSymbol(Vector<const char> string) { | 5435 MaybeObject* Heap::LookupSymbol(Vector<const char> string) { |
| 5424 Object* symbol = NULL; | 5436 Object* symbol = NULL; |
| 5425 Object* new_table; | 5437 Object* new_table; |
| 5426 { MaybeObject* maybe_new_table = | 5438 { MaybeObject* maybe_new_table = |
| 5427 symbol_table()->LookupSymbol(string, &symbol); | 5439 symbol_table()->LookupSymbol(string, &symbol); |
| 5428 if (!maybe_new_table->ToObject(&new_table)) return maybe_new_table; | 5440 if (!maybe_new_table->ToObject(&new_table)) return maybe_new_table; |
| 5429 } | 5441 } |
| 5430 // Can't use set_symbol_table because SymbolTable::cast knows that | 5442 // Can't use set_symbol_table because SymbolTable::cast knows that |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5502 | 5514 |
| 5503 | 5515 |
| 5504 bool Heap::LookupSymbolIfExists(String* string, String** symbol) { | 5516 bool Heap::LookupSymbolIfExists(String* string, String** symbol) { |
| 5505 if (string->IsSymbol()) { | 5517 if (string->IsSymbol()) { |
| 5506 *symbol = string; | 5518 *symbol = string; |
| 5507 return true; | 5519 return true; |
| 5508 } | 5520 } |
| 5509 return symbol_table()->LookupSymbolIfExists(string, symbol); | 5521 return symbol_table()->LookupSymbolIfExists(string, symbol); |
| 5510 } | 5522 } |
| 5511 | 5523 |
| 5512 | |
| 5513 #ifdef DEBUG | |
| 5514 void Heap::ZapFromSpace() { | 5524 void Heap::ZapFromSpace() { |
| 5515 NewSpacePageIterator it(new_space_.FromSpaceStart(), | 5525 NewSpacePageIterator it(new_space_.FromSpaceStart(), |
| 5516 new_space_.FromSpaceEnd()); | 5526 new_space_.FromSpaceEnd()); |
| 5517 while (it.has_next()) { | 5527 while (it.has_next()) { |
| 5518 NewSpacePage* page = it.next(); | 5528 NewSpacePage* page = it.next(); |
| 5519 for (Address cursor = page->area_start(), limit = page->area_end(); | 5529 for (Address cursor = page->area_start(), limit = page->area_end(); |
| 5520 cursor < limit; | 5530 cursor < limit; |
| 5521 cursor += kPointerSize) { | 5531 cursor += kPointerSize) { |
| 5522 Memory::Address_at(cursor) = kFromSpaceZapValue; | 5532 Memory::Address_at(cursor) = kFromSpaceZapValue; |
| 5523 } | 5533 } |
| 5524 } | 5534 } |
| 5525 } | 5535 } |
| 5526 #endif // DEBUG | |
| 5527 | 5536 |
| 5528 | 5537 |
| 5529 void Heap::IterateAndMarkPointersToFromSpace(Address start, | 5538 void Heap::IterateAndMarkPointersToFromSpace(Address start, |
| 5530 Address end, | 5539 Address end, |
| 5531 ObjectSlotCallback callback) { | 5540 ObjectSlotCallback callback) { |
| 5532 Address slot_address = start; | 5541 Address slot_address = start; |
| 5533 | 5542 |
| 5534 // We are not collecting slots on new space objects during mutation | 5543 // We are not collecting slots on new space objects during mutation |
| 5535 // thus we have to scan for pointers to evacuation candidates when we | 5544 // thus we have to scan for pointers to evacuation candidates when we |
| 5536 // promote objects. But we should not record any slots in non-black | 5545 // promote objects. But we should not record any slots in non-black |
| (...skipping 716 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6253 roots_[kStackLimitRootIndex] = | 6262 roots_[kStackLimitRootIndex] = |
| 6254 reinterpret_cast<Object*>( | 6263 reinterpret_cast<Object*>( |
| 6255 (isolate_->stack_guard()->jslimit() & ~kSmiTagMask) | kSmiTag); | 6264 (isolate_->stack_guard()->jslimit() & ~kSmiTagMask) | kSmiTag); |
| 6256 roots_[kRealStackLimitRootIndex] = | 6265 roots_[kRealStackLimitRootIndex] = |
| 6257 reinterpret_cast<Object*>( | 6266 reinterpret_cast<Object*>( |
| 6258 (isolate_->stack_guard()->real_jslimit() & ~kSmiTagMask) | kSmiTag); | 6267 (isolate_->stack_guard()->real_jslimit() & ~kSmiTagMask) | kSmiTag); |
| 6259 } | 6268 } |
| 6260 | 6269 |
| 6261 | 6270 |
| 6262 void Heap::TearDown() { | 6271 void Heap::TearDown() { |
| 6263 #ifdef DEBUG | 6272 #ifdef VERIFY_HEAP |
| 6264 if (FLAG_verify_heap) { | 6273 if (FLAG_verify_heap) { |
| 6265 Verify(); | 6274 Verify(); |
| 6266 } | 6275 } |
| 6267 #endif | 6276 #endif |
| 6277 |
| 6268 if (FLAG_print_cumulative_gc_stat) { | 6278 if (FLAG_print_cumulative_gc_stat) { |
| 6269 PrintF("\n\n"); | 6279 PrintF("\n\n"); |
| 6270 PrintF("gc_count=%d ", gc_count_); | 6280 PrintF("gc_count=%d ", gc_count_); |
| 6271 PrintF("mark_sweep_count=%d ", ms_count_); | 6281 PrintF("mark_sweep_count=%d ", ms_count_); |
| 6272 PrintF("max_gc_pause=%d ", get_max_gc_pause()); | 6282 PrintF("max_gc_pause=%d ", get_max_gc_pause()); |
| 6273 PrintF("total_gc_time=%d ", total_gc_time_ms_); | 6283 PrintF("total_gc_time=%d ", total_gc_time_ms_); |
| 6274 PrintF("min_in_mutator=%d ", get_min_in_mutator()); | 6284 PrintF("min_in_mutator=%d ", get_min_in_mutator()); |
| 6275 PrintF("max_alive_after_gc=%" V8_PTR_PREFIX "d ", | 6285 PrintF("max_alive_after_gc=%" V8_PTR_PREFIX "d ", |
| 6276 get_max_alive_after_gc()); | 6286 get_max_alive_after_gc()); |
| 6277 PrintF("\n\n"); | 6287 PrintF("\n\n"); |
| (...skipping 909 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7187 new_space_strings_.Rewind(last); | 7197 new_space_strings_.Rewind(last); |
| 7188 last = 0; | 7198 last = 0; |
| 7189 for (int i = 0; i < old_space_strings_.length(); ++i) { | 7199 for (int i = 0; i < old_space_strings_.length(); ++i) { |
| 7190 if (old_space_strings_[i] == heap_->raw_unchecked_the_hole_value()) { | 7200 if (old_space_strings_[i] == heap_->raw_unchecked_the_hole_value()) { |
| 7191 continue; | 7201 continue; |
| 7192 } | 7202 } |
| 7193 ASSERT(!heap_->InNewSpace(old_space_strings_[i])); | 7203 ASSERT(!heap_->InNewSpace(old_space_strings_[i])); |
| 7194 old_space_strings_[last++] = old_space_strings_[i]; | 7204 old_space_strings_[last++] = old_space_strings_[i]; |
| 7195 } | 7205 } |
| 7196 old_space_strings_.Rewind(last); | 7206 old_space_strings_.Rewind(last); |
| 7207 #ifdef VERIFY_HEAP |
| 7197 if (FLAG_verify_heap) { | 7208 if (FLAG_verify_heap) { |
| 7198 Verify(); | 7209 Verify(); |
| 7199 } | 7210 } |
| 7211 #endif |
| 7200 } | 7212 } |
| 7201 | 7213 |
| 7202 | 7214 |
| 7203 void ExternalStringTable::TearDown() { | 7215 void ExternalStringTable::TearDown() { |
| 7204 new_space_strings_.Free(); | 7216 new_space_strings_.Free(); |
| 7205 old_space_strings_.Free(); | 7217 old_space_strings_.Free(); |
| 7206 } | 7218 } |
| 7207 | 7219 |
| 7208 | 7220 |
| 7209 void Heap::QueueMemoryChunkForFree(MemoryChunk* chunk) { | 7221 void Heap::QueueMemoryChunkForFree(MemoryChunk* chunk) { |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7327 static_cast<int>(object_sizes_last_time_[index])); | 7339 static_cast<int>(object_sizes_last_time_[index])); |
| 7328 FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(ADJUST_LAST_TIME_OBJECT_COUNT) | 7340 FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(ADJUST_LAST_TIME_OBJECT_COUNT) |
| 7329 #undef ADJUST_LAST_TIME_OBJECT_COUNT | 7341 #undef ADJUST_LAST_TIME_OBJECT_COUNT |
| 7330 | 7342 |
| 7331 memcpy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); | 7343 memcpy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); |
| 7332 memcpy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); | 7344 memcpy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); |
| 7333 ClearObjectStats(); | 7345 ClearObjectStats(); |
| 7334 } | 7346 } |
| 7335 | 7347 |
| 7336 } } // namespace v8::internal | 7348 } } // namespace v8::internal |
| OLD | NEW |