OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "../include/v8stdint.h" | 5 #include "../include/v8stdint.h" |
6 | 6 |
7 #include "preparse-data-format.h" | 7 #include "preparse-data-format.h" |
8 #include "preparse-data.h" | 8 #include "preparse-data.h" |
9 | 9 |
10 #include "checks.h" | 10 #include "checks.h" |
11 #include "globals.h" | 11 #include "globals.h" |
12 #include "hashmap.h" | 12 #include "hashmap.h" |
13 | 13 |
14 namespace v8 { | 14 namespace v8 { |
15 namespace internal { | 15 namespace internal { |
16 | 16 |
17 | 17 |
18 template <typename Char> | |
19 static int vector_hash(Vector<const Char> string) { | |
20 int hash = 0; | |
21 for (int i = 0; i < string.length(); i++) { | |
22 int c = static_cast<int>(string[i]); | |
23 hash += c; | |
24 hash += (hash << 10); | |
25 hash ^= (hash >> 6); | |
26 } | |
27 return hash; | |
28 } | |
29 | |
30 | |
31 static bool vector_compare(void* a, void* b) { | |
32 CompleteParserRecorder::Key* string1 = | |
33 reinterpret_cast<CompleteParserRecorder::Key*>(a); | |
34 CompleteParserRecorder::Key* string2 = | |
35 reinterpret_cast<CompleteParserRecorder::Key*>(b); | |
36 if (string1->is_one_byte != string2->is_one_byte) return false; | |
37 int length = string1->literal_bytes.length(); | |
38 if (string2->literal_bytes.length() != length) return false; | |
39 return memcmp(string1->literal_bytes.start(), | |
40 string2->literal_bytes.start(), length) == 0; | |
41 } | |
42 | |
43 | |
44 CompleteParserRecorder::CompleteParserRecorder() | 18 CompleteParserRecorder::CompleteParserRecorder() |
45 : function_store_(0), | 19 : function_store_(0) { |
46 literal_chars_(0), | |
47 symbol_store_(0), | |
48 symbol_keys_(0), | |
49 string_table_(vector_compare), | |
50 symbol_id_(0) { | |
51 preamble_[PreparseDataConstants::kMagicOffset] = | 20 preamble_[PreparseDataConstants::kMagicOffset] = |
52 PreparseDataConstants::kMagicNumber; | 21 PreparseDataConstants::kMagicNumber; |
53 preamble_[PreparseDataConstants::kVersionOffset] = | 22 preamble_[PreparseDataConstants::kVersionOffset] = |
54 PreparseDataConstants::kCurrentVersion; | 23 PreparseDataConstants::kCurrentVersion; |
55 preamble_[PreparseDataConstants::kHasErrorOffset] = false; | 24 preamble_[PreparseDataConstants::kHasErrorOffset] = false; |
56 preamble_[PreparseDataConstants::kFunctionsSizeOffset] = 0; | 25 preamble_[PreparseDataConstants::kFunctionsSizeOffset] = 0; |
57 preamble_[PreparseDataConstants::kSymbolCountOffset] = 0; | |
58 preamble_[PreparseDataConstants::kSizeOffset] = 0; | 26 preamble_[PreparseDataConstants::kSizeOffset] = 0; |
59 ASSERT_EQ(6, PreparseDataConstants::kHeaderSize); | 27 ASSERT_EQ(5, PreparseDataConstants::kHeaderSize); |
60 #ifdef DEBUG | 28 #ifdef DEBUG |
61 prev_start_ = -1; | 29 prev_start_ = -1; |
62 #endif | 30 #endif |
63 } | 31 } |
64 | 32 |
65 | 33 |
66 void CompleteParserRecorder::LogMessage(int start_pos, | 34 void CompleteParserRecorder::LogMessage(int start_pos, |
67 int end_pos, | 35 int end_pos, |
68 const char* message, | 36 const char* message, |
69 const char* arg_opt, | 37 const char* arg_opt, |
(...skipping 16 matching lines...) Expand all Loading... |
86 | 54 |
87 | 55 |
88 void CompleteParserRecorder::WriteString(Vector<const char> str) { | 56 void CompleteParserRecorder::WriteString(Vector<const char> str) { |
89 function_store_.Add(str.length()); | 57 function_store_.Add(str.length()); |
90 for (int i = 0; i < str.length(); i++) { | 58 for (int i = 0; i < str.length(); i++) { |
91 function_store_.Add(str[i]); | 59 function_store_.Add(str[i]); |
92 } | 60 } |
93 } | 61 } |
94 | 62 |
95 | 63 |
96 void CompleteParserRecorder::LogOneByteSymbol(int start, | |
97 Vector<const uint8_t> literal) { | |
98 int hash = vector_hash(literal); | |
99 LogSymbol(start, hash, true, literal); | |
100 } | |
101 | |
102 | |
103 void CompleteParserRecorder::LogTwoByteSymbol(int start, | |
104 Vector<const uint16_t> literal) { | |
105 int hash = vector_hash(literal); | |
106 LogSymbol(start, hash, false, Vector<const byte>::cast(literal)); | |
107 } | |
108 | |
109 | |
110 void CompleteParserRecorder::LogSymbol(int start, | |
111 int hash, | |
112 bool is_one_byte, | |
113 Vector<const byte> literal_bytes) { | |
114 Key key = { is_one_byte, literal_bytes }; | |
115 HashMap::Entry* entry = string_table_.Lookup(&key, hash, true); | |
116 int id = static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); | |
117 if (id == 0) { | |
118 // Copy literal contents for later comparison. | |
119 key.literal_bytes = | |
120 Vector<const byte>::cast(literal_chars_.AddBlock(literal_bytes)); | |
121 // Put (symbol_id_ + 1) into entry and increment it. | |
122 id = ++symbol_id_; | |
123 entry->value = reinterpret_cast<void*>(id); | |
124 Vector<Key> symbol = symbol_keys_.AddBlock(1, key); | |
125 entry->key = &symbol[0]; | |
126 } | |
127 WriteNumber(id - 1); | |
128 } | |
129 | |
130 | |
131 Vector<unsigned> CompleteParserRecorder::ExtractData() { | 64 Vector<unsigned> CompleteParserRecorder::ExtractData() { |
132 int function_size = function_store_.size(); | 65 int function_size = function_store_.size(); |
133 // Add terminator to symbols, then pad to unsigned size. | 66 int total_size = PreparseDataConstants::kHeaderSize + function_size; |
134 int symbol_size = symbol_store_.size(); | |
135 int padding = sizeof(unsigned) - (symbol_size % sizeof(unsigned)); | |
136 symbol_store_.AddBlock(padding, PreparseDataConstants::kNumberTerminator); | |
137 symbol_size += padding; | |
138 int total_size = PreparseDataConstants::kHeaderSize + function_size | |
139 + (symbol_size / sizeof(unsigned)); | |
140 Vector<unsigned> data = Vector<unsigned>::New(total_size); | 67 Vector<unsigned> data = Vector<unsigned>::New(total_size); |
141 preamble_[PreparseDataConstants::kFunctionsSizeOffset] = function_size; | 68 preamble_[PreparseDataConstants::kFunctionsSizeOffset] = function_size; |
142 preamble_[PreparseDataConstants::kSymbolCountOffset] = symbol_id_; | |
143 OS::MemCopy(data.start(), preamble_, sizeof(preamble_)); | 69 OS::MemCopy(data.start(), preamble_, sizeof(preamble_)); |
144 int symbol_start = PreparseDataConstants::kHeaderSize + function_size; | |
145 if (function_size > 0) { | 70 if (function_size > 0) { |
146 function_store_.WriteTo(data.SubVector(PreparseDataConstants::kHeaderSize, | 71 function_store_.WriteTo(data.SubVector(PreparseDataConstants::kHeaderSize, |
147 symbol_start)); | 72 total_size)); |
148 } | |
149 if (!has_error()) { | |
150 symbol_store_.WriteTo( | |
151 Vector<byte>::cast(data.SubVector(symbol_start, total_size))); | |
152 } | 73 } |
153 return data; | 74 return data; |
154 } | 75 } |
155 | 76 |
156 | 77 |
157 void CompleteParserRecorder::WriteNumber(int number) { | |
158 // Split the number into chunks of 7 bits. Write them one after another (the | |
159 // most significant first). Use the MSB of each byte for signalling that the | |
160 // number continues. See ScriptDataImpl::ReadNumber for the reading side. | |
161 ASSERT(number >= 0); | |
162 | |
163 int mask = (1 << 28) - 1; | |
164 int i = 28; | |
165 // 26 million symbols ought to be enough for anybody. | |
166 ASSERT(number <= mask); | |
167 while (number < mask) { | |
168 mask >>= 7; | |
169 i -= 7; | |
170 } | |
171 while (i > 0) { | |
172 symbol_store_.Add(static_cast<byte>(number >> i) | 0x80u); | |
173 number &= mask; | |
174 mask >>= 7; | |
175 i -= 7; | |
176 } | |
177 ASSERT(number < (1 << 7)); | |
178 symbol_store_.Add(static_cast<byte>(number)); | |
179 } | |
180 | |
181 | |
182 } } // namespace v8::internal. | 78 } } // namespace v8::internal. |
OLD | NEW |