Home | History | Annotate | Download | only in interpreter
      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 
     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 
     23 void ConstantArrayBuilder::ConstantArraySlice::Reserve() {
     24   DCHECK_GT(available(), 0u);
     25   reserved_++;
     26   DCHECK_LE(reserved_, capacity() - constants_.size());
     27 }
     28 
     29 
     30 void ConstantArrayBuilder::ConstantArraySlice::Unreserve() {
     31   DCHECK_GT(reserved_, 0u);
     32   reserved_--;
     33 }
     34 
     35 
     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 
     46 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 
     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 
     69 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 
     78 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 
     89 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 
     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 
    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 
    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 
    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 
    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