Move CopyElements to the accessor of the target.

Review URL: https://chromiumcodereview.appspot.com/11416238

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13292 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
verwaest@chromium.org 2013-01-02 10:09:42 +00:00
parent bccef0c712
commit 537d1d89b0
4 changed files with 130 additions and 104 deletions

View File

@ -576,7 +576,7 @@ BUILTIN(ArrayPush) {
ElementsAccessor* accessor = array->GetElementsAccessor(); ElementsAccessor* accessor = array->GetElementsAccessor();
MaybeObject* maybe_failure = accessor->CopyElements( MaybeObject* maybe_failure = accessor->CopyElements(
NULL, 0, new_elms, kind, 0, NULL, 0, kind, new_elms, 0,
ElementsAccessor::kCopyToEndAndInitializeToHole, elms_obj); ElementsAccessor::kCopyToEndAndInitializeToHole, elms_obj);
ASSERT(!maybe_failure->IsFailure()); ASSERT(!maybe_failure->IsFailure());
USE(maybe_failure); USE(maybe_failure);
@ -623,7 +623,7 @@ BUILTIN(ArrayPush) {
ElementsAccessor* accessor = array->GetElementsAccessor(); ElementsAccessor* accessor = array->GetElementsAccessor();
MaybeObject* maybe_failure = accessor->CopyElements( MaybeObject* maybe_failure = accessor->CopyElements(
NULL, 0, new_elms, kind, 0, NULL, 0, kind, new_elms, 0,
ElementsAccessor::kCopyToEndAndInitializeToHole, elms_obj); ElementsAccessor::kCopyToEndAndInitializeToHole, elms_obj);
ASSERT(!maybe_failure->IsFailure()); ASSERT(!maybe_failure->IsFailure());
USE(maybe_failure); USE(maybe_failure);
@ -785,7 +785,7 @@ BUILTIN(ArrayUnshift) {
ElementsKind kind = array->GetElementsKind(); ElementsKind kind = array->GetElementsKind();
ElementsAccessor* accessor = array->GetElementsAccessor(); ElementsAccessor* accessor = array->GetElementsAccessor();
MaybeObject* maybe_failure = accessor->CopyElements( MaybeObject* maybe_failure = accessor->CopyElements(
NULL, 0, new_elms, kind, to_add, NULL, 0, kind, new_elms, to_add,
ElementsAccessor::kCopyToEndAndInitializeToHole, elms); ElementsAccessor::kCopyToEndAndInitializeToHole, elms);
ASSERT(!maybe_failure->IsFailure()); ASSERT(!maybe_failure->IsFailure());
USE(maybe_failure); USE(maybe_failure);
@ -934,9 +934,8 @@ BUILTIN(ArraySlice) {
if (!maybe_array->To(&result_array)) return maybe_array; if (!maybe_array->To(&result_array)) return maybe_array;
ElementsAccessor* accessor = object->GetElementsAccessor(); ElementsAccessor* accessor = object->GetElementsAccessor();
MaybeObject* maybe_failure = MaybeObject* maybe_failure = accessor->CopyElements(
accessor->CopyElements(NULL, k, result_array->elements(), NULL, k, kind, result_array->elements(), 0, result_len, elms);
kind, 0, result_len, elms);
ASSERT(!maybe_failure->IsFailure()); ASSERT(!maybe_failure->IsFailure());
USE(maybe_failure); USE(maybe_failure);
@ -1037,9 +1036,9 @@ BUILTIN(ArraySplice) {
if (actual_delete_count > 0) { if (actual_delete_count > 0) {
AssertNoAllocation no_gc; AssertNoAllocation no_gc;
ElementsAccessor* accessor = array->GetElementsAccessor(); ElementsAccessor* accessor = array->GetElementsAccessor();
MaybeObject* maybe_failure = MaybeObject* maybe_failure = accessor->CopyElements(
accessor->CopyElements(NULL, actual_start, result_array->elements(), NULL, actual_start, elements_kind, result_array->elements(),
elements_kind, 0, actual_delete_count, elms_obj); 0, actual_delete_count, elms_obj);
// Cannot fail since the origin and target array are of the same elements // Cannot fail since the origin and target array are of the same elements
// kind. // kind.
ASSERT(!maybe_failure->IsFailure()); ASSERT(!maybe_failure->IsFailure());
@ -1105,12 +1104,12 @@ BUILTIN(ArraySplice) {
if (actual_start > 0) { if (actual_start > 0) {
// Copy the part before actual_start as is. // Copy the part before actual_start as is.
MaybeObject* maybe_failure = accessor->CopyElements( MaybeObject* maybe_failure = accessor->CopyElements(
NULL, 0, new_elms, kind, 0, actual_start, elms); NULL, 0, kind, new_elms, 0, actual_start, elms);
ASSERT(!maybe_failure->IsFailure()); ASSERT(!maybe_failure->IsFailure());
USE(maybe_failure); USE(maybe_failure);
} }
MaybeObject* maybe_failure = accessor->CopyElements( MaybeObject* maybe_failure = accessor->CopyElements(
NULL, actual_start + actual_delete_count, new_elms, kind, NULL, actual_start + actual_delete_count, kind, new_elms,
actual_start + item_count, actual_start + item_count,
ElementsAccessor::kCopyToEndAndInitializeToHole, elms); ElementsAccessor::kCopyToEndAndInitializeToHole, elms);
ASSERT(!maybe_failure->IsFailure()); ASSERT(!maybe_failure->IsFailure());
@ -1220,13 +1219,14 @@ BUILTIN(ArrayConcat) {
int j = 0; int j = 0;
FixedArrayBase* storage = result_array->elements(); FixedArrayBase* storage = result_array->elements();
ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind);
for (int i = 0; i < n_arguments; i++) { for (int i = 0; i < n_arguments; i++) {
JSArray* array = JSArray::cast(args[i]); JSArray* array = JSArray::cast(args[i]);
int len = Smi::cast(array->length())->value(); int len = Smi::cast(array->length())->value();
ElementsKind from_kind = array->GetElementsKind();
if (len > 0) { if (len > 0) {
ElementsAccessor* accessor = array->GetElementsAccessor();
MaybeObject* maybe_failure = MaybeObject* maybe_failure =
accessor->CopyElements(array, 0, storage, elements_kind, j, len); accessor->CopyElements(array, 0, from_kind, storage, j, len);
if (maybe_failure->IsFailure()) return maybe_failure; if (maybe_failure->IsFailure()) return maybe_failure;
j += len; j += len;
} }

View File

@ -686,7 +686,7 @@ class ElementsAccessorBase : public ElementsAccessor {
MUST_USE_RESULT static MaybeObject* CopyElementsImpl(FixedArrayBase* from, MUST_USE_RESULT static MaybeObject* CopyElementsImpl(FixedArrayBase* from,
uint32_t from_start, uint32_t from_start,
FixedArrayBase* to, FixedArrayBase* to,
ElementsKind to_kind, ElementsKind from_kind,
uint32_t to_start, uint32_t to_start,
int packed_size, int packed_size,
int copy_size) { int copy_size) {
@ -696,8 +696,8 @@ class ElementsAccessorBase : public ElementsAccessor {
MUST_USE_RESULT virtual MaybeObject* CopyElements(JSObject* from_holder, MUST_USE_RESULT virtual MaybeObject* CopyElements(JSObject* from_holder,
uint32_t from_start, uint32_t from_start,
ElementsKind from_kind,
FixedArrayBase* to, FixedArrayBase* to,
ElementsKind to_kind,
uint32_t to_start, uint32_t to_start,
int copy_size, int copy_size,
FixedArrayBase* from) { FixedArrayBase* from) {
@ -707,8 +707,7 @@ class ElementsAccessorBase : public ElementsAccessor {
} }
if (from_holder) { if (from_holder) {
ElementsKind elements_kind = from_holder->GetElementsKind(); bool is_packed = IsFastPackedElementsKind(from_kind) &&
bool is_packed = IsFastPackedElementsKind(elements_kind) &&
from_holder->IsJSArray(); from_holder->IsJSArray();
if (is_packed) { if (is_packed) {
packed_size = Smi::cast(JSArray::cast(from_holder)->length())->value(); packed_size = Smi::cast(JSArray::cast(from_holder)->length())->value();
@ -718,7 +717,7 @@ class ElementsAccessorBase : public ElementsAccessor {
} }
} }
return ElementsAccessorSubclass::CopyElementsImpl( return ElementsAccessorSubclass::CopyElementsImpl(
from, from_start, to, to_kind, to_start, packed_size, copy_size); from, from_start, to, from_kind, to_start, packed_size, copy_size);
} }
MUST_USE_RESULT virtual MaybeObject* AddElementsToFixedArray( MUST_USE_RESULT virtual MaybeObject* AddElementsToFixedArray(
@ -1003,6 +1002,41 @@ class FastElementsAccessor
}; };
static inline ElementsKind ElementsKindForArray(FixedArrayBase* array) {
switch (array->map()->instance_type()) {
case FIXED_ARRAY_TYPE:
if (array->IsDictionary()) {
return DICTIONARY_ELEMENTS;
} else {
return FAST_HOLEY_ELEMENTS;
}
case FIXED_DOUBLE_ARRAY_TYPE:
return FAST_HOLEY_DOUBLE_ELEMENTS;
case EXTERNAL_BYTE_ARRAY_TYPE:
return EXTERNAL_BYTE_ELEMENTS;
case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
return EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
case EXTERNAL_SHORT_ARRAY_TYPE:
return EXTERNAL_SHORT_ELEMENTS;
case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
return EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
case EXTERNAL_INT_ARRAY_TYPE:
return EXTERNAL_INT_ELEMENTS;
case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
return EXTERNAL_UNSIGNED_INT_ELEMENTS;
case EXTERNAL_FLOAT_ARRAY_TYPE:
return EXTERNAL_FLOAT_ELEMENTS;
case EXTERNAL_DOUBLE_ARRAY_TYPE:
return EXTERNAL_DOUBLE_ELEMENTS;
case EXTERNAL_PIXEL_ARRAY_TYPE:
return EXTERNAL_PIXEL_ELEMENTS;
default:
UNREACHABLE();
}
return FAST_HOLEY_ELEMENTS;
}
template<typename FastElementsAccessorSubclass, template<typename FastElementsAccessorSubclass,
typename KindTraits> typename KindTraits>
class FastSmiOrObjectElementsAccessor class FastSmiOrObjectElementsAccessor
@ -1018,29 +1052,49 @@ class FastSmiOrObjectElementsAccessor
static MaybeObject* CopyElementsImpl(FixedArrayBase* from, static MaybeObject* CopyElementsImpl(FixedArrayBase* from,
uint32_t from_start, uint32_t from_start,
FixedArrayBase* to, FixedArrayBase* to,
ElementsKind to_kind, ElementsKind from_kind,
uint32_t to_start, uint32_t to_start,
int packed_size, int packed_size,
int copy_size) { int copy_size) {
if (IsFastSmiOrObjectElementsKind(to_kind)) { ElementsKind to_kind = KindTraits::Kind;
switch (from_kind) {
case FAST_SMI_ELEMENTS:
case FAST_HOLEY_SMI_ELEMENTS:
case FAST_ELEMENTS:
case FAST_HOLEY_ELEMENTS:
CopyObjectToObjectElements( CopyObjectToObjectElements(
from, KindTraits::Kind, from_start, to, to_kind, to_start, copy_size); from, from_kind, from_start, to, to_kind, to_start, copy_size);
} else if (IsFastDoubleElementsKind(to_kind)) { return to->GetHeap()->undefined_value();
if (IsFastSmiElementsKind(KindTraits::Kind)) { case FAST_DOUBLE_ELEMENTS:
if (IsFastPackedElementsKind(KindTraits::Kind) && case FAST_HOLEY_DOUBLE_ELEMENTS:
packed_size != kPackedSizeNotKnown) { return CopyDoubleToObjectElements(
CopyPackedSmiToDoubleElements( from, from_start, to, to_kind, to_start, copy_size);
from, from_start, to, to_start, packed_size, copy_size); case DICTIONARY_ELEMENTS:
} else { CopyDictionaryToObjectElements(
CopySmiToDoubleElements(from, from_start, to, to_start, copy_size); from, from_start, to, to_kind, to_start, copy_size);
return to->GetHeap()->undefined_value();
case NON_STRICT_ARGUMENTS_ELEMENTS: {
// TODO(verwaest): This is a temporary hack to support extending
// NON_STRICT_ARGUMENTS_ELEMENTS in SetFastElementsCapacityAndLength.
// This case should be UNREACHABLE().
FixedArray* parameter_map = FixedArray::cast(from);
FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1));
ElementsKind from_kind = ElementsKindForArray(arguments);
return CopyElementsImpl(arguments, from_start, to, from_kind,
to_start, packed_size, copy_size);
} }
} else { case EXTERNAL_BYTE_ELEMENTS:
CopyObjectToDoubleElements(from, from_start, to, to_start, copy_size); case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
} case EXTERNAL_SHORT_ELEMENTS:
} else { case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
case EXTERNAL_INT_ELEMENTS:
case EXTERNAL_UNSIGNED_INT_ELEMENTS:
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
case EXTERNAL_PIXEL_ELEMENTS:
UNREACHABLE(); UNREACHABLE();
} }
return to->GetHeap()->undefined_value(); return NULL;
} }
@ -1129,22 +1183,40 @@ class FastDoubleElementsAccessor
static MaybeObject* CopyElementsImpl(FixedArrayBase* from, static MaybeObject* CopyElementsImpl(FixedArrayBase* from,
uint32_t from_start, uint32_t from_start,
FixedArrayBase* to, FixedArrayBase* to,
ElementsKind to_kind, ElementsKind from_kind,
uint32_t to_start, uint32_t to_start,
int packed_size, int packed_size,
int copy_size) { int copy_size) {
switch (to_kind) { switch (from_kind) {
case FAST_SMI_ELEMENTS: case FAST_SMI_ELEMENTS:
case FAST_ELEMENTS: CopyPackedSmiToDoubleElements(
from, from_start, to, to_start, packed_size, copy_size);
break;
case FAST_HOLEY_SMI_ELEMENTS: case FAST_HOLEY_SMI_ELEMENTS:
case FAST_HOLEY_ELEMENTS: CopySmiToDoubleElements(from, from_start, to, to_start, copy_size);
return CopyDoubleToObjectElements( break;
from, from_start, to, to_kind, to_start, copy_size);
case FAST_DOUBLE_ELEMENTS: case FAST_DOUBLE_ELEMENTS:
case FAST_HOLEY_DOUBLE_ELEMENTS: case FAST_HOLEY_DOUBLE_ELEMENTS:
CopyDoubleToDoubleElements(from, from_start, to, to_start, copy_size); CopyDoubleToDoubleElements(from, from_start, to, to_start, copy_size);
return from; break;
default: case FAST_ELEMENTS:
case FAST_HOLEY_ELEMENTS:
CopyObjectToDoubleElements(from, from_start, to, to_start, copy_size);
break;
case DICTIONARY_ELEMENTS:
CopyDictionaryToDoubleElements(
from, from_start, to, to_start, copy_size);
break;
case NON_STRICT_ARGUMENTS_ELEMENTS:
case EXTERNAL_BYTE_ELEMENTS:
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
case EXTERNAL_SHORT_ELEMENTS:
case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
case EXTERNAL_INT_ELEMENTS:
case EXTERNAL_UNSIGNED_INT_ELEMENTS:
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
case EXTERNAL_PIXEL_ELEMENTS:
UNREACHABLE(); UNREACHABLE();
} }
return to->GetHeap()->undefined_value(); return to->GetHeap()->undefined_value();
@ -1460,27 +1532,12 @@ class DictionaryElementsAccessor
MUST_USE_RESULT static MaybeObject* CopyElementsImpl(FixedArrayBase* from, MUST_USE_RESULT static MaybeObject* CopyElementsImpl(FixedArrayBase* from,
uint32_t from_start, uint32_t from_start,
FixedArrayBase* to, FixedArrayBase* to,
ElementsKind to_kind, ElementsKind from_kind,
uint32_t to_start, uint32_t to_start,
int packed_size, int packed_size,
int copy_size) { int copy_size) {
switch (to_kind) {
case FAST_SMI_ELEMENTS:
case FAST_ELEMENTS:
case FAST_HOLEY_SMI_ELEMENTS:
case FAST_HOLEY_ELEMENTS:
CopyDictionaryToObjectElements(
from, from_start, to, to_kind, to_start, copy_size);
return from;
case FAST_DOUBLE_ELEMENTS:
case FAST_HOLEY_DOUBLE_ELEMENTS:
CopyDictionaryToDoubleElements(
from, from_start, to, to_start, copy_size);
return from;
default:
UNREACHABLE(); UNREACHABLE();
} return NULL;
return to->GetHeap()->undefined_value();
} }
@ -1707,15 +1764,12 @@ class NonStrictArgumentsElementsAccessor : public ElementsAccessorBase<
MUST_USE_RESULT static MaybeObject* CopyElementsImpl(FixedArrayBase* from, MUST_USE_RESULT static MaybeObject* CopyElementsImpl(FixedArrayBase* from,
uint32_t from_start, uint32_t from_start,
FixedArrayBase* to, FixedArrayBase* to,
ElementsKind to_kind, ElementsKind from_kind,
uint32_t to_start, uint32_t to_start,
int packed_size, int packed_size,
int copy_size) { int copy_size) {
FixedArray* parameter_map = FixedArray::cast(from); UNREACHABLE();
FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); return NULL;
ElementsAccessor* accessor = ElementsAccessor::ForArray(arguments);
return accessor->CopyElements(NULL, from_start, to, to_kind,
to_start, copy_size, arguments);
} }
static uint32_t GetCapacityImpl(FixedArrayBase* backing_store) { static uint32_t GetCapacityImpl(FixedArrayBase* backing_store) {
@ -1761,35 +1815,7 @@ class NonStrictArgumentsElementsAccessor : public ElementsAccessorBase<
ElementsAccessor* ElementsAccessor::ForArray(FixedArrayBase* array) { ElementsAccessor* ElementsAccessor::ForArray(FixedArrayBase* array) {
switch (array->map()->instance_type()) { return elements_accessors_[ElementsKindForArray(array)];
case FIXED_ARRAY_TYPE:
if (array->IsDictionary()) {
return elements_accessors_[DICTIONARY_ELEMENTS];
} else {
return elements_accessors_[FAST_HOLEY_ELEMENTS];
}
case EXTERNAL_BYTE_ARRAY_TYPE:
return elements_accessors_[EXTERNAL_BYTE_ELEMENTS];
case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
return elements_accessors_[EXTERNAL_UNSIGNED_BYTE_ELEMENTS];
case EXTERNAL_SHORT_ARRAY_TYPE:
return elements_accessors_[EXTERNAL_SHORT_ELEMENTS];
case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
return elements_accessors_[EXTERNAL_UNSIGNED_SHORT_ELEMENTS];
case EXTERNAL_INT_ARRAY_TYPE:
return elements_accessors_[EXTERNAL_INT_ELEMENTS];
case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
return elements_accessors_[EXTERNAL_UNSIGNED_INT_ELEMENTS];
case EXTERNAL_FLOAT_ARRAY_TYPE:
return elements_accessors_[EXTERNAL_FLOAT_ELEMENTS];
case EXTERNAL_DOUBLE_ARRAY_TYPE:
return elements_accessors_[EXTERNAL_DOUBLE_ELEMENTS];
case EXTERNAL_PIXEL_ARRAY_TYPE:
return elements_accessors_[EXTERNAL_PIXEL_ELEMENTS];
default:
UNREACHABLE();
return NULL;
}
} }

View File

@ -143,17 +143,17 @@ class ElementsAccessor {
MUST_USE_RESULT virtual MaybeObject* CopyElements( MUST_USE_RESULT virtual MaybeObject* CopyElements(
JSObject* source_holder, JSObject* source_holder,
uint32_t source_start, uint32_t source_start,
ElementsKind source_kind,
FixedArrayBase* destination, FixedArrayBase* destination,
ElementsKind destination_kind,
uint32_t destination_start, uint32_t destination_start,
int copy_size, int copy_size,
FixedArrayBase* source = NULL) = 0; FixedArrayBase* source = NULL) = 0;
MUST_USE_RESULT MaybeObject* CopyElements(JSObject* from_holder, MUST_USE_RESULT MaybeObject* CopyElements(JSObject* from_holder,
FixedArrayBase* to, FixedArrayBase* to,
ElementsKind to_kind, ElementsKind from_kind,
FixedArrayBase* from = NULL) { FixedArrayBase* from = NULL) {
return CopyElements(from_holder, 0, to, to_kind, 0, return CopyElements(from_holder, 0, from_kind, to, 0,
kCopyToEndAndInitializeToHole, from); kCopyToEndAndInitializeToHole, from);
} }

View File

@ -9609,9 +9609,9 @@ MaybeObject* JSObject::SetFastElementsCapacityAndLength(
} }
} }
FixedArrayBase* old_elements = elements(); FixedArrayBase* old_elements = elements();
ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind); ElementsAccessor* accessor = ElementsAccessor::ForKind(new_elements_kind);
MaybeObject* maybe_obj = MaybeObject* maybe_obj =
accessor->CopyElements(this, new_elements, new_elements_kind); accessor->CopyElements(this, new_elements, elements_kind);
if (maybe_obj->IsFailure()) return maybe_obj; if (maybe_obj->IsFailure()) return maybe_obj;
if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) { if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) {
@ -9669,9 +9669,9 @@ MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength(
} }
FixedArrayBase* old_elements = elements(); FixedArrayBase* old_elements = elements();
ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind); ElementsAccessor* accessor = ElementsAccessor::ForKind(FAST_DOUBLE_ELEMENTS);
{ MaybeObject* maybe_obj = { MaybeObject* maybe_obj =
accessor->CopyElements(this, elems, FAST_DOUBLE_ELEMENTS); accessor->CopyElements(this, elems, elements_kind);
if (maybe_obj->IsFailure()) return maybe_obj; if (maybe_obj->IsFailure()) return maybe_obj;
} }
if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) { if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) {