1// Copyright 2018 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "src/builtins/growable-fixed-array-gen.h" 6 7#include "src/compiler/code-assembler.h" 8 9namespace v8 { 10namespace internal { 11 12void GrowableFixedArray::Push(const TNode<Object> value) { 13 const TNode<IntPtrT> length = var_length_.value(); 14 const TNode<IntPtrT> capacity = var_capacity_.value(); 15 16 Label grow(this), store(this); 17 Branch(IntPtrEqual(capacity, length), &grow, &store); 18 19 BIND(&grow); 20 { 21 var_capacity_ = NewCapacity(capacity); 22 var_array_ = ResizeFixedArray(length, var_capacity_.value()); 23 24 Goto(&store); 25 } 26 27 BIND(&store); 28 { 29 const TNode<FixedArray> array = var_array_.value(); 30 UnsafeStoreFixedArrayElement(array, length, value); 31 32 var_length_ = IntPtrAdd(length, IntPtrConstant(1)); 33 } 34} 35 36TNode<FixedArray> GrowableFixedArray::ToFixedArray() { 37 return ResizeFixedArray(length(), length()); 38} 39 40TNode<JSArray> GrowableFixedArray::ToJSArray(const TNode<Context> context) { 41 const ElementsKind kind = PACKED_ELEMENTS; 42 43 const TNode<NativeContext> native_context = LoadNativeContext(context); 44 const TNode<Map> array_map = LoadJSArrayElementsMap(kind, native_context); 45 46 // Shrink to fit if necessary. 47 { 48 Label next(this); 49 50 const TNode<IntPtrT> length = var_length_.value(); 51 const TNode<IntPtrT> capacity = var_capacity_.value(); 52 53 GotoIf(WordEqual(length, capacity), &next); 54 55 var_array_ = ResizeFixedArray(length, length); 56 var_capacity_ = length; 57 Goto(&next); 58 59 BIND(&next); 60 } 61 62 const TNode<Smi> result_length = SmiTag(length()); 63 const TNode<JSArray> result = 64 AllocateJSArray(array_map, var_array_.value(), result_length); 65 return result; 66} 67 68TNode<IntPtrT> GrowableFixedArray::NewCapacity( 69 TNode<IntPtrT> current_capacity) { 70 CSA_DCHECK(this, 71 IntPtrGreaterThanOrEqual(current_capacity, IntPtrConstant(0))); 72 73 // Growth rate is analog to JSObject::NewElementsCapacity: 74 // new_capacity = (current_capacity + (current_capacity >> 1)) + 16. 75 76 const TNode<IntPtrT> new_capacity = 77 IntPtrAdd(IntPtrAdd(current_capacity, WordShr(current_capacity, 1)), 78 IntPtrConstant(16)); 79 80 return new_capacity; 81} 82 83TNode<FixedArray> GrowableFixedArray::ResizeFixedArray( 84 const TNode<IntPtrT> element_count, const TNode<IntPtrT> new_capacity) { 85 CSA_DCHECK(this, IntPtrGreaterThanOrEqual(element_count, IntPtrConstant(0))); 86 CSA_DCHECK(this, IntPtrGreaterThanOrEqual(new_capacity, IntPtrConstant(0))); 87 CSA_DCHECK(this, IntPtrGreaterThanOrEqual(new_capacity, element_count)); 88 89 const TNode<FixedArray> from_array = var_array_.value(); 90 91 CodeStubAssembler::ExtractFixedArrayFlags flags; 92 flags |= CodeStubAssembler::ExtractFixedArrayFlag::kFixedArrays; 93 TNode<FixedArray> to_array = CAST(ExtractFixedArray( 94 from_array, base::Optional<TNode<IntPtrT>>(base::nullopt), 95 base::Optional<TNode<IntPtrT>>(element_count), 96 base::Optional<TNode<IntPtrT>>(new_capacity), flags)); 97 98 return to_array; 99} 100 101} // namespace internal 102} // namespace v8 103