LCOV - code coverage report
Current view: top level - src/parsing - preparse-data.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 192 225 85.3 %
Date: 2019-04-18 Functions: 41 54 75.9 %

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

Generated by: LCOV version 1.10