Index: src/objects.cc |
=================================================================== |
--- src/objects.cc (revision 3095) |
+++ src/objects.cc (working copy) |
@@ -1005,6 +1005,34 @@ |
case PIXEL_ARRAY_TYPE: |
accumulator->Add("<PixelArray[%u]>", PixelArray::cast(this)->length()); |
break; |
+ case EXTERNAL_BYTE_ARRAY_TYPE: |
+ accumulator->Add("<ExternalByteArray[%u]>", |
+ ExternalByteArray::cast(this)->length()); |
+ break; |
+ case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE: |
+ accumulator->Add("<ExternalUnsignedByteArray[%u]>", |
+ ExternalUnsignedByteArray::cast(this)->length()); |
+ break; |
+ case EXTERNAL_SHORT_ARRAY_TYPE: |
+ accumulator->Add("<ExternalShortArray[%u]>", |
+ ExternalShortArray::cast(this)->length()); |
+ break; |
+ case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE: |
+ accumulator->Add("<ExternalUnsignedShortArray[%u]>", |
+ ExternalUnsignedShortArray::cast(this)->length()); |
+ break; |
+ case EXTERNAL_INT_ARRAY_TYPE: |
+ accumulator->Add("<ExternalIntArray[%u]>", |
+ ExternalIntArray::cast(this)->length()); |
+ break; |
+ case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE: |
+ accumulator->Add("<ExternalUnsignedIntArray[%u]>", |
+ ExternalUnsignedIntArray::cast(this)->length()); |
+ break; |
+ case EXTERNAL_FLOAT_ARRAY_TYPE: |
+ accumulator->Add("<ExternalFloatArray[%u]>", |
+ ExternalFloatArray::cast(this)->length()); |
+ break; |
case SHARED_FUNCTION_INFO_TYPE: |
accumulator->Add("<SharedFunctionInfo>"); |
break; |
@@ -1147,6 +1175,13 @@ |
case FILLER_TYPE: |
case BYTE_ARRAY_TYPE: |
case PIXEL_ARRAY_TYPE: |
+ case EXTERNAL_BYTE_ARRAY_TYPE: |
+ case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE: |
+ case EXTERNAL_SHORT_ARRAY_TYPE: |
+ case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE: |
+ case EXTERNAL_INT_ARRAY_TYPE: |
+ case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE: |
+ case EXTERNAL_FLOAT_ARRAY_TYPE: |
break; |
case SHARED_FUNCTION_INFO_TYPE: { |
SharedFunctionInfo* shared = reinterpret_cast<SharedFunctionInfo*>(this); |
@@ -2237,7 +2272,7 @@ |
Object* JSObject::NormalizeElements() { |
- ASSERT(!HasPixelElements()); |
+ ASSERT(!HasPixelElements() && !HasExternalArrayElements()); |
if (HasDictionaryElements()) return this; |
// Get number of entries. |
@@ -2322,7 +2357,7 @@ |
Object* JSObject::DeleteElementPostInterceptor(uint32_t index, |
DeleteMode mode) { |
- ASSERT(!HasPixelElements()); |
+ ASSERT(!HasPixelElements() && !HasExternalArrayElements()); |
switch (GetElementsKind()) { |
case FAST_ELEMENTS: { |
uint32_t length = IsJSArray() ? |
@@ -2413,10 +2448,17 @@ |
} |
break; |
} |
- case PIXEL_ELEMENTS: { |
- // Pixel elements cannot be deleted. Just silently ignore here. |
+ case PIXEL_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: |
+ // Pixel and external array elements cannot be deleted. Just |
+ // silently ignore here. |
break; |
- } |
case DICTIONARY_ELEMENTS: { |
NumberDictionary* dictionary = element_dictionary(); |
int entry = dictionary->FindEntry(index); |
@@ -2507,7 +2549,15 @@ |
// Check if the object is among the indexed properties. |
switch (GetElementsKind()) { |
case PIXEL_ELEMENTS: |
- // Raw pixels do not reference other objects. |
+ 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: |
+ // Raw pixels and external arrays do not reference other |
+ // objects. |
break; |
case FAST_ELEMENTS: { |
int length = IsJSArray() ? |
@@ -2752,7 +2802,15 @@ |
case FAST_ELEMENTS: |
break; |
case PIXEL_ELEMENTS: |
- // Ignore getters and setters on pixel 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: |
+ // Ignore getters and setters on pixel and external array |
+ // elements. |
return Heap::undefined_value(); |
case DICTIONARY_ELEMENTS: { |
// Lookup the index. |
@@ -3087,7 +3145,7 @@ |
Object* FixedArray::AddKeysFromJSArray(JSArray* array) { |
- ASSERT(!array->HasPixelElements()); |
+ ASSERT(!array->HasPixelElements() && !array->HasExternalArrayElements()); |
switch (array->GetElementsKind()) { |
case JSObject::FAST_ELEMENTS: |
return UnionOfKeys(FixedArray::cast(array->elements())); |
@@ -5201,8 +5259,8 @@ |
void JSObject::SetFastElements(FixedArray* elems) { |
- // We should never end in here with a pixel array. |
- ASSERT(!HasPixelElements()); |
+ // We should never end in here with a pixel or external array. |
+ ASSERT(!HasPixelElements() && !HasExternalArrayElements()); |
#ifdef DEBUG |
// Check the provided array is filled with the_hole. |
uint32_t len = static_cast<uint32_t>(elems->length()); |
@@ -5239,8 +5297,8 @@ |
Object* JSObject::SetSlowElements(Object* len) { |
- // We should never end in here with a pixel array. |
- ASSERT(!HasPixelElements()); |
+ // We should never end in here with a pixel or external array. |
+ ASSERT(!HasPixelElements() && !HasExternalArrayElements()); |
uint32_t new_length = static_cast<uint32_t>(len->Number()); |
@@ -5318,8 +5376,8 @@ |
Object* JSObject::SetElementsLength(Object* len) { |
- // We should never end in here with a pixel array. |
- ASSERT(!HasPixelElements()); |
+ // We should never end in here with a pixel or external array. |
+ ASSERT(!HasPixelElements() && !HasExternalArrayElements()); |
Object* smi_length = len->ToSmi(); |
if (smi_length->IsSmi()) { |
@@ -5420,6 +5478,20 @@ |
} |
break; |
} |
+ 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: { |
+ // TODO(kbr): Add testcase. |
+ ExternalArray* array = ExternalArray::cast(elements()); |
+ if (index < static_cast<uint32_t>(array->length())) { |
+ return true; |
+ } |
+ break; |
+ } |
case DICTIONARY_ELEMENTS: { |
if (element_dictionary()->FindEntry(index) |
!= NumberDictionary::kNotFound) { |
@@ -5507,6 +5579,16 @@ |
PixelArray* pixels = PixelArray::cast(elements()); |
return (index < static_cast<uint32_t>(pixels->length())); |
} |
+ 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: { |
+ ExternalArray* array = ExternalArray::cast(elements()); |
+ return (index < static_cast<uint32_t>(array->length())); |
+ } |
case DICTIONARY_ELEMENTS: { |
return element_dictionary()->FindEntry(index) |
!= NumberDictionary::kNotFound; |
@@ -5550,6 +5632,19 @@ |
} |
break; |
} |
+ 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: { |
+ ExternalArray* array = ExternalArray::cast(elements()); |
+ if (index < static_cast<uint32_t>(array->length())) { |
+ return true; |
+ } |
+ break; |
+ } |
case DICTIONARY_ELEMENTS: { |
if (element_dictionary()->FindEntry(index) |
!= NumberDictionary::kNotFound) { |
@@ -5690,6 +5785,37 @@ |
PixelArray* pixels = PixelArray::cast(elements()); |
return pixels->SetValue(index, value); |
} |
+ case EXTERNAL_BYTE_ELEMENTS: { |
+ ExternalByteArray* array = ExternalByteArray::cast(elements()); |
+ return array->SetValue(index, value); |
+ } |
+ case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: { |
+ ExternalUnsignedByteArray* array = |
+ ExternalUnsignedByteArray::cast(elements()); |
+ return array->SetValue(index, value); |
+ } |
+ case EXTERNAL_SHORT_ELEMENTS: { |
+ ExternalShortArray* array = ExternalShortArray::cast(elements()); |
+ return array->SetValue(index, value); |
+ } |
+ case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: { |
+ ExternalUnsignedShortArray* array = |
+ ExternalUnsignedShortArray::cast(elements()); |
+ return array->SetValue(index, value); |
+ } |
+ case EXTERNAL_INT_ELEMENTS: { |
+ ExternalIntArray* array = ExternalIntArray::cast(elements()); |
+ return array->SetValue(index, value); |
+ } |
+ case EXTERNAL_UNSIGNED_INT_ELEMENTS: { |
+ ExternalUnsignedIntArray* array = |
+ ExternalUnsignedIntArray::cast(elements()); |
+ return array->SetValue(index, value); |
+ } |
+ case EXTERNAL_FLOAT_ELEMENTS: { |
+ ExternalFloatArray* array = ExternalFloatArray::cast(elements()); |
+ return array->SetValue(index, value); |
+ } |
case DICTIONARY_ELEMENTS: { |
// Insert element in the dictionary. |
FixedArray* elms = FixedArray::cast(elements()); |
@@ -5807,6 +5933,17 @@ |
UNIMPLEMENTED(); |
break; |
} |
+ 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: { |
+ // TODO(kbr): Add testcase and implement. |
+ UNIMPLEMENTED(); |
+ break; |
+ } |
case DICTIONARY_ELEMENTS: { |
NumberDictionary* dictionary = element_dictionary(); |
int entry = dictionary->FindEntry(index); |
@@ -5905,6 +6042,65 @@ |
} |
break; |
} |
+ case EXTERNAL_BYTE_ELEMENTS: { |
+ ExternalByteArray* array = ExternalByteArray::cast(elements()); |
+ if (index < static_cast<uint32_t>(array->length())) { |
+ int8_t value = array->get(index); |
+ return Smi::FromInt(value); |
+ } |
+ return Top::Throw(*Factory::NewIndexError(index)); |
+ } |
+ case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: { |
+ ExternalUnsignedByteArray* array = |
+ ExternalUnsignedByteArray::cast(elements()); |
+ if (index < static_cast<uint32_t>(array->length())) { |
+ uint8_t value = array->get(index); |
+ return Smi::FromInt(value); |
+ } |
+ return Top::Throw(*Factory::NewIndexError(index)); |
+ } |
+ case EXTERNAL_SHORT_ELEMENTS: { |
+ ExternalShortArray* array = ExternalShortArray::cast(elements()); |
+ if (index < static_cast<uint32_t>(array->length())) { |
+ int16_t value = array->get(index); |
+ return Smi::FromInt(value); |
+ } |
+ return Top::Throw(*Factory::NewIndexError(index)); |
+ } |
+ case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: { |
+ ExternalUnsignedShortArray* array = |
+ ExternalUnsignedShortArray::cast(elements()); |
+ if (index < static_cast<uint32_t>(array->length())) { |
+ uint16_t value = array->get(index); |
+ return Smi::FromInt(value); |
+ } |
+ return Top::Throw(*Factory::NewIndexError(index)); |
+ } |
+ case EXTERNAL_INT_ELEMENTS: { |
+ ExternalIntArray* array = ExternalIntArray::cast(elements()); |
+ if (index < static_cast<uint32_t>(array->length())) { |
+ int32_t value = array->get(index); |
+ return Heap::NumberFromInt32(value); |
+ } |
+ return Top::Throw(*Factory::NewIndexError(index)); |
+ } |
+ case EXTERNAL_UNSIGNED_INT_ELEMENTS: { |
+ ExternalUnsignedIntArray* array = |
+ ExternalUnsignedIntArray::cast(elements()); |
+ if (index < static_cast<uint32_t>(array->length())) { |
+ uint32_t value = array->get(index); |
+ return Heap::NumberFromUint32(value); |
+ } |
+ return Top::Throw(*Factory::NewIndexError(index)); |
+ } |
+ case EXTERNAL_FLOAT_ELEMENTS: { |
+ ExternalFloatArray* array = ExternalFloatArray::cast(elements()); |
+ if (index < static_cast<uint32_t>(array->length())) { |
+ float value = array->get(index); |
+ return Heap::AllocateHeapNumber(value); |
+ } |
+ return Top::Throw(*Factory::NewIndexError(index)); |
+ } |
case DICTIONARY_ELEMENTS: { |
NumberDictionary* dictionary = element_dictionary(); |
int entry = dictionary->FindEntry(index); |
@@ -5948,7 +6144,14 @@ |
} |
break; |
} |
- case PIXEL_ELEMENTS: { |
+ case PIXEL_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: { |
return true; |
} |
case DICTIONARY_ELEMENTS: { |
@@ -6172,6 +6375,16 @@ |
PixelArray* pixels = PixelArray::cast(elements()); |
return index < static_cast<uint32_t>(pixels->length()); |
} |
+ 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: { |
+ ExternalArray* array = ExternalArray::cast(elements()); |
+ return index < static_cast<uint32_t>(array->length()); |
+ } |
case DICTIONARY_ELEMENTS: { |
return element_dictionary()->FindEntry(index) |
!= NumberDictionary::kNotFound; |
@@ -6392,6 +6605,23 @@ |
ASSERT(!storage || storage->length() >= counter); |
break; |
} |
+ 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: { |
+ int length = ExternalArray::cast(elements())->length(); |
+ while (counter < length) { |
+ if (storage != NULL) { |
+ storage->set(counter, Smi::FromInt(counter), SKIP_WRITE_BARRIER); |
+ } |
+ counter++; |
+ } |
+ ASSERT(!storage || storage->length() >= counter); |
+ break; |
+ } |
case DICTIONARY_ELEMENTS: { |
if (storage != NULL) { |
element_dictionary()->CopyKeysTo(storage, filter); |
@@ -6938,7 +7168,7 @@ |
// If the object is in dictionary mode, it is converted to fast elements |
// mode. |
Object* JSObject::PrepareElementsForSort(uint32_t limit) { |
- ASSERT(!HasPixelElements()); |
+ ASSERT(!HasPixelElements() && !HasExternalArrayElements()); |
if (HasDictionaryElements()) { |
// Convert to fast elements containing only the existing properties. |
@@ -7070,6 +7300,105 @@ |
} |
+template<typename ExternalArrayClass, typename ValueType> |
+static Object* ExternalArrayIntSetter(ExternalArrayClass* receiver, |
+ uint32_t index, |
+ Object* value) { |
+ ValueType cast_value = 0; |
+ if (index < static_cast<uint32_t>(receiver->length())) { |
+ if (value->IsSmi()) { |
+ int int_value = Smi::cast(value)->value(); |
+ cast_value = static_cast<ValueType>(int_value); |
+ } else if (value->IsHeapNumber()) { |
+ double double_value = HeapNumber::cast(value)->value(); |
+ cast_value = static_cast<ValueType>(double_value); |
+ } else { |
+ // Clamp undefined to zero (default). All other types have been |
+ // converted to a number type further up in the call chain. |
+ ASSERT(value->IsUndefined()); |
+ } |
+ receiver->set(index, cast_value); |
+ } else { |
+ return Top::Throw(*Factory::NewIndexError(index)); |
+ } |
+ return Heap::NumberFromInt32(cast_value); |
+} |
+ |
+ |
+Object* ExternalByteArray::SetValue(uint32_t index, Object* value) { |
+ return ExternalArrayIntSetter<ExternalByteArray, int8_t> |
+ (this, index, value); |
+} |
+ |
+ |
+Object* ExternalUnsignedByteArray::SetValue(uint32_t index, Object* value) { |
+ return ExternalArrayIntSetter<ExternalUnsignedByteArray, uint8_t> |
+ (this, index, value); |
+} |
+ |
+ |
+Object* ExternalShortArray::SetValue(uint32_t index, Object* value) { |
+ return ExternalArrayIntSetter<ExternalShortArray, int16_t> |
+ (this, index, value); |
+} |
+ |
+ |
+Object* ExternalUnsignedShortArray::SetValue(uint32_t index, Object* value) { |
+ return ExternalArrayIntSetter<ExternalUnsignedShortArray, uint16_t> |
+ (this, index, value); |
+} |
+ |
+ |
+Object* ExternalIntArray::SetValue(uint32_t index, Object* value) { |
+ return ExternalArrayIntSetter<ExternalIntArray, int32_t> |
+ (this, index, value); |
+} |
+ |
+ |
+Object* ExternalUnsignedIntArray::SetValue(uint32_t index, Object* value) { |
+ uint32_t cast_value = 0; |
+ if (index < static_cast<uint32_t>(length())) { |
+ if (value->IsSmi()) { |
+ int int_value = Smi::cast(value)->value(); |
+ cast_value = static_cast<uint32_t>(int_value); |
+ } else if (value->IsHeapNumber()) { |
+ double double_value = HeapNumber::cast(value)->value(); |
+ cast_value = static_cast<uint32_t>(double_value); |
+ } else { |
+ // Clamp undefined to zero (default). All other types have been |
+ // converted to a number type further up in the call chain. |
+ ASSERT(value->IsUndefined()); |
+ } |
+ set(index, cast_value); |
+ } else { |
+ return Top::Throw(*Factory::NewIndexError(index)); |
+ } |
+ return Heap::NumberFromUint32(cast_value); |
+} |
+ |
+ |
+Object* ExternalFloatArray::SetValue(uint32_t index, Object* value) { |
+ float cast_value = 0; |
+ if (index < static_cast<uint32_t>(length())) { |
+ if (value->IsSmi()) { |
+ int int_value = Smi::cast(value)->value(); |
+ cast_value = static_cast<float>(int_value); |
+ } else if (value->IsHeapNumber()) { |
+ double double_value = HeapNumber::cast(value)->value(); |
+ cast_value = static_cast<float>(double_value); |
+ } else { |
+ // Clamp undefined to zero (default). All other types have been |
+ // converted to a number type further up in the call chain. |
+ ASSERT(value->IsUndefined()); |
+ } |
+ set(index, cast_value); |
+ } else { |
+ return Top::Throw(*Factory::NewIndexError(index)); |
+ } |
+ return Heap::AllocateHeapNumber(cast_value); |
+} |
+ |
+ |
Object* GlobalObject::GetPropertyCell(LookupResult* result) { |
ASSERT(!HasFastProperties()); |
Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); |