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 |