Home | History | Annotate | Download | only in parsing
      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 
     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
    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 
    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 
    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 
    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 
    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.
    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 
    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 
    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 
    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 
    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 
    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 
    282 bool ProducedPreParsedScopeData::ContainsInnerFunctions() const {
    283   return byte_data_->size() > kPlaceholderSize;
    284 }
    285 
    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 
    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 
    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 
    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 
    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 
    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 
    434 ConsumedPreParsedScopeData::ByteData::ReadingScope::ReadingScope(
    435     ConsumedPreParsedScopeData* parent)
    436     : ReadingScope(parent->scope_data_.get(), parent->data_->scope_data()) {}
    437 
    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 
    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 
    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 
    484 size_t ConsumedPreParsedScopeData::ByteData::RemainingBytes() const {
    485   DCHECK_NOT_NULL(data_);
    486   return data_->length() - index_;
    487 }
    488 
    489 ConsumedPreParsedScopeData::ConsumedPreParsedScopeData()
    490     : isolate_(nullptr), scope_data_(new ByteData()), child_index_(0) {}
    491 
    492 ConsumedPreParsedScopeData::~ConsumedPreParsedScopeData() {}
    493 
    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*
    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 
    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 
    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 
    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 
    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