Chromium Code Reviews| Index: src/objects.cc |
| diff --git a/src/objects.cc b/src/objects.cc |
| index d2ad0b7f5e866db7b3abc6b6e7b8d601db2989cd..9b4c7cbc4268da619d6b162a672d66ec3d78f7cf 100644 |
| --- a/src/objects.cc |
| +++ b/src/objects.cc |
| @@ -3260,24 +3260,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) |
| + ? 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()) { |
| 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); |
| return current_map; |
| } |
| @@ -3305,26 +3311,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) { |
| MaybeObject* maybe_next_map = |
| current_map->CopyAsElementsKind(to_kind, INSERT_TRANSITION); |
| if (!maybe_next_map->To(¤t_map)) return maybe_next_map; |
| @@ -3356,7 +3357,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)) { |
| @@ -3384,6 +3385,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) { |
| if (IsJSGlobalProxy()) { |
| Object* proto = GetPrototype(); |
| @@ -4734,7 +4740,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", |
| @@ -12535,7 +12543,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( |
| @@ -14456,10 +14466,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); |
| } |
| @@ -14560,12 +14571,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); |
| } |
| } |
| @@ -16423,6 +16436,67 @@ 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) { |
| + |
| + printf("Materializing buffer!\n"); |
|
mvstanton
2014/03/03 10:37:49
Remove this printf().
Dmitry Lomov (no reviews)
2014/03/10 09:20:35
Done.
|
| + 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()); |
| } |