Index: src/objects.cc |
diff --git a/src/objects.cc b/src/objects.cc |
index fc12cf96b338ced038a69c6a93b8e1265146485c..84ae5351d47f2c364dbe21f5ddf9a9e2dc0da44c 100644 |
--- a/src/objects.cc |
+++ b/src/objects.cc |
@@ -3256,24 +3256,30 @@ Handle<Map> Map::FindTransitionedMap(MapHandleList* candidates) { |
static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) { |
Map* current_map = map; |
- int index = GetSequenceIndexFromFastElementsKind(map->elements_kind()); |
- int to_index = IsFastElementsKind(to_kind) |
- ? GetSequenceIndexFromFastElementsKind(to_kind) |
- : GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND); |
+ int target_kind = |
+ IsFastElementsKind(to_kind) || IsExternalArrayElementsKind(to_kind) |
Toon Verwaest
2014/03/10 14:15:34
IsTransitionElementsKind(to_kind)?
Dmitry Lomov (no reviews)
2014/03/24 08:31:22
No, this is not IsTransitionElementsKind.
|
+ ? to_kind |
+ : TERMINAL_FAST_ELEMENTS_KIND; |
- ASSERT(index <= to_index); |
+ // Support for legacy API. |
+ if (IsExternalArrayElementsKind(to_kind) && |
+ !IsFixedTypedArrayElementsKind(map->elements_kind())) { |
+ return map; |
+ } |
- for (; index < to_index; ++index) { |
+ ElementsKind kind = map->elements_kind(); |
+ while (kind != target_kind) { |
+ kind = GetNextTransitionElementsKind(kind); |
if (!current_map->HasElementsTransition()) return current_map; |
current_map = current_map->elements_transition_map(); |
} |
- if (!IsFastElementsKind(to_kind) && current_map->HasElementsTransition()) { |
+ |
+ if (to_kind != kind && current_map->HasElementsTransition()) { |
Toon Verwaest
2014/03/10 14:15:34
Can this only happen for DICTIONARY elements now?
Dmitry Lomov (no reviews)
2014/03/24 08:31:22
Done.
|
Map* next_map = current_map->elements_transition_map(); |
if (next_map->elements_kind() == to_kind) return next_map; |
} |
- ASSERT(IsFastElementsKind(to_kind) |
- ? current_map->elements_kind() == to_kind |
- : current_map->elements_kind() == TERMINAL_FAST_ELEMENTS_KIND); |
+ |
+ ASSERT(current_map->elements_kind() == target_kind); |
Toon Verwaest
2014/03/10 14:15:34
This ASSERT is wrong afaict. If we didnt' have an
Dmitry Lomov (no reviews)
2014/03/24 08:31:22
target_kind is not DICTIONARY_ELEMENTS in that cas
|
return current_map; |
} |
@@ -3301,26 +3307,21 @@ bool Map::IsMapInArrayPrototypeChain() { |
static MaybeObject* AddMissingElementsTransitions(Map* map, |
ElementsKind to_kind) { |
- ASSERT(IsFastElementsKind(map->elements_kind())); |
- int index = GetSequenceIndexFromFastElementsKind(map->elements_kind()); |
- int to_index = IsFastElementsKind(to_kind) |
- ? GetSequenceIndexFromFastElementsKind(to_kind) |
- : GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND); |
- |
- ASSERT(index <= to_index); |
+ ASSERT(IsTransitionElementsKind(map->elements_kind())); |
Map* current_map = map; |
- for (; index < to_index; ++index) { |
- ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(index + 1); |
+ ElementsKind kind = map->elements_kind(); |
+ while (kind != to_kind && !IsTerminalElementsKind(kind)) { |
+ kind = GetNextTransitionElementsKind(kind); |
MaybeObject* maybe_next_map = |
- current_map->CopyAsElementsKind(next_kind, INSERT_TRANSITION); |
+ current_map->CopyAsElementsKind(kind, INSERT_TRANSITION); |
if (!maybe_next_map->To(¤t_map)) return maybe_next_map; |
} |
// In case we are exiting the fast elements kind system, just add the map in |
// the end. |
- if (!IsFastElementsKind(to_kind)) { |
+ if (kind != to_kind) { |
Toon Verwaest
2014/03/10 14:15:34
Can this only happen for DICTIONARY elements now?
Dmitry Lomov (no reviews)
2014/03/24 08:31:22
No, this happens at the end of all chains.
|
MaybeObject* maybe_next_map = |
current_map->CopyAsElementsKind(to_kind, INSERT_TRANSITION); |
if (!maybe_next_map->To(¤t_map)) return maybe_next_map; |
@@ -3352,7 +3353,7 @@ MaybeObject* JSObject::GetElementsTransitionMapSlow(ElementsKind to_kind) { |
// Only remember the map transition if there is not an already existing |
// non-matching element transition. |
!start_map->IsUndefined() && !start_map->is_shared() && |
- IsFastElementsKind(from_kind); |
+ IsTransitionElementsKind(from_kind); |
// Only store fast element maps in ascending generality. |
if (IsFastElementsKind(to_kind)) { |
@@ -3380,6 +3381,11 @@ MaybeObject* Map::AsElementsKind(ElementsKind kind) { |
} |
+Handle<Map> Map::AsElementsKind(Handle<Map> map, ElementsKind kind) { |
+ CALL_HEAP_FUNCTION(map->GetIsolate(), map->AsElementsKind(kind), Map); |
+} |
+ |
+ |
void JSObject::LocalLookupRealNamedProperty(Name* name, LookupResult* result) { |
DisallowHeapAllocation no_gc; |
if (IsJSGlobalProxy()) { |
@@ -4729,7 +4735,7 @@ Handle<SeededNumberDictionary> JSObject::NormalizeElements( |
MaybeObject* JSObject::NormalizeElements() { |
- ASSERT(!HasExternalArrayElements()); |
+ ASSERT(!HasExternalArrayElements() && !HasFixedTypedArrayElements()); |
// Find the backing store. |
FixedArrayBase* array = FixedArrayBase::cast(elements()); |
@@ -5475,7 +5481,8 @@ Handle<Object> JSObject::PreventExtensions(Handle<JSObject> object) { |
} |
// It's not possible to seal objects with external array elements |
- if (object->HasExternalArrayElements()) { |
+ if (object->HasExternalArrayElements() || |
+ object->HasFixedTypedArrayElements()) { |
Handle<Object> error = |
isolate->factory()->NewTypeError( |
"cant_prevent_ext_external_array_elements", |
@@ -5555,7 +5562,8 @@ Handle<Object> JSObject::Freeze(Handle<JSObject> object) { |
} |
// It's not possible to freeze objects with external array elements |
- if (object->HasExternalArrayElements()) { |
+ if (object->HasExternalArrayElements() || |
+ object->HasFixedTypedArrayElements()) { |
Handle<Object> error = |
isolate->factory()->NewTypeError( |
"cant_prevent_ext_external_array_elements", |
@@ -12536,7 +12544,9 @@ Handle<Object> JSObject::SetElement(Handle<JSObject> object, |
} |
// Don't allow element properties to be redefined for external arrays. |
- if (object->HasExternalArrayElements() && set_mode == DEFINE_PROPERTY) { |
+ if ((object->HasExternalArrayElements() || |
+ object->HasFixedTypedArrayElements()) && |
+ set_mode == DEFINE_PROPERTY) { |
Handle<Object> number = isolate->factory()->NewNumberFromUint(index); |
Handle<Object> args[] = { object, number }; |
Handle<Object> error = isolate->factory()->NewTypeError( |
@@ -14473,10 +14483,11 @@ Handle<Object> JSObject::PrepareElementsForSort(Handle<JSObject> object, |
object->ValidateElements(); |
object->set_map_and_elements(*new_map, *fast_elements); |
- } else if (object->HasExternalArrayElements()) { |
- // External arrays cannot have holes or undefined elements. |
+ } else if (object->HasExternalArrayElements() || |
+ object->HasFixedTypedArrayElements()) { |
+ // Typed arrays cannot have holes or undefined elements. |
return handle(Smi::FromInt( |
- ExternalArray::cast(object->elements())->length()), isolate); |
+ FixedArrayBase::cast(object->elements())->length()), isolate); |
} else if (!object->HasFastDoubleElements()) { |
EnsureWritableFastElements(object); |
} |
@@ -14577,12 +14588,14 @@ ExternalArrayType JSTypedArray::type() { |
switch (elements()->map()->instance_type()) { |
#define INSTANCE_TYPE_TO_ARRAY_TYPE(Type, type, TYPE, ctype, size) \ |
case EXTERNAL_##TYPE##_ARRAY_TYPE: \ |
+ case FIXED_##TYPE##_ARRAY_TYPE: \ |
return kExternal##Type##Array; |
TYPED_ARRAYS(INSTANCE_TYPE_TO_ARRAY_TYPE) |
#undef INSTANCE_TYPE_TO_ARRAY_TYPE |
default: |
+ UNREACHABLE(); |
return static_cast<ExternalArrayType>(-1); |
} |
} |
@@ -16440,6 +16453,66 @@ void JSTypedArray::Neuter() { |
} |
+static ElementsKind FixedToExternalElementsKind(ElementsKind elements_kind) { |
+ switch (elements_kind) { |
+#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ |
+ case TYPE##_ELEMENTS: return EXTERNAL_##TYPE##_ELEMENTS; |
+ |
+ TYPED_ARRAYS(TYPED_ARRAY_CASE) |
+#undef TYPED_ARRAY_CASE |
+ |
+ default: |
+ UNREACHABLE(); |
+ return FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND; |
+ } |
+} |
+ |
+ |
+Handle<JSArrayBuffer> JSTypedArray::MaterializeArrayBuffer( |
+ Handle<JSTypedArray> typed_array) { |
+ |
+ Handle<Map> map(typed_array->map()); |
+ Isolate* isolate = typed_array->GetIsolate(); |
+ |
+ ASSERT(IsFixedTypedArrayElementsKind(map->elements_kind())); |
+ |
+ Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer(); |
+ Handle<FixedTypedArrayBase> fixed_typed_array( |
+ FixedTypedArrayBase::cast(typed_array->elements())); |
+ Runtime::SetupArrayBufferAllocatingData(isolate, buffer, |
+ fixed_typed_array->DataSize(), false); |
+ memcpy(buffer->backing_store(), |
+ fixed_typed_array->DataPtr(), |
+ fixed_typed_array->DataSize()); |
+ Handle<ExternalArray> new_elements = |
+ isolate->factory()->NewExternalArray( |
+ fixed_typed_array->length(), typed_array->type(), |
+ static_cast<uint8_t*>(buffer->backing_store())); |
+ Handle<Map> new_map = |
+ isolate->factory()->GetElementsTransitionMap( |
+ typed_array, |
+ FixedToExternalElementsKind(map->elements_kind())); |
+ |
+ buffer->set_weak_first_view(*typed_array); |
+ ASSERT(typed_array->weak_next() == isolate->heap()->undefined_value()); |
+ typed_array->set_buffer(*buffer); |
+ typed_array->set_map_and_elements(*new_map, *new_elements); |
+ |
+ return buffer; |
+} |
+ |
+ |
+Handle<JSArrayBuffer> JSTypedArray::GetBuffer() { |
+ Handle<Object> result(buffer(), GetIsolate()); |
+ if (*result != Smi::FromInt(0)) { |
+ ASSERT(IsExternalArrayElementsKind(map()->elements_kind())); |
+ return Handle<JSArrayBuffer>::cast(result); |
+ } |
+ Handle<JSTypedArray> self(this); |
+ return MaterializeArrayBuffer(self); |
+} |
+ |
+ |
HeapType* PropertyCell::type() { |
return static_cast<HeapType*>(type_raw()); |
} |