| 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 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 91 | 91 |
| 92 | 92 |
| 93 void VariableProxy::BindTo(Variable* var) { | 93 void VariableProxy::BindTo(Variable* var) { |
| 94 DCHECK((is_this() && var->is_this()) || raw_name() == var->raw_name()); | 94 DCHECK((is_this() && var->is_this()) || raw_name() == var->raw_name()); |
| 95 set_var(var); | 95 set_var(var); |
| 96 set_is_resolved(); | 96 set_is_resolved(); |
| 97 var->set_is_used(); | 97 var->set_is_used(); |
| 98 } | 98 } |
| 99 | 99 |
| 100 | 100 |
| 101 void VariableProxy::SetFirstFeedbackICSlot(FeedbackVectorICSlot slot, | 101 void VariableProxy::AssignFeedbackVectorSlots(Isolate* isolate, |
| 102 ICSlotCache* cache) { | 102 FeedbackVectorSpec* spec, |
| 103 variable_feedback_slot_ = slot; | 103 ICSlotCache* cache) { |
| 104 if (var()->IsUnallocated()) { | |
| 105 cache->Put(var(), slot); | |
| 106 } | |
| 107 } | |
| 108 | |
| 109 | |
| 110 FeedbackVectorRequirements VariableProxy::ComputeFeedbackRequirements( | |
| 111 Isolate* isolate, const ICSlotCache* cache) { | |
| 112 if (UsesVariableFeedbackSlot()) { | 104 if (UsesVariableFeedbackSlot()) { |
| 113 // VariableProxies that point to the same Variable within a function can | 105 // VariableProxies that point to the same Variable within a function can |
| 114 // make their loads from the same IC slot. | 106 // make their loads from the same IC slot. |
| 115 if (var()->IsUnallocated()) { | 107 if (var()->IsUnallocated()) { |
| 116 ZoneHashMap::Entry* entry = cache->Get(var()); | 108 ZoneHashMap::Entry* entry = cache->Get(var()); |
| 117 if (entry != NULL) { | 109 if (entry != NULL) { |
| 118 variable_feedback_slot_ = FeedbackVectorICSlot( | 110 variable_feedback_slot_ = FeedbackVectorICSlot( |
| 119 static_cast<int>(reinterpret_cast<intptr_t>(entry->value))); | 111 static_cast<int>(reinterpret_cast<intptr_t>(entry->value))); |
| 120 return FeedbackVectorRequirements(0, 0); | 112 return; |
| 121 } | 113 } |
| 122 } | 114 } |
| 123 return FeedbackVectorRequirements(0, 1); | 115 variable_feedback_slot_ = spec->AddLoadICSlot(); |
| 116 if (var()->IsUnallocated()) { |
| 117 cache->Put(var(), variable_feedback_slot_); |
| 118 } |
| 124 } | 119 } |
| 125 return FeedbackVectorRequirements(0, 0); | |
| 126 } | 120 } |
| 127 | 121 |
| 128 | 122 |
| 129 static int GetStoreICSlots(Expression* expr) { | 123 static void AssignVectorSlots(Expression* expr, FeedbackVectorSpec* spec, |
| 130 int ic_slots = 0; | 124 FeedbackVectorICSlot* out_slot) { |
| 131 if (FLAG_vector_stores) { | 125 if (FLAG_vector_stores) { |
| 132 Property* property = expr->AsProperty(); | 126 Property* property = expr->AsProperty(); |
| 133 LhsKind assign_type = Property::GetAssignType(property); | 127 LhsKind assign_type = Property::GetAssignType(property); |
| 134 if ((assign_type == VARIABLE && | 128 if ((assign_type == VARIABLE && |
| 135 expr->AsVariableProxy()->var()->IsUnallocated()) || | 129 expr->AsVariableProxy()->var()->IsUnallocated()) || |
| 136 assign_type == NAMED_PROPERTY || assign_type == KEYED_PROPERTY) { | 130 assign_type == NAMED_PROPERTY || assign_type == KEYED_PROPERTY) { |
| 137 ic_slots++; | 131 // TODO(ishell): consider using ICSlotCache for variables here. |
| 132 FeedbackVectorSlotKind kind = assign_type == KEYED_PROPERTY |
| 133 ? FeedbackVectorSlotKind::KEYED_STORE_IC |
| 134 : FeedbackVectorSlotKind::STORE_IC; |
| 135 *out_slot = spec->AddSlot(kind); |
| 138 } | 136 } |
| 139 } | 137 } |
| 140 return ic_slots; | |
| 141 } | 138 } |
| 142 | 139 |
| 143 | 140 |
| 144 static FeedbackVectorSlotKind GetStoreICKind(Expression* expr) { | 141 void ForEachStatement::AssignFeedbackVectorSlots(Isolate* isolate, |
| 145 LhsKind assign_type = Property::GetAssignType(expr->AsProperty()); | 142 FeedbackVectorSpec* spec, |
| 146 return assign_type == KEYED_PROPERTY ? FeedbackVectorSlotKind::KEYED_STORE_IC | 143 ICSlotCache* cache) { |
| 147 : FeedbackVectorSlotKind::STORE_IC; | 144 AssignVectorSlots(each(), spec, &each_slot_); |
| 148 } | 145 } |
| 149 | 146 |
| 150 | 147 |
| 151 FeedbackVectorRequirements ForEachStatement::ComputeFeedbackRequirements( | |
| 152 Isolate* isolate, const ICSlotCache* cache) { | |
| 153 int ic_slots = GetStoreICSlots(each()); | |
| 154 return FeedbackVectorRequirements(0, ic_slots); | |
| 155 } | |
| 156 | |
| 157 | |
| 158 FeedbackVectorSlotKind ForEachStatement::FeedbackICSlotKind(int index) { | |
| 159 return GetStoreICKind(each()); | |
| 160 } | |
| 161 | |
| 162 | |
| 163 Assignment::Assignment(Zone* zone, Token::Value op, Expression* target, | 148 Assignment::Assignment(Zone* zone, Token::Value op, Expression* target, |
| 164 Expression* value, int pos) | 149 Expression* value, int pos) |
| 165 : Expression(zone, pos), | 150 : Expression(zone, pos), |
| 166 bit_field_( | 151 bit_field_( |
| 167 IsUninitializedField::encode(false) | KeyTypeField::encode(ELEMENT) | | 152 IsUninitializedField::encode(false) | KeyTypeField::encode(ELEMENT) | |
| 168 StoreModeField::encode(STANDARD_STORE) | TokenField::encode(op)), | 153 StoreModeField::encode(STANDARD_STORE) | TokenField::encode(op)), |
| 169 target_(target), | 154 target_(target), |
| 170 value_(value), | 155 value_(value), |
| 171 binary_operation_(NULL), | 156 binary_operation_(NULL), |
| 172 slot_(FeedbackVectorICSlot::Invalid()) {} | 157 slot_(FeedbackVectorICSlot::Invalid()) {} |
| 173 | 158 |
| 174 | 159 |
| 175 FeedbackVectorRequirements Assignment::ComputeFeedbackRequirements( | 160 void Assignment::AssignFeedbackVectorSlots(Isolate* isolate, |
| 176 Isolate* isolate, const ICSlotCache* cache) { | 161 FeedbackVectorSpec* spec, |
| 177 int ic_slots = GetStoreICSlots(target()); | 162 ICSlotCache* cache) { |
| 178 return FeedbackVectorRequirements(0, ic_slots); | 163 AssignVectorSlots(target(), spec, &slot_); |
| 179 } | 164 } |
| 180 | 165 |
| 181 | 166 |
| 182 FeedbackVectorSlotKind Assignment::FeedbackICSlotKind(int index) { | 167 void CountOperation::AssignFeedbackVectorSlots(Isolate* isolate, |
| 183 return GetStoreICKind(target()); | 168 FeedbackVectorSpec* spec, |
| 169 ICSlotCache* cache) { |
| 170 AssignVectorSlots(expression(), spec, &slot_); |
| 184 } | 171 } |
| 185 | 172 |
| 186 | 173 |
| 187 FeedbackVectorRequirements CountOperation::ComputeFeedbackRequirements( | |
| 188 Isolate* isolate, const ICSlotCache* cache) { | |
| 189 int ic_slots = GetStoreICSlots(expression()); | |
| 190 return FeedbackVectorRequirements(0, ic_slots); | |
| 191 } | |
| 192 | |
| 193 | |
| 194 FeedbackVectorSlotKind CountOperation::FeedbackICSlotKind(int index) { | |
| 195 return GetStoreICKind(expression()); | |
| 196 } | |
| 197 | |
| 198 | |
| 199 Token::Value Assignment::binary_op() const { | 174 Token::Value Assignment::binary_op() const { |
| 200 switch (op()) { | 175 switch (op()) { |
| 201 case Token::ASSIGN_BIT_OR: return Token::BIT_OR; | 176 case Token::ASSIGN_BIT_OR: return Token::BIT_OR; |
| 202 case Token::ASSIGN_BIT_XOR: return Token::BIT_XOR; | 177 case Token::ASSIGN_BIT_XOR: return Token::BIT_XOR; |
| 203 case Token::ASSIGN_BIT_AND: return Token::BIT_AND; | 178 case Token::ASSIGN_BIT_AND: return Token::BIT_AND; |
| 204 case Token::ASSIGN_SHL: return Token::SHL; | 179 case Token::ASSIGN_SHL: return Token::SHL; |
| 205 case Token::ASSIGN_SAR: return Token::SAR; | 180 case Token::ASSIGN_SAR: return Token::SAR; |
| 206 case Token::ASSIGN_SHR: return Token::SHR; | 181 case Token::ASSIGN_SHR: return Token::SHR; |
| 207 case Token::ASSIGN_ADD: return Token::ADD; | 182 case Token::ASSIGN_ADD: return Token::ADD; |
| 208 case Token::ASSIGN_SUB: return Token::SUB; | 183 case Token::ASSIGN_SUB: return Token::SUB; |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 276 } else if (value_->AsMaterializedLiteral() != NULL) { | 251 } else if (value_->AsMaterializedLiteral() != NULL) { |
| 277 kind_ = MATERIALIZED_LITERAL; | 252 kind_ = MATERIALIZED_LITERAL; |
| 278 } else if (value_->IsLiteral()) { | 253 } else if (value_->IsLiteral()) { |
| 279 kind_ = CONSTANT; | 254 kind_ = CONSTANT; |
| 280 } else { | 255 } else { |
| 281 kind_ = COMPUTED; | 256 kind_ = COMPUTED; |
| 282 } | 257 } |
| 283 } | 258 } |
| 284 | 259 |
| 285 | 260 |
| 286 FeedbackVectorRequirements ClassLiteral::ComputeFeedbackRequirements( | 261 void ClassLiteral::AssignFeedbackVectorSlots(Isolate* isolate, |
| 287 Isolate* isolate, const ICSlotCache* cache) { | 262 FeedbackVectorSpec* spec, |
| 288 if (!FLAG_vector_stores) return FeedbackVectorRequirements(0, 0); | 263 ICSlotCache* cache) { |
| 264 if (!FLAG_vector_stores) return; |
| 289 | 265 |
| 290 // 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 |
| 291 // ICs must mirror FullCodeGenerator::VisitClassLiteral. | 267 // ICs must mirror FullCodeGenerator::VisitClassLiteral. |
| 292 int ic_slots = 0; | 268 int ic_slots = 0; |
| 293 if (NeedsProxySlot()) { | 269 if (NeedsProxySlot()) { |
| 294 ic_slots++; | 270 ic_slots++; |
| 295 } | 271 } |
| 296 | 272 |
| 297 for (int i = 0; i < properties()->length(); i++) { | 273 for (int i = 0; i < properties()->length(); i++) { |
| 298 ObjectLiteral::Property* property = properties()->at(i); | 274 ObjectLiteral::Property* property = properties()->at(i); |
| 299 // In case we don't end up using any slots. | 275 // In case we don't end up using any slots. |
| 300 property->set_ic_slot_count(0); | 276 property->set_ic_slot_count(0); |
| 301 | 277 |
| 302 Expression* value = property->value(); | 278 Expression* value = property->value(); |
| 303 if (FunctionLiteral::NeedsHomeObject(value)) { | 279 if (FunctionLiteral::NeedsHomeObject(value)) { |
| 304 property->set_ic_slot_count(1); | 280 property->set_ic_slot_count(1); |
| 305 ic_slots++; | 281 ic_slots++; |
| 306 } | 282 } |
| 307 } | 283 } |
| 308 | 284 |
| 309 return FeedbackVectorRequirements(0, ic_slots); | 285 if (ic_slots > 0) { |
| 286 slot_ = spec->AddStoreICSlots(ic_slots); |
| 287 } |
| 310 } | 288 } |
| 311 | 289 |
| 312 | 290 |
| 313 void ClassLiteral::LayoutFeedbackSlots() { | 291 void ClassLiteral::LayoutFeedbackSlots() { |
| 314 int base_slot = slot_.ToInt(); | 292 int base_slot = slot_.ToInt(); |
| 315 if (NeedsProxySlot()) base_slot++; | 293 if (NeedsProxySlot()) base_slot++; |
| 316 | 294 |
| 317 for (int i = 0; i < properties()->length(); i++) { | 295 for (int i = 0; i < properties()->length(); i++) { |
| 318 ObjectLiteral::Property* property = properties()->at(i); | 296 ObjectLiteral::Property* property = properties()->at(i); |
| 319 base_slot += property->set_base_slot(base_slot); | 297 base_slot += property->set_base_slot(base_slot); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 340 | 318 |
| 341 void ObjectLiteral::LayoutFeedbackSlots() { | 319 void ObjectLiteral::LayoutFeedbackSlots() { |
| 342 int base_slot = slot_.ToInt(); | 320 int base_slot = slot_.ToInt(); |
| 343 for (int i = 0; i < properties()->length(); i++) { | 321 for (int i = 0; i < properties()->length(); i++) { |
| 344 ObjectLiteral::Property* property = properties()->at(i); | 322 ObjectLiteral::Property* property = properties()->at(i); |
| 345 base_slot += property->set_base_slot(base_slot); | 323 base_slot += property->set_base_slot(base_slot); |
| 346 } | 324 } |
| 347 } | 325 } |
| 348 | 326 |
| 349 | 327 |
| 350 FeedbackVectorRequirements ObjectLiteral::ComputeFeedbackRequirements( | 328 void ObjectLiteral::AssignFeedbackVectorSlots(Isolate* isolate, |
| 351 Isolate* isolate, const ICSlotCache* cache) { | 329 FeedbackVectorSpec* spec, |
| 352 if (!FLAG_vector_stores) return FeedbackVectorRequirements(0, 0); | 330 ICSlotCache* cache) { |
| 331 if (!FLAG_vector_stores) return; |
| 353 | 332 |
| 354 // This logic that computes the number of slots needed for vector store | 333 // This logic that computes the number of slots needed for vector store |
| 355 // ics must mirror FullCodeGenerator::VisitObjectLiteral. | 334 // ics must mirror FullCodeGenerator::VisitObjectLiteral. |
| 356 int property_index = 0; | 335 int property_index = 0; |
| 357 for (; property_index < properties()->length(); property_index++) { | 336 for (; property_index < properties()->length(); property_index++) { |
| 358 ObjectLiteral::Property* property = properties()->at(property_index); | 337 ObjectLiteral::Property* property = properties()->at(property_index); |
| 359 // In case we don't end up using any slots. | 338 // In case we don't end up using any slots. |
| 360 property->set_ic_slot_count(0); | 339 property->set_ic_slot_count(0); |
| 361 | 340 |
| 362 if (property->is_computed_name()) break; | 341 if (property->is_computed_name()) break; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 412 } | 391 } |
| 413 } | 392 } |
| 414 | 393 |
| 415 // How many slots did we allocate? | 394 // How many slots did we allocate? |
| 416 int ic_slots = 0; | 395 int ic_slots = 0; |
| 417 for (int i = 0; i < properties()->length(); i++) { | 396 for (int i = 0; i < properties()->length(); i++) { |
| 418 ObjectLiteral::Property* property = properties()->at(i); | 397 ObjectLiteral::Property* property = properties()->at(i); |
| 419 ic_slots += property->ic_slot_count(); | 398 ic_slots += property->ic_slot_count(); |
| 420 } | 399 } |
| 421 | 400 |
| 422 return FeedbackVectorRequirements(0, ic_slots); | 401 if (ic_slots > 0) { |
| 402 slot_ = spec->AddStoreICSlots(ic_slots); |
| 403 } |
| 423 } | 404 } |
| 424 | 405 |
| 425 | 406 |
| 426 void ObjectLiteral::CalculateEmitStore(Zone* zone) { | 407 void ObjectLiteral::CalculateEmitStore(Zone* zone) { |
| 427 const auto GETTER = ObjectLiteral::Property::GETTER; | 408 const auto GETTER = ObjectLiteral::Property::GETTER; |
| 428 const auto SETTER = ObjectLiteral::Property::SETTER; | 409 const auto SETTER = ObjectLiteral::Property::SETTER; |
| 429 | 410 |
| 430 ZoneAllocationPolicy allocator(zone); | 411 ZoneAllocationPolicy allocator(zone); |
| 431 | 412 |
| 432 ZoneHashMap table(Literal::Match, ZoneHashMap::kDefaultHashMapCapacity, | 413 ZoneHashMap table(Literal::Match, ZoneHashMap::kDefaultHashMapCapacity, |
| (...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 775 } | 756 } |
| 776 | 757 |
| 777 | 758 |
| 778 bool Call::IsUsingCallFeedbackSlot(Isolate* isolate) const { | 759 bool Call::IsUsingCallFeedbackSlot(Isolate* isolate) const { |
| 779 // SuperConstructorCall uses a CallConstructStub, which wants | 760 // SuperConstructorCall uses a CallConstructStub, which wants |
| 780 // a Slot, in addition to any IC slots requested elsewhere. | 761 // a Slot, in addition to any IC slots requested elsewhere. |
| 781 return GetCallType(isolate) == SUPER_CALL; | 762 return GetCallType(isolate) == SUPER_CALL; |
| 782 } | 763 } |
| 783 | 764 |
| 784 | 765 |
| 785 FeedbackVectorRequirements Call::ComputeFeedbackRequirements( | 766 void Call::AssignFeedbackVectorSlots(Isolate* isolate, FeedbackVectorSpec* spec, |
| 786 Isolate* isolate, const ICSlotCache* cache) { | 767 ICSlotCache* cache) { |
| 787 int ic_slots = IsUsingCallFeedbackICSlot(isolate) ? 1 : 0; | 768 if (IsUsingCallFeedbackICSlot(isolate)) { |
| 788 int slots = IsUsingCallFeedbackSlot(isolate) ? 1 : 0; | 769 ic_slot_ = spec->AddCallICSlot(); |
| 789 return FeedbackVectorRequirements(slots, ic_slots); | 770 } |
| 771 if (IsUsingCallFeedbackSlot(isolate)) { |
| 772 slot_ = spec->AddStubSlot(); |
| 773 } |
| 790 } | 774 } |
| 791 | 775 |
| 792 | 776 |
| 793 Call::CallType Call::GetCallType(Isolate* isolate) const { | 777 Call::CallType Call::GetCallType(Isolate* isolate) const { |
| 794 VariableProxy* proxy = expression()->AsVariableProxy(); | 778 VariableProxy* proxy = expression()->AsVariableProxy(); |
| 795 if (proxy != NULL) { | 779 if (proxy != NULL) { |
| 796 if (proxy->var()->is_possibly_eval(isolate)) { | 780 if (proxy->var()->is_possibly_eval(isolate)) { |
| 797 return POSSIBLY_EVAL_CALL; | 781 return POSSIBLY_EVAL_CALL; |
| 798 } else if (proxy->var()->IsUnallocatedOrGlobalSlot()) { | 782 } else if (proxy->var()->IsUnallocatedOrGlobalSlot()) { |
| 799 return GLOBAL_CALL; | 783 return GLOBAL_CALL; |
| (...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1188 bool Literal::Match(void* literal1, void* literal2) { | 1172 bool Literal::Match(void* literal1, void* literal2) { |
| 1189 const AstValue* x = static_cast<Literal*>(literal1)->raw_value(); | 1173 const AstValue* x = static_cast<Literal*>(literal1)->raw_value(); |
| 1190 const AstValue* y = static_cast<Literal*>(literal2)->raw_value(); | 1174 const AstValue* y = static_cast<Literal*>(literal2)->raw_value(); |
| 1191 return (x->IsString() && y->IsString() && x->AsString() == y->AsString()) || | 1175 return (x->IsString() && y->IsString() && x->AsString() == y->AsString()) || |
| 1192 (x->IsNumber() && y->IsNumber() && x->AsNumber() == y->AsNumber()); | 1176 (x->IsNumber() && y->IsNumber() && x->AsNumber() == y->AsNumber()); |
| 1193 } | 1177 } |
| 1194 | 1178 |
| 1195 | 1179 |
| 1196 } // namespace internal | 1180 } // namespace internal |
| 1197 } // namespace v8 | 1181 } // namespace v8 |
| OLD | NEW |