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