| Index: src/objects.cc
 | 
| ===================================================================
 | 
| --- src/objects.cc	(revision 7683)
 | 
| +++ src/objects.cc	(working copy)
 | 
| @@ -1045,6 +1045,10 @@
 | 
|        accumulator->Add("<ExternalFloatArray[%u]>",
 | 
|                         ExternalFloatArray::cast(this)->length());
 | 
|        break;
 | 
| +    case EXTERNAL_DOUBLE_ARRAY_TYPE:
 | 
| +      accumulator->Add("<ExternalDoubleArray[%u]>",
 | 
| +                       ExternalDoubleArray::cast(this)->length());
 | 
| +      break;
 | 
|      case SHARED_FUNCTION_INFO_TYPE:
 | 
|        accumulator->Add("<SharedFunctionInfo>");
 | 
|        break;
 | 
| @@ -1174,6 +1178,7 @@
 | 
|      case EXTERNAL_INT_ARRAY_TYPE:
 | 
|      case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
 | 
|      case EXTERNAL_FLOAT_ARRAY_TYPE:
 | 
| +    case EXTERNAL_DOUBLE_ARRAY_TYPE:
 | 
|        break;
 | 
|      case SHARED_FUNCTION_INFO_TYPE:
 | 
|        SharedFunctionInfo::BodyDescriptor::IterateBody(this, v);
 | 
| @@ -2848,6 +2853,7 @@
 | 
|      case EXTERNAL_INT_ELEMENTS:
 | 
|      case EXTERNAL_UNSIGNED_INT_ELEMENTS:
 | 
|      case EXTERNAL_FLOAT_ELEMENTS:
 | 
| +    case EXTERNAL_DOUBLE_ELEMENTS:
 | 
|        // Pixel and external array elements cannot be deleted. Just
 | 
|        // silently ignore here.
 | 
|        break;
 | 
| @@ -2967,6 +2973,7 @@
 | 
|      case EXTERNAL_INT_ELEMENTS:
 | 
|      case EXTERNAL_UNSIGNED_INT_ELEMENTS:
 | 
|      case EXTERNAL_FLOAT_ELEMENTS:
 | 
| +    case EXTERNAL_DOUBLE_ELEMENTS:
 | 
|        // Raw pixels and external arrays do not reference other
 | 
|        // objects.
 | 
|        break;
 | 
| @@ -3238,6 +3245,7 @@
 | 
|        case EXTERNAL_INT_ELEMENTS:
 | 
|        case EXTERNAL_UNSIGNED_INT_ELEMENTS:
 | 
|        case EXTERNAL_FLOAT_ELEMENTS:
 | 
| +      case EXTERNAL_DOUBLE_ELEMENTS:
 | 
|          // Ignore getters and setters on pixel and external array
 | 
|          // elements.
 | 
|          return heap->undefined_value();
 | 
| @@ -3464,6 +3472,7 @@
 | 
|        case EXTERNAL_INT_ELEMENTS:
 | 
|        case EXTERNAL_UNSIGNED_INT_ELEMENTS:
 | 
|        case EXTERNAL_FLOAT_ELEMENTS:
 | 
| +      case EXTERNAL_DOUBLE_ELEMENTS:
 | 
|          // Ignore getters and setters on pixel and external array
 | 
|          // elements.
 | 
|          return isolate->heap()->undefined_value();
 | 
| @@ -6874,6 +6883,49 @@
 | 
|  }
 | 
|  
 | 
|  
 | 
| +Object* Map::GetPrototypeTransition(Object* prototype) {
 | 
| +  FixedArray* cache = prototype_transitions();
 | 
| +  int capacity = cache->length();
 | 
| +  if (capacity == 0) return NULL;
 | 
| +  int finger = Smi::cast(cache->get(0))->value();
 | 
| +  for (int i = 1; i < finger; i += 2) {
 | 
| +    if (cache->get(i) == prototype) return cache->get(i + 1);
 | 
| +  }
 | 
| +  return NULL;
 | 
| +}
 | 
| +
 | 
| +
 | 
| +MaybeObject* Map::PutPrototypeTransition(Object* prototype, Map* map) {
 | 
| +  // Don't cache prototype transition if this map is shared.
 | 
| +  if (is_shared() || !FLAG_cache_prototype_transitions) return this;
 | 
| +
 | 
| +  FixedArray* cache = prototype_transitions();
 | 
| +
 | 
| +  int capacity = cache->length();
 | 
| +
 | 
| +  int finger = (capacity == 0) ? 1 : Smi::cast(cache->get(0))->value();
 | 
| +
 | 
| +  if (finger >= capacity) {
 | 
| +    if (capacity > kMaxCachedPrototypeTransitions) return this;
 | 
| +
 | 
| +    FixedArray* new_cache;
 | 
| +    { MaybeObject* maybe_cache = heap()->AllocateFixedArray(finger * 2 + 1);
 | 
| +      if (!maybe_cache->To<FixedArray>(&new_cache)) return maybe_cache;
 | 
| +    }
 | 
| +
 | 
| +    for (int i = 1; i < capacity; i++) new_cache->set(i, cache->get(i));
 | 
| +    cache = new_cache;
 | 
| +    set_prototype_transitions(cache);
 | 
| +  }
 | 
| +
 | 
| +  cache->set(finger, prototype);
 | 
| +  cache->set(finger + 1, map);
 | 
| +  cache->set(0, Smi::FromInt(finger + 2));
 | 
| +
 | 
| +  return cache;
 | 
| +}
 | 
| +
 | 
| +
 | 
|  MaybeObject* JSObject::SetPrototype(Object* value,
 | 
|                                      bool skip_hidden_prototypes) {
 | 
|    Heap* heap = GetHeap();
 | 
| @@ -6924,11 +6976,25 @@
 | 
|    }
 | 
|  
 | 
|    // Set the new prototype of the object.
 | 
| -  Object* new_map;
 | 
| -  { MaybeObject* maybe_new_map = real_receiver->map()->CopyDropTransitions();
 | 
| -    if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
 | 
| +  Map* map = real_receiver->map();
 | 
| +
 | 
| +  // Nothing to do if prototype is already set.
 | 
| +  if (map->prototype() == value) return value;
 | 
| +
 | 
| +  Object* new_map = map->GetPrototypeTransition(value);
 | 
| +  if (new_map == NULL) {
 | 
| +    { MaybeObject* maybe_new_map = map->CopyDropTransitions();
 | 
| +      if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
 | 
| +    }
 | 
| +
 | 
| +    { MaybeObject* maybe_new_cache =
 | 
| +          map->PutPrototypeTransition(value, Map::cast(new_map));
 | 
| +      if (maybe_new_cache->IsFailure()) return maybe_new_cache;
 | 
| +    }
 | 
| +
 | 
| +    Map::cast(new_map)->set_prototype(value);
 | 
|    }
 | 
| -  Map::cast(new_map)->set_prototype(value);
 | 
| +  ASSERT(Map::cast(new_map)->prototype() == value);
 | 
|    real_receiver->set_map(Map::cast(new_map));
 | 
|  
 | 
|    heap->ClearInstanceofCache();
 | 
| @@ -6963,7 +7029,8 @@
 | 
|      case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
 | 
|      case EXTERNAL_INT_ELEMENTS:
 | 
|      case EXTERNAL_UNSIGNED_INT_ELEMENTS:
 | 
| -    case EXTERNAL_FLOAT_ELEMENTS: {
 | 
| +    case EXTERNAL_FLOAT_ELEMENTS:
 | 
| +    case EXTERNAL_DOUBLE_ELEMENTS: {
 | 
|        ExternalArray* array = ExternalArray::cast(elements());
 | 
|        if (index < static_cast<uint32_t>(array->length())) {
 | 
|          return true;
 | 
| @@ -7085,7 +7152,8 @@
 | 
|      case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
 | 
|      case EXTERNAL_INT_ELEMENTS:
 | 
|      case EXTERNAL_UNSIGNED_INT_ELEMENTS:
 | 
| -    case EXTERNAL_FLOAT_ELEMENTS: {
 | 
| +    case EXTERNAL_FLOAT_ELEMENTS:
 | 
| +    case EXTERNAL_DOUBLE_ELEMENTS: {
 | 
|        ExternalArray* array = ExternalArray::cast(elements());
 | 
|        if (index < static_cast<uint32_t>(array->length())) return FAST_ELEMENT;
 | 
|        break;
 | 
| @@ -7144,7 +7212,8 @@
 | 
|      case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
 | 
|      case EXTERNAL_INT_ELEMENTS:
 | 
|      case EXTERNAL_UNSIGNED_INT_ELEMENTS:
 | 
| -    case EXTERNAL_FLOAT_ELEMENTS: {
 | 
| +    case EXTERNAL_FLOAT_ELEMENTS:
 | 
| +    case EXTERNAL_DOUBLE_ELEMENTS: {
 | 
|        ExternalArray* array = ExternalArray::cast(elements());
 | 
|        if (index < static_cast<uint32_t>(array->length())) {
 | 
|          return true;
 | 
| @@ -7465,6 +7534,10 @@
 | 
|        ExternalFloatArray* array = ExternalFloatArray::cast(elements());
 | 
|        return array->SetValue(index, value);
 | 
|      }
 | 
| +    case EXTERNAL_DOUBLE_ELEMENTS: {
 | 
| +      ExternalDoubleArray* array = ExternalDoubleArray::cast(elements());
 | 
| +      return array->SetValue(index, value);
 | 
| +    }
 | 
|      case DICTIONARY_ELEMENTS: {
 | 
|        // Insert element in the dictionary.
 | 
|        FixedArray* elms = FixedArray::cast(elements());
 | 
| @@ -7606,7 +7679,8 @@
 | 
|      case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
 | 
|      case EXTERNAL_INT_ELEMENTS:
 | 
|      case EXTERNAL_UNSIGNED_INT_ELEMENTS:
 | 
| -    case EXTERNAL_FLOAT_ELEMENTS: {
 | 
| +    case EXTERNAL_FLOAT_ELEMENTS:
 | 
| +    case EXTERNAL_DOUBLE_ELEMENTS: {
 | 
|        MaybeObject* maybe_value = GetExternalElement(index);
 | 
|        Object* value;
 | 
|        if (!maybe_value->ToObject(&value)) return maybe_value;
 | 
| @@ -7708,7 +7782,8 @@
 | 
|      case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
 | 
|      case EXTERNAL_INT_ELEMENTS:
 | 
|      case EXTERNAL_UNSIGNED_INT_ELEMENTS:
 | 
| -    case EXTERNAL_FLOAT_ELEMENTS: {
 | 
| +    case EXTERNAL_FLOAT_ELEMENTS:
 | 
| +    case EXTERNAL_DOUBLE_ELEMENTS: {
 | 
|        MaybeObject* maybe_value = GetExternalElement(index);
 | 
|        Object* value;
 | 
|        if (!maybe_value->ToObject(&value)) return maybe_value;
 | 
| @@ -7811,6 +7886,14 @@
 | 
|        }
 | 
|        break;
 | 
|      }
 | 
| +    case EXTERNAL_DOUBLE_ELEMENTS: {
 | 
| +      ExternalDoubleArray* array = ExternalDoubleArray::cast(elements());
 | 
| +      if (index < static_cast<uint32_t>(array->length())) {
 | 
| +        double value = array->get(index);
 | 
| +        return GetHeap()->AllocateHeapNumber(value);
 | 
| +      }
 | 
| +      break;
 | 
| +    }
 | 
|      case FAST_ELEMENTS:
 | 
|      case DICTIONARY_ELEMENTS:
 | 
|        UNREACHABLE();
 | 
| @@ -7840,7 +7923,8 @@
 | 
|      case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
 | 
|      case EXTERNAL_INT_ELEMENTS:
 | 
|      case EXTERNAL_UNSIGNED_INT_ELEMENTS:
 | 
| -    case EXTERNAL_FLOAT_ELEMENTS: {
 | 
| +    case EXTERNAL_FLOAT_ELEMENTS:
 | 
| +    case EXTERNAL_DOUBLE_ELEMENTS: {
 | 
|        return true;
 | 
|      }
 | 
|      case DICTIONARY_ELEMENTS: {
 | 
| @@ -8077,7 +8161,8 @@
 | 
|      case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
 | 
|      case EXTERNAL_INT_ELEMENTS:
 | 
|      case EXTERNAL_UNSIGNED_INT_ELEMENTS:
 | 
| -    case EXTERNAL_FLOAT_ELEMENTS: {
 | 
| +    case EXTERNAL_FLOAT_ELEMENTS:
 | 
| +    case EXTERNAL_DOUBLE_ELEMENTS: {
 | 
|        ExternalArray* array = ExternalArray::cast(elements());
 | 
|        return index < static_cast<uint32_t>(array->length());
 | 
|      }
 | 
| @@ -8318,7 +8403,8 @@
 | 
|      case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
 | 
|      case EXTERNAL_INT_ELEMENTS:
 | 
|      case EXTERNAL_UNSIGNED_INT_ELEMENTS:
 | 
| -    case EXTERNAL_FLOAT_ELEMENTS: {
 | 
| +    case EXTERNAL_FLOAT_ELEMENTS:
 | 
| +    case EXTERNAL_DOUBLE_ELEMENTS: {
 | 
|        int length = ExternalArray::cast(elements())->length();
 | 
|        while (counter < length) {
 | 
|          if (storage != NULL) {
 | 
| @@ -9233,6 +9319,26 @@
 | 
|  }
 | 
|  
 | 
|  
 | 
| +MaybeObject* ExternalDoubleArray::SetValue(uint32_t index, Object* value) {
 | 
| +  double double_value = 0;
 | 
| +  Heap* heap = GetHeap();
 | 
| +  if (index < static_cast<uint32_t>(length())) {
 | 
| +    if (value->IsSmi()) {
 | 
| +      int int_value = Smi::cast(value)->value();
 | 
| +      double_value = static_cast<double>(int_value);
 | 
| +    } else if (value->IsHeapNumber()) {
 | 
| +      double_value = HeapNumber::cast(value)->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, double_value);
 | 
| +  }
 | 
| +  return heap->AllocateHeapNumber(double_value);
 | 
| +}
 | 
| +
 | 
| +
 | 
|  JSGlobalPropertyCell* GlobalObject::GetPropertyCell(LookupResult* result) {
 | 
|    ASSERT(!HasFastProperties());
 | 
|    Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry());
 | 
| 
 |