| 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 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 114 return FeedbackVectorRequirements(0, 0); | 114 return FeedbackVectorRequirements(0, 0); |
| 115 } | 115 } |
| 116 } | 116 } |
| 117 } | 117 } |
| 118 return FeedbackVectorRequirements(0, 1); | 118 return FeedbackVectorRequirements(0, 1); |
| 119 } | 119 } |
| 120 return FeedbackVectorRequirements(0, 0); | 120 return FeedbackVectorRequirements(0, 0); |
| 121 } | 121 } |
| 122 | 122 |
| 123 | 123 |
| 124 static int GetStoreICSlots(Expression* expr) { |
| 125 int ic_slots = 0; |
| 126 if (FLAG_vector_stores) { |
| 127 Property* property = expr->AsProperty(); |
| 128 LhsKind assign_type = Property::GetAssignType(property); |
| 129 if ((assign_type == VARIABLE && |
| 130 expr->AsVariableProxy()->var()->IsUnallocated()) || |
| 131 assign_type == NAMED_PROPERTY || assign_type == KEYED_PROPERTY) { |
| 132 ic_slots++; |
| 133 } |
| 134 } |
| 135 return ic_slots; |
| 136 } |
| 137 |
| 138 |
| 139 static Code::Kind GetStoreICKind(Expression* expr) { |
| 140 LhsKind assign_type = Property::GetAssignType(expr->AsProperty()); |
| 141 return assign_type == KEYED_PROPERTY ? Code::KEYED_STORE_IC : Code::STORE_IC; |
| 142 } |
| 143 |
| 144 |
| 145 FeedbackVectorRequirements ForEachStatement::ComputeFeedbackRequirements( |
| 146 Isolate* isolate, const ICSlotCache* cache) { |
| 147 int ic_slots = GetStoreICSlots(each()); |
| 148 return FeedbackVectorRequirements(0, ic_slots); |
| 149 } |
| 150 |
| 151 |
| 152 Code::Kind ForEachStatement::FeedbackICSlotKind(int index) { |
| 153 return GetStoreICKind(each()); |
| 154 } |
| 155 |
| 156 |
| 124 Assignment::Assignment(Zone* zone, Token::Value op, Expression* target, | 157 Assignment::Assignment(Zone* zone, Token::Value op, Expression* target, |
| 125 Expression* value, int pos) | 158 Expression* value, int pos) |
| 126 : Expression(zone, pos), | 159 : Expression(zone, pos), |
| 127 bit_field_(IsUninitializedField::encode(false) | | 160 bit_field_( |
| 128 KeyTypeField::encode(ELEMENT) | | 161 IsUninitializedField::encode(false) | KeyTypeField::encode(ELEMENT) | |
| 129 StoreModeField::encode(STANDARD_STORE) | | 162 StoreModeField::encode(STANDARD_STORE) | TokenField::encode(op)), |
| 130 TokenField::encode(op)), | |
| 131 target_(target), | 163 target_(target), |
| 132 value_(value), | 164 value_(value), |
| 133 binary_operation_(NULL) {} | 165 binary_operation_(NULL), |
| 166 slot_(FeedbackVectorICSlot::Invalid()) {} |
| 167 |
| 168 |
| 169 FeedbackVectorRequirements Assignment::ComputeFeedbackRequirements( |
| 170 Isolate* isolate, const ICSlotCache* cache) { |
| 171 int ic_slots = GetStoreICSlots(target()); |
| 172 return FeedbackVectorRequirements(0, ic_slots); |
| 173 } |
| 174 |
| 175 |
| 176 Code::Kind Assignment::FeedbackICSlotKind(int index) { |
| 177 return GetStoreICKind(target()); |
| 178 } |
| 179 |
| 180 |
| 181 FeedbackVectorRequirements CountOperation::ComputeFeedbackRequirements( |
| 182 Isolate* isolate, const ICSlotCache* cache) { |
| 183 int ic_slots = GetStoreICSlots(expression()); |
| 184 return FeedbackVectorRequirements(0, ic_slots); |
| 185 } |
| 186 |
| 187 |
| 188 Code::Kind CountOperation::FeedbackICSlotKind(int index) { |
| 189 return GetStoreICKind(expression()); |
| 190 } |
| 134 | 191 |
| 135 | 192 |
| 136 Token::Value Assignment::binary_op() const { | 193 Token::Value Assignment::binary_op() const { |
| 137 switch (op()) { | 194 switch (op()) { |
| 138 case Token::ASSIGN_BIT_OR: return Token::BIT_OR; | 195 case Token::ASSIGN_BIT_OR: return Token::BIT_OR; |
| 139 case Token::ASSIGN_BIT_XOR: return Token::BIT_XOR; | 196 case Token::ASSIGN_BIT_XOR: return Token::BIT_XOR; |
| 140 case Token::ASSIGN_BIT_AND: return Token::BIT_AND; | 197 case Token::ASSIGN_BIT_AND: return Token::BIT_AND; |
| 141 case Token::ASSIGN_SHL: return Token::SHL; | 198 case Token::ASSIGN_SHL: return Token::SHL; |
| 142 case Token::ASSIGN_SAR: return Token::SAR; | 199 case Token::ASSIGN_SAR: return Token::SAR; |
| 143 case Token::ASSIGN_SHR: return Token::SHR; | 200 case Token::ASSIGN_SHR: return Token::SHR; |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 246 void ObjectLiteral::Property::set_emit_store(bool emit_store) { | 303 void ObjectLiteral::Property::set_emit_store(bool emit_store) { |
| 247 emit_store_ = emit_store; | 304 emit_store_ = emit_store; |
| 248 } | 305 } |
| 249 | 306 |
| 250 | 307 |
| 251 bool ObjectLiteral::Property::emit_store() { | 308 bool ObjectLiteral::Property::emit_store() { |
| 252 return emit_store_; | 309 return emit_store_; |
| 253 } | 310 } |
| 254 | 311 |
| 255 | 312 |
| 313 FeedbackVectorRequirements ObjectLiteral::ComputeFeedbackRequirements( |
| 314 Isolate* isolate, const ICSlotCache* cache) { |
| 315 if (!FLAG_vector_stores) return FeedbackVectorRequirements(0, 0); |
| 316 |
| 317 // This logic that computes the number of slots needed for vector store |
| 318 // ics must mirror FullCodeGenerator::VisitObjectLiteral. |
| 319 int ic_slots = 0; |
| 320 for (int i = 0; i < properties()->length(); i++) { |
| 321 ObjectLiteral::Property* property = properties()->at(i); |
| 322 if (property->IsCompileTimeValue()) continue; |
| 323 |
| 324 Expression* value = property->value(); |
| 325 if (property->is_computed_name() && |
| 326 property->kind() != ObjectLiteral::Property::PROTOTYPE) { |
| 327 if (FunctionLiteral::NeedsHomeObject(value)) ic_slots++; |
| 328 } else if (property->emit_store()) { |
| 329 if (property->kind() == ObjectLiteral::Property::MATERIALIZED_LITERAL || |
| 330 property->kind() == ObjectLiteral::Property::COMPUTED) { |
| 331 Literal* key = property->key()->AsLiteral(); |
| 332 if (key->value()->IsInternalizedString()) ic_slots++; |
| 333 if (FunctionLiteral::NeedsHomeObject(value)) ic_slots++; |
| 334 } else if (property->kind() == ObjectLiteral::Property::GETTER || |
| 335 property->kind() == ObjectLiteral::Property::SETTER) { |
| 336 // We might need a slot for the home object. |
| 337 if (FunctionLiteral::NeedsHomeObject(value)) ic_slots++; |
| 338 } |
| 339 } |
| 340 } |
| 341 |
| 342 #ifdef DEBUG |
| 343 // FullCodeGenerator::VisitObjectLiteral verifies that it consumes slot_count_ |
| 344 // slots. |
| 345 slot_count_ = ic_slots; |
| 346 #endif |
| 347 return FeedbackVectorRequirements(0, ic_slots); |
| 348 } |
| 349 |
| 350 |
| 351 FeedbackVectorICSlot ObjectLiteral::SlotForHomeObject(Expression* value, |
| 352 int* slot_index) const { |
| 353 if (FLAG_vector_stores && FunctionLiteral::NeedsHomeObject(value)) { |
| 354 DCHECK(slot_index != NULL && *slot_index >= 0 && *slot_index < slot_count_); |
| 355 FeedbackVectorICSlot slot = GetNthSlot(*slot_index); |
| 356 *slot_index += 1; |
| 357 return slot; |
| 358 } |
| 359 return FeedbackVectorICSlot::Invalid(); |
| 360 } |
| 361 |
| 362 |
| 256 void ObjectLiteral::CalculateEmitStore(Zone* zone) { | 363 void ObjectLiteral::CalculateEmitStore(Zone* zone) { |
| 257 const auto GETTER = ObjectLiteral::Property::GETTER; | 364 const auto GETTER = ObjectLiteral::Property::GETTER; |
| 258 const auto SETTER = ObjectLiteral::Property::SETTER; | 365 const auto SETTER = ObjectLiteral::Property::SETTER; |
| 259 | 366 |
| 260 ZoneAllocationPolicy allocator(zone); | 367 ZoneAllocationPolicy allocator(zone); |
| 261 | 368 |
| 262 ZoneHashMap table(Literal::Match, ZoneHashMap::kDefaultHashMapCapacity, | 369 ZoneHashMap table(Literal::Match, ZoneHashMap::kDefaultHashMapCapacity, |
| 263 allocator); | 370 allocator); |
| 264 for (int i = properties()->length() - 1; i >= 0; i--) { | 371 for (int i = properties()->length() - 1; i >= 0; i--) { |
| 265 ObjectLiteral::Property* property = properties()->at(i); | 372 ObjectLiteral::Property* property = properties()->at(i); |
| (...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 583 // TODO(rossberg): all RecordTypeFeedback functions should disappear | 690 // TODO(rossberg): all RecordTypeFeedback functions should disappear |
| 584 // once we use the common type field in the AST consistently. | 691 // once we use the common type field in the AST consistently. |
| 585 | 692 |
| 586 void Expression::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) { | 693 void Expression::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) { |
| 587 set_to_boolean_types(oracle->ToBooleanTypes(test_id())); | 694 set_to_boolean_types(oracle->ToBooleanTypes(test_id())); |
| 588 } | 695 } |
| 589 | 696 |
| 590 | 697 |
| 591 bool Call::IsUsingCallFeedbackICSlot(Isolate* isolate) const { | 698 bool Call::IsUsingCallFeedbackICSlot(Isolate* isolate) const { |
| 592 CallType call_type = GetCallType(isolate); | 699 CallType call_type = GetCallType(isolate); |
| 593 if (IsUsingCallFeedbackSlot(isolate) || call_type == POSSIBLY_EVAL_CALL) { | 700 if (call_type == POSSIBLY_EVAL_CALL) { |
| 701 return false; |
| 702 } |
| 703 if (call_type == SUPER_CALL && !FLAG_vector_stores) { |
| 594 return false; | 704 return false; |
| 595 } | 705 } |
| 596 return true; | 706 return true; |
| 597 } | 707 } |
| 598 | 708 |
| 599 | 709 |
| 600 bool Call::IsUsingCallFeedbackSlot(Isolate* isolate) const { | 710 bool Call::IsUsingCallFeedbackSlot(Isolate* isolate) const { |
| 601 // SuperConstructorCall uses a CallConstructStub, which wants | 711 // SuperConstructorCall uses a CallConstructStub, which wants |
| 602 // a Slot, not an IC slot. | 712 // a Slot, in addition to any IC slots requested elsewhere. |
| 603 return GetCallType(isolate) == SUPER_CALL; | 713 return GetCallType(isolate) == SUPER_CALL; |
| 604 } | 714 } |
| 605 | 715 |
| 606 | 716 |
| 607 FeedbackVectorRequirements Call::ComputeFeedbackRequirements( | 717 FeedbackVectorRequirements Call::ComputeFeedbackRequirements( |
| 608 Isolate* isolate, const ICSlotCache* cache) { | 718 Isolate* isolate, const ICSlotCache* cache) { |
| 609 int ic_slots = IsUsingCallFeedbackICSlot(isolate) ? 1 : 0; | 719 int ic_slots = IsUsingCallFeedbackICSlot(isolate) ? 1 : 0; |
| 610 int slots = IsUsingCallFeedbackSlot(isolate) ? 1 : 0; | 720 int slots = IsUsingCallFeedbackSlot(isolate) ? 1 : 0; |
| 611 // A Call uses either a slot or an IC slot. | |
| 612 DCHECK((ic_slots & slots) == 0); | |
| 613 return FeedbackVectorRequirements(slots, ic_slots); | 721 return FeedbackVectorRequirements(slots, ic_slots); |
| 614 } | 722 } |
| 615 | 723 |
| 616 | 724 |
| 617 Call::CallType Call::GetCallType(Isolate* isolate) const { | 725 Call::CallType Call::GetCallType(Isolate* isolate) const { |
| 618 VariableProxy* proxy = expression()->AsVariableProxy(); | 726 VariableProxy* proxy = expression()->AsVariableProxy(); |
| 619 if (proxy != NULL) { | 727 if (proxy != NULL) { |
| 620 if (proxy->var()->is_possibly_eval(isolate)) { | 728 if (proxy->var()->is_possibly_eval(isolate)) { |
| 621 return POSSIBLY_EVAL_CALL; | 729 return POSSIBLY_EVAL_CALL; |
| 622 } else if (proxy->var()->IsUnallocated()) { | 730 } else if (proxy->var()->IsUnallocated()) { |
| (...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1011 // static | 1119 // static |
| 1012 bool Literal::Match(void* literal1, void* literal2) { | 1120 bool Literal::Match(void* literal1, void* literal2) { |
| 1013 const AstValue* x = static_cast<Literal*>(literal1)->raw_value(); | 1121 const AstValue* x = static_cast<Literal*>(literal1)->raw_value(); |
| 1014 const AstValue* y = static_cast<Literal*>(literal2)->raw_value(); | 1122 const AstValue* y = static_cast<Literal*>(literal2)->raw_value(); |
| 1015 return (x->IsString() && y->IsString() && x->AsString() == y->AsString()) || | 1123 return (x->IsString() && y->IsString() && x->AsString() == y->AsString()) || |
| 1016 (x->IsNumber() && y->IsNumber() && x->AsNumber() == y->AsNumber()); | 1124 (x->IsNumber() && y->IsNumber() && x->AsNumber() == y->AsNumber()); |
| 1017 } | 1125 } |
| 1018 | 1126 |
| 1019 | 1127 |
| 1020 } } // namespace v8::internal | 1128 } } // namespace v8::internal |
| OLD | NEW |