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()); |