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
33namespace v8 {
34namespace internal {
35
36// Generic and general data used by preparse data recorders and readers.
37
38class 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.
66class 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
106class 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
166class 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
181class 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