preparse-data-impl.h 6.9 KB
Newer Older
1 2 3 4
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5 6
#ifndef V8_PARSING_PREPARSE_DATA_IMPL_H_
#define V8_PARSING_PREPARSE_DATA_IMPL_H_
7

8
#include "src/parsing/preparse-data.h"
9 10 11 12 13 14 15 16 17

#include "src/assert-scope.h"

namespace v8 {
namespace internal {

// Classes which are internal to prepared-scope-data.cc, but are exposed in
// a header for tests.

18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
// Wraps a ZoneVector<uint8_t> to have with functions named the same as
// PodArray<uint8_t>.
class ZoneVectorWrapper {
 public:
  ZoneVectorWrapper() = default;
  explicit ZoneVectorWrapper(ZoneVector<uint8_t>* data) : data_(data) {}

  int data_length() const { return static_cast<int>(data_->size()); }

  uint8_t get(int index) const { return data_->at(index); }

 private:
  ZoneVector<uint8_t>* data_ = nullptr;
};

33
template <class Data>
34
class BaseConsumedPreparseData : public ConsumedPreparseData {
35
 public:
36
  class ByteData : public PreparseByteDataConstants {
37
   public:
38
    ByteData() {}
39 40 41 42 43 44

    // Reading from the ByteData is only allowed when a ReadingScope is on the
    // stack. This ensures that we have a DisallowHeapAllocation in place
    // whenever ByteData holds a raw pointer into the heap.
    class ReadingScope {
     public:
45
      ReadingScope(ByteData* consumed_data, Data data)
46 47
          : consumed_data_(consumed_data) {
        consumed_data->data_ = data;
48 49 50
#ifdef DEBUG
        consumed_data->has_data_ = true;
#endif
51
      }
52
      explicit ReadingScope(BaseConsumedPreparseData<Data>* parent)
53
          : ReadingScope(parent->scope_data_.get(), parent->GetScopeData()) {}
54 55 56 57 58
      ~ReadingScope() {
#ifdef DEBUG
        consumed_data_->has_data_ = false;
#endif
      }
59 60 61

     private:
      ByteData* consumed_data_;
62
      DISALLOW_HEAP_ALLOCATION(no_gc)
63 64
    };

65
    void SetPosition(int position) {
66
      DCHECK_LE(position, data_.data_length());
67 68
      index_ = position;
    }
69 70

    size_t RemainingBytes() const {
71
      DCHECK(has_data_);
72 73
      DCHECK_LE(index_, data_.data_length());
      return data_.data_length() - index_;
74 75
    }

76
    bool HasRemainingBytes(size_t bytes) const {
77
      DCHECK(has_data_);
78
      return index_ <= data_.data_length() && bytes <= RemainingBytes();
79 80 81
    }

    int32_t ReadUint32() {
82
      DCHECK(has_data_);
83
      DCHECK(HasRemainingBytes(kUint32Size));
84
      // Check that there indeed is an integer following.
85
      DCHECK_EQ(data_.get(index_++), kUint32Size);
86 87 88 89
      int32_t result = data_.get(index_) + (data_.get(index_ + 1) << 8) +
                       (data_.get(index_ + 2) << 16) +
                       (data_.get(index_ + 3) << 24);
      index_ += 4;
90 91 92 93
      stored_quarters_ = 0;
      return result;
    }

94
    int32_t ReadVarint32() {
95 96
      DCHECK(HasRemainingBytes(kVarint32MinSize));
      DCHECK_EQ(data_.get(index_++), kVarint32MinSize);
97 98 99 100 101 102 103 104 105
      int32_t value = 0;
      bool has_another_byte;
      unsigned shift = 0;
      do {
        uint8_t byte = data_.get(index_++);
        value |= static_cast<int32_t>(byte & 0x7F) << shift;
        shift += 7;
        has_another_byte = byte & 0x80;
      } while (has_another_byte);
106
      DCHECK_EQ(data_.get(index_++), kVarint32EndMarker);
107 108 109 110
      stored_quarters_ = 0;
      return value;
    }

111
    uint8_t ReadUint8() {
112
      DCHECK(has_data_);
113
      DCHECK(HasRemainingBytes(kUint8Size));
114
      // Check that there indeed is a byte following.
115
      DCHECK_EQ(data_.get(index_++), kUint8Size);
116
      stored_quarters_ = 0;
117
      return data_.get(index_++);
118 119 120
    }

    uint8_t ReadQuarter() {
121
      DCHECK(has_data_);
122
      if (stored_quarters_ == 0) {
123
        DCHECK(HasRemainingBytes(kUint8Size));
124
        // Check that there indeed are quarters following.
125 126
        DCHECK_EQ(data_.get(index_++), kQuarterMarker);
        stored_byte_ = data_.get(index_++);
127 128 129 130 131 132 133 134 135 136 137
        stored_quarters_ = 4;
      }
      // Read the first 2 bits from stored_byte_.
      uint8_t result = (stored_byte_ >> 6) & 3;
      DCHECK_LE(result, 3);
      --stored_quarters_;
      stored_byte_ <<= 2;
      return result;
    }

   private:
138 139 140 141 142 143 144
    Data data_ = {};
    int index_ = 0;
    uint8_t stored_quarters_ = 0;
    uint8_t stored_byte_ = 0;
#ifdef DEBUG
    bool has_data_ = false;
#endif
145 146
  };

147
  BaseConsumedPreparseData() : scope_data_(new ByteData()), child_index_(0) {}
148

149
  virtual Data GetScopeData() = 0;
150

151
  virtual ProducedPreparseData* GetChildData(Zone* zone, int child_index) = 0;
152

153
  ProducedPreparseData* GetDataForSkippableFunction(
154 155 156 157 158 159 160
      Zone* zone, int start_position, int* end_position, int* num_parameters,
      int* num_inner_functions, bool* uses_super_property,
      LanguageMode* language_mode) final;

  void RestoreScopeAllocationData(DeclarationScope* scope) final;

#ifdef DEBUG
161
  bool VerifyDataStart();
162 163 164
#endif

 private:
165
  void RestoreDataForScope(Scope* scope);
166 167 168 169 170 171 172 173
  void RestoreDataForVariable(Variable* var);
  void RestoreDataForInnerScopes(Scope* scope);

  std::unique_ptr<ByteData> scope_data_;
  // When consuming the data, these indexes point to the data we're going to
  // consume next.
  int child_index_;

174
  DISALLOW_COPY_AND_ASSIGN(BaseConsumedPreparseData);
175 176
};

177 178
// Implementation of ConsumedPreparseData for on-heap data.
class OnHeapConsumedPreparseData final
179
    : public BaseConsumedPreparseData<PreparseData> {
180
 public:
181
  OnHeapConsumedPreparseData(Isolate* isolate, Handle<PreparseData> data);
182

183
  PreparseData GetScopeData() final;
184
  ProducedPreparseData* GetChildData(Zone* zone, int child_index) final;
185 186 187

 private:
  Isolate* isolate_;
188
  Handle<PreparseData> data_;
189 190
};

191 192
// A serialized PreparseData in zone memory (as apposed to being on-heap).
class ZonePreparseData : public ZoneObject {
193
 public:
194
  ZonePreparseData(Zone* zone, Vector<uint8_t>* byte_data, int child_length);
195

196
  Handle<PreparseData> Serialize(Isolate* isolate);
197

198
  int children_length() const { return static_cast<int>(children_.size()); }
199

200
  ZonePreparseData* get_child(int index) { return children_[index]; }
201

202
  void set_child(int index, ZonePreparseData* child) {
203
    DCHECK_NOT_NULL(child);
204 205 206 207 208 209 210
    children_[index] = child;
  }

  ZoneVector<uint8_t>* byte_data() { return &byte_data_; }

 private:
  ZoneVector<uint8_t> byte_data_;
211
  ZoneVector<ZonePreparseData*> children_;
212

213
  DISALLOW_COPY_AND_ASSIGN(ZonePreparseData);
214 215
};

216 217 218 219 220 221
ZonePreparseData* PreparseDataBuilder::ByteData::CopyToZone(
    Zone* zone, int children_length) {
  DCHECK(is_finalized_);
  return new (zone) ZonePreparseData(zone, &zone_byte_data_, children_length);
}

222
// Implementation of ConsumedPreparseData for PreparseData
223
// serialized into zone memory.
224 225
class ZoneConsumedPreparseData final
    : public BaseConsumedPreparseData<ZoneVectorWrapper> {
226
 public:
227
  ZoneConsumedPreparseData(Zone* zone, ZonePreparseData* data);
228

229
  ZoneVectorWrapper GetScopeData() final;
230
  ProducedPreparseData* GetChildData(Zone* zone, int child_index) final;
231 232

 private:
233
  ZonePreparseData* data_;
234 235 236 237 238 239
  ZoneVectorWrapper scope_data_wrapper_;
};

}  // namespace internal
}  // namespace v8

240
#endif  // V8_PARSING_PREPARSE_DATA_IMPL_H_