| 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 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 80 // Will be 4 * reserved_semispace_size_ to ensure that young | 80 // Will be 4 * reserved_semispace_size_ to ensure that young |
| 81 // generation can be aligned to its size. | 81 // generation can be aligned to its size. |
| 82 maximum_committed_(0), | 82 maximum_committed_(0), |
| 83 survived_since_last_expansion_(0), | 83 survived_since_last_expansion_(0), |
| 84 sweep_generation_(0), | 84 sweep_generation_(0), |
| 85 always_allocate_scope_depth_(0), | 85 always_allocate_scope_depth_(0), |
| 86 linear_allocation_scope_depth_(0), | 86 linear_allocation_scope_depth_(0), |
| 87 contexts_disposed_(0), | 87 contexts_disposed_(0), |
| 88 global_ic_age_(0), | 88 global_ic_age_(0), |
| 89 flush_monomorphic_ics_(false), | 89 flush_monomorphic_ics_(false), |
| 90 allocation_mementos_found_(0), | |
| 91 scan_on_scavenge_pages_(0), | 90 scan_on_scavenge_pages_(0), |
| 92 new_space_(this), | 91 new_space_(this), |
| 93 old_pointer_space_(NULL), | 92 old_pointer_space_(NULL), |
| 94 old_data_space_(NULL), | 93 old_data_space_(NULL), |
| 95 code_space_(NULL), | 94 code_space_(NULL), |
| 96 map_space_(NULL), | 95 map_space_(NULL), |
| 97 cell_space_(NULL), | 96 cell_space_(NULL), |
| 98 property_cell_space_(NULL), | 97 property_cell_space_(NULL), |
| 99 lo_space_(NULL), | 98 lo_space_(NULL), |
| 100 gc_state_(NOT_IN_GC), | 99 gc_state_(NOT_IN_GC), |
| (...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 499 PagedSpaces spaces(this); | 498 PagedSpaces spaces(this); |
| 500 for (PagedSpace* space = spaces.next(); | 499 for (PagedSpace* space = spaces.next(); |
| 501 space != NULL; | 500 space != NULL; |
| 502 space = spaces.next()) { | 501 space = spaces.next()) { |
| 503 space->RepairFreeListsAfterBoot(); | 502 space->RepairFreeListsAfterBoot(); |
| 504 } | 503 } |
| 505 } | 504 } |
| 506 | 505 |
| 507 | 506 |
| 508 void Heap::GarbageCollectionEpilogue() { | 507 void Heap::GarbageCollectionEpilogue() { |
| 508 if (FLAG_allocation_site_pretenuring) { |
| 509 int tenure_decisions = 0; |
| 510 int dont_tenure_decisions = 0; |
| 511 int allocation_mementos_found = 0; |
| 512 |
| 513 Object* cur = allocation_sites_list(); |
| 514 while (cur->IsAllocationSite()) { |
| 515 AllocationSite* casted = AllocationSite::cast(cur); |
| 516 allocation_mementos_found += casted->memento_found_count()->value(); |
| 517 if (casted->DigestPretenuringFeedback()) { |
| 518 if (casted->GetPretenureMode() == TENURED) { |
| 519 tenure_decisions++; |
| 520 } else { |
| 521 dont_tenure_decisions++; |
| 522 } |
| 523 } |
| 524 cur = casted->weak_next(); |
| 525 } |
| 526 |
| 527 // TODO(mvstanton): Pretenure decisions are only made once for an allocation |
| 528 // site. Find a sane way to decide about revisiting the decision later. |
| 529 |
| 530 if (FLAG_trace_track_allocation_sites && |
| 531 (allocation_mementos_found > 0 || |
| 532 tenure_decisions > 0 || |
| 533 dont_tenure_decisions > 0)) { |
| 534 PrintF("GC: (#mementos, #tenure decisions, #donttenure decisions) " |
| 535 "(%d, %d, %d)\n", |
| 536 allocation_mementos_found, |
| 537 tenure_decisions, |
| 538 dont_tenure_decisions); |
| 539 } |
| 540 } |
| 541 |
| 509 store_buffer()->GCEpilogue(); | 542 store_buffer()->GCEpilogue(); |
| 510 | 543 |
| 511 // In release mode, we only zap the from space under heap verification. | 544 // In release mode, we only zap the from space under heap verification. |
| 512 if (Heap::ShouldZapGarbage()) { | 545 if (Heap::ShouldZapGarbage()) { |
| 513 ZapFromSpace(); | 546 ZapFromSpace(); |
| 514 } | 547 } |
| 515 | 548 |
| 516 #ifdef VERIFY_HEAP | 549 #ifdef VERIFY_HEAP |
| 517 if (FLAG_verify_heap) { | 550 if (FLAG_verify_heap) { |
| 518 Verify(); | 551 Verify(); |
| (...skipping 867 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1386 } | 1419 } |
| 1387 | 1420 |
| 1388 private: | 1421 private: |
| 1389 Heap* heap_; | 1422 Heap* heap_; |
| 1390 }; | 1423 }; |
| 1391 | 1424 |
| 1392 | 1425 |
| 1393 void Heap::Scavenge() { | 1426 void Heap::Scavenge() { |
| 1394 RelocationLock relocation_lock(this); | 1427 RelocationLock relocation_lock(this); |
| 1395 | 1428 |
| 1396 allocation_mementos_found_ = 0; | |
| 1397 | |
| 1398 #ifdef VERIFY_HEAP | 1429 #ifdef VERIFY_HEAP |
| 1399 if (FLAG_verify_heap) VerifyNonPointerSpacePointers(this); | 1430 if (FLAG_verify_heap) VerifyNonPointerSpacePointers(this); |
| 1400 #endif | 1431 #endif |
| 1401 | 1432 |
| 1402 gc_state_ = SCAVENGE; | 1433 gc_state_ = SCAVENGE; |
| 1403 | 1434 |
| 1404 // Implements Cheney's copying algorithm | 1435 // Implements Cheney's copying algorithm |
| 1405 LOG(isolate_, ResourceEvent("scavenge", "begin")); | 1436 LOG(isolate_, ResourceEvent("scavenge", "begin")); |
| 1406 | 1437 |
| 1407 // Clear descriptor cache. | 1438 // Clear descriptor cache. |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1510 &IsUnscavengedHeapObject); | 1541 &IsUnscavengedHeapObject); |
| 1511 isolate_->global_handles()->IterateNewSpaceWeakIndependentRoots( | 1542 isolate_->global_handles()->IterateNewSpaceWeakIndependentRoots( |
| 1512 &scavenge_visitor); | 1543 &scavenge_visitor); |
| 1513 new_space_front = DoScavenge(&scavenge_visitor, new_space_front); | 1544 new_space_front = DoScavenge(&scavenge_visitor, new_space_front); |
| 1514 | 1545 |
| 1515 UpdateNewSpaceReferencesInExternalStringTable( | 1546 UpdateNewSpaceReferencesInExternalStringTable( |
| 1516 &UpdateNewSpaceReferenceInExternalStringTableEntry); | 1547 &UpdateNewSpaceReferenceInExternalStringTableEntry); |
| 1517 | 1548 |
| 1518 promotion_queue_.Destroy(); | 1549 promotion_queue_.Destroy(); |
| 1519 | 1550 |
| 1520 if (!FLAG_watch_ic_patching) { | |
| 1521 isolate()->runtime_profiler()->UpdateSamplesAfterScavenge(); | |
| 1522 } | |
| 1523 incremental_marking()->UpdateMarkingDequeAfterScavenge(); | 1551 incremental_marking()->UpdateMarkingDequeAfterScavenge(); |
| 1524 | 1552 |
| 1525 ScavengeWeakObjectRetainer weak_object_retainer(this); | 1553 ScavengeWeakObjectRetainer weak_object_retainer(this); |
| 1526 ProcessWeakReferences(&weak_object_retainer); | 1554 ProcessWeakReferences(&weak_object_retainer); |
| 1527 | 1555 |
| 1528 ASSERT(new_space_front == new_space_.top()); | 1556 ASSERT(new_space_front == new_space_.top()); |
| 1529 | 1557 |
| 1530 // Set age mark. | 1558 // Set age mark. |
| 1531 new_space_.set_age_mark(new_space_.top()); | 1559 new_space_.set_age_mark(new_space_.top()); |
| 1532 | 1560 |
| 1533 new_space_.LowerInlineAllocationLimit( | 1561 new_space_.LowerInlineAllocationLimit( |
| 1534 new_space_.inline_allocation_limit_step()); | 1562 new_space_.inline_allocation_limit_step()); |
| 1535 | 1563 |
| 1536 // Update how much has survived scavenge. | 1564 // Update how much has survived scavenge. |
| 1537 IncrementYoungSurvivorsCounter(static_cast<int>( | 1565 IncrementYoungSurvivorsCounter(static_cast<int>( |
| 1538 (PromotedSpaceSizeOfObjects() - survived_watermark) + new_space_.Size())); | 1566 (PromotedSpaceSizeOfObjects() - survived_watermark) + new_space_.Size())); |
| 1539 | 1567 |
| 1540 LOG(isolate_, ResourceEvent("scavenge", "end")); | 1568 LOG(isolate_, ResourceEvent("scavenge", "end")); |
| 1541 | 1569 |
| 1542 gc_state_ = NOT_IN_GC; | 1570 gc_state_ = NOT_IN_GC; |
| 1543 | 1571 |
| 1544 scavenges_since_last_idle_round_++; | 1572 scavenges_since_last_idle_round_++; |
| 1545 | |
| 1546 if (FLAG_trace_track_allocation_sites && allocation_mementos_found_ > 0) { | |
| 1547 PrintF("AllocationMementos found during scavenge = %d\n", | |
| 1548 allocation_mementos_found_); | |
| 1549 } | |
| 1550 } | 1573 } |
| 1551 | 1574 |
| 1552 | 1575 |
| 1553 String* Heap::UpdateNewSpaceReferenceInExternalStringTableEntry(Heap* heap, | 1576 String* Heap::UpdateNewSpaceReferenceInExternalStringTableEntry(Heap* heap, |
| 1554 Object** p) { | 1577 Object** p) { |
| 1555 MapWord first_word = HeapObject::cast(*p)->map_word(); | 1578 MapWord first_word = HeapObject::cast(*p)->map_word(); |
| 1556 | 1579 |
| 1557 if (!first_word.IsForwardingAddress()) { | 1580 if (!first_word.IsForwardingAddress()) { |
| 1558 // Unreachable external string can be finalized. | 1581 // Unreachable external string can be finalized. |
| 1559 heap->FinalizeExternalString(String::cast(*p)); | 1582 heap->FinalizeExternalString(String::cast(*p)); |
| (...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1908 Object* allocation_site_obj = | 1931 Object* allocation_site_obj = |
| 1909 VisitWeakList<AllocationSite>(this, | 1932 VisitWeakList<AllocationSite>(this, |
| 1910 allocation_sites_list(), | 1933 allocation_sites_list(), |
| 1911 retainer, record_slots); | 1934 retainer, record_slots); |
| 1912 set_allocation_sites_list(allocation_site_obj); | 1935 set_allocation_sites_list(allocation_site_obj); |
| 1913 } | 1936 } |
| 1914 | 1937 |
| 1915 | 1938 |
| 1916 void Heap::VisitExternalResources(v8::ExternalResourceVisitor* visitor) { | 1939 void Heap::VisitExternalResources(v8::ExternalResourceVisitor* visitor) { |
| 1917 DisallowHeapAllocation no_allocation; | 1940 DisallowHeapAllocation no_allocation; |
| 1918 | 1941 // All external strings are listed in the external string table. |
| 1919 // Both the external string table and the string table may contain | |
| 1920 // external strings, but neither lists them exhaustively, nor is the | |
| 1921 // intersection set empty. Therefore we iterate over the external string | |
| 1922 // table first, ignoring internalized strings, and then over the | |
| 1923 // internalized string table. | |
| 1924 | 1942 |
| 1925 class ExternalStringTableVisitorAdapter : public ObjectVisitor { | 1943 class ExternalStringTableVisitorAdapter : public ObjectVisitor { |
| 1926 public: | 1944 public: |
| 1927 explicit ExternalStringTableVisitorAdapter( | 1945 explicit ExternalStringTableVisitorAdapter( |
| 1928 v8::ExternalResourceVisitor* visitor) : visitor_(visitor) {} | 1946 v8::ExternalResourceVisitor* visitor) : visitor_(visitor) {} |
| 1929 virtual void VisitPointers(Object** start, Object** end) { | 1947 virtual void VisitPointers(Object** start, Object** end) { |
| 1930 for (Object** p = start; p < end; p++) { | 1948 for (Object** p = start; p < end; p++) { |
| 1931 // Visit non-internalized external strings, | 1949 ASSERT((*p)->IsExternalString()); |
| 1932 // since internalized strings are listed in the string table. | 1950 visitor_->VisitExternalString(Utils::ToLocal( |
| 1933 if (!(*p)->IsInternalizedString()) { | 1951 Handle<String>(String::cast(*p)))); |
| 1934 ASSERT((*p)->IsExternalString()); | |
| 1935 visitor_->VisitExternalString(Utils::ToLocal( | |
| 1936 Handle<String>(String::cast(*p)))); | |
| 1937 } | |
| 1938 } | 1952 } |
| 1939 } | 1953 } |
| 1940 private: | 1954 private: |
| 1941 v8::ExternalResourceVisitor* visitor_; | 1955 v8::ExternalResourceVisitor* visitor_; |
| 1942 } external_string_table_visitor(visitor); | 1956 } external_string_table_visitor(visitor); |
| 1943 | 1957 |
| 1944 external_string_table_.Iterate(&external_string_table_visitor); | 1958 external_string_table_.Iterate(&external_string_table_visitor); |
| 1945 | |
| 1946 class StringTableVisitorAdapter : public ObjectVisitor { | |
| 1947 public: | |
| 1948 explicit StringTableVisitorAdapter( | |
| 1949 v8::ExternalResourceVisitor* visitor) : visitor_(visitor) {} | |
| 1950 virtual void VisitPointers(Object** start, Object** end) { | |
| 1951 for (Object** p = start; p < end; p++) { | |
| 1952 if ((*p)->IsExternalString()) { | |
| 1953 ASSERT((*p)->IsInternalizedString()); | |
| 1954 visitor_->VisitExternalString(Utils::ToLocal( | |
| 1955 Handle<String>(String::cast(*p)))); | |
| 1956 } | |
| 1957 } | |
| 1958 } | |
| 1959 private: | |
| 1960 v8::ExternalResourceVisitor* visitor_; | |
| 1961 } string_table_visitor(visitor); | |
| 1962 | |
| 1963 string_table()->IterateElements(&string_table_visitor); | |
| 1964 } | 1959 } |
| 1965 | 1960 |
| 1966 | 1961 |
| 1967 class NewSpaceScavenger : public StaticNewSpaceVisitor<NewSpaceScavenger> { | 1962 class NewSpaceScavenger : public StaticNewSpaceVisitor<NewSpaceScavenger> { |
| 1968 public: | 1963 public: |
| 1969 static inline void VisitPointer(Heap* heap, Object** p) { | 1964 static inline void VisitPointer(Heap* heap, Object** p) { |
| 1970 Object* object = *p; | 1965 Object* object = *p; |
| 1971 if (!heap->InNewSpace(object)) return; | 1966 if (!heap->InNewSpace(object)) return; |
| 1972 Heap::ScavengeObject(reinterpret_cast<HeapObject**>(p), | 1967 Heap::ScavengeObject(reinterpret_cast<HeapObject**>(p), |
| 1973 reinterpret_cast<HeapObject*>(object)); | 1968 reinterpret_cast<HeapObject*>(object)); |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2163 heap->CopyBlock(target->address(), source->address(), size); | 2158 heap->CopyBlock(target->address(), source->address(), size); |
| 2164 | 2159 |
| 2165 // Set the forwarding address. | 2160 // Set the forwarding address. |
| 2166 source->set_map_word(MapWord::FromForwardingAddress(target)); | 2161 source->set_map_word(MapWord::FromForwardingAddress(target)); |
| 2167 | 2162 |
| 2168 if (logging_and_profiling_mode == LOGGING_AND_PROFILING_ENABLED) { | 2163 if (logging_and_profiling_mode == LOGGING_AND_PROFILING_ENABLED) { |
| 2169 // Update NewSpace stats if necessary. | 2164 // Update NewSpace stats if necessary. |
| 2170 RecordCopiedObject(heap, target); | 2165 RecordCopiedObject(heap, target); |
| 2171 Isolate* isolate = heap->isolate(); | 2166 Isolate* isolate = heap->isolate(); |
| 2172 HeapProfiler* heap_profiler = isolate->heap_profiler(); | 2167 HeapProfiler* heap_profiler = isolate->heap_profiler(); |
| 2173 if (heap_profiler->is_profiling()) { | 2168 if (heap_profiler->is_tracking_object_moves()) { |
| 2174 heap_profiler->ObjectMoveEvent(source->address(), target->address(), | 2169 heap_profiler->ObjectMoveEvent(source->address(), target->address(), |
| 2175 size); | 2170 size); |
| 2176 } | 2171 } |
| 2177 if (isolate->logger()->is_logging_code_events() || | 2172 if (isolate->logger()->is_logging_code_events() || |
| 2178 isolate->cpu_profiler()->is_profiling()) { | 2173 isolate->cpu_profiler()->is_profiling()) { |
| 2179 if (target->IsSharedFunctionInfo()) { | 2174 if (target->IsSharedFunctionInfo()) { |
| 2180 PROFILE(isolate, SharedFunctionInfoMoveEvent( | 2175 PROFILE(isolate, SharedFunctionInfoMoveEvent( |
| 2181 source->address(), target->address())); | 2176 source->address(), target->address())); |
| 2182 } | 2177 } |
| 2183 } | 2178 } |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2414 LOGGING_AND_PROFILING_ENABLED>::Initialize(); | 2409 LOGGING_AND_PROFILING_ENABLED>::Initialize(); |
| 2415 ScavengingVisitor<IGNORE_MARKS, LOGGING_AND_PROFILING_ENABLED>::Initialize(); | 2410 ScavengingVisitor<IGNORE_MARKS, LOGGING_AND_PROFILING_ENABLED>::Initialize(); |
| 2416 } | 2411 } |
| 2417 | 2412 |
| 2418 | 2413 |
| 2419 void Heap::SelectScavengingVisitorsTable() { | 2414 void Heap::SelectScavengingVisitorsTable() { |
| 2420 bool logging_and_profiling = | 2415 bool logging_and_profiling = |
| 2421 isolate()->logger()->is_logging() || | 2416 isolate()->logger()->is_logging() || |
| 2422 isolate()->cpu_profiler()->is_profiling() || | 2417 isolate()->cpu_profiler()->is_profiling() || |
| 2423 (isolate()->heap_profiler() != NULL && | 2418 (isolate()->heap_profiler() != NULL && |
| 2424 isolate()->heap_profiler()->is_profiling()); | 2419 isolate()->heap_profiler()->is_tracking_object_moves()); |
| 2425 | 2420 |
| 2426 if (!incremental_marking()->IsMarking()) { | 2421 if (!incremental_marking()->IsMarking()) { |
| 2427 if (!logging_and_profiling) { | 2422 if (!logging_and_profiling) { |
| 2428 scavenging_visitors_table_.CopyFrom( | 2423 scavenging_visitors_table_.CopyFrom( |
| 2429 ScavengingVisitor<IGNORE_MARKS, | 2424 ScavengingVisitor<IGNORE_MARKS, |
| 2430 LOGGING_AND_PROFILING_DISABLED>::GetTable()); | 2425 LOGGING_AND_PROFILING_DISABLED>::GetTable()); |
| 2431 } else { | 2426 } else { |
| 2432 scavenging_visitors_table_.CopyFrom( | 2427 scavenging_visitors_table_.CopyFrom( |
| 2433 ScavengingVisitor<IGNORE_MARKS, | 2428 ScavengingVisitor<IGNORE_MARKS, |
| 2434 LOGGING_AND_PROFILING_ENABLED>::GetTable()); | 2429 LOGGING_AND_PROFILING_ENABLED>::GetTable()); |
| (...skipping 1526 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3961 } | 3956 } |
| 3962 | 3957 |
| 3963 | 3958 |
| 3964 MaybeObject* Heap::AllocateSubString(String* buffer, | 3959 MaybeObject* Heap::AllocateSubString(String* buffer, |
| 3965 int start, | 3960 int start, |
| 3966 int end, | 3961 int end, |
| 3967 PretenureFlag pretenure) { | 3962 PretenureFlag pretenure) { |
| 3968 int length = end - start; | 3963 int length = end - start; |
| 3969 if (length <= 0) { | 3964 if (length <= 0) { |
| 3970 return empty_string(); | 3965 return empty_string(); |
| 3971 } else if (length == 1) { | 3966 } |
| 3967 |
| 3968 // Make an attempt to flatten the buffer to reduce access time. |
| 3969 buffer = buffer->TryFlattenGetString(); |
| 3970 |
| 3971 if (length == 1) { |
| 3972 return LookupSingleCharacterStringFromCode(buffer->Get(start)); | 3972 return LookupSingleCharacterStringFromCode(buffer->Get(start)); |
| 3973 } else if (length == 2) { | 3973 } else if (length == 2) { |
| 3974 // Optimization for 2-byte strings often used as keys in a decompression | 3974 // Optimization for 2-byte strings often used as keys in a decompression |
| 3975 // dictionary. Check whether we already have the string in the string | 3975 // dictionary. Check whether we already have the string in the string |
| 3976 // table to prevent creation of many unnecessary strings. | 3976 // table to prevent creation of many unnecessary strings. |
| 3977 uint16_t c1 = buffer->Get(start); | 3977 uint16_t c1 = buffer->Get(start); |
| 3978 uint16_t c2 = buffer->Get(start + 1); | 3978 uint16_t c2 = buffer->Get(start + 1); |
| 3979 return MakeOrFindTwoCharacterString(this, c1, c2); | 3979 return MakeOrFindTwoCharacterString(this, c1, c2); |
| 3980 } | 3980 } |
| 3981 | 3981 |
| 3982 // Make an attempt to flatten the buffer to reduce access time. | |
| 3983 buffer = buffer->TryFlattenGetString(); | |
| 3984 | |
| 3985 if (!FLAG_string_slices || | 3982 if (!FLAG_string_slices || |
| 3986 !buffer->IsFlat() || | 3983 !buffer->IsFlat() || |
| 3987 length < SlicedString::kMinLength || | 3984 length < SlicedString::kMinLength || |
| 3988 pretenure == TENURED) { | 3985 pretenure == TENURED) { |
| 3989 Object* result; | 3986 Object* result; |
| 3990 // WriteToFlat takes care of the case when an indirect string has a | 3987 // WriteToFlat takes care of the case when an indirect string has a |
| 3991 // different encoding from its underlying string. These encodings may | 3988 // different encoding from its underlying string. These encodings may |
| 3992 // differ because of externalization. | 3989 // differ because of externalization. |
| 3993 bool is_one_byte = buffer->IsOneByteRepresentation(); | 3990 bool is_one_byte = buffer->IsOneByteRepresentation(); |
| 3994 { MaybeObject* maybe_result = is_one_byte | 3991 { MaybeObject* maybe_result = is_one_byte |
| (...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4350 | 4347 |
| 4351 #ifdef VERIFY_HEAP | 4348 #ifdef VERIFY_HEAP |
| 4352 if (FLAG_verify_heap) { | 4349 if (FLAG_verify_heap) { |
| 4353 code->Verify(); | 4350 code->Verify(); |
| 4354 } | 4351 } |
| 4355 #endif | 4352 #endif |
| 4356 return new_code; | 4353 return new_code; |
| 4357 } | 4354 } |
| 4358 | 4355 |
| 4359 | 4356 |
| 4357 void Heap::InitializeAllocationMemento(AllocationMemento* memento, |
| 4358 AllocationSite* allocation_site) { |
| 4359 memento->set_map_no_write_barrier(allocation_memento_map()); |
| 4360 ASSERT(allocation_site->map() == allocation_site_map()); |
| 4361 memento->set_allocation_site(allocation_site, SKIP_WRITE_BARRIER); |
| 4362 if (FLAG_allocation_site_pretenuring) { |
| 4363 allocation_site->IncrementMementoCreateCount(); |
| 4364 } |
| 4365 } |
| 4366 |
| 4367 |
| 4360 MaybeObject* Heap::AllocateWithAllocationSite(Map* map, AllocationSpace space, | 4368 MaybeObject* Heap::AllocateWithAllocationSite(Map* map, AllocationSpace space, |
| 4361 Handle<AllocationSite> allocation_site) { | 4369 Handle<AllocationSite> allocation_site) { |
| 4362 ASSERT(gc_state_ == NOT_IN_GC); | 4370 ASSERT(gc_state_ == NOT_IN_GC); |
| 4363 ASSERT(map->instance_type() != MAP_TYPE); | 4371 ASSERT(map->instance_type() != MAP_TYPE); |
| 4364 // If allocation failures are disallowed, we may allocate in a different | 4372 // If allocation failures are disallowed, we may allocate in a different |
| 4365 // space when new space is full and the object is not a large object. | 4373 // space when new space is full and the object is not a large object. |
| 4366 AllocationSpace retry_space = | 4374 AllocationSpace retry_space = |
| 4367 (space != NEW_SPACE) ? space : TargetSpaceId(map->instance_type()); | 4375 (space != NEW_SPACE) ? space : TargetSpaceId(map->instance_type()); |
| 4368 int size = map->instance_size() + AllocationMemento::kSize; | 4376 int size = map->instance_size() + AllocationMemento::kSize; |
| 4369 Object* result; | 4377 Object* result; |
| 4370 MaybeObject* maybe_result = AllocateRaw(size, space, retry_space); | 4378 MaybeObject* maybe_result = AllocateRaw(size, space, retry_space); |
| 4371 if (!maybe_result->ToObject(&result)) return maybe_result; | 4379 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 4372 // No need for write barrier since object is white and map is in old space. | 4380 // No need for write barrier since object is white and map is in old space. |
| 4373 HeapObject::cast(result)->set_map_no_write_barrier(map); | 4381 HeapObject::cast(result)->set_map_no_write_barrier(map); |
| 4374 AllocationMemento* alloc_memento = reinterpret_cast<AllocationMemento*>( | 4382 AllocationMemento* alloc_memento = reinterpret_cast<AllocationMemento*>( |
| 4375 reinterpret_cast<Address>(result) + map->instance_size()); | 4383 reinterpret_cast<Address>(result) + map->instance_size()); |
| 4376 alloc_memento->set_map_no_write_barrier(allocation_memento_map()); | 4384 InitializeAllocationMemento(alloc_memento, *allocation_site); |
| 4377 ASSERT(allocation_site->map() == allocation_site_map()); | |
| 4378 alloc_memento->set_allocation_site(*allocation_site, SKIP_WRITE_BARRIER); | |
| 4379 return result; | 4385 return result; |
| 4380 } | 4386 } |
| 4381 | 4387 |
| 4382 | 4388 |
| 4383 MaybeObject* Heap::Allocate(Map* map, AllocationSpace space) { | 4389 MaybeObject* Heap::Allocate(Map* map, AllocationSpace space) { |
| 4384 ASSERT(gc_state_ == NOT_IN_GC); | 4390 ASSERT(gc_state_ == NOT_IN_GC); |
| 4385 ASSERT(map->instance_type() != MAP_TYPE); | 4391 ASSERT(map->instance_type() != MAP_TYPE); |
| 4386 // If allocation failures are disallowed, we may allocate in a different | 4392 // If allocation failures are disallowed, we may allocate in a different |
| 4387 // space when new space is full and the object is not a large object. | 4393 // space when new space is full and the object is not a large object. |
| 4388 AllocationSpace retry_space = | 4394 AllocationSpace retry_space = |
| (...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4801 MaybeObject* Heap::CopyJSObject(JSObject* source, AllocationSite* site) { | 4807 MaybeObject* Heap::CopyJSObject(JSObject* source, AllocationSite* site) { |
| 4802 // Never used to copy functions. If functions need to be copied we | 4808 // Never used to copy functions. If functions need to be copied we |
| 4803 // have to be careful to clear the literals array. | 4809 // have to be careful to clear the literals array. |
| 4804 SLOW_ASSERT(!source->IsJSFunction()); | 4810 SLOW_ASSERT(!source->IsJSFunction()); |
| 4805 | 4811 |
| 4806 // Make the clone. | 4812 // Make the clone. |
| 4807 Map* map = source->map(); | 4813 Map* map = source->map(); |
| 4808 int object_size = map->instance_size(); | 4814 int object_size = map->instance_size(); |
| 4809 Object* clone; | 4815 Object* clone; |
| 4810 | 4816 |
| 4811 ASSERT(site == NULL || (AllocationSite::CanTrack(map->instance_type()) && | 4817 ASSERT(site == NULL || AllocationSite::CanTrack(map->instance_type())); |
| 4812 map->instance_type() == JS_ARRAY_TYPE)); | |
| 4813 | 4818 |
| 4814 WriteBarrierMode wb_mode = UPDATE_WRITE_BARRIER; | 4819 WriteBarrierMode wb_mode = UPDATE_WRITE_BARRIER; |
| 4815 | 4820 |
| 4816 // If we're forced to always allocate, we use the general allocation | 4821 // If we're forced to always allocate, we use the general allocation |
| 4817 // functions which may leave us with an object in old space. | 4822 // functions which may leave us with an object in old space. |
| 4818 if (always_allocate()) { | 4823 if (always_allocate()) { |
| 4819 { MaybeObject* maybe_clone = | 4824 { MaybeObject* maybe_clone = |
| 4820 AllocateRaw(object_size, NEW_SPACE, OLD_POINTER_SPACE); | 4825 AllocateRaw(object_size, NEW_SPACE, OLD_POINTER_SPACE); |
| 4821 if (!maybe_clone->ToObject(&clone)) return maybe_clone; | 4826 if (!maybe_clone->ToObject(&clone)) return maybe_clone; |
| 4822 } | 4827 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 4841 SLOW_ASSERT(InNewSpace(clone)); | 4846 SLOW_ASSERT(InNewSpace(clone)); |
| 4842 // Since we know the clone is allocated in new space, we can copy | 4847 // Since we know the clone is allocated in new space, we can copy |
| 4843 // the contents without worrying about updating the write barrier. | 4848 // the contents without worrying about updating the write barrier. |
| 4844 CopyBlock(HeapObject::cast(clone)->address(), | 4849 CopyBlock(HeapObject::cast(clone)->address(), |
| 4845 source->address(), | 4850 source->address(), |
| 4846 object_size); | 4851 object_size); |
| 4847 | 4852 |
| 4848 if (site != NULL) { | 4853 if (site != NULL) { |
| 4849 AllocationMemento* alloc_memento = reinterpret_cast<AllocationMemento*>( | 4854 AllocationMemento* alloc_memento = reinterpret_cast<AllocationMemento*>( |
| 4850 reinterpret_cast<Address>(clone) + object_size); | 4855 reinterpret_cast<Address>(clone) + object_size); |
| 4851 alloc_memento->set_map_no_write_barrier(allocation_memento_map()); | 4856 InitializeAllocationMemento(alloc_memento, site); |
| 4852 ASSERT(site->map() == allocation_site_map()); | |
| 4853 alloc_memento->set_allocation_site(site, SKIP_WRITE_BARRIER); | |
| 4854 HeapProfiler* profiler = isolate()->heap_profiler(); | |
| 4855 if (profiler->is_tracking_allocations()) { | |
| 4856 profiler->UpdateObjectSizeEvent(HeapObject::cast(clone)->address(), | |
| 4857 object_size); | |
| 4858 profiler->NewObjectEvent(alloc_memento->address(), | |
| 4859 AllocationMemento::kSize); | |
| 4860 } | |
| 4861 } | 4857 } |
| 4862 } | 4858 } |
| 4863 | 4859 |
| 4864 SLOW_ASSERT( | 4860 SLOW_ASSERT( |
| 4865 JSObject::cast(clone)->GetElementsKind() == source->GetElementsKind()); | 4861 JSObject::cast(clone)->GetElementsKind() == source->GetElementsKind()); |
| 4866 FixedArrayBase* elements = FixedArrayBase::cast(source->elements()); | 4862 FixedArrayBase* elements = FixedArrayBase::cast(source->elements()); |
| 4867 FixedArray* properties = FixedArray::cast(source->properties()); | 4863 FixedArray* properties = FixedArray::cast(source->properties()); |
| 4868 // Update elements if necessary. | 4864 // Update elements if necessary. |
| 4869 if (elements->length() > 0) { | 4865 if (elements->length() > 0) { |
| 4870 Object* elem; | 4866 Object* elem; |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4974 // Reset the map for the object. | 4970 // Reset the map for the object. |
| 4975 object->set_map(constructor->initial_map()); | 4971 object->set_map(constructor->initial_map()); |
| 4976 | 4972 |
| 4977 // Reinitialize the object from the constructor map. | 4973 // Reinitialize the object from the constructor map. |
| 4978 InitializeJSObjectFromMap(object, FixedArray::cast(properties), map); | 4974 InitializeJSObjectFromMap(object, FixedArray::cast(properties), map); |
| 4979 return object; | 4975 return object; |
| 4980 } | 4976 } |
| 4981 | 4977 |
| 4982 | 4978 |
| 4983 MaybeObject* Heap::AllocateStringFromOneByte(Vector<const uint8_t> string, | 4979 MaybeObject* Heap::AllocateStringFromOneByte(Vector<const uint8_t> string, |
| 4984 PretenureFlag pretenure) { | 4980 PretenureFlag pretenure) { |
| 4985 int length = string.length(); | 4981 int length = string.length(); |
| 4986 if (length == 1) { | 4982 if (length == 1) { |
| 4987 return Heap::LookupSingleCharacterStringFromCode(string[0]); | 4983 return Heap::LookupSingleCharacterStringFromCode(string[0]); |
| 4988 } | 4984 } |
| 4989 Object* result; | 4985 Object* result; |
| 4990 { MaybeObject* maybe_result = | 4986 { MaybeObject* maybe_result = |
| 4991 AllocateRawOneByteString(string.length(), pretenure); | 4987 AllocateRawOneByteString(string.length(), pretenure); |
| 4992 if (!maybe_result->ToObject(&result)) return maybe_result; | 4988 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 4993 } | 4989 } |
| 4994 | 4990 |
| (...skipping 2966 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7961 static_cast<int>(object_sizes_last_time_[index])); | 7957 static_cast<int>(object_sizes_last_time_[index])); |
| 7962 CODE_AGE_LIST_COMPLETE(ADJUST_LAST_TIME_OBJECT_COUNT) | 7958 CODE_AGE_LIST_COMPLETE(ADJUST_LAST_TIME_OBJECT_COUNT) |
| 7963 #undef ADJUST_LAST_TIME_OBJECT_COUNT | 7959 #undef ADJUST_LAST_TIME_OBJECT_COUNT |
| 7964 | 7960 |
| 7965 OS::MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); | 7961 OS::MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); |
| 7966 OS::MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); | 7962 OS::MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); |
| 7967 ClearObjectStats(); | 7963 ClearObjectStats(); |
| 7968 } | 7964 } |
| 7969 | 7965 |
| 7970 } } // namespace v8::internal | 7966 } } // namespace v8::internal |
| OLD | NEW |