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-04-17 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 V8_EXPORT_PRIVATE 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     2991851 :         : preparser_(preparser), builder_(nullptr) {}
     110             : 
     111             :     void Start(DeclarationScope* function_scope);
     112             :     void SetSkippableFunction(DeclarationScope* function_scope,
     113             :                               int function_length, int num_inner_functions);
     114     2681360 :     inline ~DataGatheringScope() {
     115     2991856 :       if (builder_ == nullptr) return;
     116     2681366 :       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 V8_EXPORT_PRIVATE ByteData : public ZoneObject,
     129             :                                      public PreparseByteDataConstants {
     130             :    public:
     131             :     ByteData()
     132     2681358 :         : byte_data_(nullptr), index_(0), free_quarters_in_last_byte_(0) {}
     133             : 
     134           5 :     ~ByteData() {}
     135             : 
     136             :     void Start(std::vector<uint8_t>* buffer);
     137             :     void Finalize(Zone* zone);
     138             : 
     139             :     Handle<PreparseData> CopyToHeap(Isolate* isolate, int children_length);
     140             :     inline ZonePreparseData* CopyToZone(Zone* zone, int children_length);
     141             : 
     142             :     void Reserve(size_t bytes);
     143             :     void Add(uint8_t byte);
     144             :     int length() const;
     145             : 
     146             :     void WriteVarint32(uint32_t data);
     147             :     void WriteUint8(uint8_t data);
     148             :     void WriteQuarter(uint8_t data);
     149             : 
     150             : #ifdef DEBUG
     151             :     void WriteUint32(uint32_t data);
     152             :     // For overwriting previously written data at position 0.
     153             :     void SaveCurrentSizeAtFirstUint32();
     154             : #endif
     155             : 
     156             :    private:
     157             :     union {
     158             :       struct {
     159             :         // Only used during construction (is_finalized_ == false).
     160             :         std::vector<uint8_t>* byte_data_;
     161             :         int index_;
     162             :       };
     163             :       // Once the data is finalized, it lives in a Zone, this implies
     164             :       // is_finalized_ == true.
     165             :       Vector<uint8_t> zone_byte_data_;
     166             :     };
     167             :     uint8_t free_quarters_in_last_byte_;
     168             : 
     169             : #ifdef DEBUG
     170             :     bool is_finalized_ = false;
     171             : #endif
     172             :   };
     173             : 
     174             :   // Saves the information needed for allocating the Scope's (and its
     175             :   // subscopes') variables.
     176             :   void SaveScopeAllocationData(DeclarationScope* scope, Parser* parser);
     177             : 
     178             :   // In some cases, PreParser cannot produce the same Scope structure as
     179             :   // Parser. If it happens, we're unable to produce the data that would enable
     180             :   // skipping the inner functions of that function.
     181             :   void Bailout() {
     182          63 :     bailed_out_ = true;
     183             :     // We don't need to call Bailout on existing / future children: the only way
     184             :     // to try to retrieve their data is through calling Serialize on the parent,
     185             :     // and if the parent is bailed out, it won't call Serialize on its children.
     186             :   }
     187             : 
     188             :   bool bailed_out() const { return bailed_out_; }
     189             : 
     190             : #ifdef DEBUG
     191             :   bool ThisOrParentBailedOut() const {
     192             :     if (bailed_out_) return true;
     193             :     if (parent_ == nullptr) return false;
     194             :     return parent_->ThisOrParentBailedOut();
     195             :   }
     196             : #endif  // DEBUG
     197             : 
     198             :   bool HasInnerFunctions() const;
     199             :   bool HasData() const;
     200             :   bool HasDataForParent() const;
     201             : 
     202             :   static bool ScopeNeedsData(Scope* scope);
     203             : 
     204             :  private:
     205             :   friend class BuilderProducedPreparseData;
     206             : 
     207             :   Handle<PreparseData> Serialize(Isolate* isolate);
     208             :   ZonePreparseData* Serialize(Zone* zone);
     209             : 
     210             :   void FinalizeChildren(Zone* zone);
     211             :   void AddChild(PreparseDataBuilder* child);
     212             : 
     213             :   void SaveDataForScope(Scope* scope);
     214             :   void SaveDataForVariable(Variable* var);
     215             :   void SaveDataForInnerScopes(Scope* scope);
     216             :   bool SaveDataForSkippableFunction(PreparseDataBuilder* builder);
     217             : 
     218             :   void CopyByteData(Zone* zone);
     219             : 
     220             :   PreparseDataBuilder* parent_;
     221             :   ByteData byte_data_;
     222             :   union {
     223             :     ScopedPtrList<PreparseDataBuilder> children_buffer_;
     224             :     Vector<PreparseDataBuilder*> children_;
     225             :   };
     226             : 
     227             :   DeclarationScope* function_scope_;
     228             :   int function_length_;
     229             :   int num_inner_functions_;
     230             :   int num_inner_with_data_;
     231             : 
     232             :   // Whether we've given up producing the data for this function.
     233             :   bool bailed_out_ : 1;
     234             :   bool has_data_ : 1;
     235             : 
     236             : #ifdef DEBUG
     237             :   bool finalized_children_ = false;
     238             : #endif
     239             : 
     240             :   DISALLOW_COPY_AND_ASSIGN(PreparseDataBuilder);
     241             : };
     242             : 
     243       87801 : class ProducedPreparseData : public ZoneObject {
     244             :  public:
     245             :   // If there is data (if the Scope contains skippable inner functions), move
     246             :   // the data into the heap and return a Handle to it; otherwise return a null
     247             :   // MaybeHandle.
     248             :   virtual Handle<PreparseData> Serialize(Isolate* isolate) = 0;
     249             : 
     250             :   // If there is data (if the Scope contains skippable inner functions), return
     251             :   // an off-heap ZonePreparseData representing the data; otherwise
     252             :   // return nullptr.
     253             :   virtual ZonePreparseData* Serialize(Zone* zone) = 0;
     254             : 
     255             :   // Create a ProducedPreparseData which is a proxy for a previous
     256             :   // produced PreparseData in zone.
     257             :   static ProducedPreparseData* For(PreparseDataBuilder* builder, Zone* zone);
     258             : 
     259             :   // Create a ProducedPreparseData which is a proxy for a previous
     260             :   // produced PreparseData on the heap.
     261             :   static ProducedPreparseData* For(Handle<PreparseData> data, Zone* zone);
     262             : 
     263             :   // Create a ProducedPreparseData which is a proxy for a previous
     264             :   // produced PreparseData in zone.
     265             :   static ProducedPreparseData* For(ZonePreparseData* data, Zone* zone);
     266             : };
     267             : 
     268             : class ConsumedPreparseData {
     269             :  public:
     270             :   // Creates a ConsumedPreparseData representing the data of an on-heap
     271             :   // PreparseData |data|.
     272             :   V8_EXPORT_PRIVATE static std::unique_ptr<ConsumedPreparseData> For(
     273             :       Isolate* isolate, Handle<PreparseData> data);
     274             : 
     275             :   // Creates a ConsumedPreparseData representing the data of an off-heap
     276             :   // ZonePreparseData |data|.
     277             :   static std::unique_ptr<ConsumedPreparseData> For(Zone* zone,
     278             :                                                    ZonePreparseData* data);
     279             : 
     280       36778 :   virtual ~ConsumedPreparseData() = default;
     281             : 
     282             :   virtual ProducedPreparseData* GetDataForSkippableFunction(
     283             :       Zone* zone, int start_position, int* end_position, int* num_parameters,
     284             :       int* function_length, int* num_inner_functions, bool* uses_super_property,
     285             :       LanguageMode* language_mode) = 0;
     286             : 
     287             :   // Restores the information needed for allocating the Scope's (and its
     288             :   // subscopes') variables.
     289             :   virtual void RestoreScopeAllocationData(DeclarationScope* scope) = 0;
     290             : 
     291             :  protected:
     292       36778 :   ConsumedPreparseData() = default;
     293             : 
     294             :  private:
     295             :   DISALLOW_COPY_AND_ASSIGN(ConsumedPreparseData);
     296             : };
     297             : 
     298             : }  // namespace internal
     299             : }  // namespace v8
     300             : 
     301             : #endif  // V8_PARSING_PREPARSE_DATA_H_

Generated by: LCOV version 1.10