Line data Source code
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 :
9 : namespace v8 {
10 : namespace internal {
11 :
12 336 : void GrowableFixedArray::Push(TNode<Object> const value) {
13 : TNode<IntPtrT> const length = var_length_.value();
14 : TNode<IntPtrT> const capacity = var_capacity_.value();
15 :
16 672 : Label grow(this), store(this);
17 672 : Branch(IntPtrEqual(capacity, length), &grow, &store);
18 :
19 336 : BIND(&grow);
20 : {
21 336 : var_capacity_ = NewCapacity(capacity);
22 336 : var_array_ = ResizeFixedArray(length, var_capacity_.value());
23 :
24 336 : Goto(&store);
25 : }
26 :
27 336 : BIND(&store);
28 : {
29 : TNode<FixedArray> const array = var_array_.value();
30 : UnsafeStoreFixedArrayElement(array, length, value);
31 :
32 336 : var_length_ = IntPtrAdd(length, IntPtrConstant(1));
33 : }
34 336 : }
35 :
36 224 : TNode<JSArray> GrowableFixedArray::ToJSArray(TNode<Context> const context) {
37 : const ElementsKind kind = PACKED_ELEMENTS;
38 :
39 224 : TNode<Context> const native_context = LoadNativeContext(context);
40 224 : TNode<Map> const array_map = LoadJSArrayElementsMap(kind, native_context);
41 :
42 : // Shrink to fit if necessary.
43 : {
44 448 : Label next(this);
45 :
46 : TNode<IntPtrT> const length = var_length_.value();
47 : TNode<IntPtrT> const capacity = var_capacity_.value();
48 :
49 448 : GotoIf(WordEqual(length, capacity), &next);
50 :
51 224 : var_array_ = ResizeFixedArray(length, length);
52 : var_capacity_ = length;
53 224 : Goto(&next);
54 :
55 224 : BIND(&next);
56 : }
57 :
58 224 : TNode<Smi> const result_length = SmiTag(length());
59 : TNode<JSArray> const result =
60 224 : AllocateJSArray(array_map, var_array_.value(), result_length);
61 224 : return result;
62 : }
63 :
64 336 : TNode<IntPtrT> GrowableFixedArray::NewCapacity(
65 : TNode<IntPtrT> current_capacity) {
66 : CSA_ASSERT(this,
67 : IntPtrGreaterThanOrEqual(current_capacity, IntPtrConstant(0)));
68 :
69 : // Growth rate is analog to JSObject::NewElementsCapacity:
70 : // new_capacity = (current_capacity + (current_capacity >> 1)) + 16.
71 :
72 : TNode<IntPtrT> const new_capacity =
73 : IntPtrAdd(IntPtrAdd(current_capacity, WordShr(current_capacity, 1)),
74 336 : IntPtrConstant(16));
75 :
76 336 : return new_capacity;
77 : }
78 :
79 560 : TNode<FixedArray> GrowableFixedArray::ResizeFixedArray(
80 : TNode<IntPtrT> const element_count, TNode<IntPtrT> const new_capacity) {
81 : CSA_ASSERT(this, IntPtrGreaterThanOrEqual(element_count, IntPtrConstant(0)));
82 : CSA_ASSERT(this, IntPtrGreaterThanOrEqual(new_capacity, IntPtrConstant(0)));
83 : CSA_ASSERT(this, IntPtrGreaterThanOrEqual(new_capacity, element_count));
84 :
85 : TNode<FixedArray> const from_array = var_array_.value();
86 :
87 : CodeStubAssembler::ExtractFixedArrayFlags flags;
88 : flags |= CodeStubAssembler::ExtractFixedArrayFlag::kFixedArrays;
89 560 : TNode<FixedArray> to_array = CAST(ExtractFixedArray(
90 : from_array, nullptr, element_count, new_capacity, flags));
91 :
92 560 : return to_array;
93 : }
94 :
95 : } // namespace internal
96 59456 : } // namespace v8
|