blob: 7ce50b580e998e0f170f6c8bd29eb237627f1ffd [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// Copyright 2015 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/interpreter/constant-array-builder.h"
6
7#include "src/isolate.h"
8#include "src/objects-inl.h"
9
10namespace v8 {
11namespace internal {
12namespace interpreter {
13
Ben Murdochda12d292016-06-02 14:46:10 +010014ConstantArrayBuilder::ConstantArraySlice::ConstantArraySlice(
15 Zone* zone, size_t start_index, size_t capacity, OperandSize operand_size)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016 : start_index_(start_index),
17 capacity_(capacity),
18 reserved_(0),
Ben Murdochda12d292016-06-02 14:46:10 +010019 operand_size_(operand_size),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020 constants_(zone) {}
21
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022void ConstantArrayBuilder::ConstantArraySlice::Reserve() {
23 DCHECK_GT(available(), 0u);
24 reserved_++;
25 DCHECK_LE(reserved_, capacity() - constants_.size());
26}
27
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000028void ConstantArrayBuilder::ConstantArraySlice::Unreserve() {
29 DCHECK_GT(reserved_, 0u);
30 reserved_--;
31}
32
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000033size_t ConstantArrayBuilder::ConstantArraySlice::Allocate(
34 Handle<Object> object) {
35 DCHECK_GT(available(), 0u);
36 size_t index = constants_.size();
37 DCHECK_LT(index, capacity());
38 constants_.push_back(object);
39 return index + start_index();
40}
41
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000042Handle<Object> ConstantArrayBuilder::ConstantArraySlice::At(
43 size_t index) const {
Ben Murdochda12d292016-06-02 14:46:10 +010044 DCHECK_GE(index, start_index());
45 DCHECK_LT(index, start_index() + size());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000046 return constants_[index - start_index()];
47}
48
Ben Murdochda12d292016-06-02 14:46:10 +010049STATIC_CONST_MEMBER_DEFINITION const size_t ConstantArrayBuilder::k8BitCapacity;
50STATIC_CONST_MEMBER_DEFINITION const size_t
51 ConstantArrayBuilder::k16BitCapacity;
52STATIC_CONST_MEMBER_DEFINITION const size_t
53 ConstantArrayBuilder::k32BitCapacity;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000054
55ConstantArrayBuilder::ConstantArrayBuilder(Isolate* isolate, Zone* zone)
Ben Murdochda12d292016-06-02 14:46:10 +010056 : isolate_(isolate), constants_map_(isolate->heap(), zone) {
57 idx_slice_[0] =
58 new (zone) ConstantArraySlice(zone, 0, k8BitCapacity, OperandSize::kByte);
59 idx_slice_[1] = new (zone) ConstantArraySlice(
60 zone, k8BitCapacity, k16BitCapacity, OperandSize::kShort);
61 idx_slice_[2] = new (zone) ConstantArraySlice(
62 zone, k8BitCapacity + k16BitCapacity, k32BitCapacity, OperandSize::kQuad);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000063}
64
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000065size_t ConstantArrayBuilder::size() const {
Ben Murdochda12d292016-06-02 14:46:10 +010066 size_t i = arraysize(idx_slice_);
67 while (i > 0) {
68 ConstantArraySlice* slice = idx_slice_[--i];
69 if (slice->size() > 0) {
70 return slice->start_index() + slice->size();
71 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000072 }
Ben Murdochda12d292016-06-02 14:46:10 +010073 return idx_slice_[0]->size();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000074}
75
Ben Murdochda12d292016-06-02 14:46:10 +010076const ConstantArrayBuilder::ConstantArraySlice*
77ConstantArrayBuilder::IndexToSlice(size_t index) const {
78 for (const ConstantArraySlice* slice : idx_slice_) {
79 if (index <= slice->max_index()) {
80 return slice;
81 }
82 }
83 UNREACHABLE();
84 return nullptr;
85}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000086
87Handle<Object> ConstantArrayBuilder::At(size_t index) const {
Ben Murdochda12d292016-06-02 14:46:10 +010088 const ConstantArraySlice* slice = IndexToSlice(index);
89 if (index < slice->start_index() + slice->size()) {
90 return slice->At(index);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000091 } else {
Ben Murdochda12d292016-06-02 14:46:10 +010092 DCHECK_LT(index, slice->capacity());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000093 return isolate_->factory()->the_hole_value();
94 }
95}
96
Ben Murdoch097c5b22016-05-18 11:27:45 +010097Handle<FixedArray> ConstantArrayBuilder::ToFixedArray() {
98 Handle<FixedArray> fixed_array = isolate_->factory()->NewFixedArray(
99 static_cast<int>(size()), PretenureFlag::TENURED);
Ben Murdochda12d292016-06-02 14:46:10 +0100100 int array_index = 0;
101 for (const ConstantArraySlice* slice : idx_slice_) {
102 if (array_index == fixed_array->length()) {
103 break;
104 }
105 DCHECK(array_index == 0 ||
106 base::bits::IsPowerOfTwo32(static_cast<uint32_t>(array_index)));
107 // Copy objects from slice into array.
108 for (size_t i = 0; i < slice->size(); ++i) {
109 fixed_array->set(array_index++, *slice->At(slice->start_index() + i));
110 }
111 // Insert holes where reservations led to unused slots.
112 size_t padding =
113 std::min(static_cast<size_t>(fixed_array->length() - array_index),
114 slice->capacity() - slice->size());
115 for (size_t i = 0; i < padding; i++) {
116 fixed_array->set(array_index++, *isolate_->factory()->the_hole_value());
117 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000118 }
Ben Murdochda12d292016-06-02 14:46:10 +0100119 DCHECK_EQ(array_index, fixed_array->length());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100120 constants_map()->Clear();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000121 return fixed_array;
122}
123
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000124size_t ConstantArrayBuilder::Insert(Handle<Object> object) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100125 index_t* entry = constants_map()->Find(object);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000126 return (entry == nullptr) ? AllocateEntry(object) : *entry;
127}
128
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000129ConstantArrayBuilder::index_t ConstantArrayBuilder::AllocateEntry(
130 Handle<Object> object) {
131 DCHECK(!object->IsOddball());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100132 index_t* entry = constants_map()->Get(object);
Ben Murdochda12d292016-06-02 14:46:10 +0100133 for (size_t i = 0; i < arraysize(idx_slice_); ++i) {
134 if (idx_slice_[i]->available() > 0) {
135 size_t index = idx_slice_[i]->Allocate(object);
136 *entry = static_cast<index_t>(index);
137 return *entry;
138 break;
139 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000140 }
Ben Murdochda12d292016-06-02 14:46:10 +0100141 UNREACHABLE();
142 return kMaxUInt32;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000143}
144
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000145OperandSize ConstantArrayBuilder::CreateReservedEntry() {
Ben Murdochda12d292016-06-02 14:46:10 +0100146 for (size_t i = 0; i < arraysize(idx_slice_); ++i) {
147 if (idx_slice_[i]->available() > 0) {
148 idx_slice_[i]->Reserve();
149 return idx_slice_[i]->operand_size();
150 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000151 }
Ben Murdochda12d292016-06-02 14:46:10 +0100152 UNREACHABLE();
153 return OperandSize::kNone;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000154}
155
Ben Murdochda12d292016-06-02 14:46:10 +0100156ConstantArrayBuilder::ConstantArraySlice*
157ConstantArrayBuilder::OperandSizeToSlice(OperandSize operand_size) const {
158 ConstantArraySlice* slice = nullptr;
159 switch (operand_size) {
160 case OperandSize::kNone:
161 UNREACHABLE();
162 break;
163 case OperandSize::kByte:
164 slice = idx_slice_[0];
165 break;
166 case OperandSize::kShort:
167 slice = idx_slice_[1];
168 break;
169 case OperandSize::kQuad:
170 slice = idx_slice_[2];
171 break;
172 }
173 DCHECK(slice->operand_size() == operand_size);
174 return slice;
175}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000176
177size_t ConstantArrayBuilder::CommitReservedEntry(OperandSize operand_size,
178 Handle<Object> object) {
179 DiscardReservedEntry(operand_size);
180 size_t index;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100181 index_t* entry = constants_map()->Find(object);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000182 if (nullptr == entry) {
183 index = AllocateEntry(object);
184 } else {
Ben Murdochda12d292016-06-02 14:46:10 +0100185 ConstantArraySlice* slice = OperandSizeToSlice(operand_size);
186 if (*entry > slice->max_index()) {
187 // The object is already in the constant array, but may have an
188 // index too big for the reserved operand_size. So, duplicate
189 // entry with the smaller operand size.
190 *entry = static_cast<index_t>(slice->Allocate(object));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000191 }
192 index = *entry;
193 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000194 return index;
195}
196
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000197void ConstantArrayBuilder::DiscardReservedEntry(OperandSize operand_size) {
Ben Murdochda12d292016-06-02 14:46:10 +0100198 OperandSizeToSlice(operand_size)->Unreserve();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000199}
200
201} // namespace interpreter
202} // namespace internal
203} // namespace v8