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 #include "../include/v8stdint.h"
     29 
     30 #include "preparse-data-format.h"
     31 #include "preparse-data.h"
     32 
     33 #include "checks.h"
     34 #include "globals.h"
     35 #include "hashmap.h"
     36 
     37 namespace v8 {
     38 namespace internal {
     39 
     40 // ----------------------------------------------------------------------------
     41 // FunctionLoggingParserRecorder
     42 
     43 FunctionLoggingParserRecorder::FunctionLoggingParserRecorder()
     44     : function_store_(0),
     45       is_recording_(true),
     46       pause_count_(0) {
     47   preamble_[PreparseDataConstants::kMagicOffset] =
     48       PreparseDataConstants::kMagicNumber;
     49   preamble_[PreparseDataConstants::kVersionOffset] =
     50       PreparseDataConstants::kCurrentVersion;
     51   preamble_[PreparseDataConstants::kHasErrorOffset] = false;
     52   preamble_[PreparseDataConstants::kFunctionsSizeOffset] = 0;
     53   preamble_[PreparseDataConstants::kSymbolCountOffset] = 0;
     54   preamble_[PreparseDataConstants::kSizeOffset] = 0;
     55   ASSERT_EQ(6, PreparseDataConstants::kHeaderSize);
     56 #ifdef DEBUG
     57   prev_start_ = -1;
     58 #endif
     59 }
     60 
     61 
     62 void FunctionLoggingParserRecorder::LogMessage(int start_pos,
     63                                                int end_pos,
     64                                                const char* message,
     65                                                const char* arg_opt) {
     66   if (has_error()) return;
     67   preamble_[PreparseDataConstants::kHasErrorOffset] = true;
     68   function_store_.Reset();
     69   STATIC_ASSERT(PreparseDataConstants::kMessageStartPos == 0);
     70   function_store_.Add(start_pos);
     71   STATIC_ASSERT(PreparseDataConstants::kMessageEndPos == 1);
     72   function_store_.Add(end_pos);
     73   STATIC_ASSERT(PreparseDataConstants::kMessageArgCountPos == 2);
     74   function_store_.Add((arg_opt == NULL) ? 0 : 1);
     75   STATIC_ASSERT(PreparseDataConstants::kMessageTextPos == 3);
     76   WriteString(CStrVector(message));
     77   if (arg_opt != NULL) WriteString(CStrVector(arg_opt));
     78   is_recording_ = false;
     79 }
     80 
     81 
     82 void FunctionLoggingParserRecorder::WriteString(Vector<const char> str) {
     83   function_store_.Add(str.length());
     84   for (int i = 0; i < str.length(); i++) {
     85     function_store_.Add(str[i]);
     86   }
     87 }
     88 
     89 // ----------------------------------------------------------------------------
     90 // PartialParserRecorder -  Record both function entries and symbols.
     91 
     92 Vector<unsigned> PartialParserRecorder::ExtractData() {
     93   int function_size = function_store_.size();
     94   int total_size = PreparseDataConstants::kHeaderSize + function_size;
     95   Vector<unsigned> data = Vector<unsigned>::New(total_size);
     96   preamble_[PreparseDataConstants::kFunctionsSizeOffset] = function_size;
     97   preamble_[PreparseDataConstants::kSymbolCountOffset] = 0;
     98   memcpy(data.start(), preamble_, sizeof(preamble_));
     99   int symbol_start = PreparseDataConstants::kHeaderSize + function_size;
    100   if (function_size > 0) {
    101     function_store_.WriteTo(data.SubVector(PreparseDataConstants::kHeaderSize,
    102                                            symbol_start));
    103   }
    104   return data;
    105 }
    106 
    107 
    108 // ----------------------------------------------------------------------------
    109 // CompleteParserRecorder -  Record both function entries and symbols.
    110 
    111 CompleteParserRecorder::CompleteParserRecorder()
    112     : FunctionLoggingParserRecorder(),
    113       literal_chars_(0),
    114       symbol_store_(0),
    115       symbol_keys_(0),
    116       symbol_table_(vector_compare),
    117       symbol_id_(0) {
    118 }
    119 
    120 
    121 void CompleteParserRecorder::LogSymbol(int start,
    122                                        int hash,
    123                                        bool is_ascii,
    124                                        Vector<const byte> literal_bytes) {
    125   Key key = { is_ascii, literal_bytes };
    126   HashMap::Entry* entry = symbol_table_.Lookup(&key, hash, true);
    127   int id = static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
    128   if (id == 0) {
    129     // Copy literal contents for later comparison.
    130     key.literal_bytes =
    131         Vector<const byte>::cast(literal_chars_.AddBlock(literal_bytes));
    132     // Put (symbol_id_ + 1) into entry and increment it.
    133     id = ++symbol_id_;
    134     entry->value = reinterpret_cast<void*>(id);
    135     Vector<Key> symbol = symbol_keys_.AddBlock(1, key);
    136     entry->key = &symbol[0];
    137   }
    138   WriteNumber(id - 1);
    139 }
    140 
    141 
    142 Vector<unsigned> CompleteParserRecorder::ExtractData() {
    143   int function_size = function_store_.size();
    144   // Add terminator to symbols, then pad to unsigned size.
    145   int symbol_size = symbol_store_.size();
    146   int padding = sizeof(unsigned) - (symbol_size % sizeof(unsigned));
    147   symbol_store_.AddBlock(padding, PreparseDataConstants::kNumberTerminator);
    148   symbol_size += padding;
    149   int total_size = PreparseDataConstants::kHeaderSize + function_size
    150       + (symbol_size / sizeof(unsigned));
    151   Vector<unsigned> data = Vector<unsigned>::New(total_size);
    152   preamble_[PreparseDataConstants::kFunctionsSizeOffset] = function_size;
    153   preamble_[PreparseDataConstants::kSymbolCountOffset] = symbol_id_;
    154   memcpy(data.start(), preamble_, sizeof(preamble_));
    155   int symbol_start = PreparseDataConstants::kHeaderSize + function_size;
    156   if (function_size > 0) {
    157     function_store_.WriteTo(data.SubVector(PreparseDataConstants::kHeaderSize,
    158                                            symbol_start));
    159   }
    160   if (!has_error()) {
    161     symbol_store_.WriteTo(
    162         Vector<byte>::cast(data.SubVector(symbol_start, total_size)));
    163   }
    164   return data;
    165 }
    166 
    167 
    168 void CompleteParserRecorder::WriteNumber(int number) {
    169   ASSERT(number >= 0);
    170 
    171   int mask = (1 << 28) - 1;
    172   for (int i = 28; i > 0; i -= 7) {
    173     if (number > mask) {
    174       symbol_store_.Add(static_cast<byte>(number >> i) | 0x80u);
    175       number &= mask;
    176     }
    177     mask >>= 7;
    178   }
    179   symbol_store_.Add(static_cast<byte>(number));
    180 }
    181 
    182 
    183 } }  // namespace v8::internal.
    184