Changed allocation to allow large objects to be allocated in new space.
This avoids back-to-back mark-sweep collections. Review URL: http://codereview.chromium.org/136001 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2219 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
531a6db569
commit
7dab62ee96
@ -34,7 +34,7 @@
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
int Heap::MaxHeapObjectSize() {
|
||||
int Heap::MaxObjectSizeInPagedSpace() {
|
||||
return Page::kMaxHeapObjectSize;
|
||||
}
|
||||
|
||||
|
88
src/heap.cc
88
src/heap.cc
@ -943,10 +943,32 @@ void Heap::ScavengeObjectSlow(HeapObject** p, HeapObject* object) {
|
||||
|
||||
// If the object should be promoted, we try to copy it to old space.
|
||||
if (ShouldBePromoted(object->address(), object_size)) {
|
||||
Object* result;
|
||||
if (object_size > MaxObjectSizeInPagedSpace()) {
|
||||
result = lo_space_->AllocateRawFixedArray(object_size);
|
||||
if (!result->IsFailure()) {
|
||||
// Save the from-space object pointer and its map pointer at the
|
||||
// top of the to space to be swept and copied later. Write the
|
||||
// forwarding address over the map word of the from-space
|
||||
// object.
|
||||
HeapObject* target = HeapObject::cast(result);
|
||||
promotion_queue.insert(object, first_word.ToMap());
|
||||
object->set_map_word(MapWord::FromForwardingAddress(target));
|
||||
|
||||
// Give the space allocated for the result a proper map by
|
||||
// treating it as a free list node (not linked into the free
|
||||
// list).
|
||||
FreeListNode* node = FreeListNode::FromAddress(target->address());
|
||||
node->set_size(object_size);
|
||||
|
||||
*p = target;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
OldSpace* target_space = Heap::TargetSpace(object);
|
||||
ASSERT(target_space == Heap::old_pointer_space_ ||
|
||||
target_space == Heap::old_data_space_);
|
||||
Object* result = target_space->AllocateRaw(object_size);
|
||||
result = target_space->AllocateRaw(object_size);
|
||||
if (!result->IsFailure()) {
|
||||
HeapObject* target = HeapObject::cast(result);
|
||||
if (target_space == Heap::old_pointer_space_) {
|
||||
@ -978,7 +1000,7 @@ void Heap::ScavengeObjectSlow(HeapObject** p, HeapObject* object) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// The object should remain in new space or the old space allocation failed.
|
||||
Object* result = new_space_.AllocateRaw(object_size);
|
||||
// Failed allocation at this point is utterly unexpected.
|
||||
@ -1698,7 +1720,7 @@ Object* Heap::AllocateByteArray(int length, PretenureFlag pretenure) {
|
||||
}
|
||||
int size = ByteArray::SizeFor(length);
|
||||
AllocationSpace space =
|
||||
size > MaxHeapObjectSize() ? LO_SPACE : OLD_DATA_SPACE;
|
||||
size > MaxObjectSizeInPagedSpace() ? LO_SPACE : OLD_DATA_SPACE;
|
||||
|
||||
Object* result = AllocateRaw(size, space, OLD_DATA_SPACE);
|
||||
|
||||
@ -1713,7 +1735,7 @@ Object* Heap::AllocateByteArray(int length, PretenureFlag pretenure) {
|
||||
Object* Heap::AllocateByteArray(int length) {
|
||||
int size = ByteArray::SizeFor(length);
|
||||
AllocationSpace space =
|
||||
size > MaxHeapObjectSize() ? LO_SPACE : NEW_SPACE;
|
||||
size > MaxObjectSizeInPagedSpace() ? LO_SPACE : NEW_SPACE;
|
||||
|
||||
Object* result = AllocateRaw(size, space, OLD_DATA_SPACE);
|
||||
|
||||
@ -1748,7 +1770,7 @@ Object* Heap::CreateCode(const CodeDesc& desc,
|
||||
int obj_size = Code::SizeFor(body_size, sinfo_size);
|
||||
ASSERT(IsAligned(obj_size, Code::kCodeAlignment));
|
||||
Object* result;
|
||||
if (obj_size > MaxHeapObjectSize()) {
|
||||
if (obj_size > MaxObjectSizeInPagedSpace()) {
|
||||
result = lo_space_->AllocateRawCode(obj_size);
|
||||
} else {
|
||||
result = code_space_->AllocateRaw(obj_size);
|
||||
@ -1788,7 +1810,7 @@ Object* Heap::CopyCode(Code* code) {
|
||||
// Allocate an object the same size as the code object.
|
||||
int obj_size = code->Size();
|
||||
Object* result;
|
||||
if (obj_size > MaxHeapObjectSize()) {
|
||||
if (obj_size > MaxObjectSizeInPagedSpace()) {
|
||||
result = lo_space_->AllocateRawCode(obj_size);
|
||||
} else {
|
||||
result = code_space_->AllocateRaw(obj_size);
|
||||
@ -1963,7 +1985,7 @@ Object* Heap::AllocateJSObjectFromMap(Map* map, PretenureFlag pretenure) {
|
||||
// Allocate the JSObject.
|
||||
AllocationSpace space =
|
||||
(pretenure == TENURED) ? OLD_POINTER_SPACE : NEW_SPACE;
|
||||
if (map->instance_size() > MaxHeapObjectSize()) space = LO_SPACE;
|
||||
if (map->instance_size() > MaxObjectSizeInPagedSpace()) space = LO_SPACE;
|
||||
Object* obj = Allocate(map, space);
|
||||
if (obj->IsFailure()) return obj;
|
||||
|
||||
@ -2250,7 +2272,7 @@ Object* Heap::AllocateInternalSymbol(unibrow::CharacterStream* buffer,
|
||||
|
||||
// Allocate string.
|
||||
AllocationSpace space =
|
||||
(size > MaxHeapObjectSize()) ? LO_SPACE : OLD_DATA_SPACE;
|
||||
(size > MaxObjectSizeInPagedSpace()) ? LO_SPACE : OLD_DATA_SPACE;
|
||||
Object* result = AllocateRaw(size, space, OLD_DATA_SPACE);
|
||||
if (result->IsFailure()) return result;
|
||||
|
||||
@ -2272,13 +2294,16 @@ Object* Heap::AllocateInternalSymbol(unibrow::CharacterStream* buffer,
|
||||
Object* Heap::AllocateRawAsciiString(int length, PretenureFlag pretenure) {
|
||||
AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE;
|
||||
int size = SeqAsciiString::SizeFor(length);
|
||||
if (size > MaxHeapObjectSize()) {
|
||||
space = LO_SPACE;
|
||||
}
|
||||
|
||||
// Use AllocateRaw rather than Allocate because the object's size cannot be
|
||||
// determined from the map.
|
||||
Object* result = AllocateRaw(size, space, OLD_DATA_SPACE);
|
||||
Object* result = Failure::OutOfMemoryException();
|
||||
if (space == NEW_SPACE) {
|
||||
result = size <= kMaxObjectSizeInNewSpace
|
||||
? new_space_.AllocateRaw(size)
|
||||
: lo_space_->AllocateRawFixedArray(size);
|
||||
} else {
|
||||
if (size > MaxObjectSizeInPagedSpace()) space = LO_SPACE;
|
||||
result = AllocateRaw(size, space, OLD_DATA_SPACE);
|
||||
}
|
||||
if (result->IsFailure()) return result;
|
||||
|
||||
// Determine the map based on the string's length.
|
||||
@ -2302,13 +2327,16 @@ Object* Heap::AllocateRawAsciiString(int length, PretenureFlag pretenure) {
|
||||
Object* Heap::AllocateRawTwoByteString(int length, PretenureFlag pretenure) {
|
||||
AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE;
|
||||
int size = SeqTwoByteString::SizeFor(length);
|
||||
if (size > MaxHeapObjectSize()) {
|
||||
space = LO_SPACE;
|
||||
}
|
||||
|
||||
// Use AllocateRaw rather than Allocate because the object's size cannot be
|
||||
// determined from the map.
|
||||
Object* result = AllocateRaw(size, space, OLD_DATA_SPACE);
|
||||
Object* result = Failure::OutOfMemoryException();
|
||||
if (space == NEW_SPACE) {
|
||||
result = size <= kMaxObjectSizeInNewSpace
|
||||
? new_space_.AllocateRaw(size)
|
||||
: lo_space_->AllocateRawFixedArray(size);
|
||||
} else {
|
||||
if (size > MaxObjectSizeInPagedSpace()) space = LO_SPACE;
|
||||
result = AllocateRaw(size, space, OLD_DATA_SPACE);
|
||||
}
|
||||
if (result->IsFailure()) return result;
|
||||
|
||||
// Determine the map based on the string's length.
|
||||
@ -2345,9 +2373,9 @@ Object* Heap::AllocateRawFixedArray(int length) {
|
||||
if (always_allocate()) return AllocateFixedArray(length, NOT_TENURED);
|
||||
// Allocate the raw data for a fixed array.
|
||||
int size = FixedArray::SizeFor(length);
|
||||
return (size > MaxHeapObjectSize())
|
||||
? lo_space_->AllocateRawFixedArray(size)
|
||||
: new_space_.AllocateRaw(size);
|
||||
return size <= kMaxObjectSizeInNewSpace
|
||||
? new_space_.AllocateRaw(size)
|
||||
: lo_space_->AllocateRawFixedArray(size);
|
||||
}
|
||||
|
||||
|
||||
@ -2395,8 +2423,14 @@ Object* Heap::AllocateFixedArray(int length, PretenureFlag pretenure) {
|
||||
if (length == 0) return empty_fixed_array();
|
||||
|
||||
int size = FixedArray::SizeFor(length);
|
||||
Object* result;
|
||||
if (size > MaxHeapObjectSize()) {
|
||||
Object* result = Failure::OutOfMemoryException();
|
||||
if (pretenure != TENURED) {
|
||||
result = size <= kMaxObjectSizeInNewSpace
|
||||
? new_space_.AllocateRaw(size)
|
||||
: lo_space_->AllocateRawFixedArray(size);
|
||||
}
|
||||
if (result->IsFailure()) {
|
||||
if (size > MaxObjectSizeInPagedSpace()) {
|
||||
result = lo_space_->AllocateRawFixedArray(size);
|
||||
} else {
|
||||
AllocationSpace space =
|
||||
@ -2404,7 +2438,7 @@ Object* Heap::AllocateFixedArray(int length, PretenureFlag pretenure) {
|
||||
result = AllocateRaw(size, space, OLD_POINTER_SPACE);
|
||||
}
|
||||
if (result->IsFailure()) return result;
|
||||
|
||||
}
|
||||
// Initialize the object.
|
||||
reinterpret_cast<Array*>(result)->set_map(fixed_array_map());
|
||||
FixedArray* array = FixedArray::cast(result);
|
||||
@ -2504,7 +2538,7 @@ STRUCT_LIST(MAKE_CASE)
|
||||
}
|
||||
int size = map->instance_size();
|
||||
AllocationSpace space =
|
||||
(size > MaxHeapObjectSize()) ? LO_SPACE : OLD_POINTER_SPACE;
|
||||
(size > MaxObjectSizeInPagedSpace()) ? LO_SPACE : OLD_POINTER_SPACE;
|
||||
Object* result = Heap::Allocate(map, space);
|
||||
if (result->IsFailure()) return result;
|
||||
Struct::cast(result)->InitializeBody(size);
|
||||
|
@ -242,9 +242,8 @@ class Heap : public AllStatic {
|
||||
// all available bytes. Check MaxHeapObjectSize() instead.
|
||||
static int Available();
|
||||
|
||||
// Returns the maximum object size that heap supports. Objects larger than
|
||||
// the maximum heap object size are allocated in a large object space.
|
||||
static inline int MaxHeapObjectSize();
|
||||
// Returns the maximum object size in paged space.
|
||||
static inline int MaxObjectSizeInPagedSpace();
|
||||
|
||||
// Returns of size of all objects residing in the heap.
|
||||
static int SizeOfObjects();
|
||||
@ -830,6 +829,8 @@ class Heap : public AllStatic {
|
||||
|
||||
static const int kMaxMapSpaceSize = 8*MB;
|
||||
|
||||
static const int kMaxObjectSizeInNewSpace = 256*KB;
|
||||
|
||||
static NewSpace new_space_;
|
||||
static OldSpace* old_pointer_space_;
|
||||
static OldSpace* old_data_space_;
|
||||
|
@ -113,7 +113,7 @@ void Builtins::Generate_JSConstructCall(MacroAssembler* masm) {
|
||||
// Make sure that the maximum heap object size will never cause us
|
||||
// problem here, because it is always greater than the maximum
|
||||
// instance size that can be represented in a byte.
|
||||
ASSERT(Heap::MaxHeapObjectSize() >= (1 << kBitsPerByte));
|
||||
ASSERT(Heap::MaxObjectSizeInPagedSpace() >= (1 << kBitsPerByte));
|
||||
ExternalReference new_space_allocation_top =
|
||||
ExternalReference::new_space_allocation_top_address();
|
||||
__ mov(ebx, Operand::StaticVariable(new_space_allocation_top));
|
||||
@ -175,7 +175,7 @@ void Builtins::Generate_JSConstructCall(MacroAssembler* masm) {
|
||||
// ebx: JSObject
|
||||
// edi: start of next object (will be start of FixedArray)
|
||||
// edx: number of elements in properties array
|
||||
ASSERT(Heap::MaxHeapObjectSize() >
|
||||
ASSERT(Heap::MaxObjectSizeInPagedSpace() >
|
||||
(FixedArray::kHeaderSize + 255*kPointerSize));
|
||||
__ lea(ecx, Operand(edi, edx, times_4, FixedArray::kHeaderSize));
|
||||
__ cmp(ecx, Operand::StaticVariable(new_space_allocation_limit));
|
||||
|
@ -947,13 +947,18 @@ void EncodeFreeRegion(Address free_start, int free_size) {
|
||||
|
||||
|
||||
// Try to promote all objects in new space. Heap numbers and sequential
|
||||
// strings are promoted to the code space, all others to the old space.
|
||||
// strings are promoted to the code space, large objects to large object space,
|
||||
// and all others to the old space.
|
||||
inline Object* MCAllocateFromNewSpace(HeapObject* object, int object_size) {
|
||||
Object* forwarded;
|
||||
if (object_size > Heap::MaxObjectSizeInPagedSpace()) {
|
||||
forwarded = Failure::Exception();
|
||||
} else {
|
||||
OldSpace* target_space = Heap::TargetSpace(object);
|
||||
ASSERT(target_space == Heap::old_pointer_space() ||
|
||||
target_space == Heap::old_data_space());
|
||||
Object* forwarded = target_space->MCAllocateRaw(object_size);
|
||||
|
||||
forwarded = target_space->MCAllocateRaw(object_size);
|
||||
}
|
||||
if (forwarded->IsFailure()) {
|
||||
forwarded = Heap::new_space()->MCAllocateRaw(object_size);
|
||||
}
|
||||
|
@ -1261,15 +1261,19 @@ RelativeAddress Serializer::Allocate(HeapObject* obj) {
|
||||
found = Heap::InSpace(obj, s);
|
||||
}
|
||||
CHECK(found);
|
||||
int size = obj->Size();
|
||||
if (s == NEW_SPACE) {
|
||||
Space* space = Heap::TargetSpace(obj);
|
||||
if (size > Heap::MaxObjectSizeInPagedSpace()) {
|
||||
s = LO_SPACE;
|
||||
} else {
|
||||
OldSpace* space = Heap::TargetSpace(obj);
|
||||
ASSERT(space == Heap::old_pointer_space() ||
|
||||
space == Heap::old_data_space());
|
||||
s = (space == Heap::old_pointer_space()) ?
|
||||
OLD_POINTER_SPACE :
|
||||
OLD_DATA_SPACE;
|
||||
}
|
||||
int size = obj->Size();
|
||||
}
|
||||
GCTreatment gc_treatment = DataObject;
|
||||
if (obj->IsFixedArray()) gc_treatment = PointerObject;
|
||||
else if (obj->IsCode()) gc_treatment = CodeObject;
|
||||
|
@ -1041,7 +1041,6 @@ class SemiSpaceIterator : public ObjectIterator {
|
||||
|
||||
HeapObject* object = HeapObject::FromAddress(current_);
|
||||
int size = (size_func_ == NULL) ? object->Size() : size_func_(object);
|
||||
ASSERT_OBJECT_SIZE(size);
|
||||
|
||||
current_ += size;
|
||||
return object;
|
||||
|
@ -208,7 +208,7 @@ TEST(GarbageCollection) {
|
||||
|
||||
v8::HandleScope sc;
|
||||
// check GC when heap is empty
|
||||
int free_bytes = Heap::MaxHeapObjectSize();
|
||||
int free_bytes = Heap::MaxObjectSizeInPagedSpace();
|
||||
CHECK(Heap::CollectGarbage(free_bytes, NEW_SPACE));
|
||||
|
||||
// allocate a function and keep it in global object's property
|
||||
@ -782,7 +782,7 @@ TEST(Iteration) {
|
||||
Factory::NewStringFromAscii(CStrVector("abcdefghij"), TENURED);
|
||||
|
||||
// Allocate a large string (for large object space).
|
||||
int large_size = Heap::MaxHeapObjectSize() + 1;
|
||||
int large_size = Heap::MaxObjectSizeInPagedSpace() + 1;
|
||||
char* str = new char[large_size];
|
||||
for (int i = 0; i < large_size - 1; ++i) str[i] = 'a';
|
||||
str[large_size - 1] = '\0';
|
||||
|
@ -86,8 +86,8 @@ TEST(Promotion) {
|
||||
v8::HandleScope sc;
|
||||
|
||||
// Allocate a fixed array in the new space.
|
||||
int array_size =
|
||||
(Heap::MaxHeapObjectSize() - Array::kHeaderSize) / (kPointerSize * 4);
|
||||
int array_size = (Heap::MaxObjectSizeInPagedSpace() - Array::kHeaderSize) /
|
||||
(kPointerSize * 4);
|
||||
Object* obj = Heap::AllocateFixedArray(array_size);
|
||||
CHECK(!obj->IsFailure());
|
||||
|
||||
@ -118,7 +118,8 @@ TEST(NoPromotion) {
|
||||
CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE));
|
||||
|
||||
// Allocate a big Fixed array in the new space.
|
||||
int size = (Heap::MaxHeapObjectSize() - Array::kHeaderSize) / kPointerSize;
|
||||
int size = (Heap::MaxObjectSizeInPagedSpace() - Array::kHeaderSize) /
|
||||
kPointerSize;
|
||||
Object* obj = Heap::AllocateFixedArray(size);
|
||||
|
||||
Handle<FixedArray> array(FixedArray::cast(obj));
|
||||
|
Loading…
Reference in New Issue
Block a user