Differentate between code target pointers and heap pointers in constant pools.

Separate out code target pointers from normal heap pointer entries in constant
pool arrays so that the GC can correctly relocate these pointers using the
appropriate mechanism.

R=mstarzinger@chromium.org

Review URL: https://codereview.chromium.org/183883011

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19773 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
rmcilroy@chromium.org 2014-03-10 19:05:43 +00:00
parent 9cfd807cba
commit a199ba80ef
13 changed files with 231 additions and 116 deletions

View File

@ -81,14 +81,16 @@ Handle<FixedDoubleArray> Factory::NewFixedDoubleArray(int size,
Handle<ConstantPoolArray> Factory::NewConstantPoolArray(
int number_of_int64_entries,
int number_of_ptr_entries,
int number_of_code_ptr_entries,
int number_of_heap_ptr_entries,
int number_of_int32_entries) {
ASSERT(number_of_int64_entries > 0 || number_of_ptr_entries > 0 ||
number_of_int32_entries > 0);
ASSERT(number_of_int64_entries > 0 || number_of_code_ptr_entries > 0 ||
number_of_heap_ptr_entries > 0 || number_of_int32_entries > 0);
CALL_HEAP_FUNCTION(
isolate(),
isolate()->heap()->AllocateConstantPoolArray(number_of_int64_entries,
number_of_ptr_entries,
number_of_code_ptr_entries,
number_of_heap_ptr_entries,
number_of_int32_entries),
ConstantPoolArray);
}

View File

@ -61,7 +61,8 @@ class Factory {
Handle<ConstantPoolArray> NewConstantPoolArray(
int number_of_int64_entries,
int number_of_ptr_entries,
int number_of_code_ptr_entries,
int number_of_heap_ptr_entries,
int number_of_int32_entries);
Handle<SeededNumberDictionary> NewSeededNumberDictionary(

View File

@ -5084,20 +5084,23 @@ MaybeObject* Heap::CopyFixedDoubleArrayWithMap(FixedDoubleArray* src,
MaybeObject* Heap::CopyConstantPoolArrayWithMap(ConstantPoolArray* src,
Map* map) {
int int64_entries = src->count_of_int64_entries();
int ptr_entries = src->count_of_ptr_entries();
int code_ptr_entries = src->count_of_code_ptr_entries();
int heap_ptr_entries = src->count_of_heap_ptr_entries();
int int32_entries = src->count_of_int32_entries();
Object* obj;
{ MaybeObject* maybe_obj =
AllocateConstantPoolArray(int64_entries, ptr_entries, int32_entries);
AllocateConstantPoolArray(int64_entries, code_ptr_entries,
heap_ptr_entries, int32_entries);
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
HeapObject* dst = HeapObject::cast(obj);
dst->set_map_no_write_barrier(map);
int size = ConstantPoolArray::SizeFor(
int64_entries, code_ptr_entries, heap_ptr_entries, int32_entries);
CopyBlock(
dst->address() + ConstantPoolArray::kLengthOffset,
src->address() + ConstantPoolArray::kLengthOffset,
ConstantPoolArray::SizeFor(int64_entries, ptr_entries, int32_entries)
- ConstantPoolArray::kLengthOffset);
size - ConstantPoolArray::kLengthOffset);
return obj;
}
@ -5234,12 +5237,14 @@ MaybeObject* Heap::AllocateRawFixedDoubleArray(int length,
MaybeObject* Heap::AllocateConstantPoolArray(int number_of_int64_entries,
int number_of_ptr_entries,
int number_of_code_ptr_entries,
int number_of_heap_ptr_entries,
int number_of_int32_entries) {
ASSERT(number_of_int64_entries > 0 || number_of_ptr_entries > 0 ||
number_of_int32_entries > 0);
ASSERT(number_of_int64_entries > 0 || number_of_code_ptr_entries > 0 ||
number_of_heap_ptr_entries > 0 || number_of_int32_entries > 0);
int size = ConstantPoolArray::SizeFor(number_of_int64_entries,
number_of_ptr_entries,
number_of_code_ptr_entries,
number_of_heap_ptr_entries,
number_of_int32_entries);
#ifndef V8_HOST_ARCH_64_BIT
size += kPointerSize;
@ -5256,29 +5261,38 @@ MaybeObject* Heap::AllocateConstantPoolArray(int number_of_int64_entries,
ConstantPoolArray* constant_pool =
reinterpret_cast<ConstantPoolArray*>(object);
constant_pool->SetEntryCounts(number_of_int64_entries,
number_of_ptr_entries,
number_of_code_ptr_entries,
number_of_heap_ptr_entries,
number_of_int32_entries);
if (number_of_ptr_entries > 0) {
if (number_of_code_ptr_entries > 0) {
int offset =
constant_pool->OffsetOfElementAt(constant_pool->first_code_ptr_index());
MemsetPointer(
HeapObject::RawField(
constant_pool,
constant_pool->OffsetOfElementAt(constant_pool->first_ptr_index())),
reinterpret_cast<Address*>(HeapObject::RawField(constant_pool, offset)),
isolate()->builtins()->builtin(Builtins::kIllegal)->entry(),
number_of_code_ptr_entries);
}
if (number_of_heap_ptr_entries > 0) {
int offset =
constant_pool->OffsetOfElementAt(constant_pool->first_code_ptr_index());
MemsetPointer(
HeapObject::RawField(constant_pool, offset),
undefined_value(),
number_of_ptr_entries);
number_of_heap_ptr_entries);
}
return constant_pool;
}
MaybeObject* Heap::AllocateEmptyConstantPoolArray() {
int size = ConstantPoolArray::SizeFor(0, 0, 0);
int size = ConstantPoolArray::SizeFor(0, 0, 0, 0);
Object* result;
{ MaybeObject* maybe_result =
AllocateRaw(size, OLD_DATA_SPACE, OLD_DATA_SPACE);
if (!maybe_result->ToObject(&result)) return maybe_result;
}
HeapObject::cast(result)->set_map_no_write_barrier(constant_pool_array_map());
ConstantPoolArray::cast(result)->SetEntryCounts(0, 0, 0);
ConstantPoolArray::cast(result)->SetEntryCounts(0, 0, 0, 0);
return result;
}

View File

@ -1012,9 +1012,10 @@ class Heap {
PretenureFlag pretenure = NOT_TENURED);
MUST_USE_RESULT MaybeObject* AllocateConstantPoolArray(
int first_int64_index,
int first_ptr_index,
int first_int32_index);
int number_of_int64_entries,
int number_of_code_ptr_entries,
int number_of_heap_ptr_entries,
int number_of_int32_entries);
// Allocates a fixed double array with uninitialized values. Returns
// Failure::RetryAfterGC(requested_bytes, space) if the allocation failed.

View File

@ -2076,8 +2076,8 @@ int MarkCompactCollector::DiscoverAndPromoteBlackObjectsOnPage(
}
Object* target = allocation->ToObjectUnchecked();
MigrateObject(HeapObject::cast(target)->address(),
object->address(),
MigrateObject(HeapObject::cast(target),
object,
size,
NEW_SPACE);
}
@ -2819,19 +2819,21 @@ void MarkCompactCollector::ClearWeakCollections() {
// pointer iteration. This is an issue if the store buffer overflows and we
// have to scan the entire old space, including dead objects, looking for
// pointers to new space.
void MarkCompactCollector::MigrateObject(Address dst,
Address src,
void MarkCompactCollector::MigrateObject(HeapObject* dst,
HeapObject* src,
int size,
AllocationSpace dest) {
Address dst_addr = dst->address();
Address src_addr = src->address();
HeapProfiler* heap_profiler = heap()->isolate()->heap_profiler();
if (heap_profiler->is_tracking_object_moves()) {
heap_profiler->ObjectMoveEvent(src, dst, size);
heap_profiler->ObjectMoveEvent(src_addr, dst_addr, size);
}
ASSERT(heap()->AllowedToBeMigrated(HeapObject::FromAddress(src), dest));
ASSERT(heap()->AllowedToBeMigrated(src, dest));
ASSERT(dest != LO_SPACE && size <= Page::kMaxRegularHeapObjectSize);
if (dest == OLD_POINTER_SPACE) {
Address src_slot = src;
Address dst_slot = dst;
Address src_slot = src_addr;
Address dst_slot = dst_addr;
ASSERT(IsAligned(size, kPointerSize));
for (int remaining = size / kPointerSize; remaining > 0; remaining--) {
@ -2852,8 +2854,8 @@ void MarkCompactCollector::MigrateObject(Address dst,
dst_slot += kPointerSize;
}
if (compacting_ && HeapObject::FromAddress(dst)->IsJSFunction()) {
Address code_entry_slot = dst + JSFunction::kCodeEntryOffset;
if (compacting_ && dst->IsJSFunction()) {
Address code_entry_slot = dst_addr + JSFunction::kCodeEntryOffset;
Address code_entry = Memory::Address_at(code_entry_slot);
if (Page::FromAddress(code_entry)->IsEvacuationCandidate()) {
@ -2863,21 +2865,36 @@ void MarkCompactCollector::MigrateObject(Address dst,
code_entry_slot,
SlotsBuffer::IGNORE_OVERFLOW);
}
} else if (compacting_ && dst->IsConstantPoolArray()) {
ConstantPoolArray* constant_pool = ConstantPoolArray::cast(dst);
for (int i = 0; i < constant_pool->count_of_code_ptr_entries(); i++) {
Address code_entry_slot =
dst_addr + constant_pool->OffsetOfElementAt(i);
Address code_entry = Memory::Address_at(code_entry_slot);
if (Page::FromAddress(code_entry)->IsEvacuationCandidate()) {
SlotsBuffer::AddTo(&slots_buffer_allocator_,
&migration_slots_buffer_,
SlotsBuffer::CODE_ENTRY_SLOT,
code_entry_slot,
SlotsBuffer::IGNORE_OVERFLOW);
}
}
}
} else if (dest == CODE_SPACE) {
PROFILE(isolate(), CodeMoveEvent(src, dst));
heap()->MoveBlock(dst, src, size);
PROFILE(isolate(), CodeMoveEvent(src_addr, dst_addr));
heap()->MoveBlock(dst_addr, src_addr, size);
SlotsBuffer::AddTo(&slots_buffer_allocator_,
&migration_slots_buffer_,
SlotsBuffer::RELOCATED_CODE_OBJECT,
dst,
dst_addr,
SlotsBuffer::IGNORE_OVERFLOW);
Code::cast(HeapObject::FromAddress(dst))->Relocate(dst - src);
Code::cast(dst)->Relocate(dst_addr - src_addr);
} else {
ASSERT(dest == OLD_DATA_SPACE || dest == NEW_SPACE);
heap()->MoveBlock(dst, src, size);
heap()->MoveBlock(dst_addr, src_addr, size);
}
Memory::Address_at(src) = dst;
Memory::Address_at(src_addr) = dst_addr;
}
@ -3012,8 +3029,8 @@ bool MarkCompactCollector::TryPromoteObject(HeapObject* object,
MaybeObject* maybe_result = target_space->AllocateRaw(object_size);
if (maybe_result->ToObject(&result)) {
HeapObject* target = HeapObject::cast(result);
MigrateObject(target->address(),
object->address(),
MigrateObject(target,
object,
object_size,
target_space->identity());
heap()->mark_compact_collector()->tracer()->
@ -3091,8 +3108,8 @@ void MarkCompactCollector::EvacuateLiveObjectsFromPage(Page* p) {
Object* target_object = target->ToObjectUnchecked();
MigrateObject(HeapObject::cast(target_object)->address(),
object_addr,
MigrateObject(HeapObject::cast(target_object),
object,
size,
space->identity());
ASSERT(object->map_word().IsForwardingAddress());

View File

@ -696,8 +696,8 @@ class MarkCompactCollector {
SlotsBuffer::AdditionMode mode =
SlotsBuffer::FAIL_ON_OVERFLOW));
void MigrateObject(Address dst,
Address src,
void MigrateObject(HeapObject* dst,
HeapObject* src,
int size,
AllocationSpace to_old_space);

View File

@ -403,6 +403,13 @@ void FixedDoubleArray::FixedDoubleArrayVerify() {
void ConstantPoolArray::ConstantPoolArrayVerify() {
CHECK(IsConstantPoolArray());
for (int i = 0; i < count_of_code_ptr_entries(); i++) {
Address code_entry = get_code_ptr_entry(first_code_ptr_index() + i);
VerifyPointer(Code::GetCodeFromTargetAddress(code_entry));
}
for (int i = 0; i < count_of_heap_ptr_entries(); i++) {
VerifyObjectField(OffsetOfElementAt(first_heap_ptr_index() + i));
}
}

View File

@ -2198,8 +2198,12 @@ bool FixedDoubleArray::is_the_hole(int index) {
}
SMI_ACCESSORS(ConstantPoolArray, first_ptr_index, kFirstPointerIndexOffset)
SMI_ACCESSORS(ConstantPoolArray, first_int32_index, kFirstInt32IndexOffset)
SMI_ACCESSORS(
ConstantPoolArray, first_code_ptr_index, kFirstCodePointerIndexOffset)
SMI_ACCESSORS(
ConstantPoolArray, first_heap_ptr_index, kFirstHeapPointerIndexOffset)
SMI_ACCESSORS(
ConstantPoolArray, first_int32_index, kFirstInt32IndexOffset)
int ConstantPoolArray::first_int64_index() {
@ -2208,12 +2212,17 @@ int ConstantPoolArray::first_int64_index() {
int ConstantPoolArray::count_of_int64_entries() {
return first_ptr_index();
return first_code_ptr_index();
}
int ConstantPoolArray::count_of_ptr_entries() {
return first_int32_index() - first_ptr_index();
int ConstantPoolArray::count_of_code_ptr_entries() {
return first_heap_ptr_index() - first_code_ptr_index();
}
int ConstantPoolArray::count_of_heap_ptr_entries() {
return first_int32_index() - first_heap_ptr_index();
}
@ -2223,32 +2232,44 @@ int ConstantPoolArray::count_of_int32_entries() {
void ConstantPoolArray::SetEntryCounts(int number_of_int64_entries,
int number_of_ptr_entries,
int number_of_code_ptr_entries,
int number_of_heap_ptr_entries,
int number_of_int32_entries) {
set_first_ptr_index(number_of_int64_entries);
set_first_int32_index(number_of_int64_entries + number_of_ptr_entries);
set_length(number_of_int64_entries + number_of_ptr_entries +
number_of_int32_entries);
int current_index = number_of_int64_entries;
set_first_code_ptr_index(current_index);
current_index += number_of_code_ptr_entries;
set_first_heap_ptr_index(current_index);
current_index += number_of_heap_ptr_entries;
set_first_int32_index(current_index);
current_index += number_of_int32_entries;
set_length(current_index);
}
int64_t ConstantPoolArray::get_int64_entry(int index) {
ASSERT(map() == GetHeap()->constant_pool_array_map());
ASSERT(index >= 0 && index < first_ptr_index());
ASSERT(index >= 0 && index < first_code_ptr_index());
return READ_INT64_FIELD(this, OffsetOfElementAt(index));
}
double ConstantPoolArray::get_int64_entry_as_double(int index) {
STATIC_ASSERT(kDoubleSize == kInt64Size);
ASSERT(map() == GetHeap()->constant_pool_array_map());
ASSERT(index >= 0 && index < first_ptr_index());
ASSERT(index >= 0 && index < first_code_ptr_index());
return READ_DOUBLE_FIELD(this, OffsetOfElementAt(index));
}
Object* ConstantPoolArray::get_ptr_entry(int index) {
Address ConstantPoolArray::get_code_ptr_entry(int index) {
ASSERT(map() == GetHeap()->constant_pool_array_map());
ASSERT(index >= first_ptr_index() && index < first_int32_index());
ASSERT(index >= first_code_ptr_index() && index < first_heap_ptr_index());
return reinterpret_cast<Address>(READ_FIELD(this, OffsetOfElementAt(index)));
}
Object* ConstantPoolArray::get_heap_ptr_entry(int index) {
ASSERT(map() == GetHeap()->constant_pool_array_map());
ASSERT(index >= first_heap_ptr_index() && index < first_int32_index());
return READ_FIELD(this, OffsetOfElementAt(index));
}
@ -2260,9 +2281,16 @@ int32_t ConstantPoolArray::get_int32_entry(int index) {
}
void ConstantPoolArray::set(int index, Address value) {
ASSERT(map() == GetHeap()->constant_pool_array_map());
ASSERT(index >= first_code_ptr_index() && index < first_heap_ptr_index());
WRITE_FIELD(this, OffsetOfElementAt(index), reinterpret_cast<Object*>(value));
}
void ConstantPoolArray::set(int index, Object* value) {
ASSERT(map() == GetHeap()->constant_pool_array_map());
ASSERT(index >= first_ptr_index() && index < first_int32_index());
ASSERT(index >= first_code_ptr_index() && index < first_int32_index());
WRITE_FIELD(this, OffsetOfElementAt(index), value);
WRITE_BARRIER(GetHeap(), this, OffsetOfElementAt(index), value);
}
@ -2270,7 +2298,7 @@ void ConstantPoolArray::set(int index, Object* value) {
void ConstantPoolArray::set(int index, int64_t value) {
ASSERT(map() == GetHeap()->constant_pool_array_map());
ASSERT(index >= first_int64_index() && index < first_ptr_index());
ASSERT(index >= first_int64_index() && index < first_code_ptr_index());
WRITE_INT64_FIELD(this, OffsetOfElementAt(index), value);
}
@ -2278,7 +2306,7 @@ void ConstantPoolArray::set(int index, int64_t value) {
void ConstantPoolArray::set(int index, double value) {
STATIC_ASSERT(kDoubleSize == kInt64Size);
ASSERT(map() == GetHeap()->constant_pool_array_map());
ASSERT(index >= first_int64_index() && index < first_ptr_index());
ASSERT(index >= first_int64_index() && index < first_code_ptr_index());
WRITE_DOUBLE_FIELD(this, OffsetOfElementAt(index), value);
}
@ -3846,7 +3874,8 @@ int HeapObject::SizeFromMap(Map* map) {
if (instance_type == CONSTANT_POOL_ARRAY_TYPE) {
return ConstantPoolArray::SizeFor(
reinterpret_cast<ConstantPoolArray*>(this)->count_of_int64_entries(),
reinterpret_cast<ConstantPoolArray*>(this)->count_of_ptr_entries(),
reinterpret_cast<ConstantPoolArray*>(this)->count_of_code_ptr_entries(),
reinterpret_cast<ConstantPoolArray*>(this)->count_of_heap_ptr_entries(),
reinterpret_cast<ConstantPoolArray*>(this)->count_of_int32_entries());
}
if (instance_type >= FIRST_FIXED_TYPED_ARRAY_TYPE &&

View File

@ -604,11 +604,14 @@ void ConstantPoolArray::ConstantPoolArrayPrint(FILE* out) {
HeapObject::PrintHeader(out, "ConstantPoolArray");
PrintF(out, " - length: %d", length());
for (int i = 0; i < length(); i++) {
if (i < first_ptr_index()) {
if (i < first_code_ptr_index()) {
PrintF(out, "\n [%d]: double: %g", i, get_int64_entry_as_double(i));
} else if (i < first_heap_ptr_index()) {
PrintF(out, "\n [%d]: code target pointer: %p", i,
reinterpret_cast<void*>(get_code_ptr_entry(i)));
} else if (i < first_int32_index()) {
PrintF(out, "\n [%d]: pointer: %p", i,
reinterpret_cast<void*>(get_ptr_entry(i)));
PrintF(out, "\n [%d]: heap pointer: %p", i,
reinterpret_cast<void*>(get_heap_ptr_entry(i)));
} else {
PrintF(out, "\n [%d]: int32: %d", i, get_int32_entry(i));
}

View File

@ -489,16 +489,16 @@ void StaticMarkingVisitor<StaticVisitor>::VisitConstantPoolArray(
Map* map, HeapObject* object) {
Heap* heap = map->GetHeap();
ConstantPoolArray* constant_pool = ConstantPoolArray::cast(object);
if (constant_pool->count_of_ptr_entries() > 0) {
int first_ptr_offset = constant_pool->OffsetOfElementAt(
constant_pool->first_ptr_index());
int last_ptr_offset = constant_pool->OffsetOfElementAt(
constant_pool->first_ptr_index() +
constant_pool->count_of_ptr_entries() - 1);
StaticVisitor::VisitPointers(
heap,
HeapObject::RawField(object, first_ptr_offset),
HeapObject::RawField(object, last_ptr_offset));
for (int i = 0; i < constant_pool->count_of_code_ptr_entries(); i++) {
int index = constant_pool->first_code_ptr_index() + i;
Address code_entry =
reinterpret_cast<Address>(constant_pool->RawFieldOfElementAt(index));
StaticVisitor::VisitCodeEntry(heap, code_entry);
}
for (int i = 0; i < constant_pool->count_of_heap_ptr_entries(); i++) {
int index = constant_pool->first_heap_ptr_index() + i;
StaticVisitor::VisitPointer(heap,
constant_pool->RawFieldOfElementAt(index));
}
}

View File

@ -9452,13 +9452,13 @@ bool Map::EquivalentToForNormalization(Map* other,
void ConstantPoolArray::ConstantPoolIterateBody(ObjectVisitor* v) {
if (count_of_ptr_entries() > 0) {
int first_ptr_offset = OffsetOfElementAt(first_ptr_index());
int last_ptr_offset =
OffsetOfElementAt(first_ptr_index() + count_of_ptr_entries() - 1);
v->VisitPointers(
HeapObject::RawField(this, first_ptr_offset),
HeapObject::RawField(this, last_ptr_offset));
for (int i = 0; i < count_of_code_ptr_entries(); i++) {
int index = first_code_ptr_index() + i;
v->VisitCodeEntry(reinterpret_cast<Address>(RawFieldOfElementAt(index)));
}
for (int i = 0; i < count_of_heap_ptr_entries(); i++) {
int index = first_heap_ptr_index() + i;
v->VisitPointer(RawFieldOfElementAt(index));
}
}

View File

@ -3158,29 +3158,35 @@ class FixedDoubleArray: public FixedArrayBase {
// ConstantPoolArray describes a fixed-sized array containing constant pool
// entires.
// The format of the pool is:
// [0]: Field holding the first index which is a pointer entry
// [1]: Field holding the first index which is a int32 entry
// [2] ... [first_ptr_index() - 1]: 64 bit entries
// [first_ptr_index()] ... [first_int32_index() - 1]: pointer entries
// [first_int32_index()] ... [length - 1]: 32 bit entries
// [0]: Field holding the first index which is a raw code target pointer entry
// [1]: Field holding the first index which is a heap pointer entry
// [2]: Field holding the first index which is a int32 entry
// [3] ... [first_code_ptr_index() - 1] : 64 bit entries
// [first_code_ptr_index()] ... [first_heap_ptr_index() - 1] : code pointers
// [first_heap_ptr_index()] ... [first_int32_index() - 1] : heap pointers
// [first_int32_index()] ... [length - 1] : 32 bit entries
class ConstantPoolArray: public FixedArrayBase {
public:
// Getters for the field storing the first index for different type entries.
inline int first_ptr_index();
inline int first_code_ptr_index();
inline int first_heap_ptr_index();
inline int first_int64_index();
inline int first_int32_index();
// Getters for counts of different type entries.
inline int count_of_ptr_entries();
inline int count_of_code_ptr_entries();
inline int count_of_heap_ptr_entries();
inline int count_of_int64_entries();
inline int count_of_int32_entries();
// Setter and getter for pool elements.
inline Object* get_ptr_entry(int index);
inline Address get_code_ptr_entry(int index);
inline Object* get_heap_ptr_entry(int index);
inline int64_t get_int64_entry(int index);
inline int32_t get_int32_entry(int index);
inline double get_int64_entry_as_double(int index);
inline void set(int index, Address value);
inline void set(int index, Object* value);
inline void set(int index, int64_t value);
inline void set(int index, double value);
@ -3188,7 +3194,8 @@ class ConstantPoolArray: public FixedArrayBase {
// Set up initial state.
inline void SetEntryCounts(int number_of_int64_entries,
int number_of_ptr_entries,
int number_of_code_ptr_entries,
int number_of_heap_ptr_entries,
int number_of_int32_entries);
// Copy operations
@ -3196,10 +3203,12 @@ class ConstantPoolArray: public FixedArrayBase {
// Garbage collection support.
inline static int SizeFor(int number_of_int64_entries,
int number_of_ptr_entries,
int number_of_code_ptr_entries,
int number_of_heap_ptr_entries,
int number_of_int32_entries) {
return RoundUp(OffsetAt(number_of_int64_entries,
number_of_ptr_entries,
number_of_code_ptr_entries,
number_of_heap_ptr_entries,
number_of_int32_entries),
kPointerSize);
}
@ -3208,22 +3217,33 @@ class ConstantPoolArray: public FixedArrayBase {
inline int OffsetOfElementAt(int index) {
ASSERT(index < length());
if (index >= first_int32_index()) {
return OffsetAt(count_of_int64_entries(), count_of_ptr_entries(),
index - first_int32_index());
} else if (index >= first_ptr_index()) {
return OffsetAt(count_of_int64_entries(), index - first_ptr_index(), 0);
return OffsetAt(count_of_int64_entries(), count_of_code_ptr_entries(),
count_of_heap_ptr_entries(), index - first_int32_index());
} else if (index >= first_heap_ptr_index()) {
return OffsetAt(count_of_int64_entries(), count_of_code_ptr_entries(),
index - first_heap_ptr_index(), 0);
} else if (index >= first_code_ptr_index()) {
return OffsetAt(count_of_int64_entries(), index - first_code_ptr_index(),
0, 0);
} else {
return OffsetAt(index, 0, 0);
return OffsetAt(index, 0, 0, 0);
}
}
// Casting.
static inline ConstantPoolArray* cast(Object* obj);
// Garbage collection support.
Object** RawFieldOfElementAt(int index) {
return HeapObject::RawField(this, OffsetOfElementAt(index));
}
// Layout description.
static const int kFirstPointerIndexOffset = FixedArray::kHeaderSize;
static const int kFirstCodePointerIndexOffset = FixedArray::kHeaderSize;
static const int kFirstHeapPointerIndexOffset =
kFirstCodePointerIndexOffset + kPointerSize;
static const int kFirstInt32IndexOffset =
kFirstPointerIndexOffset + kPointerSize;
kFirstHeapPointerIndexOffset + kPointerSize;
static const int kFirstOffset = kFirstInt32IndexOffset + kPointerSize;
// Dispatched behavior.
@ -3233,15 +3253,18 @@ class ConstantPoolArray: public FixedArrayBase {
DECLARE_VERIFIER(ConstantPoolArray)
private:
inline void set_first_ptr_index(int value);
inline void set_first_code_ptr_index(int value);
inline void set_first_heap_ptr_index(int value);
inline void set_first_int32_index(int value);
inline static int OffsetAt(int number_of_int64_entries,
int number_of_ptr_entries,
int number_of_code_ptr_entries,
int number_of_heap_ptr_entries,
int number_of_int32_entries) {
return kFirstOffset
+ (number_of_int64_entries * kInt64Size)
+ (number_of_ptr_entries * kPointerSize)
+ (number_of_code_ptr_entries * kPointerSize)
+ (number_of_heap_ptr_entries * kPointerSize)
+ (number_of_int32_entries * kInt32Size);
}

View File

@ -11,6 +11,15 @@
using namespace v8::internal;
Code* DummyCode(LocalContext* context) {
CompileRun("function foo() {};");
i::Handle<i::JSFunction> fun = v8::Utils::OpenHandle(
*v8::Local<v8::Function>::Cast(
(*context)->Global()->Get(v8_str("foo"))));
return fun->code();
}
TEST(ConstantPool) {
LocalContext context;
Isolate* isolate = CcTest::i_isolate();
@ -19,32 +28,41 @@ TEST(ConstantPool) {
v8::HandleScope scope(context->GetIsolate());
// Check construction.
Handle<ConstantPoolArray> array = factory->NewConstantPoolArray(3, 2, 1);
Handle<ConstantPoolArray> array = factory->NewConstantPoolArray(3, 1, 2, 1);
CHECK_EQ(array->count_of_int64_entries(), 3);
CHECK_EQ(array->count_of_ptr_entries(), 2);
CHECK_EQ(array->count_of_code_ptr_entries(), 1);
CHECK_EQ(array->count_of_heap_ptr_entries(), 2);
CHECK_EQ(array->count_of_int32_entries(), 1);
CHECK_EQ(array->length(), 6);
CHECK_EQ(array->length(), 7);
CHECK_EQ(array->first_int64_index(), 0);
CHECK_EQ(array->first_ptr_index(), 3);
CHECK_EQ(array->first_int32_index(), 5);
CHECK_EQ(array->first_code_ptr_index(), 3);
CHECK_EQ(array->first_heap_ptr_index(), 4);
CHECK_EQ(array->first_int32_index(), 6);
// Check getters and setters.
int64_t big_number = V8_2PART_UINT64_C(0x12345678, 9ABCDEF0);
Handle<Object> object = factory->NewHeapNumber(4.0);
Code* code = DummyCode(&context);
array->set(0, big_number);
array->set(1, 0.5);
array->set(3, *object);
array->set(5, 50);
array->set(2, 3e-24);
array->set(3, code->entry());
array->set(4, code);
array->set(5, *object);
array->set(6, 50);
CHECK_EQ(array->get_int64_entry(0), big_number);
CHECK_EQ(array->get_int64_entry_as_double(1), 0.5);
CHECK_EQ(array->get_ptr_entry(3), *object);
CHECK_EQ(array->get_int32_entry(5), 50);
CHECK_EQ(array->get_int64_entry_as_double(2), 3e-24);
CHECK_EQ(array->get_code_ptr_entry(3), code->entry());
CHECK_EQ(array->get_heap_ptr_entry(4), code);
CHECK_EQ(array->get_heap_ptr_entry(5), *object);
CHECK_EQ(array->get_int32_entry(6), 50);
// Check pointers are updated on GC.
Object* old_ptr = array->get_ptr_entry(3);
Object* old_ptr = array->get_heap_ptr_entry(5);
CHECK_EQ(*object, old_ptr);
heap->CollectGarbage(NEW_SPACE);
Object* new_ptr = array->get_ptr_entry(3);
Object* new_ptr = array->get_heap_ptr_entry(5);
CHECK_NE(*object, old_ptr);
CHECK_EQ(*object, new_ptr);
}