• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/preparse-data.h"
6 
7 #include <vector>
8 
9 #include "src/ast/scopes.h"
10 #include "src/ast/variables.h"
11 #include "src/base/logging.h"
12 #include "src/base/platform/wrappers.h"
13 #include "src/handles/handles.h"
14 #include "src/objects/objects-inl.h"
15 #include "src/objects/shared-function-info.h"
16 #include "src/parsing/parser.h"
17 #include "src/parsing/preparse-data-impl.h"
18 #include "src/parsing/preparser.h"
19 #include "src/roots/roots.h"
20 #include "src/zone/zone-list-inl.h"  // crbug.com/v8/8816
21 #include "src/zone/zone-utils.h"
22 
23 namespace v8 {
24 namespace internal {
25 
26 namespace {
27 
28 using ScopeSloppyEvalCanExtendVarsBit = base::BitField8<bool, 0, 1>;
29 using InnerScopeCallsEvalField = ScopeSloppyEvalCanExtendVarsBit::Next<bool, 1>;
30 using NeedsPrivateNameContextChainRecalcField =
31     InnerScopeCallsEvalField::Next<bool, 1>;
32 using ShouldSaveClassVariableIndexField =
33     NeedsPrivateNameContextChainRecalcField::Next<bool, 1>;
34 
35 using VariableMaybeAssignedField = base::BitField8<bool, 0, 1>;
36 using VariableContextAllocatedField = VariableMaybeAssignedField::Next<bool, 1>;
37 
38 using HasDataField = base::BitField<bool, 0, 1>;
39 using LengthEqualsParametersField = HasDataField::Next<bool, 1>;
40 using NumberOfParametersField = LengthEqualsParametersField::Next<uint16_t, 16>;
41 
42 using LanguageField = base::BitField8<LanguageMode, 0, 1>;
43 using UsesSuperField = LanguageField::Next<bool, 1>;
44 STATIC_ASSERT(LanguageModeSize <= LanguageField::kNumValues);
45 
46 }  // namespace
47 
48 /*
49 
50   Internal data format for the backing store of PreparseDataBuilder and
51   PreparseData::scope_data (on the heap):
52 
53   (Skippable function data:)
54   ------------------------------------
55   | scope_data_start (debug only)    |
56   ------------------------------------
57   | data for inner function n        |
58   | ...                              |
59   ------------------------------------
60   | data for inner function 1        |
61   | ...                              |
62   ------------------------------------
63   (Scope allocation data:)             << scope_data_start points here in debug
64   ------------------------------------
65   magic value (debug only)
66   ------------------------------------
67   scope positions (debug only)
68   ------------------------------------
69   | scope type << only in debug      |
70   | eval                             |
71   | ----------------------           |
72   | | data for variables |           |
73   | | ...                |           |
74   | ----------------------           |
75   ------------------------------------
76   ------------------------------------
77   | data for inner scope m           | << but not for function scopes
78   | ...                              |
79   ------------------------------------
80   ...
81   ------------------------------------
82   | data for inner scope 1           |
83   | ...                              |
84   ------------------------------------
85 
86   PreparseData::child_data is an array of PreparseData objects, one
87   for each skippable inner function.
88 
89   ConsumedPreparseData wraps a PreparseData and reads data from it.
90 
91  */
92 
PreparseDataBuilder(Zone * zone,PreparseDataBuilder * parent_builder,std::vector<void * > * children_buffer)93 PreparseDataBuilder::PreparseDataBuilder(Zone* zone,
94                                          PreparseDataBuilder* parent_builder,
95                                          std::vector<void*>* children_buffer)
96     : parent_(parent_builder),
97       byte_data_(),
98       children_buffer_(children_buffer),
99       function_scope_(nullptr),
100       function_length_(-1),
101       num_inner_functions_(0),
102       num_inner_with_data_(0),
103       bailed_out_(false),
104       has_data_(false) {}
105 
Start(DeclarationScope * function_scope)106 void PreparseDataBuilder::DataGatheringScope::Start(
107     DeclarationScope* function_scope) {
108   Zone* main_zone = preparser_->main_zone();
109   builder_ = main_zone->New<PreparseDataBuilder>(
110       main_zone, preparser_->preparse_data_builder(),
111       preparser_->preparse_data_builder_buffer());
112   preparser_->set_preparse_data_builder(builder_);
113   function_scope->set_preparse_data_builder(builder_);
114 }
115 
Close()116 void PreparseDataBuilder::DataGatheringScope::Close() {
117   PreparseDataBuilder* parent = builder_->parent_;
118   preparser_->set_preparse_data_builder(parent);
119   builder_->FinalizeChildren(preparser_->main_zone());
120 
121   if (parent == nullptr) return;
122   if (!builder_->HasDataForParent()) return;
123   parent->AddChild(builder_);
124 }
125 
Start(std::vector<uint8_t> * buffer)126 void PreparseDataBuilder::ByteData::Start(std::vector<uint8_t>* buffer) {
127   DCHECK(!is_finalized_);
128   byte_data_ = buffer;
129   DCHECK_EQ(byte_data_->size(), 0);
130   DCHECK_EQ(index_, 0);
131 }
132 
133 // This struct is just a type tag for Zone::NewArray<T>(size_t) call.
134 struct RawPreparseData {};
135 
Finalize(Zone * zone)136 void PreparseDataBuilder::ByteData::Finalize(Zone* zone) {
137   uint8_t* raw_zone_data = zone->NewArray<uint8_t, RawPreparseData>(index_);
138   memcpy(raw_zone_data, byte_data_->data(), index_);
139   byte_data_->resize(0);
140   zone_byte_data_ = base::Vector<uint8_t>(raw_zone_data, index_);
141 #ifdef DEBUG
142   is_finalized_ = true;
143 #endif
144 }
145 
Reserve(size_t bytes)146 void PreparseDataBuilder::ByteData::Reserve(size_t bytes) {
147   // Make sure we have at least {bytes} capacity left in the buffer_.
148   DCHECK_LE(length(), byte_data_->size());
149   size_t capacity = byte_data_->size() - length();
150   if (capacity >= bytes) return;
151   size_t delta = bytes - capacity;
152   byte_data_->insert(byte_data_->end(), delta, 0);
153 }
154 
length() const155 int PreparseDataBuilder::ByteData::length() const { return index_; }
156 
Add(uint8_t byte)157 void PreparseDataBuilder::ByteData::Add(uint8_t byte) {
158   DCHECK_LE(0, index_);
159   DCHECK_LT(index_, byte_data_->size());
160   (*byte_data_)[index_++] = byte;
161 }
162 
163 #ifdef DEBUG
WriteUint32(uint32_t data)164 void PreparseDataBuilder::ByteData::WriteUint32(uint32_t data) {
165   DCHECK(!is_finalized_);
166   Add(kUint32Size);
167   Add(data & 0xFF);
168   Add((data >> 8) & 0xFF);
169   Add((data >> 16) & 0xFF);
170   Add((data >> 24) & 0xFF);
171   free_quarters_in_last_byte_ = 0;
172 }
173 
SaveCurrentSizeAtFirstUint32()174 void PreparseDataBuilder::ByteData::SaveCurrentSizeAtFirstUint32() {
175   int current_length = length();
176   index_ = 0;
177   CHECK_EQ(byte_data_->at(0), kUint32Size);
178   WriteUint32(current_length);
179   index_ = current_length;
180 }
181 #endif
182 
WriteVarint32(uint32_t data)183 void PreparseDataBuilder::ByteData::WriteVarint32(uint32_t data) {
184 #ifdef DEBUG
185   // Save expected item size in debug mode.
186   Add(kVarint32MinSize);
187 #endif
188   // See ValueSerializer::WriteVarint.
189   do {
190     uint8_t next_byte = (data & 0x7F);
191     data >>= 7;
192     // Add continue bit.
193     if (data) next_byte |= 0x80;
194     Add(next_byte & 0xFF);
195   } while (data);
196 #ifdef DEBUG
197   Add(kVarint32EndMarker);
198 #endif
199   free_quarters_in_last_byte_ = 0;
200 }
201 
WriteUint8(uint8_t data)202 void PreparseDataBuilder::ByteData::WriteUint8(uint8_t data) {
203   DCHECK(!is_finalized_);
204 #ifdef DEBUG
205   // Save expected item size in debug mode.
206   Add(kUint8Size);
207 #endif
208   Add(data);
209   free_quarters_in_last_byte_ = 0;
210 }
211 
WriteQuarter(uint8_t data)212 void PreparseDataBuilder::ByteData::WriteQuarter(uint8_t data) {
213   DCHECK(!is_finalized_);
214   DCHECK_LE(data, 3);
215   if (free_quarters_in_last_byte_ == 0) {
216 #ifdef DEBUG
217     // Save a marker in debug mode.
218     Add(kQuarterMarker);
219 #endif
220     Add(0);
221     free_quarters_in_last_byte_ = 3;
222   } else {
223     --free_quarters_in_last_byte_;
224   }
225 
226   uint8_t shift_amount = free_quarters_in_last_byte_ * 2;
227   DCHECK_EQ(byte_data_->at(index_ - 1) & (3 << shift_amount), 0);
228   (*byte_data_)[index_ - 1] |= (data << shift_amount);
229 }
230 
SetSkippableFunction(DeclarationScope * function_scope,int function_length,int num_inner_functions)231 void PreparseDataBuilder::DataGatheringScope::SetSkippableFunction(
232     DeclarationScope* function_scope, int function_length,
233     int num_inner_functions) {
234   DCHECK_NULL(builder_->function_scope_);
235   builder_->function_scope_ = function_scope;
236   DCHECK_EQ(builder_->num_inner_functions_, 0);
237   builder_->function_length_ = function_length;
238   builder_->num_inner_functions_ = num_inner_functions;
239   builder_->parent_->has_data_ = true;
240 }
241 
HasInnerFunctions() const242 bool PreparseDataBuilder::HasInnerFunctions() const {
243   return !children_.empty();
244 }
245 
HasData() const246 bool PreparseDataBuilder::HasData() const { return !bailed_out_ && has_data_; }
247 
HasDataForParent() const248 bool PreparseDataBuilder::HasDataForParent() const {
249   return HasData() || function_scope_ != nullptr;
250 }
251 
AddChild(PreparseDataBuilder * child)252 void PreparseDataBuilder::AddChild(PreparseDataBuilder* child) {
253   DCHECK(!finalized_children_);
254   children_buffer_.Add(child);
255 }
256 
FinalizeChildren(Zone * zone)257 void PreparseDataBuilder::FinalizeChildren(Zone* zone) {
258   DCHECK(!finalized_children_);
259   base::Vector<PreparseDataBuilder*> children =
260       CloneVector(zone, children_buffer_.ToConstVector());
261   children_buffer_.Rewind();
262   children_ = children;
263 #ifdef DEBUG
264   finalized_children_ = true;
265 #endif
266 }
267 
ScopeNeedsData(Scope * scope)268 bool PreparseDataBuilder::ScopeNeedsData(Scope* scope) {
269   if (scope->is_function_scope()) {
270     // Default constructors don't need data (they cannot contain inner functions
271     // defined by the user). Other functions do.
272     return !IsDefaultConstructor(scope->AsDeclarationScope()->function_kind());
273   }
274   if (!scope->is_hidden()) {
275     for (Variable* var : *scope->locals()) {
276       if (IsSerializableVariableMode(var->mode())) return true;
277     }
278   }
279   for (Scope* inner = scope->inner_scope(); inner != nullptr;
280        inner = inner->sibling()) {
281     if (ScopeNeedsData(inner)) return true;
282   }
283   return false;
284 }
285 
SaveDataForSkippableFunction(PreparseDataBuilder * builder)286 bool PreparseDataBuilder::SaveDataForSkippableFunction(
287     PreparseDataBuilder* builder) {
288   DeclarationScope* function_scope = builder->function_scope_;
289   // Start position is used for a sanity check when consuming the data, we could
290   // remove it in the future if we're very pressed for space but it's been good
291   // at catching bugs in the wild so far.
292   byte_data_.WriteVarint32(function_scope->start_position());
293   byte_data_.WriteVarint32(function_scope->end_position());
294 
295   bool has_data = builder->HasData();
296   bool length_equals_parameters =
297       function_scope->num_parameters() == builder->function_length_;
298   uint32_t has_data_and_num_parameters =
299       HasDataField::encode(has_data) |
300       LengthEqualsParametersField::encode(length_equals_parameters) |
301       NumberOfParametersField::encode(function_scope->num_parameters());
302   byte_data_.WriteVarint32(has_data_and_num_parameters);
303   if (!length_equals_parameters) {
304     byte_data_.WriteVarint32(builder->function_length_);
305   }
306   byte_data_.WriteVarint32(builder->num_inner_functions_);
307 
308   uint8_t language_and_super =
309       LanguageField::encode(function_scope->language_mode()) |
310       UsesSuperField::encode(function_scope->uses_super_property());
311   byte_data_.WriteQuarter(language_and_super);
312   return has_data;
313 }
314 
SaveScopeAllocationData(DeclarationScope * scope,Parser * parser)315 void PreparseDataBuilder::SaveScopeAllocationData(DeclarationScope* scope,
316                                                   Parser* parser) {
317   if (!has_data_) return;
318   DCHECK(HasInnerFunctions());
319 
320   byte_data_.Start(parser->preparse_data_buffer());
321 
322 #ifdef DEBUG
323   // Reserve Uint32 for scope_data_start debug info.
324   byte_data_.Reserve(kUint32Size);
325   byte_data_.WriteUint32(0);
326 #endif
327   byte_data_.Reserve(children_.size() * kSkippableFunctionMaxDataSize);
328   DCHECK(finalized_children_);
329   for (const auto& builder : children_) {
330     // Keep track of functions with inner data. {children_} contains also the
331     // builders that have no inner functions at all.
332     if (SaveDataForSkippableFunction(builder)) num_inner_with_data_++;
333   }
334 
335   // Don't save incomplete scope information when bailed out.
336   if (!bailed_out_) {
337 #ifdef DEBUG
338   // function data items, kSkippableMinFunctionDataSize each.
339   CHECK_GE(byte_data_.length(), kPlaceholderSize);
340   CHECK_LE(byte_data_.length(), std::numeric_limits<uint32_t>::max());
341 
342   byte_data_.SaveCurrentSizeAtFirstUint32();
343   // For a data integrity check, write a value between data about skipped
344   // inner funcs and data about variables.
345   byte_data_.Reserve(kUint32Size * 3);
346   byte_data_.WriteUint32(kMagicValue);
347   byte_data_.WriteUint32(scope->start_position());
348   byte_data_.WriteUint32(scope->end_position());
349 #endif
350 
351   if (ScopeNeedsData(scope)) SaveDataForScope(scope);
352   }
353   byte_data_.Finalize(parser->factory()->zone());
354 }
355 
SaveDataForScope(Scope * scope)356 void PreparseDataBuilder::SaveDataForScope(Scope* scope) {
357   DCHECK_NE(scope->end_position(), kNoSourcePosition);
358   DCHECK(ScopeNeedsData(scope));
359 
360 #ifdef DEBUG
361   byte_data_.Reserve(kUint8Size);
362   byte_data_.WriteUint8(scope->scope_type());
363 #endif
364 
365   uint8_t scope_data_flags =
366       ScopeSloppyEvalCanExtendVarsBit::encode(
367           scope->is_declaration_scope() &&
368           scope->AsDeclarationScope()->sloppy_eval_can_extend_vars()) |
369       InnerScopeCallsEvalField::encode(scope->inner_scope_calls_eval()) |
370       NeedsPrivateNameContextChainRecalcField::encode(
371           scope->is_function_scope() &&
372           scope->AsDeclarationScope()
373               ->needs_private_name_context_chain_recalc()) |
374       ShouldSaveClassVariableIndexField::encode(
375           scope->is_class_scope() &&
376           scope->AsClassScope()->should_save_class_variable_index());
377   byte_data_.Reserve(kUint8Size);
378   byte_data_.WriteUint8(scope_data_flags);
379 
380   if (scope->is_function_scope()) {
381     Variable* function = scope->AsDeclarationScope()->function_var();
382     if (function != nullptr) SaveDataForVariable(function);
383   }
384 
385   for (Variable* var : *scope->locals()) {
386     if (IsSerializableVariableMode(var->mode())) SaveDataForVariable(var);
387   }
388 
389   SaveDataForInnerScopes(scope);
390 }
391 
SaveDataForVariable(Variable * var)392 void PreparseDataBuilder::SaveDataForVariable(Variable* var) {
393 #ifdef DEBUG
394   // Store the variable name in debug mode; this way we can check that we
395   // restore data to the correct variable.
396   const AstRawString* name = var->raw_name();
397   byte_data_.Reserve(kUint32Size + (name->length() + 1) * kUint8Size);
398   byte_data_.WriteUint8(name->is_one_byte());
399   byte_data_.WriteUint32(name->length());
400   for (int i = 0; i < name->length(); ++i) {
401     byte_data_.WriteUint8(name->raw_data()[i]);
402   }
403 #endif
404 
405   byte variable_data = VariableMaybeAssignedField::encode(
406                            var->maybe_assigned() == kMaybeAssigned) |
407                        VariableContextAllocatedField::encode(
408                            var->has_forced_context_allocation());
409   byte_data_.Reserve(kUint8Size);
410   byte_data_.WriteQuarter(variable_data);
411 }
412 
SaveDataForInnerScopes(Scope * scope)413 void PreparseDataBuilder::SaveDataForInnerScopes(Scope* scope) {
414   // Inner scopes are stored in the reverse order, but we'd like to write the
415   // data in the logical order. There might be many inner scopes, so we don't
416   // want to recurse here.
417   for (Scope* inner = scope->inner_scope(); inner != nullptr;
418        inner = inner->sibling()) {
419     if (inner->IsSkippableFunctionScope()) {
420       // Don't save data about function scopes, since they'll have their own
421       // PreparseDataBuilder where their data is saved.
422       DCHECK_NOT_NULL(inner->AsDeclarationScope()->preparse_data_builder());
423       continue;
424     }
425     if (!ScopeNeedsData(inner)) continue;
426     SaveDataForScope(inner);
427   }
428 }
429 
430 
CopyToHeap(Isolate * isolate,int children_length)431 Handle<PreparseData> PreparseDataBuilder::ByteData::CopyToHeap(
432     Isolate* isolate, int children_length) {
433   DCHECK(is_finalized_);
434   int data_length = zone_byte_data_.length();
435   Handle<PreparseData> data =
436       isolate->factory()->NewPreparseData(data_length, children_length);
437   data->copy_in(0, zone_byte_data_.begin(), data_length);
438   return data;
439 }
440 
CopyToLocalHeap(LocalIsolate * isolate,int children_length)441 Handle<PreparseData> PreparseDataBuilder::ByteData::CopyToLocalHeap(
442     LocalIsolate* isolate, int children_length) {
443   DCHECK(is_finalized_);
444   int data_length = zone_byte_data_.length();
445   Handle<PreparseData> data =
446       isolate->factory()->NewPreparseData(data_length, children_length);
447   data->copy_in(0, zone_byte_data_.begin(), data_length);
448   return data;
449 }
450 
Serialize(Isolate * isolate)451 Handle<PreparseData> PreparseDataBuilder::Serialize(Isolate* isolate) {
452   DCHECK(HasData());
453   DCHECK(!ThisOrParentBailedOut());
454   Handle<PreparseData> data =
455       byte_data_.CopyToHeap(isolate, num_inner_with_data_);
456   int i = 0;
457   DCHECK(finalized_children_);
458   for (const auto& builder : children_) {
459     if (!builder->HasData()) continue;
460     Handle<PreparseData> child_data = builder->Serialize(isolate);
461     data->set_child(i++, *child_data);
462   }
463   DCHECK_EQ(i, data->children_length());
464   return data;
465 }
466 
Serialize(LocalIsolate * isolate)467 Handle<PreparseData> PreparseDataBuilder::Serialize(LocalIsolate* isolate) {
468   DCHECK(HasData());
469   DCHECK(!ThisOrParentBailedOut());
470   Handle<PreparseData> data =
471       byte_data_.CopyToLocalHeap(isolate, num_inner_with_data_);
472   int i = 0;
473   DCHECK(finalized_children_);
474   for (const auto& builder : children_) {
475     if (!builder->HasData()) continue;
476     Handle<PreparseData> child_data = builder->Serialize(isolate);
477     data->set_child(i++, *child_data);
478   }
479   DCHECK_EQ(i, data->children_length());
480   return data;
481 }
482 
Serialize(Zone * zone)483 ZonePreparseData* PreparseDataBuilder::Serialize(Zone* zone) {
484   DCHECK(HasData());
485   DCHECK(!ThisOrParentBailedOut());
486   ZonePreparseData* data = byte_data_.CopyToZone(zone, num_inner_with_data_);
487   int i = 0;
488   DCHECK(finalized_children_);
489   for (const auto& builder : children_) {
490     if (!builder->HasData()) continue;
491     ZonePreparseData* child = builder->Serialize(zone);
492     data->set_child(i++, child);
493   }
494   DCHECK_EQ(i, data->children_length());
495   return data;
496 }
497 
498 class BuilderProducedPreparseData final : public ProducedPreparseData {
499  public:
BuilderProducedPreparseData(PreparseDataBuilder * builder)500   explicit BuilderProducedPreparseData(PreparseDataBuilder* builder)
501       : builder_(builder) {
502     DCHECK(builder->HasData());
503   }
504 
Serialize(Isolate * isolate)505   Handle<PreparseData> Serialize(Isolate* isolate) final {
506     return builder_->Serialize(isolate);
507   }
508 
Serialize(LocalIsolate * isolate)509   Handle<PreparseData> Serialize(LocalIsolate* isolate) final {
510     return builder_->Serialize(isolate);
511   }
512 
Serialize(Zone * zone)513   ZonePreparseData* Serialize(Zone* zone) final {
514     return builder_->Serialize(zone);
515   }
516 
517  private:
518   PreparseDataBuilder* builder_;
519 };
520 
521 class OnHeapProducedPreparseData final : public ProducedPreparseData {
522  public:
OnHeapProducedPreparseData(Handle<PreparseData> data)523   explicit OnHeapProducedPreparseData(Handle<PreparseData> data)
524       : data_(data) {}
525 
Serialize(Isolate * isolate)526   Handle<PreparseData> Serialize(Isolate* isolate) final {
527     DCHECK(!data_->is_null());
528     return data_;
529   }
530 
Serialize(LocalIsolate * isolate)531   Handle<PreparseData> Serialize(LocalIsolate* isolate) final {
532     DCHECK(!data_->is_null());
533     DCHECK_IMPLIES(!isolate->is_main_thread(),
534                    isolate->heap()->ContainsLocalHandle(data_.location()));
535     return data_;
536   }
537 
Serialize(Zone * zone)538   ZonePreparseData* Serialize(Zone* zone) final {
539     // Not required.
540     UNREACHABLE();
541   }
542 
543  private:
544   Handle<PreparseData> data_;
545 };
546 
547 class ZoneProducedPreparseData final : public ProducedPreparseData {
548  public:
ZoneProducedPreparseData(ZonePreparseData * data)549   explicit ZoneProducedPreparseData(ZonePreparseData* data) : data_(data) {}
550 
Serialize(Isolate * isolate)551   Handle<PreparseData> Serialize(Isolate* isolate) final {
552     return data_->Serialize(isolate);
553   }
554 
Serialize(LocalIsolate * isolate)555   Handle<PreparseData> Serialize(LocalIsolate* isolate) final {
556     return data_->Serialize(isolate);
557   }
558 
Serialize(Zone * zone)559   ZonePreparseData* Serialize(Zone* zone) final {
560     base::Vector<uint8_t> data(data_->byte_data()->data(),
561                                data_->byte_data()->size());
562     return zone->New<ZonePreparseData>(zone, &data, data_->children_length());
563   }
564 
565  private:
566   ZonePreparseData* data_;
567 };
568 
For(PreparseDataBuilder * builder,Zone * zone)569 ProducedPreparseData* ProducedPreparseData::For(PreparseDataBuilder* builder,
570                                                 Zone* zone) {
571   return zone->New<BuilderProducedPreparseData>(builder);
572 }
573 
For(Handle<PreparseData> data,Zone * zone)574 ProducedPreparseData* ProducedPreparseData::For(Handle<PreparseData> data,
575                                                 Zone* zone) {
576   return zone->New<OnHeapProducedPreparseData>(data);
577 }
578 
For(ZonePreparseData * data,Zone * zone)579 ProducedPreparseData* ProducedPreparseData::For(ZonePreparseData* data,
580                                                 Zone* zone) {
581   return zone->New<ZoneProducedPreparseData>(data);
582 }
583 
584 template <class Data>
585 ProducedPreparseData*
GetDataForSkippableFunction(Zone * zone,int start_position,int * end_position,int * num_parameters,int * function_length,int * num_inner_functions,bool * uses_super_property,LanguageMode * language_mode)586 BaseConsumedPreparseData<Data>::GetDataForSkippableFunction(
587     Zone* zone, int start_position, int* end_position, int* num_parameters,
588     int* function_length, int* num_inner_functions, bool* uses_super_property,
589     LanguageMode* language_mode) {
590   // The skippable function *must* be the next function in the data. Use the
591   // start position as a sanity check.
592   typename ByteData::ReadingScope reading_scope(this);
593   CHECK(scope_data_->HasRemainingBytes(
594       PreparseByteDataConstants::kSkippableFunctionMinDataSize));
595   int start_position_from_data = scope_data_->ReadVarint32();
596   CHECK_EQ(start_position, start_position_from_data);
597   *end_position = scope_data_->ReadVarint32();
598   DCHECK_GT(*end_position, start_position);
599 
600   uint32_t has_data_and_num_parameters = scope_data_->ReadVarint32();
601   bool has_data = HasDataField::decode(has_data_and_num_parameters);
602   *num_parameters =
603       NumberOfParametersField::decode(has_data_and_num_parameters);
604   bool length_equals_parameters =
605       LengthEqualsParametersField::decode(has_data_and_num_parameters);
606   if (length_equals_parameters) {
607     *function_length = *num_parameters;
608   } else {
609     *function_length = scope_data_->ReadVarint32();
610   }
611   *num_inner_functions = scope_data_->ReadVarint32();
612 
613   uint8_t language_and_super = scope_data_->ReadQuarter();
614   *language_mode = LanguageMode(LanguageField::decode(language_and_super));
615   *uses_super_property = UsesSuperField::decode(language_and_super);
616 
617   if (!has_data) return nullptr;
618 
619   // Retrieve the corresponding PreparseData and associate it to the
620   // skipped function. If the skipped functions contains inner functions, those
621   // can be skipped when the skipped function is eagerly parsed.
622   return GetChildData(zone, child_index_++);
623 }
624 
625 template <class Data>
RestoreScopeAllocationData(DeclarationScope * scope,AstValueFactory * ast_value_factory,Zone * zone)626 void BaseConsumedPreparseData<Data>::RestoreScopeAllocationData(
627     DeclarationScope* scope, AstValueFactory* ast_value_factory, Zone* zone) {
628   DCHECK_EQ(scope->scope_type(), ScopeType::FUNCTION_SCOPE);
629   typename ByteData::ReadingScope reading_scope(this);
630 
631 #ifdef DEBUG
632   int magic_value_from_data = scope_data_->ReadUint32();
633   // Check that we've consumed all inner function data.
634   DCHECK_EQ(magic_value_from_data, ByteData::kMagicValue);
635 
636   int start_position_from_data = scope_data_->ReadUint32();
637   int end_position_from_data = scope_data_->ReadUint32();
638   DCHECK_EQ(start_position_from_data, scope->start_position());
639   DCHECK_EQ(end_position_from_data, scope->end_position());
640 #endif
641 
642   RestoreDataForScope(scope, ast_value_factory, zone);
643 
644   // Check that we consumed all scope data.
645   DCHECK_EQ(scope_data_->RemainingBytes(), 0);
646 }
647 
648 template <typename Data>
RestoreDataForScope(Scope * scope,AstValueFactory * ast_value_factory,Zone * zone)649 void BaseConsumedPreparseData<Data>::RestoreDataForScope(
650     Scope* scope, AstValueFactory* ast_value_factory, Zone* zone) {
651   if (scope->is_declaration_scope() &&
652       scope->AsDeclarationScope()->is_skipped_function()) {
653     return;
654   }
655 
656   // It's possible that scope is not present in the data at all (since PreParser
657   // doesn't create the corresponding scope). In this case, the Scope won't
658   // contain any variables for which we need the data.
659   if (!PreparseDataBuilder::ScopeNeedsData(scope)) return;
660 
661   // scope_type is stored only in debug mode.
662   DCHECK_EQ(scope_data_->ReadUint8(), scope->scope_type());
663 
664   CHECK(scope_data_->HasRemainingBytes(ByteData::kUint8Size));
665   uint32_t scope_data_flags = scope_data_->ReadUint8();
666   if (ScopeSloppyEvalCanExtendVarsBit::decode(scope_data_flags)) {
667     scope->RecordEvalCall();
668   }
669   if (InnerScopeCallsEvalField::decode(scope_data_flags)) {
670     scope->RecordInnerScopeEvalCall();
671   }
672   if (NeedsPrivateNameContextChainRecalcField::decode(scope_data_flags)) {
673     scope->AsDeclarationScope()->RecordNeedsPrivateNameContextChainRecalc();
674   }
675   if (ShouldSaveClassVariableIndexField::decode(scope_data_flags)) {
676     Variable* var = scope->AsClassScope()->class_variable();
677     // An anonymous class whose class variable needs to be saved might not
678     // have the class variable created during reparse since we skip parsing
679     // the inner scopes that contain potential access to static private
680     // methods. So create it now.
681     if (var == nullptr) {
682       DCHECK(scope->AsClassScope()->is_anonymous_class());
683       var = scope->AsClassScope()->DeclareClassVariable(
684           ast_value_factory, nullptr, kNoSourcePosition);
685       AstNodeFactory factory(ast_value_factory, zone);
686       Declaration* declaration =
687           factory.NewVariableDeclaration(kNoSourcePosition);
688       scope->declarations()->Add(declaration);
689       declaration->set_var(var);
690     }
691     var->set_is_used();
692     var->ForceContextAllocation();
693     scope->AsClassScope()->set_should_save_class_variable_index();
694   }
695 
696   if (scope->is_function_scope()) {
697     Variable* function = scope->AsDeclarationScope()->function_var();
698     if (function != nullptr) RestoreDataForVariable(function);
699   }
700   for (Variable* var : *scope->locals()) {
701     if (IsSerializableVariableMode(var->mode())) RestoreDataForVariable(var);
702   }
703 
704   RestoreDataForInnerScopes(scope, ast_value_factory, zone);
705 }
706 
707 template <typename Data>
RestoreDataForVariable(Variable * var)708 void BaseConsumedPreparseData<Data>::RestoreDataForVariable(Variable* var) {
709 #ifdef DEBUG
710   const AstRawString* name = var->raw_name();
711   bool data_one_byte = scope_data_->ReadUint8();
712   DCHECK_IMPLIES(name->is_one_byte(), data_one_byte);
713   DCHECK_EQ(scope_data_->ReadUint32(), static_cast<uint32_t>(name->length()));
714   if (!name->is_one_byte() && data_one_byte) {
715     // It's possible that "name" is a two-byte representation of the string
716     // stored in the data.
717     for (int i = 0; i < 2 * name->length(); i += 2) {
718 #if defined(V8_TARGET_LITTLE_ENDIAN)
719       DCHECK_EQ(scope_data_->ReadUint8(), name->raw_data()[i]);
720       DCHECK_EQ(0, name->raw_data()[i + 1]);
721 #else
722       DCHECK_EQ(scope_data_->ReadUint8(), name->raw_data()[i + 1]);
723       DCHECK_EQ(0, name->raw_data()[i]);
724 #endif  // V8_TARGET_LITTLE_ENDIAN
725     }
726   } else {
727     for (int i = 0; i < name->length(); ++i) {
728       DCHECK_EQ(scope_data_->ReadUint8(), name->raw_data()[i]);
729     }
730   }
731 #endif
732   uint8_t variable_data = scope_data_->ReadQuarter();
733   if (VariableMaybeAssignedField::decode(variable_data)) {
734     var->SetMaybeAssigned();
735   }
736   if (VariableContextAllocatedField::decode(variable_data)) {
737     var->set_is_used();
738     var->ForceContextAllocation();
739   }
740 }
741 
742 template <typename Data>
RestoreDataForInnerScopes(Scope * scope,AstValueFactory * ast_value_factory,Zone * zone)743 void BaseConsumedPreparseData<Data>::RestoreDataForInnerScopes(
744     Scope* scope, AstValueFactory* ast_value_factory, Zone* zone) {
745   for (Scope* inner = scope->inner_scope(); inner != nullptr;
746        inner = inner->sibling()) {
747     RestoreDataForScope(inner, ast_value_factory, zone);
748   }
749 }
750 
751 #ifdef DEBUG
752 template <class Data>
VerifyDataStart()753 bool BaseConsumedPreparseData<Data>::VerifyDataStart() {
754   typename ByteData::ReadingScope reading_scope(this);
755   // The first uint32 contains the size of the skippable function data.
756   int scope_data_start = scope_data_->ReadUint32();
757   scope_data_->SetPosition(scope_data_start);
758   CHECK_EQ(scope_data_->ReadUint32(), ByteData::kMagicValue);
759   // The first data item is scope_data_start. Skip over it.
760   scope_data_->SetPosition(ByteData::kPlaceholderSize);
761   return true;
762 }
763 #endif
764 
GetScopeData()765 PreparseData OnHeapConsumedPreparseData::GetScopeData() { return *data_; }
766 
GetChildData(Zone * zone,int index)767 ProducedPreparseData* OnHeapConsumedPreparseData::GetChildData(Zone* zone,
768                                                                int index) {
769   DisallowGarbageCollection no_gc;
770   Handle<PreparseData> child_data_handle(data_->get_child(index), isolate_);
771   return ProducedPreparseData::For(child_data_handle, zone);
772 }
773 
OnHeapConsumedPreparseData(LocalIsolate * isolate,Handle<PreparseData> data)774 OnHeapConsumedPreparseData::OnHeapConsumedPreparseData(
775     LocalIsolate* isolate, Handle<PreparseData> data)
776     : BaseConsumedPreparseData<PreparseData>(), isolate_(isolate), data_(data) {
777   DCHECK_NOT_NULL(isolate);
778   DCHECK(data->IsPreparseData());
779   DCHECK(VerifyDataStart());
780 }
781 
ZonePreparseData(Zone * zone,base::Vector<uint8_t> * byte_data,int children_length)782 ZonePreparseData::ZonePreparseData(Zone* zone, base::Vector<uint8_t>* byte_data,
783                                    int children_length)
784     : byte_data_(byte_data->begin(), byte_data->end(), zone),
785       children_(children_length, zone) {}
786 
Serialize(Isolate * isolate)787 Handle<PreparseData> ZonePreparseData::Serialize(Isolate* isolate) {
788   int data_size = static_cast<int>(byte_data()->size());
789   int child_data_length = children_length();
790   Handle<PreparseData> result =
791       isolate->factory()->NewPreparseData(data_size, child_data_length);
792   result->copy_in(0, byte_data()->data(), data_size);
793 
794   for (int i = 0; i < child_data_length; i++) {
795     ZonePreparseData* child = get_child(i);
796     DCHECK_NOT_NULL(child);
797     Handle<PreparseData> child_data = child->Serialize(isolate);
798     result->set_child(i, *child_data);
799   }
800   return result;
801 }
802 
Serialize(LocalIsolate * isolate)803 Handle<PreparseData> ZonePreparseData::Serialize(LocalIsolate* isolate) {
804   int data_size = static_cast<int>(byte_data()->size());
805   int child_data_length = children_length();
806   Handle<PreparseData> result =
807       isolate->factory()->NewPreparseData(data_size, child_data_length);
808   result->copy_in(0, byte_data()->data(), data_size);
809 
810   for (int i = 0; i < child_data_length; i++) {
811     ZonePreparseData* child = get_child(i);
812     DCHECK_NOT_NULL(child);
813     Handle<PreparseData> child_data = child->Serialize(isolate);
814     result->set_child(i, *child_data);
815   }
816   return result;
817 }
818 
ZoneConsumedPreparseData(Zone * zone,ZonePreparseData * data)819 ZoneConsumedPreparseData::ZoneConsumedPreparseData(Zone* zone,
820                                                    ZonePreparseData* data)
821     : data_(data), scope_data_wrapper_(data_->byte_data()) {
822   DCHECK(VerifyDataStart());
823 }
824 
GetScopeData()825 ZoneVectorWrapper ZoneConsumedPreparseData::GetScopeData() {
826   return scope_data_wrapper_;
827 }
828 
GetChildData(Zone * zone,int child_index)829 ProducedPreparseData* ZoneConsumedPreparseData::GetChildData(Zone* zone,
830                                                              int child_index) {
831   CHECK_GT(data_->children_length(), child_index);
832   ZonePreparseData* child_data = data_->get_child(child_index);
833   if (child_data == nullptr) return nullptr;
834   return ProducedPreparseData::For(child_data, zone);
835 }
836 
For(Isolate * isolate,Handle<PreparseData> data)837 std::unique_ptr<ConsumedPreparseData> ConsumedPreparseData::For(
838     Isolate* isolate, Handle<PreparseData> data) {
839   return ConsumedPreparseData::For(isolate->main_thread_local_isolate(), data);
840 }
841 
For(LocalIsolate * isolate,Handle<PreparseData> data)842 std::unique_ptr<ConsumedPreparseData> ConsumedPreparseData::For(
843     LocalIsolate* isolate, Handle<PreparseData> data) {
844   DCHECK(!data.is_null());
845   return std::make_unique<OnHeapConsumedPreparseData>(isolate, data);
846 }
847 
For(Zone * zone,ZonePreparseData * data)848 std::unique_ptr<ConsumedPreparseData> ConsumedPreparseData::For(
849     Zone* zone, ZonePreparseData* data) {
850   if (data == nullptr) return {};
851   return std::make_unique<ZoneConsumedPreparseData>(zone, data);
852 }
853 
854 }  // namespace internal
855 }  // namespace v8
856