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 // ----------------------------------------------------------------------------
     91 // PartialParserRecorder -  Record both function entries and symbols.
     92 
     93 Vector<unsigned> PartialParserRecorder::ExtractData() {
     94   int function_size = function_store_.size();
     95   int total_size = PreparseDataConstants::kHeaderSize + function_size;
     96   Vector<unsigned> data = Vector<unsigned>::New(total_size);
     97   preamble_[PreparseDataConstants::kFunctionsSizeOffset] = function_size;
     98   preamble_[PreparseDataConstants::kSymbolCountOffset] = 0;
     99   OS::MemCopy(data.start(), preamble_, sizeof(preamble_));
    100   int symbol_start = PreparseDataConstants::kHeaderSize + function_size;
    101   if (function_size > 0) {
    102     function_store_.WriteTo(data.SubVector(PreparseDataConstants::kHeaderSize,
    103                                            symbol_start));
    104   }
    105   return data;
    106 }
    107 
    108 
    109 // ----------------------------------------------------------------------------
    110 // CompleteParserRecorder -  Record both function entries and symbols.
    111 
    112 CompleteParserRecorder::CompleteParserRecorder()
    113     : FunctionLoggingParserRecorder(),
    114       literal_chars_(0),
    115       symbol_store_(0),
    116       symbol_keys_(0),
    117       string_table_(vector_compare),
    118       symbol_id_(0) {
    119 }
    120 
    121 
    122 void CompleteParserRecorder::LogSymbol(int start,
    123                                        int hash,
    124                                        bool is_ascii,
    125                                        Vector<const byte> literal_bytes) {
    126   Key key = { is_ascii, literal_bytes };
    127   HashMap::Entry* entry = string_table_.Lookup(&key, hash, true);
    128   int id = static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
    129   if (id == 0) {
    130     // Copy literal contents for later comparison.
    131     key.literal_bytes =
    132         Vector<const byte>::cast(literal_chars_.AddBlock(literal_bytes));
    133     // Put (symbol_id_ + 1) into entry and increment it.
    134     id = ++symbol_id_;
    135     entry->value = reinterpret_cast<void*>(id);
    136     Vector<Key> symbol = symbol_keys_.AddBlock(1, key);
    137     entry->key = &symbol[0];
    138   }
    139   WriteNumber(id - 1);
    140 }
    141 
    142 
    143 Vector<unsigned> CompleteParserRecorder::ExtractData() {
    144   int function_size = function_store_.size();
    145   // Add terminator to symbols, then pad to unsigned size.
    146   int symbol_size = symbol_store_.size();
    147   int padding = sizeof(unsigned) - (symbol_size % sizeof(unsigned));
    148   symbol_store_.AddBlock(padding, PreparseDataConstants::kNumberTerminator);
    149   symbol_size += padding;
    150   int total_size = PreparseDataConstants::kHeaderSize + function_size
    151       + (symbol_size / sizeof(unsigned));
    152   Vector<unsigned> data = Vector<unsigned>::New(total_size);
    153   preamble_[PreparseDataConstants::kFunctionsSizeOffset] = function_size;
    154   preamble_[PreparseDataConstants::kSymbolCountOffset] = symbol_id_;
    155   OS::MemCopy(data.start(), preamble_, sizeof(preamble_));
    156   int symbol_start = PreparseDataConstants::kHeaderSize + function_size;
    157   if (function_size > 0) {
    158     function_store_.WriteTo(data.SubVector(PreparseDataConstants::kHeaderSize,
    159                                            symbol_start));
    160   }
    161   if (!has_error()) {
    162     symbol_store_.WriteTo(
    163         Vector<byte>::cast(data.SubVector(symbol_start, total_size)));
    164   }
    165   return data;
    166 }
    167 
    168 
    169 void CompleteParserRecorder::WriteNumber(int number) {
    170   ASSERT(number >= 0);
    171 
    172   int mask = (1 << 28) - 1;
    173   for (int i = 28; i > 0; i -= 7) {
    174     if (number > mask) {
    175       symbol_store_.Add(static_cast<byte>(number >> i) | 0x80u);
    176       number &= mask;
    177     }
    178     mask >>= 7;
    179   }
    180   symbol_store_.Add(static_cast<byte>(number));
    181 }
    182 
    183 
    184 } }  // namespace v8::internal.
    185