| 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 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 220 DCHECK_NOT_NULL(expr->AsFunctionLiteral()->scope()); | 220 DCHECK_NOT_NULL(expr->AsFunctionLiteral()->scope()); |
| 221 return expr->AsFunctionLiteral()->scope()->NeedsHomeObject(); | 221 return expr->AsFunctionLiteral()->scope()->NeedsHomeObject(); |
| 222 } | 222 } |
| 223 | 223 |
| 224 | 224 |
| 225 ObjectLiteralProperty::ObjectLiteralProperty(Expression* key, Expression* value, | 225 ObjectLiteralProperty::ObjectLiteralProperty(Expression* key, Expression* value, |
| 226 Kind kind, bool is_static, | 226 Kind kind, bool is_static, |
| 227 bool is_computed_name) | 227 bool is_computed_name) |
| 228 : key_(key), | 228 : key_(key), |
| 229 value_(value), | 229 value_(value), |
| 230 ic_slot_or_count_(FeedbackVectorICSlot::Invalid().ToInt()), | 230 slot_(FeedbackVectorICSlot::Invalid()), |
| 231 kind_(kind), | 231 kind_(kind), |
| 232 emit_store_(true), | 232 emit_store_(true), |
| 233 is_static_(is_static), | 233 is_static_(is_static), |
| 234 is_computed_name_(is_computed_name) {} | 234 is_computed_name_(is_computed_name) {} |
| 235 | 235 |
| 236 | 236 |
| 237 ObjectLiteralProperty::ObjectLiteralProperty(AstValueFactory* ast_value_factory, | 237 ObjectLiteralProperty::ObjectLiteralProperty(AstValueFactory* ast_value_factory, |
| 238 Expression* key, Expression* value, | 238 Expression* key, Expression* value, |
| 239 bool is_static, | 239 bool is_static, |
| 240 bool is_computed_name) | 240 bool is_computed_name) |
| 241 : key_(key), | 241 : key_(key), |
| 242 value_(value), | 242 value_(value), |
| 243 ic_slot_or_count_(FeedbackVectorICSlot::Invalid().ToInt()), | 243 slot_(FeedbackVectorICSlot::Invalid()), |
| 244 emit_store_(true), | 244 emit_store_(true), |
| 245 is_static_(is_static), | 245 is_static_(is_static), |
| 246 is_computed_name_(is_computed_name) { | 246 is_computed_name_(is_computed_name) { |
| 247 if (!is_computed_name && | 247 if (!is_computed_name && |
| 248 key->AsLiteral()->raw_value()->EqualsString( | 248 key->AsLiteral()->raw_value()->EqualsString( |
| 249 ast_value_factory->proto_string())) { | 249 ast_value_factory->proto_string())) { |
| 250 kind_ = PROTOTYPE; | 250 kind_ = PROTOTYPE; |
| 251 } else if (value_->AsMaterializedLiteral() != NULL) { | 251 } else if (value_->AsMaterializedLiteral() != NULL) { |
| 252 kind_ = MATERIALIZED_LITERAL; | 252 kind_ = MATERIALIZED_LITERAL; |
| 253 } else if (value_->IsLiteral()) { | 253 } else if (value_->IsLiteral()) { |
| 254 kind_ = CONSTANT; | 254 kind_ = CONSTANT; |
| 255 } else { | 255 } else { |
| 256 kind_ = COMPUTED; | 256 kind_ = COMPUTED; |
| 257 } | 257 } |
| 258 } | 258 } |
| 259 | 259 |
| 260 | 260 |
| 261 void ClassLiteral::AssignFeedbackVectorSlots(Isolate* isolate, | 261 void ClassLiteral::AssignFeedbackVectorSlots(Isolate* isolate, |
| 262 FeedbackVectorSpec* spec, | 262 FeedbackVectorSpec* spec, |
| 263 ICSlotCache* cache) { | 263 ICSlotCache* cache) { |
| 264 if (!FLAG_vector_stores) return; | 264 if (!FLAG_vector_stores) return; |
| 265 | 265 |
| 266 // This logic that computes the number of slots needed for vector store | 266 // This logic that computes the number of slots needed for vector store |
| 267 // ICs must mirror FullCodeGenerator::VisitClassLiteral. | 267 // ICs must mirror FullCodeGenerator::VisitClassLiteral. |
| 268 int ic_slots = 0; | |
| 269 if (NeedsProxySlot()) { | 268 if (NeedsProxySlot()) { |
| 270 ic_slots++; | 269 slot_ = spec->AddStoreICSlot(); |
| 271 } | 270 } |
| 272 | 271 |
| 273 for (int i = 0; i < properties()->length(); i++) { | 272 for (int i = 0; i < properties()->length(); i++) { |
| 274 ObjectLiteral::Property* property = properties()->at(i); | 273 ObjectLiteral::Property* property = properties()->at(i); |
| 275 // In case we don't end up using any slots. | |
| 276 property->set_ic_slot_count(0); | |
| 277 | |
| 278 Expression* value = property->value(); | 274 Expression* value = property->value(); |
| 279 if (FunctionLiteral::NeedsHomeObject(value)) { | 275 if (FunctionLiteral::NeedsHomeObject(value)) { |
| 280 property->set_ic_slot_count(1); | 276 property->set_slot(spec->AddStoreICSlot()); |
| 281 ic_slots++; | |
| 282 } | 277 } |
| 283 } | 278 } |
| 284 | |
| 285 if (ic_slots > 0) { | |
| 286 slot_ = spec->AddStoreICSlots(ic_slots); | |
| 287 } | |
| 288 } | 279 } |
| 289 | 280 |
| 290 | 281 |
| 291 void ClassLiteral::LayoutFeedbackSlots() { | |
| 292 int base_slot = slot_.ToInt(); | |
| 293 if (NeedsProxySlot()) base_slot++; | |
| 294 | |
| 295 for (int i = 0; i < properties()->length(); i++) { | |
| 296 ObjectLiteral::Property* property = properties()->at(i); | |
| 297 base_slot += property->set_base_slot(base_slot); | |
| 298 } | |
| 299 } | |
| 300 | |
| 301 | |
| 302 bool ObjectLiteral::Property::IsCompileTimeValue() { | 282 bool ObjectLiteral::Property::IsCompileTimeValue() { |
| 303 return kind_ == CONSTANT || | 283 return kind_ == CONSTANT || |
| 304 (kind_ == MATERIALIZED_LITERAL && | 284 (kind_ == MATERIALIZED_LITERAL && |
| 305 CompileTimeValue::IsCompileTimeValue(value_)); | 285 CompileTimeValue::IsCompileTimeValue(value_)); |
| 306 } | 286 } |
| 307 | 287 |
| 308 | 288 |
| 309 void ObjectLiteral::Property::set_emit_store(bool emit_store) { | 289 void ObjectLiteral::Property::set_emit_store(bool emit_store) { |
| 310 emit_store_ = emit_store; | 290 emit_store_ = emit_store; |
| 311 } | 291 } |
| 312 | 292 |
| 313 | 293 |
| 314 bool ObjectLiteral::Property::emit_store() { | 294 bool ObjectLiteral::Property::emit_store() { |
| 315 return emit_store_; | 295 return emit_store_; |
| 316 } | 296 } |
| 317 | 297 |
| 318 | 298 |
| 319 void ObjectLiteral::LayoutFeedbackSlots() { | |
| 320 int base_slot = slot_.ToInt(); | |
| 321 for (int i = 0; i < properties()->length(); i++) { | |
| 322 ObjectLiteral::Property* property = properties()->at(i); | |
| 323 base_slot += property->set_base_slot(base_slot); | |
| 324 } | |
| 325 } | |
| 326 | |
| 327 | |
| 328 void ObjectLiteral::AssignFeedbackVectorSlots(Isolate* isolate, | 299 void ObjectLiteral::AssignFeedbackVectorSlots(Isolate* isolate, |
| 329 FeedbackVectorSpec* spec, | 300 FeedbackVectorSpec* spec, |
| 330 ICSlotCache* cache) { | 301 ICSlotCache* cache) { |
| 331 if (!FLAG_vector_stores) return; | 302 if (!FLAG_vector_stores) return; |
| 332 | 303 |
| 333 // This logic that computes the number of slots needed for vector store | 304 // This logic that computes the number of slots needed for vector store |
| 334 // ics must mirror FullCodeGenerator::VisitObjectLiteral. | 305 // ics must mirror FullCodeGenerator::VisitObjectLiteral. |
| 335 int property_index = 0; | 306 int property_index = 0; |
| 336 for (; property_index < properties()->length(); property_index++) { | 307 for (; property_index < properties()->length(); property_index++) { |
| 337 ObjectLiteral::Property* property = properties()->at(property_index); | 308 ObjectLiteral::Property* property = properties()->at(property_index); |
| 338 // In case we don't end up using any slots. | |
| 339 property->set_ic_slot_count(0); | |
| 340 | |
| 341 if (property->is_computed_name()) break; | 309 if (property->is_computed_name()) break; |
| 342 if (property->IsCompileTimeValue()) continue; | 310 if (property->IsCompileTimeValue()) continue; |
| 343 | 311 |
| 344 Literal* key = property->key()->AsLiteral(); | 312 Literal* key = property->key()->AsLiteral(); |
| 345 Expression* value = property->value(); | 313 Expression* value = property->value(); |
| 346 switch (property->kind()) { | 314 switch (property->kind()) { |
| 347 case ObjectLiteral::Property::CONSTANT: | 315 case ObjectLiteral::Property::CONSTANT: |
| 348 UNREACHABLE(); | 316 UNREACHABLE(); |
| 349 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 317 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 350 // Fall through. | 318 // Fall through. |
| 351 case ObjectLiteral::Property::COMPUTED: | 319 case ObjectLiteral::Property::COMPUTED: |
| 352 // It is safe to use [[Put]] here because the boilerplate already | 320 // It is safe to use [[Put]] here because the boilerplate already |
| 353 // contains computed properties with an uninitialized value. | 321 // contains computed properties with an uninitialized value. |
| 354 if (key->value()->IsInternalizedString()) { | 322 if (key->value()->IsInternalizedString()) { |
| 355 if (property->emit_store()) { | 323 if (property->emit_store()) { |
| 356 int slot_count = 1; | 324 property->set_slot(spec->AddStoreICSlot()); |
| 357 if (FunctionLiteral::NeedsHomeObject(value)) { | 325 if (FunctionLiteral::NeedsHomeObject(value)) { |
| 358 slot_count++; | 326 spec->AddStoreICSlot(); |
| 359 } | 327 } |
| 360 property->set_ic_slot_count(slot_count); | |
| 361 } | 328 } |
| 362 break; | 329 break; |
| 363 } | 330 } |
| 364 if (property->emit_store() && FunctionLiteral::NeedsHomeObject(value)) { | 331 if (property->emit_store() && FunctionLiteral::NeedsHomeObject(value)) { |
| 365 property->set_ic_slot_count(1); | 332 property->set_slot(spec->AddStoreICSlot()); |
| 366 } | 333 } |
| 367 break; | 334 break; |
| 368 case ObjectLiteral::Property::PROTOTYPE: | 335 case ObjectLiteral::Property::PROTOTYPE: |
| 369 break; | 336 break; |
| 370 case ObjectLiteral::Property::GETTER: | 337 case ObjectLiteral::Property::GETTER: |
| 371 if (property->emit_store() && FunctionLiteral::NeedsHomeObject(value)) { | 338 if (property->emit_store() && FunctionLiteral::NeedsHomeObject(value)) { |
| 372 property->set_ic_slot_count(1); | 339 property->set_slot(spec->AddStoreICSlot()); |
| 373 } | 340 } |
| 374 break; | 341 break; |
| 375 case ObjectLiteral::Property::SETTER: | 342 case ObjectLiteral::Property::SETTER: |
| 376 if (property->emit_store() && FunctionLiteral::NeedsHomeObject(value)) { | 343 if (property->emit_store() && FunctionLiteral::NeedsHomeObject(value)) { |
| 377 property->set_ic_slot_count(1); | 344 property->set_slot(spec->AddStoreICSlot()); |
| 378 } | 345 } |
| 379 break; | 346 break; |
| 380 } | 347 } |
| 381 } | 348 } |
| 382 | 349 |
| 383 for (; property_index < properties()->length(); property_index++) { | 350 for (; property_index < properties()->length(); property_index++) { |
| 384 ObjectLiteral::Property* property = properties()->at(property_index); | 351 ObjectLiteral::Property* property = properties()->at(property_index); |
| 385 | 352 |
| 386 Expression* value = property->value(); | 353 Expression* value = property->value(); |
| 387 if (property->kind() != ObjectLiteral::Property::PROTOTYPE) { | 354 if (property->kind() != ObjectLiteral::Property::PROTOTYPE) { |
| 388 if (FunctionLiteral::NeedsHomeObject(value)) { | 355 if (FunctionLiteral::NeedsHomeObject(value)) { |
| 389 property->set_ic_slot_count(1); | 356 property->set_slot(spec->AddStoreICSlot()); |
| 390 } | 357 } |
| 391 } | 358 } |
| 392 } | 359 } |
| 393 | |
| 394 // How many slots did we allocate? | |
| 395 int ic_slots = 0; | |
| 396 for (int i = 0; i < properties()->length(); i++) { | |
| 397 ObjectLiteral::Property* property = properties()->at(i); | |
| 398 ic_slots += property->ic_slot_count(); | |
| 399 } | |
| 400 | |
| 401 if (ic_slots > 0) { | |
| 402 slot_ = spec->AddStoreICSlots(ic_slots); | |
| 403 } | |
| 404 } | 360 } |
| 405 | 361 |
| 406 | 362 |
| 407 void ObjectLiteral::CalculateEmitStore(Zone* zone) { | 363 void ObjectLiteral::CalculateEmitStore(Zone* zone) { |
| 408 const auto GETTER = ObjectLiteral::Property::GETTER; | 364 const auto GETTER = ObjectLiteral::Property::GETTER; |
| 409 const auto SETTER = ObjectLiteral::Property::SETTER; | 365 const auto SETTER = ObjectLiteral::Property::SETTER; |
| 410 | 366 |
| 411 ZoneAllocationPolicy allocator(zone); | 367 ZoneAllocationPolicy allocator(zone); |
| 412 | 368 |
| 413 ZoneHashMap table(Literal::Match, ZoneHashMap::kDefaultHashMapCapacity, | 369 ZoneHashMap table(Literal::Match, ZoneHashMap::kDefaultHashMapCapacity, |
| (...skipping 758 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1172 bool Literal::Match(void* literal1, void* literal2) { | 1128 bool Literal::Match(void* literal1, void* literal2) { |
| 1173 const AstValue* x = static_cast<Literal*>(literal1)->raw_value(); | 1129 const AstValue* x = static_cast<Literal*>(literal1)->raw_value(); |
| 1174 const AstValue* y = static_cast<Literal*>(literal2)->raw_value(); | 1130 const AstValue* y = static_cast<Literal*>(literal2)->raw_value(); |
| 1175 return (x->IsString() && y->IsString() && x->AsString() == y->AsString()) || | 1131 return (x->IsString() && y->IsString() && x->AsString() == y->AsString()) || |
| 1176 (x->IsNumber() && y->IsNumber() && x->AsNumber() == y->AsNumber()); | 1132 (x->IsNumber() && y->IsNumber() && x->AsNumber() == y->AsNumber()); |
| 1177 } | 1133 } |
| 1178 | 1134 |
| 1179 | 1135 |
| 1180 } // namespace internal | 1136 } // namespace internal |
| 1181 } // namespace v8 | 1137 } // namespace v8 |
| OLD | NEW |