| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 8345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8356 set_elements(elems); | 8356 set_elements(elems); |
| 8357 | 8357 |
| 8358 if (IsJSArray()) { | 8358 if (IsJSArray()) { |
| 8359 JSArray::cast(this)->set_length(Smi::FromInt(length)); | 8359 JSArray::cast(this)->set_length(Smi::FromInt(length)); |
| 8360 } | 8360 } |
| 8361 | 8361 |
| 8362 return this; | 8362 return this; |
| 8363 } | 8363 } |
| 8364 | 8364 |
| 8365 | 8365 |
| 8366 MaybeObject* JSObject::SetSlowElements(Object* len) { | |
| 8367 // We should never end in here with a pixel or external array. | |
| 8368 ASSERT(!HasExternalArrayElements()); | |
| 8369 | |
| 8370 uint32_t new_length = static_cast<uint32_t>(len->Number()); | |
| 8371 | |
| 8372 FixedArrayBase* old_elements = elements(); | |
| 8373 ElementsKind elements_kind = GetElementsKind(); | |
| 8374 switch (elements_kind) { | |
| 8375 case FAST_SMI_ONLY_ELEMENTS: | |
| 8376 case FAST_ELEMENTS: | |
| 8377 case FAST_DOUBLE_ELEMENTS: { | |
| 8378 // Make sure we never try to shrink dense arrays into sparse arrays. | |
| 8379 ASSERT(static_cast<uint32_t>(old_elements->length()) <= new_length); | |
| 8380 MaybeObject* result = NormalizeElements(); | |
| 8381 if (result->IsFailure()) return result; | |
| 8382 | |
| 8383 // Update length for JSArrays. | |
| 8384 if (IsJSArray()) JSArray::cast(this)->set_length(len); | |
| 8385 break; | |
| 8386 } | |
| 8387 case DICTIONARY_ELEMENTS: { | |
| 8388 if (IsJSArray()) { | |
| 8389 uint32_t old_length = | |
| 8390 static_cast<uint32_t>(JSArray::cast(this)->length()->Number()); | |
| 8391 element_dictionary()->RemoveNumberEntries(new_length, old_length), | |
| 8392 JSArray::cast(this)->set_length(len); | |
| 8393 } | |
| 8394 break; | |
| 8395 } | |
| 8396 case NON_STRICT_ARGUMENTS_ELEMENTS: | |
| 8397 UNIMPLEMENTED(); | |
| 8398 break; | |
| 8399 case EXTERNAL_BYTE_ELEMENTS: | |
| 8400 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | |
| 8401 case EXTERNAL_SHORT_ELEMENTS: | |
| 8402 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | |
| 8403 case EXTERNAL_INT_ELEMENTS: | |
| 8404 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | |
| 8405 case EXTERNAL_FLOAT_ELEMENTS: | |
| 8406 case EXTERNAL_DOUBLE_ELEMENTS: | |
| 8407 case EXTERNAL_PIXEL_ELEMENTS: | |
| 8408 UNREACHABLE(); | |
| 8409 break; | |
| 8410 } | |
| 8411 | |
| 8412 if (FLAG_trace_elements_transitions) { | |
| 8413 PrintElementsTransition(stdout, elements_kind, old_elements, | |
| 8414 DICTIONARY_ELEMENTS, elements()); | |
| 8415 } | |
| 8416 | |
| 8417 return this; | |
| 8418 } | |
| 8419 | |
| 8420 | |
| 8421 MaybeObject* JSArray::Initialize(int capacity) { | 8366 MaybeObject* JSArray::Initialize(int capacity) { |
| 8422 Heap* heap = GetHeap(); | 8367 Heap* heap = GetHeap(); |
| 8423 ASSERT(capacity >= 0); | 8368 ASSERT(capacity >= 0); |
| 8424 set_length(Smi::FromInt(0)); | 8369 set_length(Smi::FromInt(0)); |
| 8425 FixedArray* new_elements; | 8370 FixedArray* new_elements; |
| 8426 if (capacity == 0) { | 8371 if (capacity == 0) { |
| 8427 new_elements = heap->empty_fixed_array(); | 8372 new_elements = heap->empty_fixed_array(); |
| 8428 } else { | 8373 } else { |
| 8429 Object* obj; | 8374 Object* obj; |
| 8430 { MaybeObject* maybe_obj = heap->AllocateFixedArrayWithHoles(capacity); | 8375 { MaybeObject* maybe_obj = heap->AllocateFixedArrayWithHoles(capacity); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 8442 Handle<FixedArray> old_backing(FixedArray::cast(elements())); | 8387 Handle<FixedArray> old_backing(FixedArray::cast(elements())); |
| 8443 int old_size = old_backing->length(); | 8388 int old_size = old_backing->length(); |
| 8444 int new_size = required_size > old_size ? required_size : old_size; | 8389 int new_size = required_size > old_size ? required_size : old_size; |
| 8445 Handle<FixedArray> new_backing = FACTORY->NewFixedArray(new_size); | 8390 Handle<FixedArray> new_backing = FACTORY->NewFixedArray(new_size); |
| 8446 // Can't use this any more now because we may have had a GC! | 8391 // Can't use this any more now because we may have had a GC! |
| 8447 for (int i = 0; i < old_size; i++) new_backing->set(i, old_backing->get(i)); | 8392 for (int i = 0; i < old_size; i++) new_backing->set(i, old_backing->get(i)); |
| 8448 GetIsolate()->factory()->SetContent(self, new_backing); | 8393 GetIsolate()->factory()->SetContent(self, new_backing); |
| 8449 } | 8394 } |
| 8450 | 8395 |
| 8451 | 8396 |
| 8452 static Failure* ArrayLengthRangeError(Heap* heap) { | |
| 8453 HandleScope scope(heap->isolate()); | |
| 8454 return heap->isolate()->Throw( | |
| 8455 *FACTORY->NewRangeError("invalid_array_length", | |
| 8456 HandleVector<Object>(NULL, 0))); | |
| 8457 } | |
| 8458 | |
| 8459 | |
| 8460 MaybeObject* JSObject::SetElementsLength(Object* len) { | 8397 MaybeObject* JSObject::SetElementsLength(Object* len) { |
| 8461 // We should never end in here with a pixel or external array. | 8398 // We should never end in here with a pixel or external array. |
| 8462 ASSERT(AllowsSetElementsLength()); | 8399 ASSERT(AllowsSetElementsLength()); |
| 8463 | 8400 return GetElementsAccessor()->SetLength(this, len); |
| 8464 MaybeObject* maybe_smi_length = len->ToSmi(); | |
| 8465 Object* smi_length = Smi::FromInt(0); | |
| 8466 if (maybe_smi_length->ToObject(&smi_length) && smi_length->IsSmi()) { | |
| 8467 const int value = Smi::cast(smi_length)->value(); | |
| 8468 if (value < 0) return ArrayLengthRangeError(GetHeap()); | |
| 8469 ElementsKind elements_kind = GetElementsKind(); | |
| 8470 switch (elements_kind) { | |
| 8471 case FAST_SMI_ONLY_ELEMENTS: | |
| 8472 case FAST_ELEMENTS: | |
| 8473 case FAST_DOUBLE_ELEMENTS: { | |
| 8474 int old_capacity = FixedArrayBase::cast(elements())->length(); | |
| 8475 if (value <= old_capacity) { | |
| 8476 if (IsJSArray()) { | |
| 8477 Object* obj; | |
| 8478 if (elements_kind == FAST_ELEMENTS || | |
| 8479 elements_kind == FAST_SMI_ONLY_ELEMENTS) { | |
| 8480 MaybeObject* maybe_obj = EnsureWritableFastElements(); | |
| 8481 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | |
| 8482 } | |
| 8483 if (2 * value <= old_capacity) { | |
| 8484 // If more than half the elements won't be used, trim the array. | |
| 8485 if (value == 0) { | |
| 8486 initialize_elements(); | |
| 8487 } else { | |
| 8488 Address filler_start; | |
| 8489 int filler_size; | |
| 8490 if (elements_kind == FAST_ELEMENTS || | |
| 8491 elements_kind == FAST_SMI_ONLY_ELEMENTS) { | |
| 8492 FixedArray* fast_elements = FixedArray::cast(elements()); | |
| 8493 fast_elements->set_length(value); | |
| 8494 filler_start = fast_elements->address() + | |
| 8495 FixedArray::OffsetOfElementAt(value); | |
| 8496 filler_size = (old_capacity - value) * kPointerSize; | |
| 8497 } else { | |
| 8498 ASSERT(GetElementsKind() == FAST_DOUBLE_ELEMENTS); | |
| 8499 FixedDoubleArray* fast_double_elements = | |
| 8500 FixedDoubleArray::cast(elements()); | |
| 8501 fast_double_elements->set_length(value); | |
| 8502 filler_start = fast_double_elements->address() + | |
| 8503 FixedDoubleArray::OffsetOfElementAt(value); | |
| 8504 filler_size = (old_capacity - value) * kDoubleSize; | |
| 8505 } | |
| 8506 GetHeap()->CreateFillerObjectAt(filler_start, filler_size); | |
| 8507 } | |
| 8508 } else { | |
| 8509 // Otherwise, fill the unused tail with holes. | |
| 8510 int old_length = FastD2I(JSArray::cast(this)->length()->Number()); | |
| 8511 if (elements_kind == FAST_ELEMENTS || | |
| 8512 elements_kind == FAST_SMI_ONLY_ELEMENTS) { | |
| 8513 FixedArray* fast_elements = FixedArray::cast(elements()); | |
| 8514 for (int i = value; i < old_length; i++) { | |
| 8515 fast_elements->set_the_hole(i); | |
| 8516 } | |
| 8517 } else { | |
| 8518 ASSERT(elements_kind == FAST_DOUBLE_ELEMENTS); | |
| 8519 FixedDoubleArray* fast_double_elements = | |
| 8520 FixedDoubleArray::cast(elements()); | |
| 8521 for (int i = value; i < old_length; i++) { | |
| 8522 fast_double_elements->set_the_hole(i); | |
| 8523 } | |
| 8524 } | |
| 8525 } | |
| 8526 JSArray::cast(this)->set_length(Smi::cast(smi_length)); | |
| 8527 } | |
| 8528 return this; | |
| 8529 } | |
| 8530 int min = NewElementsCapacity(old_capacity); | |
| 8531 int new_capacity = value > min ? value : min; | |
| 8532 if (!ShouldConvertToSlowElements(new_capacity)) { | |
| 8533 MaybeObject* result; | |
| 8534 if (elements_kind == FAST_ELEMENTS || | |
| 8535 elements_kind == FAST_SMI_ONLY_ELEMENTS) { | |
| 8536 SetFastElementsCapacityMode set_capacity_mode = | |
| 8537 elements_kind == FAST_SMI_ONLY_ELEMENTS | |
| 8538 ? kAllowSmiOnlyElements | |
| 8539 : kDontAllowSmiOnlyElements; | |
| 8540 result = SetFastElementsCapacityAndLength(new_capacity, | |
| 8541 value, | |
| 8542 set_capacity_mode); | |
| 8543 } else { | |
| 8544 ASSERT(elements_kind == FAST_DOUBLE_ELEMENTS); | |
| 8545 result = SetFastDoubleElementsCapacityAndLength(new_capacity, | |
| 8546 value); | |
| 8547 } | |
| 8548 if (result->IsFailure()) return result; | |
| 8549 return this; | |
| 8550 } | |
| 8551 break; | |
| 8552 } | |
| 8553 case DICTIONARY_ELEMENTS: { | |
| 8554 if (IsJSArray()) { | |
| 8555 if (value == 0) { | |
| 8556 // If the length of a slow array is reset to zero, we clear | |
| 8557 // the array and flush backing storage. This has the added | |
| 8558 // benefit that the array returns to fast mode. | |
| 8559 Object* obj; | |
| 8560 { MaybeObject* maybe_obj = ResetElements(); | |
| 8561 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | |
| 8562 } | |
| 8563 } else { | |
| 8564 // Remove deleted elements. | |
| 8565 uint32_t old_length = | |
| 8566 static_cast<uint32_t>(JSArray::cast(this)->length()->Number()); | |
| 8567 element_dictionary()->RemoveNumberEntries(value, old_length); | |
| 8568 } | |
| 8569 JSArray::cast(this)->set_length(Smi::cast(smi_length)); | |
| 8570 } | |
| 8571 return this; | |
| 8572 } | |
| 8573 case NON_STRICT_ARGUMENTS_ELEMENTS: | |
| 8574 case EXTERNAL_BYTE_ELEMENTS: | |
| 8575 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | |
| 8576 case EXTERNAL_SHORT_ELEMENTS: | |
| 8577 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | |
| 8578 case EXTERNAL_INT_ELEMENTS: | |
| 8579 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | |
| 8580 case EXTERNAL_FLOAT_ELEMENTS: | |
| 8581 case EXTERNAL_DOUBLE_ELEMENTS: | |
| 8582 case EXTERNAL_PIXEL_ELEMENTS: | |
| 8583 UNREACHABLE(); | |
| 8584 break; | |
| 8585 } | |
| 8586 } | |
| 8587 | |
| 8588 // General slow case. | |
| 8589 if (len->IsNumber()) { | |
| 8590 uint32_t length; | |
| 8591 if (len->ToArrayIndex(&length)) { | |
| 8592 return SetSlowElements(len); | |
| 8593 } else { | |
| 8594 return ArrayLengthRangeError(GetHeap()); | |
| 8595 } | |
| 8596 } | |
| 8597 | |
| 8598 // len is not a number so make the array size one and | |
| 8599 // set only element to len. | |
| 8600 Object* obj; | |
| 8601 MaybeObject* maybe_obj = GetHeap()->AllocateFixedArray(1); | |
| 8602 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | |
| 8603 FixedArray::cast(obj)->set(0, len); | |
| 8604 | |
| 8605 maybe_obj = EnsureCanContainElements(&len, 1); | |
| 8606 if (maybe_obj->IsFailure()) return maybe_obj; | |
| 8607 | |
| 8608 if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(1)); | |
| 8609 set_elements(FixedArray::cast(obj)); | |
| 8610 return this; | |
| 8611 } | 8401 } |
| 8612 | 8402 |
| 8613 | 8403 |
| 8614 Object* Map::GetPrototypeTransition(Object* prototype) { | 8404 Object* Map::GetPrototypeTransition(Object* prototype) { |
| 8615 FixedArray* cache = prototype_transitions(); | 8405 FixedArray* cache = prototype_transitions(); |
| 8616 int number_of_transitions = NumberOfProtoTransitions(); | 8406 int number_of_transitions = NumberOfProtoTransitions(); |
| 8617 const int proto_offset = | 8407 const int proto_offset = |
| 8618 kProtoTransitionHeaderSize + kProtoTransitionPrototypeOffset; | 8408 kProtoTransitionHeaderSize + kProtoTransitionPrototypeOffset; |
| 8619 const int map_offset = kProtoTransitionHeaderSize + kProtoTransitionMapOffset; | 8409 const int map_offset = kProtoTransitionHeaderSize + kProtoTransitionMapOffset; |
| 8620 const int step = kProtoTransitionElementsPerEntry; | 8410 const int step = kProtoTransitionElementsPerEntry; |
| (...skipping 3350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11971 // If not, we generate new indices for the properties. | 11761 // If not, we generate new indices for the properties. |
| 11972 Object* result; | 11762 Object* result; |
| 11973 { MaybeObject* maybe_result = GenerateNewEnumerationIndices(); | 11763 { MaybeObject* maybe_result = GenerateNewEnumerationIndices(); |
| 11974 if (!maybe_result->ToObject(&result)) return maybe_result; | 11764 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 11975 } | 11765 } |
| 11976 } | 11766 } |
| 11977 return HashTable<Shape, Key>::EnsureCapacity(n, key); | 11767 return HashTable<Shape, Key>::EnsureCapacity(n, key); |
| 11978 } | 11768 } |
| 11979 | 11769 |
| 11980 | 11770 |
| 11981 void NumberDictionary::RemoveNumberEntries(uint32_t from, uint32_t to) { | |
| 11982 // Do nothing if the interval [from, to) is empty. | |
| 11983 if (from >= to) return; | |
| 11984 | |
| 11985 Heap* heap = GetHeap(); | |
| 11986 int removed_entries = 0; | |
| 11987 Object* sentinel = heap->null_value(); | |
| 11988 int capacity = Capacity(); | |
| 11989 for (int i = 0; i < capacity; i++) { | |
| 11990 Object* key = KeyAt(i); | |
| 11991 if (key->IsNumber()) { | |
| 11992 uint32_t number = static_cast<uint32_t>(key->Number()); | |
| 11993 if (from <= number && number < to) { | |
| 11994 SetEntry(i, sentinel, sentinel); | |
| 11995 removed_entries++; | |
| 11996 } | |
| 11997 } | |
| 11998 } | |
| 11999 | |
| 12000 // Update the number of elements. | |
| 12001 ElementsRemoved(removed_entries); | |
| 12002 } | |
| 12003 | |
| 12004 | |
| 12005 template<typename Shape, typename Key> | 11771 template<typename Shape, typename Key> |
| 12006 Object* Dictionary<Shape, Key>::DeleteProperty(int entry, | 11772 Object* Dictionary<Shape, Key>::DeleteProperty(int entry, |
| 12007 JSReceiver::DeleteMode mode) { | 11773 JSReceiver::DeleteMode mode) { |
| 12008 Heap* heap = Dictionary<Shape, Key>::GetHeap(); | 11774 Heap* heap = Dictionary<Shape, Key>::GetHeap(); |
| 12009 PropertyDetails details = DetailsAt(entry); | 11775 PropertyDetails details = DetailsAt(entry); |
| 12010 // Ignore attributes if forcing a deletion. | 11776 // Ignore attributes if forcing a deletion. |
| 12011 if (details.IsDontDelete() && mode != JSReceiver::FORCE_DELETION) { | 11777 if (details.IsDontDelete() && mode != JSReceiver::FORCE_DELETION) { |
| 12012 return heap->false_value(); | 11778 return heap->false_value(); |
| 12013 } | 11779 } |
| 12014 SetEntry(entry, heap->null_value(), heap->null_value()); | 11780 SetEntry(entry, heap->null_value(), heap->null_value()); |
| (...skipping 737 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12752 if (break_point_objects()->IsUndefined()) return 0; | 12518 if (break_point_objects()->IsUndefined()) return 0; |
| 12753 // Single break point. | 12519 // Single break point. |
| 12754 if (!break_point_objects()->IsFixedArray()) return 1; | 12520 if (!break_point_objects()->IsFixedArray()) return 1; |
| 12755 // Multiple break points. | 12521 // Multiple break points. |
| 12756 return FixedArray::cast(break_point_objects())->length(); | 12522 return FixedArray::cast(break_point_objects())->length(); |
| 12757 } | 12523 } |
| 12758 #endif // ENABLE_DEBUGGER_SUPPORT | 12524 #endif // ENABLE_DEBUGGER_SUPPORT |
| 12759 | 12525 |
| 12760 | 12526 |
| 12761 } } // namespace v8::internal | 12527 } } // namespace v8::internal |
| OLD | NEW |