V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
preparsed-scope-data.cc
1 // Copyright 2017 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/parsing/preparsed-scope-data.h"
6 
7 #include <vector>
8 
9 #include "src/ast/scopes.h"
10 #include "src/ast/variables.h"
11 #include "src/handles.h"
12 #include "src/objects-inl.h"
13 #include "src/objects/shared-function-info.h"
14 #include "src/parsing/preparsed-scope-data-impl.h"
15 #include "src/parsing/preparser.h"
16 
17 namespace v8 {
18 namespace internal {
19 
20 namespace {
21 
22 class ScopeCallsSloppyEvalField : public BitField<bool, 0, 1> {};
23 class InnerScopeCallsEvalField
24  : public BitField<bool, ScopeCallsSloppyEvalField::kNext, 1> {};
25 
26 class VariableMaybeAssignedField : public BitField8<bool, 0, 1> {};
27 class VariableContextAllocatedField
28  : public BitField8<bool, VariableMaybeAssignedField::kNext, 1> {};
29 
30 class LanguageField : public BitField8<LanguageMode, 0, 1> {};
31 class UsesSuperField : public BitField8<bool, LanguageField::kNext, 1> {};
32 STATIC_ASSERT(LanguageModeSize <= LanguageField::kNumValues);
33 
34 } // namespace
35 
36 /*
37 
38  Internal data format for the backing store of PreParsedScopeDataBuilder and
39  PreParsedScopeData::scope_data (on the heap):
40 
41  (Skippable function data:)
42  ------------------------------------
43  | scope_data_start (debug only) |
44  ------------------------------------
45  | data for inner function 1 |
46  | ... |
47  ------------------------------------
48  | data for inner function n |
49  | ... |
50  ------------------------------------
51  (Scope allocation data:) << scope_data_start points here in debug
52  ------------------------------------
53  magic value (debug only)
54  ------------------------------------
55  scope positions (debug only)
56  ------------------------------------
57  | scope type << only in debug |
58  | eval |
59  | ---------------------- |
60  | | data for variables | |
61  | | ... | |
62  | ---------------------- |
63  ------------------------------------
64  ------------------------------------
65  | data for inner scope 1 | << but not for function scopes
66  | ... |
67  ------------------------------------
68  ...
69  ------------------------------------
70  | data for inner scope m |
71  | ... |
72  ------------------------------------
73 
74  PreParsedScopeData::child_data is an array of PreParsedScopeData objects, one
75  for each skippable inner function.
76 
77  ConsumedPreParsedScopeData wraps a PreParsedScopeData and reads data from it.
78 
79  */
80 
81 void PreParsedScopeDataBuilder::ByteData::WriteUint32(uint32_t data) {
82 #ifdef DEBUG
83  // Save expected item size in debug mode.
84  backing_store_.push_back(kUint32Size);
85 #endif
86  const uint8_t* d = reinterpret_cast<uint8_t*>(&data);
87  for (int i = 0; i < 4; ++i) {
88  backing_store_.push_back(*d++);
89  }
90  free_quarters_in_last_byte_ = 0;
91 }
92 
93 #ifdef DEBUG
94 void PreParsedScopeDataBuilder::ByteData::OverwriteFirstUint32(uint32_t data) {
95  auto it = backing_store_.begin();
96  // Check that that position already holds an item of the expected size.
97  DCHECK_GE(backing_store_.size(), kUint32Size);
98  DCHECK_EQ(*it, kUint32Size);
99  ++it;
100  const uint8_t* d = reinterpret_cast<uint8_t*>(&data);
101  for (size_t i = 0; i < 4; ++i) {
102  *it++ = *d++;
103  }
104 }
105 #endif
106 
107 void PreParsedScopeDataBuilder::ByteData::WriteUint8(uint8_t data) {
108 #ifdef DEBUG
109  // Save expected item size in debug mode.
110  backing_store_.push_back(kUint8Size);
111 #endif
112  backing_store_.push_back(data);
113  free_quarters_in_last_byte_ = 0;
114 }
115 
116 void PreParsedScopeDataBuilder::ByteData::WriteQuarter(uint8_t data) {
117  DCHECK_LE(data, 3);
118  if (free_quarters_in_last_byte_ == 0) {
119 #ifdef DEBUG
120  // Save a marker in debug mode.
121  backing_store_.push_back(kQuarterMarker);
122 #endif
123  backing_store_.push_back(0);
124  free_quarters_in_last_byte_ = 3;
125  } else {
126  --free_quarters_in_last_byte_;
127  }
128 
129  uint8_t shift_amount = free_quarters_in_last_byte_ * 2;
130  DCHECK_EQ(backing_store_.back() & (3 << shift_amount), 0);
131  backing_store_.back() |= (data << shift_amount);
132 }
133 
134 Handle<PodArray<uint8_t>> PreParsedScopeDataBuilder::ByteData::Serialize(
135  Isolate* isolate) {
136  Handle<PodArray<uint8_t>> array = PodArray<uint8_t>::New(
137  isolate, static_cast<int>(backing_store_.size()), TENURED);
138 
139  DisallowHeapAllocation no_gc;
140  PodArray<uint8_t> raw_array = *array;
141 
142  int i = 0;
143  for (uint8_t item : backing_store_) {
144  raw_array->set(i++, item);
145  }
146  return array;
147 }
148 
149 PreParsedScopeDataBuilder::PreParsedScopeDataBuilder(
150  Zone* zone, PreParsedScopeDataBuilder* parent)
151  : parent_(parent),
152  byte_data_(new (zone) ByteData(zone)),
153  data_for_inner_functions_(zone),
154  bailed_out_(false) {
155  if (parent != nullptr) {
156  parent->data_for_inner_functions_.push_back(this);
157  }
158 #ifdef DEBUG
159  // Reserve space for scope_data_start, written later:
160  byte_data_->WriteUint32(0);
161 #endif
162 }
163 
164 PreParsedScopeDataBuilder::DataGatheringScope::DataGatheringScope(
165  DeclarationScope* function_scope, PreParser* preparser)
166  : preparser_(preparser), builder_(nullptr) {
167  PreParsedScopeDataBuilder* parent = preparser->preparsed_scope_data_builder();
168  Zone* main_zone = preparser->main_zone();
169  builder_ = new (main_zone) PreParsedScopeDataBuilder(main_zone, parent);
170  preparser->set_preparsed_scope_data_builder(builder_);
171  function_scope->set_preparsed_scope_data_builder(builder_);
172 }
173 
174 PreParsedScopeDataBuilder::DataGatheringScope::~DataGatheringScope() {
175  preparser_->set_preparsed_scope_data_builder(builder_->parent_);
176 }
177 
178 void PreParsedScopeDataBuilder::AddSkippableFunction(int start_position,
179  int end_position,
180  int num_parameters,
181  int num_inner_functions,
182  LanguageMode language_mode,
183  bool uses_super_property) {
184  if (bailed_out_) {
185  return;
186  }
187 
188  // Start position is used for a sanity check when consuming the data, we could
189  // remove it in the future if we're very pressed for space but it's been good
190  // at catching bugs in the wild so far.
191  byte_data_->WriteUint32(start_position);
192  byte_data_->WriteUint32(end_position);
193  byte_data_->WriteUint32(num_parameters);
194  byte_data_->WriteUint32(num_inner_functions);
195 
196  uint8_t language_and_super = LanguageField::encode(language_mode) |
197  UsesSuperField::encode(uses_super_property);
198 
199  byte_data_->WriteQuarter(language_and_super);
200 }
201 
202 void PreParsedScopeDataBuilder::SaveScopeAllocationData(
203  DeclarationScope* scope) {
204  // The data contains a uint32 (reserved space for scope_data_start) and
205  // function data items, kSkippableFunctionDataSize each.
206  DCHECK_GE(byte_data_->size(), ByteData::kPlaceholderSize);
207  DCHECK_LE(byte_data_->size(), std::numeric_limits<uint32_t>::max());
208  DCHECK_EQ(byte_data_->size() % ByteData::kSkippableFunctionDataSize,
209  ByteData::kPlaceholderSize);
210 
211  if (bailed_out_) {
212  return;
213  }
214 
215  uint32_t scope_data_start = static_cast<uint32_t>(byte_data_->size());
216 
217  // If there are no skippable inner functions, we don't need to save anything.
218  if (scope_data_start == ByteData::kPlaceholderSize) {
219  return;
220  }
221 
222 #ifdef DEBUG
223  byte_data_->OverwriteFirstUint32(scope_data_start);
224 
225  // For a data integrity check, write a value between data about skipped inner
226  // funcs and data about variables.
227  byte_data_->WriteUint32(ByteData::kMagicValue);
228  byte_data_->WriteUint32(scope->start_position());
229  byte_data_->WriteUint32(scope->end_position());
230 #endif
231 
232  SaveDataForScope(scope);
233 }
234 
235 bool PreParsedScopeDataBuilder::ContainsInnerFunctions() const {
236  return byte_data_->size() > ByteData::kPlaceholderSize;
237 }
238 
239 MaybeHandle<PreParsedScopeData> PreParsedScopeDataBuilder::Serialize(
240  Isolate* isolate) {
241  if (bailed_out_) {
242  return MaybeHandle<PreParsedScopeData>();
243  }
244 
245  DCHECK(!ThisOrParentBailedOut());
246 
247  if (byte_data_->size() <= ByteData::kPlaceholderSize) {
248  // The data contains only the placeholder.
249  return MaybeHandle<PreParsedScopeData>();
250  }
251 
252  int child_data_length = static_cast<int>(data_for_inner_functions_.size());
253  Handle<PreParsedScopeData> data =
254  isolate->factory()->NewPreParsedScopeData(child_data_length);
255 
256  Handle<PodArray<uint8_t>> scope_data_array = byte_data_->Serialize(isolate);
257  data->set_scope_data(*scope_data_array);
258 
259  int i = 0;
260  for (const auto& item : data_for_inner_functions_) {
261  Handle<PreParsedScopeData> child_data;
262  if (item->Serialize(isolate).ToHandle(&child_data)) {
263  data->set_child_data(i, *child_data);
264  } else {
265  DCHECK(data->child_data(i)->IsNull());
266  }
267  i++;
268  }
269 
270  return data;
271 }
272 
273 ZonePreParsedScopeData* PreParsedScopeDataBuilder::Serialize(Zone* zone) {
274  if (bailed_out_) {
275  return nullptr;
276  }
277 
278  DCHECK(!ThisOrParentBailedOut());
279 
280  if (byte_data_->size() <= ByteData::kPlaceholderSize) {
281  // The data contains only the placeholder.
282  return nullptr;
283  }
284 
285  int child_length = static_cast<int>(data_for_inner_functions_.size());
286  ZonePreParsedScopeData* result = new (zone) ZonePreParsedScopeData(
287  zone, byte_data_->begin(), byte_data_->end(), child_length);
288 
289  int i = 0;
290  for (const auto& item : data_for_inner_functions_) {
291  ZonePreParsedScopeData* child = item->Serialize(zone);
292  result->set_child(i, child);
293  i++;
294  }
295 
296  return result;
297 }
298 
299 bool PreParsedScopeDataBuilder::ScopeNeedsData(Scope* scope) {
300  if (scope->scope_type() == ScopeType::FUNCTION_SCOPE) {
301  // Default constructors don't need data (they cannot contain inner functions
302  // defined by the user). Other functions do.
303  return !IsDefaultConstructor(scope->AsDeclarationScope()->function_kind());
304  }
305  if (!scope->is_hidden()) {
306  for (Variable* var : *scope->locals()) {
307  if (IsDeclaredVariableMode(var->mode())) {
308  return true;
309  }
310  }
311  }
312  for (Scope* inner = scope->inner_scope(); inner != nullptr;
313  inner = inner->sibling()) {
314  if (ScopeNeedsData(inner)) {
315  return true;
316  }
317  }
318  return false;
319 }
320 
321 bool PreParsedScopeDataBuilder::ScopeIsSkippableFunctionScope(Scope* scope) {
322  // Lazy non-arrow function scopes are skippable. Lazy functions are exactly
323  // those Scopes which have their own PreParsedScopeDataBuilder object. This
324  // logic ensures that the scope allocation data is consistent with the
325  // skippable function data (both agree on where the lazy function boundaries
326  // are).
327  if (scope->scope_type() != ScopeType::FUNCTION_SCOPE) {
328  return false;
329  }
330  DeclarationScope* declaration_scope = scope->AsDeclarationScope();
331  return !declaration_scope->is_arrow_scope() &&
332  declaration_scope->preparsed_scope_data_builder() != nullptr;
333 }
334 
335 void PreParsedScopeDataBuilder::SaveDataForScope(Scope* scope) {
336  DCHECK_NE(scope->end_position(), kNoSourcePosition);
337 
338  if (!ScopeNeedsData(scope)) {
339  return;
340  }
341 
342 #ifdef DEBUG
343  byte_data_->WriteUint8(scope->scope_type());
344 #endif
345 
346  uint8_t eval =
347  ScopeCallsSloppyEvalField::encode(
348  scope->is_declaration_scope() &&
349  scope->AsDeclarationScope()->calls_sloppy_eval()) |
350  InnerScopeCallsEvalField::encode(scope->inner_scope_calls_eval());
351  byte_data_->WriteUint8(eval);
352 
353  if (scope->scope_type() == ScopeType::FUNCTION_SCOPE) {
354  Variable* function = scope->AsDeclarationScope()->function_var();
355  if (function != nullptr) {
356  SaveDataForVariable(function);
357  }
358  }
359 
360  for (Variable* var : *scope->locals()) {
361  if (IsDeclaredVariableMode(var->mode())) {
362  SaveDataForVariable(var);
363  }
364  }
365 
366  SaveDataForInnerScopes(scope);
367 }
368 
369 void PreParsedScopeDataBuilder::SaveDataForVariable(Variable* var) {
370 #ifdef DEBUG
371  // Store the variable name in debug mode; this way we can check that we
372  // restore data to the correct variable.
373  const AstRawString* name = var->raw_name();
374  byte_data_->WriteUint8(name->is_one_byte());
375  byte_data_->WriteUint32(name->length());
376  for (int i = 0; i < name->length(); ++i) {
377  byte_data_->WriteUint8(name->raw_data()[i]);
378  }
379 #endif
380  byte variable_data = VariableMaybeAssignedField::encode(
381  var->maybe_assigned() == kMaybeAssigned) |
382  VariableContextAllocatedField::encode(
383  var->has_forced_context_allocation());
384  byte_data_->WriteQuarter(variable_data);
385 }
386 
387 void PreParsedScopeDataBuilder::SaveDataForInnerScopes(Scope* scope) {
388  // Inner scopes are stored in the reverse order, but we'd like to write the
389  // data in the logical order. There might be many inner scopes, so we don't
390  // want to recurse here.
391  std::vector<Scope*> scopes;
392  for (Scope* inner = scope->inner_scope(); inner != nullptr;
393  inner = inner->sibling()) {
394  if (ScopeIsSkippableFunctionScope(inner)) {
395  // Don't save data about function scopes, since they'll have their own
396  // PreParsedScopeDataBuilder where their data is saved.
397  DCHECK_NOT_NULL(
398  inner->AsDeclarationScope()->preparsed_scope_data_builder());
399  continue;
400  }
401  scopes.push_back(inner);
402  }
403  for (auto it = scopes.rbegin(); it != scopes.rend(); ++it) {
404  SaveDataForScope(*it);
405  }
406 }
407 
409  : public ProducedPreParsedScopeData {
410  public:
412  : builder_(builder) {}
413 
414  MaybeHandle<PreParsedScopeData> Serialize(Isolate* isolate) final {
415  return builder_->Serialize(isolate);
416  }
417 
418  ZonePreParsedScopeData* Serialize(Zone* zone) final {
419  return builder_->Serialize(zone);
420  };
421 
422  private:
423  PreParsedScopeDataBuilder* builder_;
424 };
425 
427  : public ProducedPreParsedScopeData {
428  public:
430  : data_(data) {}
431 
432  MaybeHandle<PreParsedScopeData> Serialize(Isolate* isolate) final {
433  return data_;
434  }
435 
436  ZonePreParsedScopeData* Serialize(Zone* zone) final {
437  // Not required.
438  UNREACHABLE();
439  };
440 
441  private:
443 };
444 
446  public:
448  : data_(data) {}
449 
450  MaybeHandle<PreParsedScopeData> Serialize(Isolate* isolate) final {
451  return data_->Serialize(isolate);
452  }
453 
454  ZonePreParsedScopeData* Serialize(Zone* zone) final { return data_; };
455 
456  private:
457  ZonePreParsedScopeData* data_;
458 };
459 
460 ProducedPreParsedScopeData* ProducedPreParsedScopeData::For(
461  PreParsedScopeDataBuilder* builder, Zone* zone) {
462  return new (zone) BuilderProducedPreParsedScopeData(builder);
463 }
464 
465 ProducedPreParsedScopeData* ProducedPreParsedScopeData::For(
466  Handle<PreParsedScopeData> data, Zone* zone) {
467  return new (zone) OnHeapProducedPreParsedScopeData(data);
468 }
469 
470 ProducedPreParsedScopeData* ProducedPreParsedScopeData::For(
471  ZonePreParsedScopeData* data, Zone* zone) {
472  return new (zone) ZoneProducedPreParsedScopeData(data);
473 }
474 
475 template <class Data>
476 ProducedPreParsedScopeData*
477 BaseConsumedPreParsedScopeData<Data>::GetDataForSkippableFunction(
478  Zone* zone, int start_position, int* end_position, int* num_parameters,
479  int* num_inner_functions, bool* uses_super_property,
480  LanguageMode* language_mode) {
481  // The skippable function *must* be the next function in the data. Use the
482  // start position as a sanity check.
483  typename ByteData::ReadingScope reading_scope(this);
484  CHECK_GE(scope_data_->RemainingBytes(), ByteData::kSkippableFunctionDataSize);
485  int start_position_from_data = scope_data_->ReadUint32();
486  CHECK_EQ(start_position, start_position_from_data);
487 
488  *end_position = scope_data_->ReadUint32();
489  DCHECK_GT(*end_position, start_position);
490  *num_parameters = scope_data_->ReadUint32();
491  *num_inner_functions = scope_data_->ReadUint32();
492 
493  uint8_t language_and_super = scope_data_->ReadQuarter();
494  *language_mode = LanguageMode(LanguageField::decode(language_and_super));
495  *uses_super_property = UsesSuperField::decode(language_and_super);
496 
497  // Retrieve the corresponding PreParsedScopeData and associate it to the
498  // skipped function. If the skipped functions contains inner functions, those
499  // can be skipped when the skipped function is eagerly parsed.
500  return GetChildData(zone, child_index_++);
501 }
502 
503 template <class Data>
504 void BaseConsumedPreParsedScopeData<Data>::RestoreScopeAllocationData(
505  DeclarationScope* scope) {
506  DCHECK_EQ(scope->scope_type(), ScopeType::FUNCTION_SCOPE);
507  typename ByteData::ReadingScope reading_scope(this);
508 
509 #ifdef DEBUG
510  int magic_value_from_data = scope_data_->ReadUint32();
511  // Check that we've consumed all inner function data.
512  DCHECK_EQ(magic_value_from_data, ByteData::kMagicValue);
513 
514  int start_position_from_data = scope_data_->ReadUint32();
515  int end_position_from_data = scope_data_->ReadUint32();
516  DCHECK_EQ(start_position_from_data, scope->start_position());
517  DCHECK_EQ(end_position_from_data, scope->end_position());
518 #endif
519 
520  RestoreData(scope);
521 
522  // Check that we consumed all scope data.
523  DCHECK_EQ(scope_data_->RemainingBytes(), 0);
524 }
525 
526 template <typename Data>
527 void BaseConsumedPreParsedScopeData<Data>::RestoreData(Scope* scope) {
528  if (scope->is_declaration_scope() &&
529  scope->AsDeclarationScope()->is_skipped_function()) {
530  return;
531  }
532 
533  // It's possible that scope is not present in the data at all (since PreParser
534  // doesn't create the corresponding scope). In this case, the Scope won't
535  // contain any variables for which we need the data.
536  if (!PreParsedScopeDataBuilder::ScopeNeedsData(scope)) {
537  return;
538  }
539 
540  // scope_type is stored only in debug mode.
541  CHECK_GE(scope_data_->RemainingBytes(), ByteData::kUint8Size);
542  DCHECK_EQ(scope_data_->ReadUint8(), scope->scope_type());
543 
544  uint32_t eval = scope_data_->ReadUint8();
545  if (ScopeCallsSloppyEvalField::decode(eval)) {
546  scope->RecordEvalCall();
547  }
548  if (InnerScopeCallsEvalField::decode(eval)) {
549  scope->RecordInnerScopeEvalCall();
550  }
551 
552  if (scope->scope_type() == ScopeType::FUNCTION_SCOPE) {
553  Variable* function = scope->AsDeclarationScope()->function_var();
554  if (function != nullptr) {
555  RestoreDataForVariable(function);
556  }
557  }
558 
559  for (Variable* var : *scope->locals()) {
560  if (IsDeclaredVariableMode(var->mode())) {
561  RestoreDataForVariable(var);
562  }
563  }
564 
565  RestoreDataForInnerScopes(scope);
566 }
567 
568 template <typename Data>
569 void BaseConsumedPreParsedScopeData<Data>::RestoreDataForVariable(
570  Variable* var) {
571 #ifdef DEBUG
572  const AstRawString* name = var->raw_name();
573  bool data_one_byte = scope_data_->ReadUint8();
574  DCHECK_IMPLIES(name->is_one_byte(), data_one_byte);
575  DCHECK_EQ(scope_data_->ReadUint32(), static_cast<uint32_t>(name->length()));
576  if (!name->is_one_byte() && data_one_byte) {
577  // It's possible that "name" is a two-byte representation of the string
578  // stored in the data.
579  for (int i = 0; i < 2 * name->length(); i += 2) {
580 #if defined(V8_TARGET_LITTLE_ENDIAN)
581  DCHECK_EQ(scope_data_->ReadUint8(), name->raw_data()[i]);
582  DCHECK_EQ(0, name->raw_data()[i + 1]);
583 #else
584  DCHECK_EQ(scope_data_->ReadUint8(), name->raw_data()[i + 1]);
585  DCHECK_EQ(0, name->raw_data()[i]);
586 #endif // V8_TARGET_LITTLE_ENDIAN
587  }
588  } else {
589  for (int i = 0; i < name->length(); ++i) {
590  DCHECK_EQ(scope_data_->ReadUint8(), name->raw_data()[i]);
591  }
592  }
593 #endif
594  uint8_t variable_data = scope_data_->ReadQuarter();
595  if (VariableMaybeAssignedField::decode(variable_data)) {
596  var->set_maybe_assigned();
597  }
598  if (VariableContextAllocatedField::decode(variable_data)) {
599  var->set_is_used();
600  var->ForceContextAllocation();
601  }
602 }
603 
604 template <typename Data>
605 void BaseConsumedPreParsedScopeData<Data>::RestoreDataForInnerScopes(
606  Scope* scope) {
607  std::vector<Scope*> scopes;
608  for (Scope* inner = scope->inner_scope(); inner != nullptr;
609  inner = inner->sibling()) {
610  scopes.push_back(inner);
611  }
612  for (auto it = scopes.rbegin(); it != scopes.rend(); ++it) {
613  RestoreData(*it);
614  }
615 }
616 
617 #ifdef DEBUG
618 template <class Data>
619 void BaseConsumedPreParsedScopeData<Data>::VerifyDataStart() {
620  typename ByteData::ReadingScope reading_scope(this);
621  int scope_data_start = scope_data_->ReadUint32();
622  scope_data_->SetPosition(scope_data_start);
623  DCHECK_EQ(scope_data_->ReadUint32(), ByteData::kMagicValue);
624  // The first data item is scope_data_start. Skip over it.
625  scope_data_->SetPosition(ByteData::kPlaceholderSize);
626 }
627 #endif
628 
629 PodArray<uint8_t> OnHeapConsumedPreParsedScopeData::GetScopeData() {
630  return data_->scope_data();
631 }
632 
633 ProducedPreParsedScopeData* OnHeapConsumedPreParsedScopeData::GetChildData(
634  Zone* zone, int child_index) {
635  CHECK_GT(data_->length(), child_index);
636  Object* child_data = data_->child_data(child_index);
637  if (!child_data->IsPreParsedScopeData()) {
638  return nullptr;
639  }
640  Handle<PreParsedScopeData> child_data_handle(
641  PreParsedScopeData::cast(child_data), isolate_);
642  return ProducedPreParsedScopeData::For(child_data_handle, zone);
643 }
644 
645 OnHeapConsumedPreParsedScopeData::OnHeapConsumedPreParsedScopeData(
646  Isolate* isolate, Handle<PreParsedScopeData> data)
647  : BaseConsumedPreParsedScopeData<PodArray<uint8_t>>(),
648  isolate_(isolate),
649  data_(data) {
650  DCHECK_NOT_NULL(isolate);
651  DCHECK(data->IsPreParsedScopeData());
652 #ifdef DEBUG
653  VerifyDataStart();
654 #endif
655 }
656 
657 ZonePreParsedScopeData::ZonePreParsedScopeData(
658  Zone* zone, ZoneChunkList<uint8_t>::iterator byte_data_begin,
659  ZoneChunkList<uint8_t>::iterator byte_data_end, int child_length)
660  : byte_data_(byte_data_begin, byte_data_end, zone),
661  children_(child_length, zone) {}
662 
663 Handle<PreParsedScopeData> ZonePreParsedScopeData::Serialize(Isolate* isolate) {
664  int child_data_length = child_length();
665  Handle<PreParsedScopeData> result =
666  isolate->factory()->NewPreParsedScopeData(child_data_length);
667 
668  Handle<PodArray<uint8_t>> scope_data_array = PodArray<uint8_t>::New(
669  isolate, static_cast<int>(byte_data()->size()), TENURED);
670  scope_data_array->copy_in(0, byte_data()->data(),
671  static_cast<int>(byte_data()->size()));
672  result->set_scope_data(*scope_data_array);
673 
674  for (int i = 0; i < child_data_length; i++) {
675  ZonePreParsedScopeData* child = get_child(i);
676  if (child) {
677  Handle<PreParsedScopeData> child_data = child->Serialize(isolate);
678  result->set_child_data(i, *child_data);
679  }
680  }
681  return result;
682 }
683 
684 ZoneConsumedPreParsedScopeData::ZoneConsumedPreParsedScopeData(
685  Zone* zone, ZonePreParsedScopeData* data)
686  : data_(data), scope_data_wrapper_(data_->byte_data()) {
687 #ifdef DEBUG
688  VerifyDataStart();
689 #endif
690 }
691 
692 ZoneVectorWrapper ZoneConsumedPreParsedScopeData::GetScopeData() {
693  return scope_data_wrapper_;
694 }
695 
696 ProducedPreParsedScopeData* ZoneConsumedPreParsedScopeData::GetChildData(
697  Zone* zone, int child_index) {
698  CHECK_GT(data_->child_length(), child_index);
699  ZonePreParsedScopeData* child_data = data_->get_child(child_index);
700  if (child_data == nullptr) {
701  return nullptr;
702  }
703  return ProducedPreParsedScopeData::For(child_data, zone);
704 }
705 
706 std::unique_ptr<ConsumedPreParsedScopeData> ConsumedPreParsedScopeData::For(
707  Isolate* isolate, Handle<PreParsedScopeData> data) {
708  DCHECK(!data.is_null());
709  return base::make_unique<OnHeapConsumedPreParsedScopeData>(isolate, data);
710 }
711 
712 std::unique_ptr<ConsumedPreParsedScopeData> ConsumedPreParsedScopeData::For(
713  Zone* zone, ZonePreParsedScopeData* data) {
714  if (data == nullptr) return {};
715  return base::make_unique<ZoneConsumedPreParsedScopeData>(zone, data);
716 }
717 
718 } // namespace internal
719 } // namespace v8
Definition: v8.h:85
Definition: libplatform.h:13