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 37namespace v8 { 38namespace internal { 39 40// ---------------------------------------------------------------------------- 41// FunctionLoggingParserRecorder 42 43FunctionLoggingParserRecorder::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 62void 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 82void 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 92Vector<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 111CompleteParserRecorder::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 121void 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 142Vector<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 168void 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