| Index: src/runtime.cc
|
| ===================================================================
|
| --- src/runtime.cc (revision 3095)
|
| +++ src/runtime.cc (working copy)
|
| @@ -156,7 +156,7 @@
|
|
|
| // Deep copy local elements.
|
| // Pixel elements cannot be created using an object literal.
|
| - ASSERT(!copy->HasPixelElements());
|
| + ASSERT(!copy->HasPixelElements() && !copy->HasExternalArrayElements());
|
| switch (copy->GetElementsKind()) {
|
| case JSObject::FAST_ELEMENTS: {
|
| FixedArray* elements = FixedArray::cast(copy->elements());
|
| @@ -2580,6 +2580,18 @@
|
| return GetElementOrCharAt(object, index);
|
| }
|
|
|
| + // If the target object is a JSObject and has an ExternalArray as
|
| + // its elements, we need to check for negative indices and report
|
| + // exceptions. Indices larger than the array's length will be caught
|
| + // elsewhere.
|
| + if (key->IsSmi() && Smi::cast(*key)->value() < 0) {
|
| + if (object->IsJSObject() &&
|
| + JSObject::cast(*object)->HasExternalArrayElements()) {
|
| + uint32_t index = static_cast<uint32_t>(Smi::cast(*key)->value());
|
| + return Top::Throw(*Factory::NewIndexError(index));
|
| + }
|
| + }
|
| +
|
| // Convert the key to a string - possibly by calling back into JavaScript.
|
| Handle<String> name;
|
| if (key->IsString()) {
|
| @@ -2714,6 +2726,18 @@
|
| return *value;
|
| }
|
|
|
| + // If the target object is a JSObject and has an ExternalArray as
|
| + // its elements, we need to check for negative indices and report
|
| + // exceptions. Indices larger than the array's length will be caught
|
| + // elsewhere.
|
| + if (key->IsSmi() && Smi::cast(*key)->value() < 0) {
|
| + if (object->IsJSObject() &&
|
| + JSObject::cast(*object)->HasExternalArrayElements()) {
|
| + uint32_t index = static_cast<uint32_t>(Smi::cast(*key)->value());
|
| + return Top::Throw(*Factory::NewIndexError(index));
|
| + }
|
| + }
|
| +
|
| if (key->IsString()) {
|
| Handle<Object> result;
|
| if (Handle<String>::cast(key)->AsArrayIndex(&index)) {
|
| @@ -5273,6 +5297,47 @@
|
| };
|
|
|
|
|
| +template<class ExternalArrayClass, class ElementType>
|
| +static uint32_t IterateExternalArrayElements(Handle<JSObject> receiver,
|
| + bool elements_are_ints,
|
| + bool elements_are_guaranteed_smis,
|
| + uint32_t range,
|
| + ArrayConcatVisitor* visitor) {
|
| + Handle<ExternalArrayClass> array(
|
| + ExternalArrayClass::cast(receiver->elements()));
|
| + uint32_t len = Min(static_cast<uint32_t>(array->length()), range);
|
| +
|
| + if (visitor != NULL) {
|
| + if (elements_are_ints) {
|
| + if (elements_are_guaranteed_smis) {
|
| + for (uint32_t j = 0; j < len; j++) {
|
| + Handle<Smi> e(Smi::FromInt(static_cast<int>(array->get(j))));
|
| + visitor->visit(j, e);
|
| + }
|
| + } else {
|
| + for (uint32_t j = 0; j < len; j++) {
|
| + int64_t val = static_cast<int64_t>(array->get(j));
|
| + if (Smi::IsValid(static_cast<intptr_t>(val))) {
|
| + Handle<Smi> e(Smi::FromInt(static_cast<int>(val)));
|
| + visitor->visit(j, e);
|
| + } else {
|
| + Handle<Object> e(
|
| + Heap::AllocateHeapNumber(static_cast<ElementType>(val)));
|
| + visitor->visit(j, e);
|
| + }
|
| + }
|
| + }
|
| + } else {
|
| + for (uint32_t j = 0; j < len; j++) {
|
| + Handle<Object> e(Heap::AllocateHeapNumber(array->get(j)));
|
| + visitor->visit(j, e);
|
| + }
|
| + }
|
| + }
|
| +
|
| + return len;
|
| +}
|
| +
|
| /**
|
| * A helper function that visits elements of a JSObject. Only elements
|
| * whose index between 0 and range (exclusive) are visited.
|
| @@ -5322,6 +5387,48 @@
|
| }
|
| break;
|
| }
|
| + case JSObject::EXTERNAL_BYTE_ELEMENTS: {
|
| + num_of_elements =
|
| + IterateExternalArrayElements<ExternalByteArray, int8_t>(
|
| + receiver, true, true, range, visitor);
|
| + break;
|
| + }
|
| + case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
|
| + num_of_elements =
|
| + IterateExternalArrayElements<ExternalUnsignedByteArray, uint8_t>(
|
| + receiver, true, true, range, visitor);
|
| + break;
|
| + }
|
| + case JSObject::EXTERNAL_SHORT_ELEMENTS: {
|
| + num_of_elements =
|
| + IterateExternalArrayElements<ExternalShortArray, int16_t>(
|
| + receiver, true, true, range, visitor);
|
| + break;
|
| + }
|
| + case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
|
| + num_of_elements =
|
| + IterateExternalArrayElements<ExternalUnsignedShortArray, uint16_t>(
|
| + receiver, true, true, range, visitor);
|
| + break;
|
| + }
|
| + case JSObject::EXTERNAL_INT_ELEMENTS: {
|
| + num_of_elements =
|
| + IterateExternalArrayElements<ExternalIntArray, int32_t>(
|
| + receiver, true, false, range, visitor);
|
| + break;
|
| + }
|
| + case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: {
|
| + num_of_elements =
|
| + IterateExternalArrayElements<ExternalUnsignedIntArray, uint32_t>(
|
| + receiver, true, false, range, visitor);
|
| + break;
|
| + }
|
| + case JSObject::EXTERNAL_FLOAT_ELEMENTS: {
|
| + num_of_elements =
|
| + IterateExternalArrayElements<ExternalFloatArray, float>(
|
| + receiver, false, false, range, visitor);
|
| + break;
|
| + }
|
| case JSObject::DICTIONARY_ELEMENTS: {
|
| Handle<NumberDictionary> dict(receiver->element_dictionary());
|
| uint32_t capacity = dict->Capacity();
|
|
|