LCOV - code coverage report
Current view: top level - src/parsing - preparse-data.h (source / functions) Hit Total Coverage
Test: app.info Lines: 6 6 100.0 %
Date: 2019-01-20 Functions: 0 2 0.0 %

          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             : #ifndef V8_PARSING_PREPARSE_DATA_H_
       6             : #define V8_PARSING_PREPARSE_DATA_H_
       7             : 
       8             : #include "src/globals.h"
       9             : #include "src/handles.h"
      10             : #include "src/maybe-handles.h"
      11             : #include "src/zone/zone-chunk-list.h"
      12             : #include "src/zone/zone-containers.h"
      13             : 
      14             : namespace v8 {
      15             : namespace internal {
      16             : 
      17             : template <typename T>
      18             : class PodArray;
      19             : 
      20             : class Parser;
      21             : class PreParser;
      22             : class PreparseData;
      23             : class ZonePreparseData;
      24             : 
      25             : /*
      26             : 
      27             :   Skipping inner functions.
      28             : 
      29             :   Consider the following code:
      30             :   (function eager_outer() {
      31             :     function lazy_inner() {
      32             :       let a;
      33             :       function skip_me() { a; }
      34             :     }
      35             : 
      36             :     return lazy_inner;
      37             :   })();
      38             : 
      39             :   ... lazy_inner(); ...
      40             : 
      41             :   When parsing the code the first time, eager_outer is parsed and lazy_inner
      42             :   (and everything inside it) is preparsed. When lazy_inner is called, we don't
      43             :   want to parse or preparse skip_me again. Instead, we want to skip over it,
      44             :   since it has already been preparsed once.
      45             : 
      46             :   In order to be able to do this, we need to store the information needed for
      47             :   allocating the variables in lazy_inner when we preparse it, and then later do
      48             :   scope allocation based on that data.
      49             : 
      50             :   We need the following data for each scope in lazy_inner's scope tree:
      51             :   For each Variable:
      52             :   - is_used
      53             :   - maybe_assigned
      54             :   - has_forced_context_allocation
      55             : 
      56             :   For each Scope:
      57             :   - inner_scope_calls_eval_.
      58             : 
      59             :   ProducedPreparseData implements storing the above mentioned data and
      60             :   ConsumedPreparseData implements restoring it (= setting the context
      61             :   allocation status of the variables in a Scope (and its subscopes) based on the
      62             :   data).
      63             : 
      64             :  */
      65             : 
      66             : struct PreparseByteDataConstants {
      67             : #ifdef DEBUG
      68             :   static constexpr int kMagicValue = 0xC0DE0DE;
      69             : 
      70             :   static constexpr size_t kUint32Size = 5;
      71             :   static constexpr size_t kUint8Size = 2;
      72             :   static constexpr size_t kQuarterMarker = 0;
      73             :   static constexpr size_t kPlaceholderSize = kUint32Size;
      74             : #else
      75             :   static constexpr size_t kUint32Size = 4;
      76             :   static constexpr size_t kUint8Size = 1;
      77             :   static constexpr size_t kPlaceholderSize = 0;
      78             : #endif
      79             : 
      80             :   static const size_t kSkippableFunctionDataSize =
      81             :       4 * kUint32Size + 1 * kUint8Size;
      82             : };
      83             : 
      84             : class PreparseDataBuilder : public ZoneObject,
      85             :                             public PreparseByteDataConstants {
      86             :  public:
      87             :   // Create a PreparseDataBuilder object which will collect data as we
      88             :   // parse.
      89             :   explicit PreparseDataBuilder(Zone* zone, PreparseDataBuilder* parent_builder);
      90             : 
      91             :   PreparseDataBuilder* parent() const { return parent_; }
      92             : 
      93             :   // For gathering the inner function data and splitting it up according to the
      94             :   // laziness boundaries. Each lazy function gets its own
      95             :   // ProducedPreparseData, and so do all lazy functions inside it.
      96             :   class DataGatheringScope {
      97             :    public:
      98             :     explicit DataGatheringScope(PreParser* preparser)
      99     2866312 :         : preparser_(preparser), builder_(nullptr) {}
     100             : 
     101             :     void Start(DeclarationScope* function_scope);
     102             :     void SetSkippableFunction(DeclarationScope* function_scope,
     103             :                               int num_inner_functions);
     104             :     ~DataGatheringScope();
     105             : 
     106             :    private:
     107             :     PreParser* preparser_;
     108             :     PreparseDataBuilder* builder_;
     109             : 
     110             :     DISALLOW_COPY_AND_ASSIGN(DataGatheringScope);
     111             :   };
     112             : 
     113             :   class ByteData : public ZoneObject, public PreparseByteDataConstants {
     114             :    public:
     115     2567271 :     ByteData() : byte_data_(nullptr), free_quarters_in_last_byte_(0) {}
     116             : 
     117             :     ~ByteData() {}
     118             : 
     119             :     void Start(std::vector<uint8_t>* buffer);
     120             :     void Finalize(Zone* zone);
     121             : 
     122             :     Handle<PreparseData> CopyToHeap(Isolate* isolate, int children_length);
     123             :     ZonePreparseData* CopyToZone(Zone* zone, int children_length);
     124             : 
     125             :     void WriteUint32(uint32_t data);
     126             :     void WriteUint8(uint8_t data);
     127             :     void WriteQuarter(uint8_t data);
     128             : 
     129             : #ifdef DEBUG
     130             :     // For overwriting previously written data at position 0.
     131             :     void SaveCurrentSizeAtFirstUint32();
     132             :     int length() const;
     133             : #endif
     134             : 
     135             :    private:
     136             :     union {
     137             :       // Only used during construction (is_finalized_ == false).
     138             :       std::vector<uint8_t>* byte_data_;
     139             :       // Once the data is finalized, it lives in a Zone, this implies
     140             :       // is_finalized_ == true.
     141             :       Vector<uint8_t> zone_byte_data_;
     142             :     };
     143             :     uint8_t free_quarters_in_last_byte_;
     144             : 
     145             : #ifdef DEBUG
     146             :     bool is_finalized_ = false;
     147             : #endif
     148             :   };
     149             : 
     150             :   // Saves the information needed for allocating the Scope's (and its
     151             :   // subscopes') variables.
     152             :   void SaveScopeAllocationData(DeclarationScope* scope, Parser* parser);
     153             : 
     154             :   // In some cases, PreParser cannot produce the same Scope structure as
     155             :   // Parser. If it happens, we're unable to produce the data that would enable
     156             :   // skipping the inner functions of that function.
     157             :   void Bailout() {
     158          57 :     bailed_out_ = true;
     159             :     // We don't need to call Bailout on existing / future children: the only way
     160             :     // to try to retrieve their data is through calling Serialize on the parent,
     161             :     // and if the parent is bailed out, it won't call Serialize on its children.
     162             :   }
     163             : 
     164             :   bool bailed_out() const { return bailed_out_; }
     165             : 
     166             : #ifdef DEBUG
     167             :   bool ThisOrParentBailedOut() const {
     168             :     if (bailed_out_) return true;
     169             :     if (parent_ == nullptr) return false;
     170             :     return parent_->ThisOrParentBailedOut();
     171             :   }
     172             : #endif  // DEBUG
     173             : 
     174             :   bool HasInnerFunctions() const;
     175             :   bool HasData() const;
     176             :   bool HasDataForParent() const;
     177             : 
     178             :   static bool ScopeNeedsData(Scope* scope);
     179             :   static bool ScopeIsSkippableFunctionScope(Scope* scope);
     180             :   void AddSkippableFunction(int start_position, int end_position,
     181             :                             int num_parameters, int num_inner_functions,
     182             :                             LanguageMode language_mode, bool has_data,
     183             :                             bool uses_super_property);
     184             : 
     185             :  private:
     186             :   friend class BuilderProducedPreparseData;
     187             : 
     188             :   Handle<PreparseData> Serialize(Isolate* isolate);
     189             :   ZonePreparseData* Serialize(Zone* zone);
     190             : 
     191             :   void SaveDataForScope(Scope* scope);
     192             :   void SaveDataForVariable(Variable* var);
     193             :   void SaveDataForInnerScopes(Scope* scope);
     194             :   bool SaveDataForSkippableFunction(PreparseDataBuilder* builder);
     195             : 
     196             :   void CopyByteData(Zone* zone);
     197             : 
     198             :   PreparseDataBuilder* parent_;
     199             :   ByteData byte_data_;
     200             :   ZoneChunkList<PreparseDataBuilder*> children_;
     201             : 
     202             :   DeclarationScope* function_scope_;
     203             :   int num_inner_functions_;
     204             :   int num_inner_with_data_;
     205             : 
     206             :   // Whether we've given up producing the data for this function.
     207             :   bool bailed_out_ : 1;
     208             :   bool has_data_ : 1;
     209             : 
     210             :   DISALLOW_COPY_AND_ASSIGN(PreparseDataBuilder);
     211             : };
     212             : 
     213       87237 : class ProducedPreparseData : public ZoneObject {
     214             :  public:
     215             :   // If there is data (if the Scope contains skippable inner functions), move
     216             :   // the data into the heap and return a Handle to it; otherwise return a null
     217             :   // MaybeHandle.
     218             :   virtual Handle<PreparseData> Serialize(Isolate* isolate) = 0;
     219             : 
     220             :   // If there is data (if the Scope contains skippable inner functions), return
     221             :   // an off-heap ZonePreparseData representing the data; otherwise
     222             :   // return nullptr.
     223             :   virtual ZonePreparseData* Serialize(Zone* zone) = 0;
     224             : 
     225             :   // Create a ProducedPreparseData which is a proxy for a previous
     226             :   // produced PreparseData in zone.
     227             :   static ProducedPreparseData* For(PreparseDataBuilder* builder, Zone* zone);
     228             : 
     229             :   // Create a ProducedPreparseData which is a proxy for a previous
     230             :   // produced PreparseData on the heap.
     231             :   static ProducedPreparseData* For(Handle<PreparseData> data, Zone* zone);
     232             : 
     233             :   // Create a ProducedPreparseData which is a proxy for a previous
     234             :   // produced PreparseData in zone.
     235             :   static ProducedPreparseData* For(ZonePreparseData* data, Zone* zone);
     236             : };
     237             : 
     238             : class ConsumedPreparseData {
     239             :  public:
     240             :   // Creates a ConsumedPreparseData representing the data of an on-heap
     241             :   // PreparseData |data|.
     242             :   static std::unique_ptr<ConsumedPreparseData> For(Isolate* isolate,
     243             :                                                    Handle<PreparseData> data);
     244             : 
     245             :   // Creates a ConsumedPreparseData representing the data of an off-heap
     246             :   // ZonePreparseData |data|.
     247             :   static std::unique_ptr<ConsumedPreparseData> For(Zone* zone,
     248             :                                                    ZonePreparseData* data);
     249             : 
     250       37126 :   virtual ~ConsumedPreparseData() = default;
     251             : 
     252             :   virtual ProducedPreparseData* GetDataForSkippableFunction(
     253             :       Zone* zone, int start_position, int* end_position, int* num_parameters,
     254             :       int* num_inner_functions, bool* uses_super_property,
     255             :       LanguageMode* language_mode) = 0;
     256             : 
     257             :   // Restores the information needed for allocating the Scope's (and its
     258             :   // subscopes') variables.
     259             :   virtual void RestoreScopeAllocationData(DeclarationScope* scope) = 0;
     260             : 
     261             :  protected:
     262       37126 :   ConsumedPreparseData() = default;
     263             : 
     264             :  private:
     265             :   DISALLOW_COPY_AND_ASSIGN(ConsumedPreparseData);
     266             : };
     267             : 
     268             : }  // namespace internal
     269             : }  // namespace v8
     270             : 
     271             : #endif  // V8_PARSING_PREPARSE_DATA_H_

Generated by: LCOV version 1.10