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