OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/elements.h" | 5 #include "src/elements.h" |
6 | 6 |
7 #include "src/arguments.h" | 7 #include "src/arguments.h" |
8 #include "src/conversions.h" | 8 #include "src/conversions.h" |
9 #include "src/factory.h" | 9 #include "src/factory.h" |
10 #include "src/messages.h" | 10 #include "src/messages.h" |
(...skipping 663 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
674 Handle<FixedArrayBase> backing_store) final { | 674 Handle<FixedArrayBase> backing_store) final { |
675 return ElementsAccessorSubclass::ShiftImpl(receiver, backing_store); | 675 return ElementsAccessorSubclass::ShiftImpl(receiver, backing_store); |
676 } | 676 } |
677 | 677 |
678 static Handle<Object> ShiftImpl(Handle<JSArray> receiver, | 678 static Handle<Object> ShiftImpl(Handle<JSArray> receiver, |
679 Handle<FixedArrayBase> backing_store) { | 679 Handle<FixedArrayBase> backing_store) { |
680 UNREACHABLE(); | 680 UNREACHABLE(); |
681 return Handle<Object>(); | 681 return Handle<Object>(); |
682 } | 682 } |
683 | 683 |
| 684 |
684 virtual void SetLength(Handle<JSArray> array, uint32_t length) final { | 685 virtual void SetLength(Handle<JSArray> array, uint32_t length) final { |
685 ElementsAccessorSubclass::SetLengthImpl(array, length, | 686 ElementsAccessorSubclass::SetLengthImpl(array, length, |
686 handle(array->elements())); | 687 handle(array->elements())); |
687 } | 688 } |
688 | 689 |
689 static void SetLengthImpl(Handle<JSArray> array, uint32_t length, | 690 static void SetLengthImpl(Handle<JSArray> array, uint32_t length, |
690 Handle<FixedArrayBase> backing_store) { | 691 Handle<FixedArrayBase> backing_store) { |
691 DCHECK(!array->SetLengthWouldNormalize(length)); | 692 DCHECK(!array->SetLengthWouldNormalize(length)); |
692 DCHECK(IsFastElementsKind(array->GetElementsKind())); | 693 DCHECK(IsFastElementsKind(array->GetElementsKind())); |
693 uint32_t old_length = 0; | 694 uint32_t old_length = 0; |
(...skipping 1649 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2343 | 2344 |
2344 void ElementsAccessor::TearDown() { | 2345 void ElementsAccessor::TearDown() { |
2345 if (elements_accessors_ == NULL) return; | 2346 if (elements_accessors_ == NULL) return; |
2346 #define ACCESSOR_DELETE(Class, Kind, Store) delete elements_accessors_[Kind]; | 2347 #define ACCESSOR_DELETE(Class, Kind, Store) delete elements_accessors_[Kind]; |
2347 ELEMENTS_LIST(ACCESSOR_DELETE) | 2348 ELEMENTS_LIST(ACCESSOR_DELETE) |
2348 #undef ACCESSOR_DELETE | 2349 #undef ACCESSOR_DELETE |
2349 elements_accessors_ = NULL; | 2350 elements_accessors_ = NULL; |
2350 } | 2351 } |
2351 | 2352 |
2352 | 2353 |
| 2354 Handle<JSArray> ElementsAccessor::Concat(Isolate* isolate, Arguments* args, |
| 2355 uint32_t concat_size) { |
| 2356 int result_len = 0; |
| 2357 ElementsKind elements_kind = GetInitialFastElementsKind(); |
| 2358 bool has_double = false; |
| 2359 { |
| 2360 DisallowHeapAllocation no_gc; |
| 2361 // Iterate through all the arguments performing checks |
| 2362 // and calculating total length. |
| 2363 bool is_holey = false; |
| 2364 for (uint32_t i = 0; i < concat_size; i++) { |
| 2365 Object* arg = (*args)[i]; |
| 2366 int len = Smi::cast(JSArray::cast(arg)->length())->value(); |
| 2367 |
| 2368 // We shouldn't overflow when adding another len. |
| 2369 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2); |
| 2370 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt); |
| 2371 USE(kHalfOfMaxInt); |
| 2372 result_len += len; |
| 2373 DCHECK(0 <= result_len); |
| 2374 DCHECK(result_len <= FixedDoubleArray::kMaxLength); |
| 2375 |
| 2376 ElementsKind arg_kind = JSArray::cast(arg)->map()->elements_kind(); |
| 2377 has_double = has_double || IsFastDoubleElementsKind(arg_kind); |
| 2378 is_holey = is_holey || IsFastHoleyElementsKind(arg_kind); |
| 2379 if (IsMoreGeneralElementsKindTransition(elements_kind, arg_kind)) { |
| 2380 elements_kind = arg_kind; |
| 2381 } |
| 2382 } |
| 2383 if (is_holey) { |
| 2384 elements_kind = GetHoleyElementsKind(elements_kind); |
| 2385 } |
| 2386 } |
| 2387 |
| 2388 // If a double array is concatted into a fast elements array, the fast |
| 2389 // elements array needs to be initialized to contain proper holes, since |
| 2390 // boxing doubles may cause incremental marking. |
| 2391 ArrayStorageAllocationMode mode = |
| 2392 has_double && IsFastObjectElementsKind(elements_kind) |
| 2393 ? INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE |
| 2394 : DONT_INITIALIZE_ARRAY_ELEMENTS; |
| 2395 Handle<JSArray> result_array = isolate->factory()->NewJSArray( |
| 2396 elements_kind, result_len, result_len, Strength::WEAK, mode); |
| 2397 if (result_len == 0) return result_array; |
| 2398 int j = 0; |
| 2399 Handle<FixedArrayBase> storage(result_array->elements(), isolate); |
| 2400 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind); |
| 2401 for (uint32_t i = 0; i < concat_size; i++) { |
| 2402 // It is crucial to keep |array| in a raw pointer form to avoid |
| 2403 // performance degradation. |
| 2404 JSArray* array = JSArray::cast((*args)[i]); |
| 2405 int len = Smi::cast(array->length())->value(); |
| 2406 if (len > 0) { |
| 2407 ElementsKind from_kind = array->GetElementsKind(); |
| 2408 accessor->CopyElements(array, 0, from_kind, storage, j, len); |
| 2409 j += len; |
| 2410 } |
| 2411 } |
| 2412 |
| 2413 DCHECK(j == result_len); |
| 2414 return result_array; |
| 2415 } |
| 2416 |
2353 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; | 2417 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; |
2354 } // namespace internal | 2418 } // namespace internal |
2355 } // namespace v8 | 2419 } // namespace v8 |
OLD | NEW |