Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1013)

Side by Side Diff: src/ast-value-factory.cc

Issue 314603004: Parser: Delay internalizing strings and values. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: oops, #include fix Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2014 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 "src/ast-value-factory.h"
29
30 #include "src/api.h"
31 #include "src/objects.h"
32
33 namespace v8 {
34 namespace internal {
35
36 namespace {
37
38 template <typename Char>
39 int vector_hash(Vector<const Char> string) {
40 int hash = 0;
41 for (int i = 0; i < string.length(); i++) {
42 int c = static_cast<int>(string[i]);
43 hash += c;
44 hash += (hash << 10);
45 hash ^= (hash >> 6);
46 }
47 return hash;
48 }
49
50
51 // For using StringToArrayIndex.
52 class OneByteStringStream {
53 public:
54 explicit OneByteStringStream(Vector<const byte> lb) :
55 literal_bytes_(lb), pos_(0) {}
56
57 bool HasMore() { return pos_ < literal_bytes_.length(); }
58 uint16_t GetNext() { return literal_bytes_[pos_++]; }
59
60 private:
61 Vector<const byte> literal_bytes_;
62 int pos_;
63 };
64
65 }
66
67
68 bool AstString::AsArrayIndex(uint32_t* index) const {
69 if (!string_.is_null())
70 return string_->AsArrayIndex(index);
71 if (!is_one_byte_ || literal_bytes_.length() == 0 ||
72 literal_bytes_.length() > String::kMaxArrayIndexSize)
73 return false;
74 OneByteStringStream stream(literal_bytes_);
75 return StringToArrayIndex(&stream, index);
76 }
77
78
79 bool AstString::IsOneByteEqualTo(const char* data) const {
80 int length = strlen(data);
81 if (is_one_byte_ && literal_bytes_.length() == length) {
82 const char* token = reinterpret_cast<const char*>(literal_bytes_.start());
83 return !strncmp(token, data, length);
84 }
85 return false;
86 }
87
88
89 void AstString::Internalize(Isolate* isolate) {
90 if (!string_.is_null()) return;
91 if (literal_bytes_.length() == 0) {
92 string_ = isolate->factory()->empty_string();
93 } else if (is_one_byte_) {
94 string_ = isolate->factory()->InternalizeOneByteString(literal_bytes_);
95 } else {
96 string_ = isolate->factory()->InternalizeTwoByteString(
97 Vector<const uint16_t>::cast(literal_bytes_));
98 }
99 }
100
101
102 bool AstString::Compare(void* a, void* b) {
103 AstString* string1 = reinterpret_cast<AstString*>(a);
104 AstString* string2 = reinterpret_cast<AstString*>(b);
105 if (string1->is_one_byte_ != string2->is_one_byte_) return false;
106 if (string1->hash_ != string2->hash_) return false;
107 int length = string1->literal_bytes_.length();
108 if (string2->literal_bytes_.length() != length) return false;
109 return memcmp(string1->literal_bytes_.start(),
110 string2->literal_bytes_.start(), length) == 0;
111 }
112
113
114 bool AstValue::IsPropertyName() const {
115 if (type_ == STRING) {
116 uint32_t index;
117 return !string_->AsArrayIndex(&index);
118 }
119 return false;
120 }
121
122
123 bool AstValue::BooleanValue() const {
124 switch (type_) {
125 case STRING:
126 ASSERT(string_ != NULL);
127 return !string_->IsEmpty();
128 case NUMBER:
129 return DoubleToBoolean(number_);
130 case SMI:
131 return smi_ != 0;
132 case STRING_ARRAY:
133 UNREACHABLE();
134 break;
135 case BOOLEAN:
136 return bool_;
137 case NULL_TYPE:
138 return false;
139 case THE_HOLE:
140 UNREACHABLE();
141 break;
142 case UNDEFINED:
143 return false;
144 }
145 UNREACHABLE();
146 return false;
147 }
148
149
150 void AstValue::Internalize(Isolate* isolate) {
151 switch (type_) {
152 case STRING:
153 ASSERT(string_ != NULL);
154 // Strings are already internalized.
155 ASSERT(!string_->string().is_null());
156 break;
157 case NUMBER:
158 value_ = isolate->factory()->NewNumber(number_, TENURED);
159 break;
160 case SMI:
161 value_ = handle(Smi::FromInt(smi_), isolate);
162 break;
163 case BOOLEAN:
164 if (bool_) {
165 value_ = isolate->factory()->true_value();
166 } else {
167 value_ = isolate->factory()->false_value();
168 }
169 break;
170 case STRING_ARRAY: {
171 ASSERT(strings_ != NULL);
172 Factory* factory = isolate->factory();
173 int len = strings_->length();
174 Handle<FixedArray> elements = factory->NewFixedArray(len, TENURED);
175 for (int i = 0; i < len; i++) {
176 const AstString* string = (*strings_)[i];
177 Handle<Object> element = string->string();
178 // Strings are already internalized.
179 ASSERT(!element.is_null());
180 elements->set(i, *element);
181 }
182 value_ =
183 factory->NewJSArrayWithElements(elements, FAST_ELEMENTS, TENURED);
184 break;
185 }
186 case NULL_TYPE:
187 value_ = isolate->factory()->null_value();
188 break;
189 case THE_HOLE:
190 value_ = isolate->factory()->the_hole_value();
191 break;
192 case UNDEFINED:
193 value_ = isolate->factory()->undefined_value();
194 break;
195 }
196 }
197
198
199 const AstString* AstValueFactory::GetOneByteString(
200 Vector<const uint8_t> literal) {
201 return GetString(vector_hash(literal), true, literal);
202 }
203
204
205 const AstString* AstValueFactory::GetTwoByteString(
206 Vector<const uint16_t> literal) {
207 return GetString(vector_hash(literal), false,
208 Vector<const byte>::cast(literal));
209 }
210
211
212 const AstString* AstValueFactory::GetString(Handle<String> literal) {
213 DisallowHeapAllocation no_gc;
214 String::FlatContent content = literal->GetFlatContent();
215 if (content.IsAscii()) {
216 return GetOneByteString(content.ToOneByteVector());
217 }
218 ASSERT(content.IsTwoByte());
219 return GetTwoByteString(content.ToUC16Vector());
220 }
221
222
223 void AstValueFactory::Internalize(Isolate* isolate) {
224 if (isolate_) {
225 // Everything is already internalized.
226 return;
227 }
228 // Strings need to be internalized before values, because values refer to
229 // strings.
230 for (HashMap::Entry* p = string_table_.Start(); p != NULL;
231 p = string_table_.Next(p)) {
232 AstString* string = reinterpret_cast<AstString*>(p->key);
233 string->Internalize(isolate);
234 }
235 for (int i = 0; i < values_.length(); ++i) {
236 values_[i]->Internalize(isolate);
237 }
238 isolate_ = isolate;
239 }
240
241
242 const AstValue* AstValueFactory::NewString(const AstString* string) {
243 AstValue* value = new (zone_) AstValue(string);
244 ASSERT(string != NULL);
245 if (isolate_) {
246 value->Internalize(isolate_);
247 }
248 values_.Add(value);
249 return value;
250 }
251
252
253 const AstValue* AstValueFactory::NewNumber(double number) {
254 AstValue* value = new (zone_) AstValue(number);
255 if (isolate_) {
256 value->Internalize(isolate_);
257 }
258 values_.Add(value);
259 return value;
260 }
261
262
263 const AstValue* AstValueFactory::NewSmi(int number) {
264 AstValue* value =
265 new (zone_) AstValue(AstValue::SMI, number);
266 if (isolate_) {
267 value->Internalize(isolate_);
268 }
269 values_.Add(value);
270 return value;
271 }
272
273
274 const AstValue* AstValueFactory::NewBoolean(bool b) {
275 AstValue* value = new (zone_) AstValue(b);
276 if (isolate_) {
277 value->Internalize(isolate_);
278 }
279 values_.Add(value);
280 return value;
281 }
282
283
284 const AstValue* AstValueFactory::NewStringList(
285 ZoneList<const AstString*>* strings) {
286 AstValue* value = new (zone_) AstValue(strings);
287 if (isolate_) {
288 value->Internalize(isolate_);
289 }
290 values_.Add(value);
291 return value;
292 }
293
294
295 const AstValue* AstValueFactory::NewNull() {
296 AstValue* value = new (zone_) AstValue(AstValue::NULL_TYPE);
297 if (isolate_) {
298 value->Internalize(isolate_);
299 }
300 values_.Add(value);
301 return value;
302 }
303
304
305 const AstValue* AstValueFactory::NewUndefined() {
306 AstValue* value = new (zone_) AstValue(AstValue::UNDEFINED);
307 if (isolate_) {
308 value->Internalize(isolate_);
309 }
310 values_.Add(value);
311 return value;
312 }
313
314
315 const AstValue* AstValueFactory::NewTheHole() {
316 AstValue* value = new (zone_) AstValue(AstValue::THE_HOLE);
317 if (isolate_) {
318 value->Internalize(isolate_);
319 }
320 values_.Add(value);
321 return value;
322 }
323
324
325 const AstString* AstValueFactory::GetString(int hash, bool is_one_byte,
326 Vector<const byte> literal_bytes) {
327 // literal_bytes here points to whatever the user passed, and this is OK
328 // because we use vector_compare (which checks the contents) to compare
329 // against the AstStrings which are in the string_table_. We should not return
330 // this AstString.
331 AstString key(is_one_byte, literal_bytes, hash);
332 HashMap::Entry* entry = string_table_.Lookup(&key, hash, true);
333 if (entry->value == NULL) {
334 // Copy literal contents for later comparison.
335 key.literal_bytes_ =
336 Vector<const byte>::cast(literal_chars_.AddBlock(literal_bytes));
337 // This Vector will be valid as long as the Collector is alive (meaning that
338 // the AstString will not be moved).
339 Vector<AstString> new_string = string_table_keys_.AddBlock(1, key);
340 entry->key = &new_string[0];
341 if (isolate_) {
342 new_string[0].Internalize(isolate_);
343 }
344 entry->value = reinterpret_cast<void*>(1);
345 }
346 return reinterpret_cast<AstString*>(entry->key);
347 }
348
349
350 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698