Home | History | Annotate | Download | only in src
      1 // Copyright 2010 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #ifndef V8_PREPARSER_DATA_H_
     29 #define V8_PREPARSER_DATA_H_
     30 
     31 #include "hashmap.h"
     32 
     33 namespace v8 {
     34 namespace internal {
     35 
     36 // Generic and general data used by preparse data recorders and readers.
     37 
     38 class PreparseDataConstants : public AllStatic {
     39  public:
     40   // Layout and constants of the preparse data exchange format.
     41   static const unsigned kMagicNumber = 0xBadDead;
     42   static const unsigned kCurrentVersion = 6;
     43 
     44   static const int kMagicOffset = 0;
     45   static const int kVersionOffset = 1;
     46   static const int kHasErrorOffset = 2;
     47   static const int kFunctionsSizeOffset = 3;
     48   static const int kSymbolCountOffset = 4;
     49   static const int kSizeOffset = 5;
     50   static const int kHeaderSize = 6;
     51 
     52   // If encoding a message, the following positions are fixed.
     53   static const int kMessageStartPos = 0;
     54   static const int kMessageEndPos = 1;
     55   static const int kMessageArgCountPos = 2;
     56   static const int kMessageTextPos = 3;
     57 
     58   static const byte kNumberTerminator = 0x80u;
     59 };
     60 
     61 
     62 // ----------------------------------------------------------------------------
     63 // ParserRecorder - Logging of preparser data.
     64 
     65 // Abstract interface for preparse data recorder.
     66 class ParserRecorder {
     67  public:
     68   ParserRecorder() { }
     69   virtual ~ParserRecorder() { }
     70 
     71   // Logs the scope and some details of a function literal in the source.
     72   virtual void LogFunction(int start,
     73                            int end,
     74                            int literals,
     75                            int properties) = 0;
     76 
     77   // Logs a symbol creation of a literal or identifier.
     78   virtual void LogAsciiSymbol(int start, Vector<const char> literal) { }
     79   virtual void LogUC16Symbol(int start, Vector<const uc16> literal) { }
     80 
     81   // Logs an error message and marks the log as containing an error.
     82   // Further logging will be ignored, and ExtractData will return a vector
     83   // representing the error only.
     84   virtual void LogMessage(int start,
     85                           int end,
     86                           const char* message,
     87                           const char* argument_opt) = 0;
     88 
     89   virtual int function_position() = 0;
     90 
     91   virtual int symbol_position() = 0;
     92 
     93   virtual int symbol_ids() = 0;
     94 
     95   virtual Vector<unsigned> ExtractData() = 0;
     96 
     97   virtual void PauseRecording() = 0;
     98 
     99   virtual void ResumeRecording() = 0;
    100 };
    101 
    102 
    103 // ----------------------------------------------------------------------------
    104 // FunctionLoggingParserRecorder - Record only function entries
    105 
    106 class FunctionLoggingParserRecorder : public ParserRecorder {
    107  public:
    108   FunctionLoggingParserRecorder();
    109   virtual ~FunctionLoggingParserRecorder() {}
    110 
    111   virtual void LogFunction(int start, int end, int literals, int properties) {
    112     function_store_.Add(start);
    113     function_store_.Add(end);
    114     function_store_.Add(literals);
    115     function_store_.Add(properties);
    116   }
    117 
    118   // Logs an error message and marks the log as containing an error.
    119   // Further logging will be ignored, and ExtractData will return a vector
    120   // representing the error only.
    121   virtual void LogMessage(int start,
    122                           int end,
    123                           const char* message,
    124                           const char* argument_opt);
    125 
    126   virtual int function_position() { return function_store_.size(); }
    127 
    128 
    129   virtual Vector<unsigned> ExtractData() = 0;
    130 
    131   virtual void PauseRecording() {
    132     pause_count_++;
    133     is_recording_ = false;
    134   }
    135 
    136   virtual void ResumeRecording() {
    137     ASSERT(pause_count_ > 0);
    138     if (--pause_count_ == 0) is_recording_ = !has_error();
    139   }
    140 
    141  protected:
    142   bool has_error() {
    143     return static_cast<bool>(preamble_[PreparseDataConstants::kHasErrorOffset]);
    144   }
    145 
    146   bool is_recording() {
    147     return is_recording_;
    148   }
    149 
    150   void WriteString(Vector<const char> str);
    151 
    152   Collector<unsigned> function_store_;
    153   unsigned preamble_[PreparseDataConstants::kHeaderSize];
    154   bool is_recording_;
    155   int pause_count_;
    156 
    157 #ifdef DEBUG
    158   int prev_start_;
    159 #endif
    160 };
    161 
    162 
    163 // ----------------------------------------------------------------------------
    164 // PartialParserRecorder - Record only function entries
    165 
    166 class PartialParserRecorder : public FunctionLoggingParserRecorder {
    167  public:
    168   PartialParserRecorder() : FunctionLoggingParserRecorder() { }
    169   virtual void LogAsciiSymbol(int start, Vector<const char> literal) { }
    170   virtual void LogUC16Symbol(int start, Vector<const uc16> literal) { }
    171   virtual ~PartialParserRecorder() { }
    172   virtual Vector<unsigned> ExtractData();
    173   virtual int symbol_position() { return 0; }
    174   virtual int symbol_ids() { return 0; }
    175 };
    176 
    177 
    178 // ----------------------------------------------------------------------------
    179 // CompleteParserRecorder -  Record both function entries and symbols.
    180 
    181 class CompleteParserRecorder: public FunctionLoggingParserRecorder {
    182  public:
    183   CompleteParserRecorder();
    184   virtual ~CompleteParserRecorder() { }
    185 
    186   virtual void LogAsciiSymbol(int start, Vector<const char> literal) {
    187     if (!is_recording_) return;
    188     int hash = vector_hash(literal);
    189     LogSymbol(start, hash, true, Vector<const byte>::cast(literal));
    190   }
    191 
    192   virtual void LogUC16Symbol(int start, Vector<const uc16> literal) {
    193     if (!is_recording_) return;
    194     int hash = vector_hash(literal);
    195     LogSymbol(start, hash, false, Vector<const byte>::cast(literal));
    196   }
    197 
    198   virtual Vector<unsigned> ExtractData();
    199 
    200   virtual int symbol_position() { return symbol_store_.size(); }
    201   virtual int symbol_ids() { return symbol_id_; }
    202 
    203  private:
    204   struct Key {
    205     bool is_ascii;
    206     Vector<const byte> literal_bytes;
    207   };
    208 
    209   virtual void LogSymbol(int start,
    210                          int hash,
    211                          bool is_ascii,
    212                          Vector<const byte> literal);
    213 
    214   template <typename Char>
    215   static int vector_hash(Vector<const Char> string) {
    216     int hash = 0;
    217     for (int i = 0; i < string.length(); i++) {
    218       int c = static_cast<int>(string[i]);
    219       hash += c;
    220       hash += (hash << 10);
    221       hash ^= (hash >> 6);
    222     }
    223     return hash;
    224   }
    225 
    226   static bool vector_compare(void* a, void* b) {
    227     Key* string1 = reinterpret_cast<Key*>(a);
    228     Key* string2 = reinterpret_cast<Key*>(b);
    229     if (string1->is_ascii != string2->is_ascii) return false;
    230     int length = string1->literal_bytes.length();
    231     if (string2->literal_bytes.length() != length) return false;
    232     return memcmp(string1->literal_bytes.start(),
    233                   string2->literal_bytes.start(), length) == 0;
    234   }
    235 
    236   // Write a non-negative number to the symbol store.
    237   void WriteNumber(int number);
    238 
    239   Collector<byte> literal_chars_;
    240   Collector<byte> symbol_store_;
    241   Collector<Key> symbol_keys_;
    242   HashMap symbol_table_;
    243   int symbol_id_;
    244 };
    245 
    246 
    247 } }  // namespace v8::internal.
    248 
    249 #endif  // V8_PREPARSER_DATA_H_
    250