Index: src/heap/heap-inl.h |
diff --git a/src/heap/heap-inl.h b/src/heap/heap-inl.h |
index bfb5498751f29cf3bd94d785473a64e598c10345..7e869f263a1be6e6f0ead788bf2ee42f4a3bccc0 100644 |
--- a/src/heap/heap-inl.h |
+++ b/src/heap/heap-inl.h |
@@ -81,12 +81,12 @@ AllocationResult Heap::AllocateOneByteInternalizedString( |
// Compute map and object size. |
Map* map = one_byte_internalized_string_map(); |
int size = SeqOneByteString::SizeFor(str.length()); |
- AllocationSpace space = SelectSpace(size, TENURED); |
+ AllocationSpace space = SelectSpace(size, OLD_DATA_SPACE, TENURED); |
// Allocate string. |
HeapObject* result; |
{ |
- AllocationResult allocation = AllocateRaw(size, space, OLD_SPACE); |
+ AllocationResult allocation = AllocateRaw(size, space, OLD_DATA_SPACE); |
if (!allocation.To(&result)) return allocation; |
} |
@@ -113,12 +113,12 @@ AllocationResult Heap::AllocateTwoByteInternalizedString(Vector<const uc16> str, |
// Compute map and object size. |
Map* map = internalized_string_map(); |
int size = SeqTwoByteString::SizeFor(str.length()); |
- AllocationSpace space = SelectSpace(size, TENURED); |
+ AllocationSpace space = SelectSpace(size, OLD_DATA_SPACE, TENURED); |
// Allocate string. |
HeapObject* result; |
{ |
- AllocationResult allocation = AllocateRaw(size, space, OLD_SPACE); |
+ AllocationResult allocation = AllocateRaw(size, space, OLD_DATA_SPACE); |
if (!allocation.To(&result)) return allocation; |
} |
@@ -183,8 +183,10 @@ AllocationResult Heap::AllocateRaw(int size_in_bytes, AllocationSpace space, |
} |
} |
- if (OLD_SPACE == space) { |
- allocation = old_space_->AllocateRaw(size_in_bytes); |
+ if (OLD_POINTER_SPACE == space) { |
+ allocation = old_pointer_space_->AllocateRaw(size_in_bytes); |
+ } else if (OLD_DATA_SPACE == space) { |
+ allocation = old_data_space_->AllocateRaw(size_in_bytes); |
} else if (CODE_SPACE == space) { |
if (size_in_bytes <= code_space()->AreaSize()) { |
allocation = code_space_->AllocateRaw(size_in_bytes); |
@@ -325,11 +327,23 @@ bool Heap::InToSpace(Object* object) { |
} |
-bool Heap::InOldSpace(Address address) { return old_space_->Contains(address); } |
+bool Heap::InOldPointerSpace(Address address) { |
+ return old_pointer_space_->Contains(address); |
+} |
-bool Heap::InOldSpace(Object* object) { |
- return InOldSpace(reinterpret_cast<Address>(object)); |
+bool Heap::InOldPointerSpace(Object* object) { |
+ return InOldPointerSpace(reinterpret_cast<Address>(object)); |
+} |
+ |
+ |
+bool Heap::InOldDataSpace(Address address) { |
+ return old_data_space_->Contains(address); |
+} |
+ |
+ |
+bool Heap::InOldDataSpace(Object* object) { |
+ return InOldDataSpace(reinterpret_cast<Address>(object)); |
} |
@@ -361,16 +375,52 @@ void Heap::RecordWrites(Address address, int start, int len) { |
} |
+OldSpace* Heap::TargetSpace(HeapObject* object) { |
+ InstanceType type = object->map()->instance_type(); |
+ AllocationSpace space = TargetSpaceId(type); |
+ return (space == OLD_POINTER_SPACE) ? old_pointer_space_ : old_data_space_; |
+} |
+ |
+ |
+AllocationSpace Heap::TargetSpaceId(InstanceType type) { |
+ // Heap numbers and sequential strings are promoted to old data space, all |
+ // other object types are promoted to old pointer space. We do not use |
+ // object->IsHeapNumber() and object->IsSeqString() because we already |
+ // know that object has the heap object tag. |
+ |
+ // These objects are never allocated in new space. |
+ DCHECK(type != MAP_TYPE); |
+ DCHECK(type != CODE_TYPE); |
+ DCHECK(type != ODDBALL_TYPE); |
+ DCHECK(type != CELL_TYPE); |
+ |
+ if (type <= LAST_NAME_TYPE) { |
+ if (type == SYMBOL_TYPE) return OLD_POINTER_SPACE; |
+ DCHECK(type < FIRST_NONSTRING_TYPE); |
+ // There are four string representations: sequential strings, external |
+ // strings, cons strings, and sliced strings. |
+ // Only the latter two contain non-map-word pointers to heap objects. |
+ return ((type & kIsIndirectStringMask) == kIsIndirectStringTag) |
+ ? OLD_POINTER_SPACE |
+ : OLD_DATA_SPACE; |
+ } else { |
+ return (type <= LAST_DATA_TYPE) ? OLD_DATA_SPACE : OLD_POINTER_SPACE; |
+ } |
+} |
+ |
+ |
bool Heap::AllowedToBeMigrated(HeapObject* obj, AllocationSpace dst) { |
// Object migration is governed by the following rules: |
// |
- // 1) Objects in new-space can be migrated to the old space |
+ // 1) Objects in new-space can be migrated to one of the old spaces |
// that matches their target space or they stay in new-space. |
// 2) Objects in old-space stay in the same space when migrating. |
// 3) Fillers (two or more words) can migrate due to left-trimming of |
- // fixed arrays in new-space or old space. |
+ // fixed arrays in new-space, old-data-space and old-pointer-space. |
// 4) Fillers (one word) can never migrate, they are skipped by |
// incremental marking explicitly to prevent invalid pattern. |
+ // 5) Short external strings can end up in old pointer space when a cons |
+ // string in old pointer space is made external (String::MakeExternal). |
// |
// Since this function is used for debugging only, we do not place |
// asserts here, but check everything explicitly. |
@@ -380,10 +430,12 @@ bool Heap::AllowedToBeMigrated(HeapObject* obj, AllocationSpace dst) { |
AllocationSpace src = chunk->owner()->identity(); |
switch (src) { |
case NEW_SPACE: |
- return dst == src || dst == OLD_SPACE; |
- case OLD_SPACE: |
- return dst == src && |
- (dst == OLD_SPACE || obj->IsFiller() || obj->IsExternalString()); |
+ return dst == src || dst == TargetSpaceId(type); |
+ case OLD_POINTER_SPACE: |
+ return dst == src && (dst == TargetSpaceId(type) || obj->IsFiller() || |
+ obj->IsExternalString()); |
+ case OLD_DATA_SPACE: |
+ return dst == src && dst == TargetSpaceId(type); |
case CODE_SPACE: |
return dst == src && type == CODE_TYPE; |
case MAP_SPACE: |