Index: src/elements.cc |
diff --git a/src/elements.cc b/src/elements.cc |
index 331f6bc4b49162864f52c863497bfa020b453e52..f6a1697829eb52ea99a36df53eca5befe61bd0ad 100644 |
--- a/src/elements.cc |
+++ b/src/elements.cc |
@@ -131,95 +131,135 @@ 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); |
+#ifdef 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)->IsTheHole()); |
+ } |
+ } |
+#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() && |
+ (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(); |
+ 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; |
+#ifdef 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)->IsTheHole()); |
+ } |
+ } |
+#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); |
- } |
+ 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_the_hole(i + to_start); |
+ } |
+ } |
+ 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); |
+#ifdef 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)->IsTheHole()); |
+ } |
+ } |
+#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() && |
+ (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 +269,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() && |
+ (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 +476,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 +488,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 +734,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 +809,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 +1107,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 +1252,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) { |