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

Generated by: LCOV version 1.10