Chromium Code Reviews| Index: src/elements.cc |
| diff --git a/src/elements.cc b/src/elements.cc |
| index 331f6bc4b49162864f52c863497bfa020b453e52..bf8dcf8187e6d22dc75cef4fc47460a9ac5e6194 100644 |
| --- a/src/elements.cc |
| +++ b/src/elements.cc |
| @@ -131,95 +131,141 @@ static Failure* ThrowArrayLengthRangeError(Heap* heap) { |
| } |
| -void CopyObjectToObjectElements(AssertNoAllocation* no_gc, |
| - FixedArray* from_obj, |
| +void CopyObjectToObjectElements(FixedArray* from, |
| ElementsKind from_kind, |
| uint32_t from_start, |
| - FixedArray* to_obj, |
| + FixedArray* to, |
| ElementsKind to_kind, |
| uint32_t to_start, |
| - int copy_size) { |
| - ASSERT(to_obj->map() != HEAP->fixed_cow_array_map()); |
| + int raw_copy_size, |
| + WriteBarrierMode mode) { |
| + ASSERT(to->map() != HEAP->fixed_cow_array_map()); |
| ASSERT(from_kind == FAST_ELEMENTS || from_kind == FAST_SMI_ONLY_ELEMENTS); |
| ASSERT(to_kind == FAST_ELEMENTS || to_kind == FAST_SMI_ONLY_ELEMENTS); |
| - if (copy_size == -1) { |
| - copy_size = Min(from_obj->length() - from_start, |
| - to_obj->length() - to_start); |
| + int copy_size = raw_copy_size; |
| + if (raw_copy_size < 0) { |
| + ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || |
| + raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); |
| + copy_size = Min(from->length() - from_start, |
| + to->length() - to_start); |
| +#if DEBUG |
|
Jakob Kummerow
2012/03/12 15:33:28
s/#if/#ifdef/
Again below.
danno
2012/03/12 20:35:03
Done.
|
| + // FAST_ELEMENT arrays cannot be uninitialized. Ensure they are already |
| + // marked with the hole. |
| + if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { |
| + Object* hole = from->GetHeap()->the_hole_value(); |
| + for (int i = to_start + copy_size; i < to->length(); ++i) { |
| + ASSERT(to->get(i) == hole); |
|
Jakob Kummerow
2012/03/12 15:33:28
ASSERT(to->is_the_hole(i))?
danno
2012/03/12 20:35:03
Done.
|
| + } |
| + } |
| +#endif |
| } |
| - ASSERT(((copy_size + static_cast<int>(to_start)) <= to_obj->length() && |
| - (copy_size + static_cast<int>(from_start)) <= from_obj->length())); |
| + ASSERT(((copy_size + static_cast<int>(to_start)) <= to->length() && |
|
Jakob Kummerow
2012/03/12 15:33:28
nit: you can remove at least one pair of parenthes
danno
2012/03/12 20:35:03
Done.
|
| + (copy_size + static_cast<int>(from_start)) <= from->length())); |
| if (copy_size == 0) return; |
| - Address to = to_obj->address() + FixedArray::kHeaderSize; |
| - Address from = from_obj->address() + FixedArray::kHeaderSize; |
| - CopyWords(reinterpret_cast<Object**>(to) + to_start, |
| - reinterpret_cast<Object**>(from) + from_start, |
| + Address to_address = to->address() + FixedArray::kHeaderSize; |
| + Address from_address = from->address() + FixedArray::kHeaderSize; |
| + CopyWords(reinterpret_cast<Object**>(to_address) + to_start, |
| + reinterpret_cast<Object**>(from_address) + from_start, |
| copy_size); |
| - if (from_kind == FAST_ELEMENTS && to_kind == FAST_ELEMENTS) { |
| - Heap* heap = from_obj->GetHeap(); |
| - WriteBarrierMode mode = to_obj->GetWriteBarrierMode(*no_gc); |
| - if (mode == UPDATE_WRITE_BARRIER) { |
| - heap->RecordWrites(to_obj->address(), |
| - to_obj->OffsetOfElementAt(to_start), |
| + if (from_kind == FAST_ELEMENTS && to_kind == FAST_ELEMENTS && |
| + mode == UPDATE_WRITE_BARRIER) { |
| + Heap* heap = from->GetHeap(); |
| + if (!heap->InNewSpace(to)) { |
| + heap->RecordWrites(to->address(), |
| + to->OffsetOfElementAt(to_start), |
| copy_size); |
| } |
| - heap->incremental_marking()->RecordWrites(to_obj); |
| + heap->incremental_marking()->RecordWrites(to); |
| } |
| } |
| - |
| - |
| static void CopyDictionaryToObjectElements(SeededNumberDictionary* from, |
| uint32_t from_start, |
| FixedArray* to, |
| ElementsKind to_kind, |
| uint32_t to_start, |
| - int copy_size) { |
| + int raw_copy_size, |
| + WriteBarrierMode mode) { |
| + int copy_size = raw_copy_size; |
| + Heap* heap = from->GetHeap(); |
| + Object* hole = heap->the_hole_value(); |
| + if (raw_copy_size < 0) { |
| + ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || |
| + raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); |
| + copy_size = from->max_number_key() + 1 - from_start; |
| +#if DEBUG |
| + // FAST_ELEMENT arrays cannot be uninitialized. Ensure they are already |
| + // marked with the hole. |
| + if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { |
| + for (int i = to_start + copy_size; i < to->length(); ++i) { |
| + ASSERT(to->get(i) == hole); |
|
Jakob Kummerow
2012/03/12 15:33:28
ASSERT(to->is_the_hole(i))?
danno
2012/03/12 20:35:03
Done.
|
| + } |
| + } |
| +#endif |
| + } |
| + ASSERT((copy_size + static_cast<int>(to_start)) <= to->length()); |
| ASSERT(to != from); |
| ASSERT(to_kind == FAST_ELEMENTS || to_kind == FAST_SMI_ONLY_ELEMENTS); |
| - ASSERT(copy_size == -1 || |
| - (copy_size + static_cast<int>(to_start)) <= to->length()); |
| - WriteBarrierMode mode = to_kind == FAST_ELEMENTS |
| - ? UPDATE_WRITE_BARRIER |
| - : SKIP_WRITE_BARRIER; |
| - uint32_t copy_limit = (copy_size == -1) |
| - ? to->length() |
| - : Min(to_start + copy_size, static_cast<uint32_t>(to->length())); |
| - for (int i = 0; i < from->Capacity(); ++i) { |
| - Object* key = from->KeyAt(i); |
| - if (key->IsNumber()) { |
| - uint32_t entry = static_cast<uint32_t>(key->Number()); |
| - if (entry >= to_start && entry < copy_limit) { |
| - Object* value = from->ValueAt(i); |
| - ASSERT(to_kind == FAST_ELEMENTS || value->IsSmi()); |
| - to->set(entry, value, mode); |
| - } |
| + ASSERT(copy_size > 0 || copy_size == ElementsAccessor::kCopyToEnd || |
|
Jakob Kummerow
2012/03/12 15:33:28
I don't see how copy_size can ever be < 0 at this
danno
2012/03/12 20:35:03
Done.
|
| + copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); |
| + ASSERT(copy_size + static_cast<int>(to_start) <= to->length()); |
|
Jakob Kummerow
2012/03/12 15:33:28
Duplicate assertion (see line 207).
danno
2012/03/12 20:35:03
Done.
|
| + if (copy_size == 0) return; |
| + for (int i = 0; i < copy_size; i++) { |
| + int entry = from->FindEntry(i + from_start); |
| + if (entry != SeededNumberDictionary::kNotFound) { |
| + Object* value = from->ValueAt(entry); |
| + ASSERT(!value->IsTheHole()); |
| + to->set(i + to_start, value, SKIP_WRITE_BARRIER); |
| + } else { |
| + to->set(i + to_start, hole, SKIP_WRITE_BARRIER); |
|
Jakob Kummerow
2012/03/12 15:33:28
to->set_the_hole(i + to_start)?
danno
2012/03/12 20:35:03
Done.
|
| } |
| } |
| + if (to_kind == FAST_ELEMENTS) { |
| + if (!heap->InNewSpace(to)) { |
| + heap->RecordWrites(to->address(), |
| + to->OffsetOfElementAt(to_start), |
| + copy_size); |
| + } |
| + heap->incremental_marking()->RecordWrites(to); |
| + } |
| } |
| MUST_USE_RESULT static MaybeObject* CopyDoubleToObjectElements( |
| - FixedDoubleArray* from_obj, |
| + FixedDoubleArray* from, |
| uint32_t from_start, |
| - FixedArray* to_obj, |
| + FixedArray* to, |
| ElementsKind to_kind, |
| uint32_t to_start, |
| - int copy_size) { |
| + int raw_copy_size) { |
| ASSERT(to_kind == FAST_ELEMENTS || to_kind == FAST_SMI_ONLY_ELEMENTS); |
| - if (copy_size == -1) { |
| - copy_size = Min(from_obj->length() - from_start, |
| - to_obj->length() - to_start); |
| + int copy_size = raw_copy_size; |
| + if (raw_copy_size < 0) { |
| + ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || |
| + raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); |
| + copy_size = Min(from->length() - from_start, |
| + to->length() - to_start); |
| +#if DEBUG |
| + // FAST_ELEMENT arrays cannot be uninitialized. Ensure they are already |
| + // marked with the hole. |
| + if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { |
| + Object* hole = from->GetHeap()->the_hole_value(); |
| + for (int i = to_start + copy_size; i < to->length(); ++i) { |
| + ASSERT(to->get(i) == hole); |
|
Jakob Kummerow
2012/03/12 15:33:28
ASSERT(to->is_the_hole(i))?
danno
2012/03/12 20:35:03
Done.
|
| + } |
| + } |
| +#endif |
| } |
| - ASSERT(((copy_size + static_cast<int>(to_start)) <= to_obj->length() && |
| - (copy_size + static_cast<int>(from_start)) <= from_obj->length())); |
| - if (copy_size == 0) return from_obj; |
| + ASSERT(((copy_size + static_cast<int>(to_start)) <= to->length() && |
|
Jakob Kummerow
2012/03/12 15:33:28
nit: you can remove at least one pair of parenthes
danno
2012/03/12 20:35:03
Done.
|
| + (copy_size + static_cast<int>(from_start)) <= from->length())); |
| + if (copy_size == 0) return from; |
| for (int i = 0; i < copy_size; ++i) { |
| if (to_kind == FAST_SMI_ONLY_ELEMENTS) { |
| UNIMPLEMENTED(); |
| return Failure::Exception(); |
| } else { |
| - MaybeObject* maybe_value = from_obj->get(i + from_start); |
| + MaybeObject* maybe_value = from->get(i + from_start); |
| Object* value; |
| ASSERT(to_kind == FAST_ELEMENTS); |
| // Because FAST_DOUBLE_ELEMENTS -> FAST_ELEMENT allocate HeapObjects |
| @@ -229,42 +275,109 @@ MUST_USE_RESULT static MaybeObject* CopyDoubleToObjectElements( |
| // can't be taken from new space. |
| if (!maybe_value->ToObject(&value)) { |
| ASSERT(maybe_value->IsRetryAfterGC() || maybe_value->IsOutOfMemory()); |
| - Heap* heap = from_obj->GetHeap(); |
| + Heap* heap = from->GetHeap(); |
| MaybeObject* maybe_value_object = |
| - heap->AllocateHeapNumber(from_obj->get_scalar(i + from_start), |
| + heap->AllocateHeapNumber(from->get_scalar(i + from_start), |
| TENURED); |
| if (!maybe_value_object->ToObject(&value)) return maybe_value_object; |
| } |
| - to_obj->set(i + to_start, value, UPDATE_WRITE_BARRIER); |
| + to->set(i + to_start, value, UPDATE_WRITE_BARRIER); |
| } |
| } |
| - return to_obj; |
| + return to; |
| } |
| -static void CopyDoubleToDoubleElements(FixedDoubleArray* from_obj, |
| +static void CopyDoubleToDoubleElements(FixedDoubleArray* from, |
| uint32_t from_start, |
| - FixedDoubleArray* to_obj, |
| + FixedDoubleArray* to, |
| uint32_t to_start, |
| - int copy_size) { |
| - if (copy_size == -1) { |
| - copy_size = Min(from_obj->length() - from_start, |
| - to_obj->length() - to_start); |
| + int raw_copy_size) { |
| + int copy_size = raw_copy_size; |
| + if (raw_copy_size < 0) { |
| + ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || |
| + raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); |
| + copy_size = Min(from->length() - from_start, |
| + to->length() - to_start); |
| + if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { |
| + for (int i = to_start + copy_size; i < to->length(); ++i) { |
| + to->set_the_hole(i); |
| + } |
| + } |
| } |
| - ASSERT(((copy_size + static_cast<int>(to_start)) <= to_obj->length() && |
| - (copy_size + static_cast<int>(from_start)) <= from_obj->length())); |
| + ASSERT(((copy_size + static_cast<int>(to_start)) <= to->length() && |
| + (copy_size + static_cast<int>(from_start)) <= from->length())); |
| if (copy_size == 0) return; |
| - Address to = to_obj->address() + FixedDoubleArray::kHeaderSize; |
| - Address from = from_obj->address() + FixedDoubleArray::kHeaderSize; |
| - to += kDoubleSize * to_start; |
| - from += kDoubleSize * from_start; |
| + Address to_address = to->address() + FixedDoubleArray::kHeaderSize; |
| + Address from_address = from->address() + FixedDoubleArray::kHeaderSize; |
| + to_address += kDoubleSize * to_start; |
| + from_address += kDoubleSize * from_start; |
| int words_per_double = (kDoubleSize / kPointerSize); |
| - CopyWords(reinterpret_cast<Object**>(to), |
| - reinterpret_cast<Object**>(from), |
| + CopyWords(reinterpret_cast<Object**>(to_address), |
| + reinterpret_cast<Object**>(from_address), |
| words_per_double * copy_size); |
| } |
| +static void CopyObjectToDoubleElements(FixedArray* from, |
| + uint32_t from_start, |
| + FixedDoubleArray* to, |
| + uint32_t to_start, |
| + int raw_copy_size) { |
| + int copy_size = raw_copy_size; |
| + if (raw_copy_size < 0) { |
| + ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || |
| + raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); |
| + copy_size = from->length() - from_start; |
| + if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { |
| + for (int i = to_start + copy_size; i < to->length(); ++i) { |
| + to->set_the_hole(i); |
| + } |
| + } |
| + } |
| + ASSERT(((copy_size + static_cast<int>(to_start)) <= to->length() && |
|
Jakob Kummerow
2012/03/12 15:33:28
nit: you can remove at least one pair of parenthes
danno
2012/03/12 20:35:03
Done.
|
| + (copy_size + static_cast<int>(from_start)) <= from->length())); |
| + if (copy_size == 0) return; |
| + for (int i = 0; i < copy_size; i++) { |
| + Object* hole_or_object = from->get(i + from_start); |
| + if (hole_or_object->IsTheHole()) { |
| + to->set_the_hole(i + to_start); |
| + } else { |
| + to->set(i + to_start, hole_or_object->Number()); |
| + } |
| + } |
| +} |
| + |
| + |
| +static void CopyDictionaryToDoubleElements(SeededNumberDictionary* from, |
| + uint32_t from_start, |
| + FixedDoubleArray* to, |
| + uint32_t to_start, |
| + int raw_copy_size) { |
| + int copy_size = raw_copy_size; |
| + if (copy_size < 0) { |
| + ASSERT(copy_size == ElementsAccessor::kCopyToEnd || |
| + copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); |
| + copy_size = from->max_number_key() + 1 - from_start; |
| + if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { |
| + for (int i = to_start + copy_size; i < to->length(); ++i) { |
| + to->set_the_hole(i); |
| + } |
| + } |
| + } |
| + ASSERT(copy_size + static_cast<int>(to_start) <= to->length()); |
| + if (copy_size == 0) return; |
| + for (int i = 0; i < copy_size; i++) { |
| + int entry = from->FindEntry(i + from_start); |
| + if (entry != SeededNumberDictionary::kNotFound) { |
| + to->set(i + to_start, from->ValueAt(entry)->Number()); |
| + } else { |
| + to->set_the_hole(i + to_start); |
| + } |
| + } |
| +} |
| + |
| + |
| // Base class for element handler implementations. Contains the |
| // the common logic for objects with different ElementsKinds. |
| // Subclasses must specialize method for which the element |
| @@ -369,7 +482,8 @@ class ElementsAccessorBase : public ElementsAccessor { |
| FixedArrayBase* to, |
| ElementsKind to_kind, |
| uint32_t to_start, |
| - int copy_size) { |
| + int copy_size, |
| + WriteBarrierMode mode) { |
| UNREACHABLE(); |
| return NULL; |
| } |
| @@ -380,12 +494,16 @@ class ElementsAccessorBase : public ElementsAccessor { |
| ElementsKind to_kind, |
| uint32_t to_start, |
| int copy_size, |
| + WriteBarrierMode mode, |
| FixedArrayBase* from) { |
| if (from == NULL) { |
| from = from_holder->elements(); |
| } |
| + if (from->length() == 0) { |
| + return from; |
| + } |
| return ElementsAccessorSubclass::CopyElementsImpl( |
| - from, from_start, to, to_kind, to_start, copy_size); |
| + from, from_start, to, to_kind, to_start, copy_size, mode); |
| } |
| virtual MaybeObject* AddElementsToFixedArray(Object* receiver, |
| @@ -622,16 +740,21 @@ class FastObjectElementsAccessor |
| FixedArrayBase* to, |
| ElementsKind to_kind, |
| uint32_t to_start, |
| - int copy_size) { |
| + int copy_size, |
| + WriteBarrierMode mode) { |
| switch (to_kind) { |
| case FAST_SMI_ONLY_ELEMENTS: |
| case FAST_ELEMENTS: { |
| - AssertNoAllocation no_gc; |
| CopyObjectToObjectElements( |
| - &no_gc, FixedArray::cast(from), ElementsTraits::Kind, from_start, |
| - FixedArray::cast(to), to_kind, to_start, copy_size); |
| + FixedArray::cast(from), ElementsTraits::Kind, from_start, |
| + FixedArray::cast(to), to_kind, to_start, copy_size, mode); |
| return from; |
| } |
| + case FAST_DOUBLE_ELEMENTS: |
| + CopyObjectToDoubleElements( |
| + FixedArray::cast(from), from_start, |
| + FixedDoubleArray::cast(to), to_start, copy_size); |
| + return from; |
| default: |
| UNREACHABLE(); |
| } |
| @@ -692,7 +815,8 @@ class FastDoubleElementsAccessor |
| FixedArrayBase* to, |
| ElementsKind to_kind, |
| uint32_t to_start, |
| - int copy_size) { |
| + int copy_size, |
| + WriteBarrierMode mode) { |
| switch (to_kind) { |
| case FAST_SMI_ONLY_ELEMENTS: |
| case FAST_ELEMENTS: |
| @@ -989,13 +1113,19 @@ class DictionaryElementsAccessor |
| FixedArrayBase* to, |
| ElementsKind to_kind, |
| uint32_t to_start, |
| - int copy_size) { |
| + int copy_size, |
| + WriteBarrierMode mode) { |
| switch (to_kind) { |
| case FAST_SMI_ONLY_ELEMENTS: |
| case FAST_ELEMENTS: |
| CopyDictionaryToObjectElements( |
| SeededNumberDictionary::cast(from), from_start, |
| - FixedArray::cast(to), to_kind, to_start, copy_size); |
| + FixedArray::cast(to), to_kind, to_start, copy_size, mode); |
| + return from; |
| + case FAST_DOUBLE_ELEMENTS: |
| + CopyDictionaryToDoubleElements( |
| + SeededNumberDictionary::cast(from), from_start, |
| + FixedDoubleArray::cast(to), to_start, copy_size); |
| return from; |
| default: |
| UNREACHABLE(); |
| @@ -1128,12 +1258,13 @@ class NonStrictArgumentsElementsAccessor : public ElementsAccessorBase< |
| FixedArrayBase* to, |
| ElementsKind to_kind, |
| uint32_t to_start, |
| - int copy_size) { |
| + int copy_size, |
| + WriteBarrierMode mode) { |
| FixedArray* parameter_map = FixedArray::cast(from); |
| FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
| ElementsAccessor* accessor = ElementsAccessor::ForArray(arguments); |
| return accessor->CopyElements(NULL, from_start, to, to_kind, |
| - to_start, copy_size, arguments); |
| + to_start, copy_size, mode, arguments); |
| } |
| static uint32_t GetCapacityImpl(FixedArray* parameter_map) { |