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 8115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8126 for (RelocIterator it(this); !it.done(); it.next()) it.rinfo()->Print(out); | 8126 for (RelocIterator it(this); !it.done(); it.next()) it.rinfo()->Print(out); |
8127 PrintF(out, "\n"); | 8127 PrintF(out, "\n"); |
8128 } | 8128 } |
8129 #endif // ENABLE_DISASSEMBLER | 8129 #endif // ENABLE_DISASSEMBLER |
8130 | 8130 |
8131 | 8131 |
8132 static void CopyFastElementsToFast(FixedArray* source, | 8132 static void CopyFastElementsToFast(FixedArray* source, |
8133 FixedArray* destination, | 8133 FixedArray* destination, |
8134 WriteBarrierMode mode) { | 8134 WriteBarrierMode mode) { |
8135 int count = source->length(); | 8135 int count = source->length(); |
| 8136 int copy_size = Min(count, destination->length()); |
8136 if (mode == SKIP_WRITE_BARRIER || | 8137 if (mode == SKIP_WRITE_BARRIER || |
8137 !Page::FromAddress(destination->address())->IsFlagSet( | 8138 !Page::FromAddress(destination->address())->IsFlagSet( |
8138 MemoryChunk::POINTERS_FROM_HERE_ARE_INTERESTING)) { | 8139 MemoryChunk::POINTERS_FROM_HERE_ARE_INTERESTING)) { |
8139 ASSERT(count <= destination->length()); | |
8140 Address to = destination->address() + FixedArray::kHeaderSize; | 8140 Address to = destination->address() + FixedArray::kHeaderSize; |
8141 Address from = source->address() + FixedArray::kHeaderSize; | 8141 Address from = source->address() + FixedArray::kHeaderSize; |
8142 memcpy(reinterpret_cast<void*>(to), | 8142 memcpy(reinterpret_cast<void*>(to), |
8143 reinterpret_cast<void*>(from), | 8143 reinterpret_cast<void*>(from), |
8144 kPointerSize * count); | 8144 kPointerSize * copy_size); |
8145 } else { | 8145 } else { |
8146 for (int i = 0; i < count; ++i) { | 8146 for (int i = 0; i < copy_size; ++i) { |
8147 destination->set(i, source->get(i), mode); | 8147 destination->set(i, source->get(i), mode); |
8148 } | 8148 } |
8149 } | 8149 } |
8150 } | 8150 } |
8151 | 8151 |
8152 | 8152 |
8153 static void CopySlowElementsToFast(NumberDictionary* source, | 8153 static void CopySlowElementsToFast(NumberDictionary* source, |
8154 FixedArray* destination, | 8154 FixedArray* destination, |
8155 WriteBarrierMode mode) { | 8155 WriteBarrierMode mode) { |
| 8156 int destination_length = destination->length(); |
8156 for (int i = 0; i < source->Capacity(); ++i) { | 8157 for (int i = 0; i < source->Capacity(); ++i) { |
8157 Object* key = source->KeyAt(i); | 8158 Object* key = source->KeyAt(i); |
8158 if (key->IsNumber()) { | 8159 if (key->IsNumber()) { |
8159 uint32_t entry = static_cast<uint32_t>(key->Number()); | 8160 uint32_t entry = static_cast<uint32_t>(key->Number()); |
8160 destination->set(entry, source->ValueAt(i), mode); | 8161 if (entry < static_cast<uint32_t>(destination_length)) { |
| 8162 destination->set(entry, source->ValueAt(i), mode); |
| 8163 } |
8161 } | 8164 } |
8162 } | 8165 } |
8163 } | 8166 } |
8164 | 8167 |
8165 | 8168 |
8166 MaybeObject* JSObject::SetFastElementsCapacityAndLength( | 8169 MaybeObject* JSObject::SetFastElementsCapacityAndLength( |
8167 int capacity, | 8170 int capacity, |
8168 int length, | 8171 int length, |
8169 SetFastElementsCapacityMode set_capacity_mode) { | 8172 SetFastElementsCapacityMode set_capacity_mode) { |
8170 Heap* heap = GetHeap(); | 8173 Heap* heap = GetHeap(); |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8361 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 8364 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
8362 } | 8365 } |
8363 new_elements = FixedArray::cast(obj); | 8366 new_elements = FixedArray::cast(obj); |
8364 } | 8367 } |
8365 set_elements(new_elements); | 8368 set_elements(new_elements); |
8366 return this; | 8369 return this; |
8367 } | 8370 } |
8368 | 8371 |
8369 | 8372 |
8370 void JSArray::Expand(int required_size) { | 8373 void JSArray::Expand(int required_size) { |
8371 Handle<JSArray> self(this); | 8374 GetIsolate()->factory()->SetElementsCapacityAndLength( |
8372 Handle<FixedArray> old_backing(FixedArray::cast(elements())); | 8375 Handle<JSArray>(this), required_size, Smi::cast(length())->value()); |
8373 int old_size = old_backing->length(); | |
8374 int new_size = required_size > old_size ? required_size : old_size; | |
8375 Handle<FixedArray> new_backing = FACTORY->NewFixedArray(new_size); | |
8376 // Can't use this any more now because we may have had a GC! | |
8377 for (int i = 0; i < old_size; i++) new_backing->set(i, old_backing->get(i)); | |
8378 GetIsolate()->factory()->SetContent(self, new_backing); | |
8379 } | 8376 } |
8380 | 8377 |
8381 | 8378 |
8382 MaybeObject* JSObject::SetElementsLength(Object* len) { | 8379 MaybeObject* JSObject::SetElementsLength(Object* len) { |
8383 // We should never end in here with a pixel or external array. | 8380 // We should never end in here with a pixel or external array. |
8384 ASSERT(AllowsSetElementsLength()); | 8381 ASSERT(AllowsSetElementsLength()); |
8385 return GetElementsAccessor()->SetLength(this, len); | 8382 return GetElementsAccessor()->SetLength(this, len); |
8386 } | 8383 } |
8387 | 8384 |
8388 | 8385 |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8522 real_receiver->set_map(Map::cast(new_map)); | 8519 real_receiver->set_map(Map::cast(new_map)); |
8523 | 8520 |
8524 heap->ClearInstanceofCache(); | 8521 heap->ClearInstanceofCache(); |
8525 ASSERT(size == Size()); | 8522 ASSERT(size == Size()); |
8526 return value; | 8523 return value; |
8527 } | 8524 } |
8528 | 8525 |
8529 | 8526 |
8530 MaybeObject* JSObject::EnsureCanContainElements(Arguments* args, | 8527 MaybeObject* JSObject::EnsureCanContainElements(Arguments* args, |
8531 uint32_t first_arg, | 8528 uint32_t first_arg, |
8532 uint32_t arg_count) { | 8529 uint32_t arg_count, |
| 8530 EnsureElementsMode mode) { |
8533 // Elements in |Arguments| are ordered backwards (because they're on the | 8531 // Elements in |Arguments| are ordered backwards (because they're on the |
8534 // stack), but the method that's called here iterates over them in forward | 8532 // stack), but the method that's called here iterates over them in forward |
8535 // direction. | 8533 // direction. |
8536 return EnsureCanContainElements( | 8534 return EnsureCanContainElements( |
8537 args->arguments() - first_arg - (arg_count - 1), | 8535 args->arguments() - first_arg - (arg_count - 1), |
8538 arg_count); | 8536 arg_count, mode); |
8539 } | 8537 } |
8540 | 8538 |
8541 | 8539 |
8542 bool JSObject::HasElementPostInterceptor(JSReceiver* receiver, uint32_t index) { | 8540 bool JSObject::HasElementPostInterceptor(JSReceiver* receiver, uint32_t index) { |
8543 switch (GetElementsKind()) { | 8541 switch (GetElementsKind()) { |
8544 case FAST_SMI_ONLY_ELEMENTS: | 8542 case FAST_SMI_ONLY_ELEMENTS: |
8545 case FAST_ELEMENTS: { | 8543 case FAST_ELEMENTS: { |
8546 uint32_t length = IsJSArray() ? | 8544 uint32_t length = IsJSArray() ? |
8547 static_cast<uint32_t> | 8545 static_cast<uint32_t> |
8548 (Smi::cast(JSArray::cast(this)->length())->value()) : | 8546 (Smi::cast(JSArray::cast(this)->length())->value()) : |
(...skipping 931 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9480 return isolate->heap()->null_value(); | 9478 return isolate->heap()->null_value(); |
9481 } | 9479 } |
9482 | 9480 |
9483 | 9481 |
9484 MUST_USE_RESULT MaybeObject* JSObject::TransitionElementsKind( | 9482 MUST_USE_RESULT MaybeObject* JSObject::TransitionElementsKind( |
9485 ElementsKind to_kind) { | 9483 ElementsKind to_kind) { |
9486 ElementsKind from_kind = map()->elements_kind(); | 9484 ElementsKind from_kind = map()->elements_kind(); |
9487 FixedArrayBase* elms = FixedArrayBase::cast(elements()); | 9485 FixedArrayBase* elms = FixedArrayBase::cast(elements()); |
9488 uint32_t capacity = static_cast<uint32_t>(elms->length()); | 9486 uint32_t capacity = static_cast<uint32_t>(elms->length()); |
9489 uint32_t length = capacity; | 9487 uint32_t length = capacity; |
| 9488 |
9490 if (IsJSArray()) { | 9489 if (IsJSArray()) { |
9491 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); | 9490 Object* raw_length = JSArray::cast(this)->length(); |
| 9491 if (raw_length->IsUndefined()) { |
| 9492 // If length is undefined, then JSArray is being initialized and has no |
| 9493 // elements, assume a length of zero. |
| 9494 length = 0; |
| 9495 } else { |
| 9496 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); |
| 9497 } |
9492 } | 9498 } |
9493 if (from_kind == FAST_SMI_ONLY_ELEMENTS) { | 9499 |
9494 if (to_kind == FAST_DOUBLE_ELEMENTS) { | 9500 if ((from_kind == FAST_SMI_ONLY_ELEMENTS && to_kind == FAST_ELEMENTS) || |
9495 MaybeObject* maybe_result = | 9501 (length == 0)) { |
9496 SetFastDoubleElementsCapacityAndLength(capacity, length); | 9502 MaybeObject* maybe_new_map = GetElementsTransitionMap(to_kind); |
9497 if (maybe_result->IsFailure()) return maybe_result; | 9503 Map* new_map; |
9498 return this; | 9504 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
9499 } else if (to_kind == FAST_ELEMENTS) { | 9505 if (FLAG_trace_elements_transitions) { |
9500 MaybeObject* maybe_new_map = GetElementsTransitionMap(FAST_ELEMENTS); | 9506 PrintElementsTransition(stdout, from_kind, elms, to_kind, elms); |
9501 Map* new_map; | |
9502 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | |
9503 if (FLAG_trace_elements_transitions) { | |
9504 PrintElementsTransition(stdout, from_kind, elms, FAST_ELEMENTS, elms); | |
9505 } | |
9506 set_map(new_map); | |
9507 return this; | |
9508 } | 9507 } |
9509 } else if (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS) { | 9508 set_map(new_map); |
| 9509 return this; |
| 9510 } |
| 9511 |
| 9512 if (from_kind == FAST_SMI_ONLY_ELEMENTS && |
| 9513 to_kind == FAST_DOUBLE_ELEMENTS) { |
| 9514 MaybeObject* maybe_result = |
| 9515 SetFastDoubleElementsCapacityAndLength(capacity, length); |
| 9516 if (maybe_result->IsFailure()) return maybe_result; |
| 9517 return this; |
| 9518 } |
| 9519 |
| 9520 if (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS) { |
9510 MaybeObject* maybe_result = SetFastElementsCapacityAndLength( | 9521 MaybeObject* maybe_result = SetFastElementsCapacityAndLength( |
9511 capacity, length, kDontAllowSmiOnlyElements); | 9522 capacity, length, kDontAllowSmiOnlyElements); |
9512 if (maybe_result->IsFailure()) return maybe_result; | 9523 if (maybe_result->IsFailure()) return maybe_result; |
9513 return this; | 9524 return this; |
9514 } | 9525 } |
| 9526 |
9515 // This method should never be called for any other case than the ones | 9527 // This method should never be called for any other case than the ones |
9516 // handled above. | 9528 // handled above. |
9517 UNREACHABLE(); | 9529 UNREACHABLE(); |
9518 return GetIsolate()->heap()->null_value(); | 9530 return GetIsolate()->heap()->null_value(); |
9519 } | 9531 } |
9520 | 9532 |
9521 | 9533 |
9522 // static | 9534 // static |
9523 bool Map::IsValidElementsTransition(ElementsKind from_kind, | 9535 bool Map::IsValidElementsTransition(ElementsKind from_kind, |
9524 ElementsKind to_kind) { | 9536 ElementsKind to_kind) { |
(...skipping 3015 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12540 if (break_point_objects()->IsUndefined()) return 0; | 12552 if (break_point_objects()->IsUndefined()) return 0; |
12541 // Single break point. | 12553 // Single break point. |
12542 if (!break_point_objects()->IsFixedArray()) return 1; | 12554 if (!break_point_objects()->IsFixedArray()) return 1; |
12543 // Multiple break points. | 12555 // Multiple break points. |
12544 return FixedArray::cast(break_point_objects())->length(); | 12556 return FixedArray::cast(break_point_objects())->length(); |
12545 } | 12557 } |
12546 #endif // ENABLE_DEBUGGER_SUPPORT | 12558 #endif // ENABLE_DEBUGGER_SUPPORT |
12547 | 12559 |
12548 | 12560 |
12549 } } // namespace v8::internal | 12561 } } // namespace v8::internal |
OLD | NEW |