OLD | NEW |
---|---|
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 13065 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
13076 | 13076 |
13077 // Transitions from HOLEY -> PACKED are not allowed. | 13077 // Transitions from HOLEY -> PACKED are not allowed. |
13078 return !IsFastHoleyElementsKind(from_kind) || | 13078 return !IsFastHoleyElementsKind(from_kind) || |
13079 IsFastHoleyElementsKind(to_kind); | 13079 IsFastHoleyElementsKind(to_kind); |
13080 } | 13080 } |
13081 | 13081 |
13082 | 13082 |
13083 void JSArray::JSArrayUpdateLengthFromIndex(Handle<JSArray> array, | 13083 void JSArray::JSArrayUpdateLengthFromIndex(Handle<JSArray> array, |
13084 uint32_t index, | 13084 uint32_t index, |
13085 Handle<Object> value) { | 13085 Handle<Object> value) { |
13086 CALL_HEAP_FUNCTION_VOID(array->GetIsolate(), | 13086 uint32_t old_len = 0; |
13087 array->JSArrayUpdateLengthFromIndex(index, *value)); | 13087 CHECK(array->length()->ToArrayIndex(&old_len)); |
13088 // Check to see if we need to update the length. For now, we make | |
13089 // sure that the length stays within 32-bits (unsigned). | |
13090 if (index >= old_len && index != 0xffffffff) { | |
13091 Handle<Object> len = array->GetIsolate()->factory()->NewNumber( | |
13092 static_cast<double>(index) + 1); | |
13093 array->set_length(*len); | |
13094 } | |
13088 } | 13095 } |
13089 | 13096 |
13090 | 13097 |
13091 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index, | |
13092 Object* value) { | |
13093 uint32_t old_len = 0; | |
13094 CHECK(length()->ToArrayIndex(&old_len)); | |
13095 // Check to see if we need to update the length. For now, we make | |
13096 // sure that the length stays within 32-bits (unsigned). | |
13097 if (index >= old_len && index != 0xffffffff) { | |
13098 Object* len; | |
13099 { MaybeObject* maybe_len = | |
13100 GetHeap()->NumberFromDouble(static_cast<double>(index) + 1); | |
13101 if (!maybe_len->ToObject(&len)) return maybe_len; | |
13102 } | |
13103 set_length(len); | |
13104 } | |
13105 return value; | |
13106 } | |
13107 | |
13108 | |
13109 MaybeHandle<Object> JSObject::GetElementWithInterceptor( | 13098 MaybeHandle<Object> JSObject::GetElementWithInterceptor( |
13110 Handle<JSObject> object, | 13099 Handle<JSObject> object, |
13111 Handle<Object> receiver, | 13100 Handle<Object> receiver, |
13112 uint32_t index) { | 13101 uint32_t index) { |
13113 Isolate* isolate = object->GetIsolate(); | 13102 Isolate* isolate = object->GetIsolate(); |
13114 | 13103 |
13115 // Make sure that the top context does not change when doing | 13104 // Make sure that the top context does not change when doing |
13116 // callbacks or interceptor calls. | 13105 // callbacks or interceptor calls. |
13117 AssertNoContextChange ncc(isolate); | 13106 AssertNoContextChange ncc(isolate); |
13118 | 13107 |
(...skipping 1394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
14513 Handle<Object> value, | 14502 Handle<Object> value, |
14514 PropertyDetails details) { | 14503 PropertyDetails details) { |
14515 CALL_HEAP_FUNCTION(dict->GetIsolate(), | 14504 CALL_HEAP_FUNCTION(dict->GetIsolate(), |
14516 dict->Add(*name, *value, details), | 14505 dict->Add(*name, *value, details), |
14517 NameDictionary); | 14506 NameDictionary); |
14518 } | 14507 } |
14519 | 14508 |
14520 | 14509 |
14521 Handle<Object> JSObject::PrepareSlowElementsForSort( | 14510 Handle<Object> JSObject::PrepareSlowElementsForSort( |
14522 Handle<JSObject> object, uint32_t limit) { | 14511 Handle<JSObject> object, uint32_t limit) { |
14523 CALL_HEAP_FUNCTION(object->GetIsolate(), | 14512 ASSERT(object->HasDictionaryElements()); |
14524 object->PrepareSlowElementsForSort(limit), | 14513 Isolate* isolate = object->GetIsolate(); |
14525 Object); | |
14526 } | |
14527 | |
14528 | |
14529 // Collates undefined and unexisting elements below limit from position | |
14530 // zero of the elements. The object stays in Dictionary mode. | |
14531 MaybeObject* JSObject::PrepareSlowElementsForSort(uint32_t limit) { | |
14532 ASSERT(HasDictionaryElements()); | |
14533 // Must stay in dictionary mode, either because of requires_slow_elements, | 14514 // Must stay in dictionary mode, either because of requires_slow_elements, |
14534 // or because we are not going to sort (and therefore compact) all of the | 14515 // or because we are not going to sort (and therefore compact) all of the |
14535 // elements. | 14516 // elements. |
14536 SeededNumberDictionary* dict = element_dictionary(); | 14517 Handle<SeededNumberDictionary> dict(object->element_dictionary(), isolate); |
14537 HeapNumber* result_double = NULL; | 14518 Handle<SeededNumberDictionary> new_dict = |
14538 if (limit > static_cast<uint32_t>(Smi::kMaxValue)) { | 14519 isolate->factory()->NewSeededNumberDictionary(dict->NumberOfElements()); |
14539 // Allocate space for result before we start mutating the object. | |
14540 Object* new_double; | |
14541 { MaybeObject* maybe_new_double = GetHeap()->AllocateHeapNumber(0.0); | |
14542 if (!maybe_new_double->ToObject(&new_double)) return maybe_new_double; | |
14543 } | |
14544 result_double = HeapNumber::cast(new_double); | |
14545 } | |
14546 | |
14547 Object* obj; | |
14548 { MaybeObject* maybe_obj = | |
14549 SeededNumberDictionary::Allocate(GetHeap(), dict->NumberOfElements()); | |
14550 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | |
14551 } | |
14552 SeededNumberDictionary* new_dict = SeededNumberDictionary::cast(obj); | |
14553 | |
14554 DisallowHeapAllocation no_alloc; | |
14555 | 14520 |
14556 uint32_t pos = 0; | 14521 uint32_t pos = 0; |
14557 uint32_t undefs = 0; | 14522 uint32_t undefs = 0; |
14558 int capacity = dict->Capacity(); | 14523 int capacity = dict->Capacity(); |
14524 Handle<Smi> bailout(Smi::FromInt(-1), isolate); | |
14525 // Entry to the new dictionary does not cause it to grow, as we have | |
14526 // allocated one that is large enough for all entries. | |
14527 DisallowHeapAllocation no_gc; | |
14559 for (int i = 0; i < capacity; i++) { | 14528 for (int i = 0; i < capacity; i++) { |
14560 Object* k = dict->KeyAt(i); | 14529 Object* k = dict->KeyAt(i); |
14561 if (dict->IsKey(k)) { | 14530 if (!dict->IsKey(k)) continue; |
14562 ASSERT(k->IsNumber()); | 14531 |
14563 ASSERT(!k->IsSmi() || Smi::cast(k)->value() >= 0); | 14532 ASSERT(k->IsNumber()); |
14564 ASSERT(!k->IsHeapNumber() || HeapNumber::cast(k)->value() >= 0); | 14533 ASSERT(!k->IsSmi() || Smi::cast(k)->value() >= 0); |
14565 ASSERT(!k->IsHeapNumber() || HeapNumber::cast(k)->value() <= kMaxUInt32); | 14534 ASSERT(!k->IsHeapNumber() || HeapNumber::cast(k)->value() >= 0); |
14566 Object* value = dict->ValueAt(i); | 14535 ASSERT(!k->IsHeapNumber() || HeapNumber::cast(k)->value() <= kMaxUInt32); |
14567 PropertyDetails details = dict->DetailsAt(i); | 14536 |
14568 if (details.type() == CALLBACKS || details.IsReadOnly()) { | 14537 HandleScope scope(isolate); |
14569 // Bail out and do the sorting of undefineds and array holes in JS. | 14538 Handle<Object> value(dict->ValueAt(i), isolate); |
14570 // Also bail out if the element is not supposed to be moved. | 14539 PropertyDetails details = dict->DetailsAt(i); |
14571 return Smi::FromInt(-1); | 14540 if (details.type() == CALLBACKS || details.IsReadOnly()) { |
14541 // Bail out and do the sorting of undefineds and array holes in JS. | |
14542 // Also bail out if the element is not supposed to be moved. | |
14543 return bailout; | |
14544 } | |
14545 | |
14546 uint32_t key = NumberToUint32(k); | |
14547 if (key < limit) { | |
14548 if (value->IsUndefined()) { | |
14549 undefs++; | |
14550 } else if (pos > static_cast<uint32_t>(Smi::kMaxValue)) { | |
14551 // Adding an entry with the key beyond smi-range requires | |
14552 // allocation. Bailout. | |
14553 return bailout; | |
14554 } else { | |
14555 Handle<Object> result = SeededNumberDictionary::AddNumberEntry( | |
14556 new_dict, pos, value, details); | |
14557 ASSERT(result.is_identical_to(new_dict)); | |
14558 USE(result); | |
14559 pos++; | |
14572 } | 14560 } |
14573 uint32_t key = NumberToUint32(k); | 14561 } else if (key > static_cast<uint32_t>(Smi::kMaxValue)) { |
14574 // In the following we assert that adding the entry to the new dictionary | 14562 // Adding an entry with the key beyond smi-range requires |
14575 // does not cause GC. This is the case because we made sure to allocate | 14563 // allocation. Bailout. |
14576 // the dictionary big enough above, so it need not grow. | 14564 return bailout; |
14577 if (key < limit) { | 14565 } else { |
14578 if (value->IsUndefined()) { | 14566 Handle<Object> result = SeededNumberDictionary::AddNumberEntry( |
14579 undefs++; | 14567 new_dict, key, value, details); |
14580 } else { | 14568 ASSERT(result.is_identical_to(new_dict)); |
14581 if (pos > static_cast<uint32_t>(Smi::kMaxValue)) { | 14569 USE(result); |
14582 // Adding an entry with the key beyond smi-range requires | |
14583 // allocation. Bailout. | |
14584 return Smi::FromInt(-1); | |
14585 } | |
14586 new_dict->AddNumberEntry(pos, value, details)->ToObjectUnchecked(); | |
14587 pos++; | |
14588 } | |
14589 } else { | |
14590 if (key > static_cast<uint32_t>(Smi::kMaxValue)) { | |
14591 // Adding an entry with the key beyond smi-range requires | |
14592 // allocation. Bailout. | |
14593 return Smi::FromInt(-1); | |
14594 } | |
14595 new_dict->AddNumberEntry(key, value, details)->ToObjectUnchecked(); | |
14596 } | |
14597 } | 14570 } |
14598 } | 14571 } |
14599 | 14572 |
14600 uint32_t result = pos; | 14573 uint32_t result = pos; |
14601 PropertyDetails no_details = PropertyDetails(NONE, NORMAL, 0); | 14574 PropertyDetails no_details = PropertyDetails(NONE, NORMAL, 0); |
14602 Heap* heap = GetHeap(); | |
14603 while (undefs > 0) { | 14575 while (undefs > 0) { |
14604 if (pos > static_cast<uint32_t>(Smi::kMaxValue)) { | 14576 if (pos > static_cast<uint32_t>(Smi::kMaxValue)) { |
14605 // Adding an entry with the key beyond smi-range requires | 14577 // Adding an entry with the key beyond smi-range requires |
14606 // allocation. Bailout. | 14578 // allocation. Bailout. |
14607 return Smi::FromInt(-1); | 14579 return bailout; |
14608 } | 14580 } |
14609 new_dict->AddNumberEntry(pos, heap->undefined_value(), no_details)-> | 14581 HandleScope scope(isolate); |
14610 ToObjectUnchecked(); | 14582 Handle<Object> result = SeededNumberDictionary::AddNumberEntry( |
14583 new_dict, pos, isolate->factory()->undefined_value(), no_details); | |
14584 ASSERT(result.is_identical_to(new_dict)); | |
14585 USE(result); | |
14611 pos++; | 14586 pos++; |
14612 undefs--; | 14587 undefs--; |
14613 } | 14588 } |
14614 | 14589 |
14615 set_elements(new_dict); | 14590 object->set_elements(*new_dict); |
14616 | 14591 |
14617 if (result <= static_cast<uint32_t>(Smi::kMaxValue)) { | 14592 AllowHeapAllocation allocate_return_value; |
14618 return Smi::FromInt(static_cast<int>(result)); | 14593 return isolate->factory()->NewNumberFromUint(result); |
mvstanton
2014/04/15 09:56:19
Nice consolidation to use NewNumberFromUint().
| |
14619 } | |
14620 | |
14621 ASSERT_NE(NULL, result_double); | |
14622 result_double->set_value(static_cast<double>(result)); | |
14623 return result_double; | |
14624 } | 14594 } |
14625 | 14595 |
14626 | 14596 |
14627 // Collects all defined (non-hole) and non-undefined (array) elements at | 14597 // Collects all defined (non-hole) and non-undefined (array) elements at |
14628 // the start of the elements array. | 14598 // the start of the elements array. |
14629 // If the object is in dictionary mode, it is converted to fast elements | 14599 // If the object is in dictionary mode, it is converted to fast elements |
14630 // mode. | 14600 // mode. |
14631 Handle<Object> JSObject::PrepareElementsForSort(Handle<JSObject> object, | 14601 Handle<Object> JSObject::PrepareElementsForSort(Handle<JSObject> object, |
14632 uint32_t limit) { | 14602 uint32_t limit) { |
14633 Isolate* isolate = object->GetIsolate(); | 14603 Isolate* isolate = object->GetIsolate(); |
(...skipping 1986 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
16620 #define ERROR_MESSAGES_TEXTS(C, T) T, | 16590 #define ERROR_MESSAGES_TEXTS(C, T) T, |
16621 static const char* error_messages_[] = { | 16591 static const char* error_messages_[] = { |
16622 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 16592 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
16623 }; | 16593 }; |
16624 #undef ERROR_MESSAGES_TEXTS | 16594 #undef ERROR_MESSAGES_TEXTS |
16625 return error_messages_[reason]; | 16595 return error_messages_[reason]; |
16626 } | 16596 } |
16627 | 16597 |
16628 | 16598 |
16629 } } // namespace v8::internal | 16599 } } // namespace v8::internal |
OLD | NEW |