OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 "src/ast.h" | 5 #include "src/ast.h" |
6 | 6 |
7 #include <cmath> // For isfinite. | 7 #include <cmath> // For isfinite. |
8 #include "src/builtins.h" | 8 #include "src/builtins.h" |
9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
10 #include "src/contexts.h" | 10 #include "src/contexts.h" |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
213 void ObjectLiteral::Property::set_emit_store(bool emit_store) { | 213 void ObjectLiteral::Property::set_emit_store(bool emit_store) { |
214 emit_store_ = emit_store; | 214 emit_store_ = emit_store; |
215 } | 215 } |
216 | 216 |
217 | 217 |
218 bool ObjectLiteral::Property::emit_store() { | 218 bool ObjectLiteral::Property::emit_store() { |
219 return emit_store_; | 219 return emit_store_; |
220 } | 220 } |
221 | 221 |
222 | 222 |
| 223 enum ObjectLiteralPropertyState { |
| 224 kNoPropertyState = 0, |
| 225 kDataPropertyState = 1, |
| 226 kGetterPropertyState = 2, |
| 227 kSetterPropertyState = 3, |
| 228 kAccessorPropertyState = 4 // Getter and setter fixed. |
| 229 }; |
| 230 |
| 231 |
223 void ObjectLiteral::CalculateEmitStore(Zone* zone) { | 232 void ObjectLiteral::CalculateEmitStore(Zone* zone) { |
224 ZoneAllocationPolicy allocator(zone); | 233 ZoneAllocationPolicy allocator(zone); |
225 | 234 |
| 235 // Map of Literal -> ObjectLiteralPropertyState |
226 ZoneHashMap table(Literal::Match, ZoneHashMap::kDefaultHashMapCapacity, | 236 ZoneHashMap table(Literal::Match, ZoneHashMap::kDefaultHashMapCapacity, |
227 allocator); | 237 allocator); |
| 238 |
| 239 bool has_dunder_proto = false; |
| 240 |
| 241 // Visit properties from last to first. |
228 for (int i = properties()->length() - 1; i >= 0; i--) { | 242 for (int i = properties()->length() - 1; i >= 0; i--) { |
229 ObjectLiteral::Property* property = properties()->at(i); | 243 ObjectLiteral::Property* property = properties()->at(i); |
230 Literal* literal = property->key(); | 244 Literal* literal = property->key(); |
231 if (literal->value()->IsNull()) continue; | 245 ASSERT(!literal->value()->IsNull()); |
232 uint32_t hash = literal->Hash(); | 246 uint32_t hash = literal->Hash(); |
233 // If the key of a computed property is in the table, do not emit | 247 |
234 // a store for the property later. | 248 if (property->IsCompileTimeValue()) |
235 if ((property->kind() == ObjectLiteral::Property::MATERIALIZED_LITERAL || | |
236 property->kind() == ObjectLiteral::Property::COMPUTED) && | |
237 table.Lookup(literal, hash, false, allocator) != NULL) { | |
238 property->set_emit_store(false); | 249 property->set_emit_store(false); |
239 } else { | 250 |
240 // Add key to the table. | 251 ObjectLiteralPropertyState old_state, new_state; |
241 table.Lookup(literal, hash, true, allocator); | 252 |
| 253 ZoneHashMap::Entry *entry = table.Lookup(literal, hash, true, allocator); |
| 254 uintptr_t old_state_bits = reinterpret_cast<uintptr_t>(entry->value); |
| 255 old_state = static_cast<ObjectLiteralPropertyState>(old_state_bits); |
| 256 new_state = old_state; |
| 257 switch (old_state) { |
| 258 case kNoPropertyState: |
| 259 switch (property->kind()) { |
| 260 case ObjectLiteral::Property::CONSTANT: |
| 261 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 262 case ObjectLiteral::Property::COMPUTED: |
| 263 new_state = kDataPropertyState; |
| 264 break; |
| 265 case ObjectLiteral::Property::GETTER: |
| 266 new_state = kGetterPropertyState; |
| 267 break; |
| 268 case ObjectLiteral::Property::SETTER: |
| 269 new_state = kSetterPropertyState; |
| 270 break; |
| 271 case ObjectLiteral::Property::PROTOTYPE: |
| 272 if (has_dunder_proto) property->set_emit_store(false); |
| 273 has_dunder_proto = true; |
| 274 continue; |
| 275 } |
| 276 break; |
| 277 case kDataPropertyState: |
| 278 // This property is overridden by a later data property. |
| 279 switch (property->kind()) { |
| 280 case ObjectLiteral::Property::CONSTANT: |
| 281 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 282 case ObjectLiteral::Property::COMPUTED: |
| 283 case ObjectLiteral::Property::GETTER: |
| 284 case ObjectLiteral::Property::SETTER: |
| 285 property->set_emit_store(false); |
| 286 break; |
| 287 case ObjectLiteral::Property::PROTOTYPE: |
| 288 if (has_dunder_proto) property->set_emit_store(false); |
| 289 has_dunder_proto = true; |
| 290 break; |
| 291 } |
| 292 break; |
| 293 case kGetterPropertyState: |
| 294 switch (property->kind()) { |
| 295 case ObjectLiteral::Property::CONSTANT: |
| 296 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 297 case ObjectLiteral::Property::COMPUTED: |
| 298 // This getter will not have a corresponding setter. |
| 299 new_state = kAccessorPropertyState; |
| 300 property->set_emit_store(false); |
| 301 break; |
| 302 case ObjectLiteral::Property::GETTER: |
| 303 property->set_emit_store(false); |
| 304 break; |
| 305 case ObjectLiteral::Property::SETTER: |
| 306 new_state = kAccessorPropertyState; |
| 307 break; |
| 308 case ObjectLiteral::Property::PROTOTYPE: |
| 309 // This getter will not have a corresponding setter. |
| 310 new_state = kAccessorPropertyState; |
| 311 if (has_dunder_proto) property->set_emit_store(false); |
| 312 has_dunder_proto = true; |
| 313 break; |
| 314 } |
| 315 break; |
| 316 case kSetterPropertyState: |
| 317 switch (property->kind()) { |
| 318 case ObjectLiteral::Property::CONSTANT: |
| 319 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 320 case ObjectLiteral::Property::COMPUTED: |
| 321 // This setter will not have a corresponding getter. |
| 322 new_state = kAccessorPropertyState; |
| 323 property->set_emit_store(false); |
| 324 break; |
| 325 case ObjectLiteral::Property::GETTER: |
| 326 new_state = kAccessorPropertyState; |
| 327 break; |
| 328 case ObjectLiteral::Property::SETTER: |
| 329 property->set_emit_store(false); |
| 330 break; |
| 331 case ObjectLiteral::Property::PROTOTYPE: |
| 332 // This setter will not have a corresponding getter. |
| 333 new_state = kAccessorPropertyState; |
| 334 if (has_dunder_proto) property->set_emit_store(false); |
| 335 has_dunder_proto = true; |
| 336 break; |
| 337 } |
| 338 break; |
| 339 case kAccessorPropertyState: |
| 340 // This property is overridden by a later accessor property. |
| 341 switch (property->kind()) { |
| 342 case ObjectLiteral::Property::CONSTANT: |
| 343 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 344 case ObjectLiteral::Property::COMPUTED: |
| 345 case ObjectLiteral::Property::GETTER: |
| 346 case ObjectLiteral::Property::SETTER: |
| 347 property->set_emit_store(false); |
| 348 break; |
| 349 case ObjectLiteral::Property::PROTOTYPE: |
| 350 if (has_dunder_proto) property->set_emit_store(false); |
| 351 has_dunder_proto = true; |
| 352 break; |
| 353 } |
| 354 break; |
| 355 default: |
| 356 UNREACHABLE(); |
242 } | 357 } |
| 358 entry->value = reinterpret_cast<void*>(new_state); |
243 } | 359 } |
244 } | 360 } |
245 | 361 |
246 | 362 |
247 bool ObjectLiteral::IsBoilerplateProperty(ObjectLiteral::Property* property) { | 363 bool ObjectLiteral::IsBoilerplateProperty(ObjectLiteral::Property* property) { |
248 return property != NULL && | 364 return property != NULL && |
249 property->kind() != ObjectLiteral::Property::PROTOTYPE; | 365 property->kind() != ObjectLiteral::Property::PROTOTYPE; |
250 } | 366 } |
251 | 367 |
252 | 368 |
(...skipping 890 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1143 SNPrintF(buffer, "%d", Smi::cast(*value())->value()); | 1259 SNPrintF(buffer, "%d", Smi::cast(*value())->value()); |
1144 str = arr; | 1260 str = arr; |
1145 } else { | 1261 } else { |
1146 str = DoubleToCString(value()->Number(), buffer); | 1262 str = DoubleToCString(value()->Number(), buffer); |
1147 } | 1263 } |
1148 return isolate_->factory()->NewStringFromAsciiChecked(str); | 1264 return isolate_->factory()->NewStringFromAsciiChecked(str); |
1149 } | 1265 } |
1150 | 1266 |
1151 | 1267 |
1152 } } // namespace v8::internal | 1268 } } // namespace v8::internal |
OLD | NEW |