• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // 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 
10 namespace v8 {
11 namespace internal {
12 namespace interpreter {
13 
ConstantArraySlice(Zone * zone,size_t start_index,size_t capacity)14 ConstantArrayBuilder::ConstantArraySlice::ConstantArraySlice(Zone* zone,
15                                                              size_t start_index,
16                                                              size_t capacity)
17     : start_index_(start_index),
18       capacity_(capacity),
19       reserved_(0),
20       constants_(zone) {}
21 
22 
Reserve()23 void ConstantArrayBuilder::ConstantArraySlice::Reserve() {
24   DCHECK_GT(available(), 0u);
25   reserved_++;
26   DCHECK_LE(reserved_, capacity() - constants_.size());
27 }
28 
29 
Unreserve()30 void ConstantArrayBuilder::ConstantArraySlice::Unreserve() {
31   DCHECK_GT(reserved_, 0u);
32   reserved_--;
33 }
34 
35 
Allocate(Handle<Object> object)36 size_t ConstantArrayBuilder::ConstantArraySlice::Allocate(
37     Handle<Object> object) {
38   DCHECK_GT(available(), 0u);
39   size_t index = constants_.size();
40   DCHECK_LT(index, capacity());
41   constants_.push_back(object);
42   return index + start_index();
43 }
44 
45 
At(size_t index) const46 Handle<Object> ConstantArrayBuilder::ConstantArraySlice::At(
47     size_t index) const {
48   return constants_[index - start_index()];
49 }
50 
51 
52 STATIC_CONST_MEMBER_DEFINITION const size_t ConstantArrayBuilder::kMaxCapacity;
53 STATIC_CONST_MEMBER_DEFINITION const size_t ConstantArrayBuilder::kLowCapacity;
54 
55 
ConstantArrayBuilder(Isolate * isolate,Zone * zone)56 ConstantArrayBuilder::ConstantArrayBuilder(Isolate* isolate, Zone* zone)
57     : isolate_(isolate),
58       idx8_slice_(zone, 0, kLowCapacity),
59       idx16_slice_(zone, kLowCapacity, kHighCapacity),
60       constants_map_(isolate->heap(), zone) {
61   STATIC_ASSERT(kMaxCapacity == static_cast<size_t>(kMaxUInt16 + 1));
62   DCHECK_EQ(idx8_slice_.start_index(), 0u);
63   DCHECK_EQ(idx8_slice_.capacity(), kLowCapacity);
64   DCHECK_EQ(idx16_slice_.start_index(), kLowCapacity);
65   DCHECK_EQ(idx16_slice_.capacity(), kMaxCapacity - kLowCapacity);
66 }
67 
68 
size() const69 size_t ConstantArrayBuilder::size() const {
70   if (idx16_slice_.size() > 0) {
71     return idx16_slice_.start_index() + idx16_slice_.size();
72   } else {
73     return idx8_slice_.size();
74   }
75 }
76 
77 
At(size_t index) const78 Handle<Object> ConstantArrayBuilder::At(size_t index) const {
79   if (index >= idx16_slice_.start_index()) {
80     return idx16_slice_.At(index);
81   } else if (index < idx8_slice_.size()) {
82     return idx8_slice_.At(index);
83   } else {
84     return isolate_->factory()->the_hole_value();
85   }
86 }
87 
88 
ToFixedArray(Factory * factory) const89 Handle<FixedArray> ConstantArrayBuilder::ToFixedArray(Factory* factory) const {
90   Handle<FixedArray> fixed_array =
91       factory->NewFixedArray(static_cast<int>(size()), PretenureFlag::TENURED);
92   for (int i = 0; i < fixed_array->length(); i++) {
93     fixed_array->set(i, *At(static_cast<size_t>(i)));
94   }
95   return fixed_array;
96 }
97 
98 
Insert(Handle<Object> object)99 size_t ConstantArrayBuilder::Insert(Handle<Object> object) {
100   index_t* entry = constants_map_.Find(object);
101   return (entry == nullptr) ? AllocateEntry(object) : *entry;
102 }
103 
104 
AllocateEntry(Handle<Object> object)105 ConstantArrayBuilder::index_t ConstantArrayBuilder::AllocateEntry(
106     Handle<Object> object) {
107   DCHECK(!object->IsOddball());
108   size_t index;
109   index_t* entry = constants_map_.Get(object);
110   if (idx8_slice_.available() > 0) {
111     index = idx8_slice_.Allocate(object);
112   } else {
113     index = idx16_slice_.Allocate(object);
114   }
115   CHECK_LT(index, kMaxCapacity);
116   *entry = static_cast<index_t>(index);
117   return *entry;
118 }
119 
120 
CreateReservedEntry()121 OperandSize ConstantArrayBuilder::CreateReservedEntry() {
122   if (idx8_slice_.available() > 0) {
123     idx8_slice_.Reserve();
124     return OperandSize::kByte;
125   } else if (idx16_slice_.available() > 0) {
126     idx16_slice_.Reserve();
127     return OperandSize::kShort;
128   } else {
129     UNREACHABLE();
130     return OperandSize::kNone;
131   }
132 }
133 
134 
CommitReservedEntry(OperandSize operand_size,Handle<Object> object)135 size_t ConstantArrayBuilder::CommitReservedEntry(OperandSize operand_size,
136                                                  Handle<Object> object) {
137   DiscardReservedEntry(operand_size);
138   size_t index;
139   index_t* entry = constants_map_.Find(object);
140   if (nullptr == entry) {
141     index = AllocateEntry(object);
142   } else {
143     if (operand_size == OperandSize::kByte &&
144         *entry >= idx8_slice_.capacity()) {
145       // The object is already in the constant array, but has an index
146       // outside the range of an idx8 operand so we need to create a
147       // duplicate entry in the idx8 operand range to satisfy the
148       // commitment.
149       *entry = static_cast<index_t>(idx8_slice_.Allocate(object));
150     }
151     index = *entry;
152   }
153   DCHECK(operand_size == OperandSize::kShort || index < idx8_slice_.capacity());
154   DCHECK_LT(index, kMaxCapacity);
155   return index;
156 }
157 
158 
DiscardReservedEntry(OperandSize operand_size)159 void ConstantArrayBuilder::DiscardReservedEntry(OperandSize operand_size) {
160   switch (operand_size) {
161     case OperandSize::kByte:
162       idx8_slice_.Unreserve();
163       return;
164     case OperandSize::kShort:
165       idx16_slice_.Unreserve();
166       return;
167     default:
168       UNREACHABLE();
169   }
170 }
171 
172 }  // namespace interpreter
173 }  // namespace internal
174 }  // namespace v8
175