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