Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(314)

Side by Side Diff: runtime/vm/flow_graph_optimizer.cc

Issue 10541135: Some cleanups, started implementing checked instance calls, better equality operation. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/flow_graph_optimizer.h" 5 #include "vm/flow_graph_optimizer.h"
6 6
7 #include "vm/flow_graph_builder.h" 7 #include "vm/flow_graph_builder.h"
8 #include "vm/il_printer.h" 8 #include "vm/il_printer.h"
9 #include "vm/object_store.h" 9 #include "vm/object_store.h"
10 10
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 } 151 }
152 152
153 153
154 static bool HasTwoDouble(const ICData& ic_data) { 154 static bool HasTwoDouble(const ICData& ic_data) {
155 const Class& double_class = 155 const Class& double_class =
156 Class::Handle(Isolate::Current()->object_store()->double_class()); 156 Class::Handle(Isolate::Current()->object_store()->double_class());
157 return ICDataHasTwoReceiverClasses(ic_data, double_class, double_class); 157 return ICDataHasTwoReceiverClasses(ic_data, double_class, double_class);
158 } 158 }
159 159
160 160
161 void FlowGraphOptimizer::TryReplaceWithBinaryOp(InstanceCallComp* comp, 161 bool FlowGraphOptimizer::TryReplaceWithBinaryOp(InstanceCallComp* comp,
162 Token::Kind op_kind) { 162 Token::Kind op_kind) {
163 if (comp->ic_data()->NumberOfChecks() != 1) { 163 if (comp->ic_data()->NumberOfChecks() != 1) {
164 // TODO(srdjan): Not yet supported. 164 // TODO(srdjan): Not yet supported.
165 return; 165 return false;
166 } 166 }
167 167
168 BinaryOpComp::OperandsType operands_type; 168 BinaryOpComp::OperandsType operands_type;
169 169
170 if (HasTwoSmi(*comp->ic_data())) { 170 if (HasTwoSmi(*comp->ic_data())) {
171 if (op_kind == Token::kDIV || 171 if (op_kind == Token::kDIV ||
172 op_kind == Token::kMOD) { 172 op_kind == Token::kMOD) {
173 // TODO(srdjan): Not yet supported. 173 // TODO(srdjan): Not yet supported.
174 return; 174 return false;
175 } 175 }
176 176
177 operands_type = BinaryOpComp::kSmiOperands; 177 operands_type = BinaryOpComp::kSmiOperands;
178 } else if (HasTwoDouble(*comp->ic_data())) { 178 } else if (HasTwoDouble(*comp->ic_data())) {
179 if (op_kind != Token::kADD && 179 if (op_kind != Token::kADD &&
180 op_kind != Token::kSUB && 180 op_kind != Token::kSUB &&
181 op_kind != Token::kMUL && 181 op_kind != Token::kMUL &&
182 op_kind != Token::kDIV) { 182 op_kind != Token::kDIV) {
183 // TODO(vegorov): Not yet supported. 183 // TODO(vegorov): Not yet supported.
184 return; 184 return false;
185 } 185 }
186 186
187 operands_type = BinaryOpComp::kDoubleOperands; 187 operands_type = BinaryOpComp::kDoubleOperands;
188 } else { 188 } else {
189 // TODO(srdjan): Not yet supported. 189 // TODO(srdjan): Not yet supported.
190 return; 190 return false;
191 } 191 }
192 192
193 ASSERT(comp->instr() != NULL); 193 ASSERT(comp->instr() != NULL);
194 ASSERT(comp->InputCount() == 2); 194 ASSERT(comp->InputCount() == 2);
195 Value* left = comp->InputAt(0); 195 Value* left = comp->InputAt(0);
196 Value* right = comp->InputAt(1); 196 Value* right = comp->InputAt(1);
197 BinaryOpComp* bin_op = 197 BinaryOpComp* bin_op =
198 new BinaryOpComp(op_kind, 198 new BinaryOpComp(op_kind,
199 operands_type, 199 operands_type,
200 comp, 200 comp,
201 left, 201 left,
202 right); 202 right);
203 ASSERT(bin_op->ic_data() == NULL);
204 bin_op->set_ic_data(comp->ic_data()); 203 bin_op->set_ic_data(comp->ic_data());
205 bin_op->set_instr(comp->instr()); 204 comp->ReplaceWith(bin_op);
206 comp->instr()->replace_computation(bin_op); 205 return true;
207 } 206 }
208 207
209 208
210 void FlowGraphOptimizer::TryReplaceWithUnaryOp(InstanceCallComp* comp, 209 bool FlowGraphOptimizer::TryReplaceWithUnaryOp(InstanceCallComp* comp,
211 Token::Kind op_kind) { 210 Token::Kind op_kind) {
212 if (comp->ic_data()->NumberOfChecks() != 1) { 211 if (comp->ic_data()->NumberOfChecks() != 1) {
213 // TODO(srdjan): Not yet supported. 212 // TODO(srdjan): Not yet supported.
214 return; 213 return false;
215 } 214 }
216 ASSERT(comp->instr() != NULL); 215 ASSERT(comp->instr() != NULL);
217 ASSERT(comp->InputCount() == 1); 216 ASSERT(comp->InputCount() == 1);
218 Computation* unary_op = NULL; 217 Computation* unary_op = NULL;
219 if (HasOneSmi(*comp->ic_data())) { 218 if (HasOneSmi(*comp->ic_data())) {
220 unary_op = new UnarySmiOpComp(op_kind, comp, comp->InputAt(0)); 219 unary_op = new UnarySmiOpComp(op_kind, comp, comp->InputAt(0));
221 } else if (HasOneDouble(*comp->ic_data()) && (op_kind == Token::kNEGATE)) { 220 } else if (HasOneDouble(*comp->ic_data()) && (op_kind == Token::kNEGATE)) {
222 unary_op = new NumberNegateComp(comp, comp->InputAt(0)); 221 unary_op = new NumberNegateComp(comp, comp->InputAt(0));
223 } 222 }
224 if (unary_op != NULL) { 223 if (unary_op != NULL) {
225 ASSERT(unary_op->ic_data() == NULL);
226 unary_op->set_ic_data(comp->ic_data()); 224 unary_op->set_ic_data(comp->ic_data());
227 unary_op->set_instr(comp->instr()); 225 comp->ReplaceWith(unary_op);
228 comp->instr()->replace_computation(unary_op); 226 return true;
229 } 227 }
228 return false;
230 } 229 }
231 230
232 231
233 // Returns true if all targets are the same. 232 // Returns true if all targets are the same.
234 // TODO(srdjan): if targets are native use their C_function to compare. 233 // TODO(srdjan): if targets are native use their C_function to compare.
235 static bool HasOneTarget(const ICData& ic_data) { 234 static bool HasOneTarget(const ICData& ic_data) {
236 ASSERT(ic_data.NumberOfChecks() > 0); 235 ASSERT(ic_data.NumberOfChecks() > 0);
237 Function& prev_target = Function::Handle(); 236 Function& prev_target = Function::Handle();
238 GrowableArray<const Class*> classes; 237 GrowableArray<const Class*> classes;
239 ic_data.GetCheckAt(0, &classes, &prev_target); 238 ic_data.GetCheckAt(0, &classes, &prev_target);
(...skipping 19 matching lines...) Expand all
259 field = cls.LookupInstanceField(field_name); 258 field = cls.LookupInstanceField(field_name);
260 if (!field.IsNull()) { 259 if (!field.IsNull()) {
261 return field.raw(); 260 return field.raw();
262 } 261 }
263 cls = cls.SuperClass(); 262 cls = cls.SuperClass();
264 } 263 }
265 return Field::null(); 264 return Field::null();
266 } 265 }
267 266
268 267
268 // Returns all receiver class-ids and corresponding tagets for the given
269 // 'ic_data', sorted so that a smi class id is at index[0] if it exists.
270 static void ExtractClassIdsAndTargets(const ICData& ic_data,
271 ZoneGrowableArray<intptr_t>* class_ids,
272 ZoneGrowableArray<Function*>* targets) {
273 ASSERT(class_ids != NULL);
274 ASSERT(targets != NULL);
275 class_ids->Clear();
276 targets->Clear();
277 intptr_t smi_index = -1;
278 Function& target = Function::Handle();
279 GrowableArray<const Class*> classes;
280 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) {
281 ic_data.GetCheckAt(i, &classes, &target);
282 // Collect receiver class only.
283 const intptr_t class_id = (*classes[0]).id();
284 if (ic_data.num_args_tested() > 1) {
285 // Check if we have not already entered the class-id.
286 Function* target_found = NULL;
287 for (intptr_t k = 0; k < class_ids->length(); k++) {
288 if ((*class_ids)[k] == class_id) {
289 target_found = (*targets)[k];
290 break;
291 }
292 }
293 if (target_found != NULL) {
294 ASSERT(target_found->raw() == target.raw());
295 continue;
296 }
297 }
298 if (class_id == kSmi) {
299 ASSERT(smi_index < 0); // Classes entered only once in ic_data.
300 smi_index = class_ids->length();
301 }
302 class_ids->Add(class_id);
303 targets->Add(&Function::ZoneHandle(target.raw()));
304 }
305 if (smi_index >= 0) {
306 // Smi class id must be at index 0.
307 intptr_t temp_id = (*class_ids)[0];
308 Function* temp_func = (*targets)[0];
309 (*class_ids)[0] = (*class_ids)[smi_index];
310 (*targets)[0] = (*targets)[smi_index];
311 (*class_ids)[smi_index] = temp_id;
312 (*targets)[smi_index] = temp_func;
313 }
314 }
315
316
269 // Returns array of all class ids that are in ic_data. The result is 317 // Returns array of all class ids that are in ic_data. The result is
270 // normalized so that a smi class is at index 0 if it exists in the ic_data. 318 // normalized so that a smi class is at index 0 if it exists in the ic_data.
271 static ZoneGrowableArray<intptr_t>* ExtractClassIds(const ICData& ic_data) { 319 static ZoneGrowableArray<intptr_t>* ExtractClassIds(const ICData& ic_data) {
272 if (ic_data.NumberOfChecks() == 0) return NULL; 320 if (ic_data.NumberOfChecks() == 0) return NULL;
273 ZoneGrowableArray<intptr_t>* result = 321 ZoneGrowableArray<intptr_t>* result =
274 new ZoneGrowableArray<intptr_t>(ic_data.NumberOfChecks()); 322 new ZoneGrowableArray<intptr_t>(ic_data.NumberOfChecks());
275 intptr_t smi_index = -1; 323 ZoneGrowableArray<Function*>* dummy =
276 Function& target = Function::Handle(); 324 new ZoneGrowableArray<Function*>(ic_data.NumberOfChecks());
277 Class& cls = Class::Handle(); 325 ExtractClassIdsAndTargets(ic_data, result, dummy);
Vyacheslav Egorov (Google) 2012/06/13 09:02:27 how about passing NULL instead of dummy? Collectin
srdjan 2012/06/13 18:34:24 Done.
278 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) {
279 ic_data.GetOneClassCheckAt(i, &cls, &target);
280 result->Add(cls.id());
281 if (cls.id() == kSmi) {
282 ASSERT(smi_index < 0); // Classes entered only once in ic_data.
283 smi_index = i;
284 }
285 }
286 if (smi_index >= 0) {
287 // Smi class id must be at index 0.
288 intptr_t temp = (*result)[0];
289 (*result)[0] = (*result)[smi_index];
290 (*result)[smi_index] = temp;
291 }
292 return result; 326 return result;
293 } 327 }
294 328
295 329
296 // Only unique implicit instance getters can be currently handled. 330 // Only unique implicit instance getters can be currently handled.
297 void FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallComp* comp) { 331 bool FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallComp* comp) {
298 ASSERT(comp->HasICData()); 332 ASSERT(comp->HasICData());
299 const ICData& ic_data = *comp->ic_data(); 333 const ICData& ic_data = *comp->ic_data();
300 if (ic_data.NumberOfChecks() == 0) { 334 if (ic_data.NumberOfChecks() == 0) {
301 // No type feedback collected. 335 // No type feedback collected.
302 return; 336 return false;
303 } 337 }
304 Function& target = Function::Handle(); 338 Function& target = Function::Handle();
305 GrowableArray<const Class*> classes; 339 GrowableArray<const Class*> classes;
306 ic_data.GetCheckAt(0, &classes, &target); 340 ic_data.GetCheckAt(0, &classes, &target);
307 ASSERT(classes.length() == 1); 341 ASSERT(classes.length() == 1);
308 342
309 if (target.kind() == RawFunction::kImplicitGetter) { 343 if (target.kind() == RawFunction::kImplicitGetter) {
310 if (!HasOneTarget(ic_data)) { 344 if (!HasOneTarget(ic_data)) {
311 // TODO(srdjan): Implement for mutiple targets. 345 // TODO(srdjan): Implement for mutiple targets.
312 return; 346 return false;
313 } 347 }
314 // Inline implicit instance getter. 348 // Inline implicit instance getter.
315 const String& field_name = 349 const String& field_name =
316 String::Handle(Field::NameFromGetter(comp->function_name())); 350 String::Handle(Field::NameFromGetter(comp->function_name()));
317 const Field& field = Field::Handle(GetField(*classes[0], field_name)); 351 const Field& field = Field::Handle(GetField(*classes[0], field_name));
318 ASSERT(!field.IsNull()); 352 ASSERT(!field.IsNull());
319 LoadInstanceFieldComp* load = new LoadInstanceFieldComp( 353 LoadInstanceFieldComp* load = new LoadInstanceFieldComp(
320 field, comp->InputAt(0), comp, ExtractClassIds(ic_data)); 354 field, comp->InputAt(0), comp, ExtractClassIds(ic_data));
321 // Replace 'comp' with 'load'. 355 comp->ReplaceWith(load);
322 load->set_instr(comp->instr()); 356 return true;
323 comp->instr()->replace_computation(load);
324 return;
325 } 357 }
326 358
327 // Not an implicit getter. 359 // Not an implicit getter.
328 MethodRecognizer::Kind recognized_kind = 360 MethodRecognizer::Kind recognized_kind =
329 MethodRecognizer::RecognizeKind(target); 361 MethodRecognizer::RecognizeKind(target);
330 362
331 // VM objects length getter. 363 // VM objects length getter.
332 if ((recognized_kind == MethodRecognizer::kObjectArrayLength) || 364 if ((recognized_kind == MethodRecognizer::kObjectArrayLength) ||
333 (recognized_kind == MethodRecognizer::kImmutableArrayLength) || 365 (recognized_kind == MethodRecognizer::kImmutableArrayLength) ||
334 (recognized_kind == MethodRecognizer::kGrowableArrayLength)) { 366 (recognized_kind == MethodRecognizer::kGrowableArrayLength)) {
335 if (!HasOneTarget(ic_data)) { 367 if (!HasOneTarget(ic_data)) {
336 // TODO(srdjan): Implement for mutiple targets. 368 // TODO(srdjan): Implement for mutiple targets.
337 return; 369 return false;
338 } 370 }
339 intptr_t length_offset = -1; 371 intptr_t length_offset = -1;
340 switch (recognized_kind) { 372 switch (recognized_kind) {
341 case MethodRecognizer::kObjectArrayLength: 373 case MethodRecognizer::kObjectArrayLength:
342 case MethodRecognizer::kImmutableArrayLength: 374 case MethodRecognizer::kImmutableArrayLength:
343 length_offset = Array::length_offset(); 375 length_offset = Array::length_offset();
344 break; 376 break;
345 case MethodRecognizer::kGrowableArrayLength: 377 case MethodRecognizer::kGrowableArrayLength:
346 length_offset = GrowableObjectArray::length_offset(); 378 length_offset = GrowableObjectArray::length_offset();
347 break; 379 break;
348 default: 380 default:
349 UNREACHABLE(); 381 UNREACHABLE();
350 } 382 }
351 LoadVMFieldComp* load = new LoadVMFieldComp( 383 LoadVMFieldComp* load = new LoadVMFieldComp(
352 comp->InputAt(0), 384 comp->InputAt(0),
353 length_offset, 385 length_offset,
354 Type::ZoneHandle(Type::IntInterface()), 386 Type::ZoneHandle(Type::IntInterface()),
355 comp, 387 comp,
356 ExtractClassIds(ic_data)); 388 ExtractClassIds(ic_data));
357 load->set_instr(comp->instr()); 389 comp->ReplaceWith(load);
358 comp->instr()->replace_computation(load); 390 return true;
359 return;
360 } 391 }
361 392
362 if (recognized_kind == MethodRecognizer::kStringBaseLength) { 393 if (recognized_kind == MethodRecognizer::kStringBaseLength) {
363 ASSERT(HasOneTarget(ic_data)); 394 ASSERT(HasOneTarget(ic_data));
364 LoadVMFieldComp* load = new LoadVMFieldComp( 395 LoadVMFieldComp* load = new LoadVMFieldComp(
365 comp->InputAt(0), 396 comp->InputAt(0),
366 String::length_offset(), 397 String::length_offset(),
367 Type::ZoneHandle(Type::IntInterface()), 398 Type::ZoneHandle(Type::IntInterface()),
368 comp, 399 comp,
369 ExtractClassIds(ic_data)); 400 ExtractClassIds(ic_data));
370 load->set_instr(comp->instr()); 401 comp->ReplaceWith(load);
371 comp->instr()->replace_computation(load); 402 return true;
372 return;
373 } 403 }
404 return false;
374 } 405 }
375 406
376 407
377 // Inline only simple, frequently called core library methods. 408 // Inline only simple, frequently called core library methods.
378 void FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallComp* comp) { 409 bool FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallComp* comp) {
379 ASSERT(comp->HasICData()); 410 ASSERT(comp->HasICData());
380 const ICData& ic_data = *comp->ic_data(); 411 const ICData& ic_data = *comp->ic_data();
381 if ((ic_data.NumberOfChecks() == 0) || !HasOneTarget(ic_data)) { 412 if ((ic_data.NumberOfChecks() == 0) || !HasOneTarget(ic_data)) {
382 // No type feedback collected. 413 // No type feedback collected.
383 return; 414 return false;
384 } 415 }
385 Function& target = Function::Handle(); 416 Function& target = Function::Handle();
386 GrowableArray<const Class*> classes; 417 GrowableArray<const Class*> classes;
387 ic_data.GetCheckAt(0, &classes, &target); 418 ic_data.GetCheckAt(0, &classes, &target);
388 ASSERT(classes.length() == 1);
389 MethodRecognizer::Kind recognized_kind = 419 MethodRecognizer::Kind recognized_kind =
390 MethodRecognizer::RecognizeKind(target); 420 MethodRecognizer::RecognizeKind(target);
391 if (recognized_kind == MethodRecognizer::kDoubleToDouble) { 421 if (recognized_kind == MethodRecognizer::kDoubleToDouble) {
392 // TODO(srdjan): Implement. 422 // TODO(srdjan): Implement.
393 } 423 }
394 if (recognized_kind == MethodRecognizer::kIntegerToDouble) { 424 if (recognized_kind == MethodRecognizer::kIntegerToDouble) {
395 // TODO(srdjan): Implement. 425 // TODO(srdjan): Implement.
396 } 426 }
427 return false;
397 } 428 }
398 429
399 430
400 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallComp* comp) { 431 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallComp* comp) {
401 if (comp->HasICData()) { 432 if (comp->HasICData() && (comp->ic_data()->NumberOfChecks() > 0)) {
402 const String& function_name = comp->function_name(); 433 const String& function_name = comp->function_name();
403 Token::Kind op_kind = Token::GetBinaryOp(function_name); 434 Token::Kind op_kind = Token::GetBinaryOp(function_name);
Vyacheslav Egorov (Google) 2012/06/13 09:02:27 Can we just store op_kind in the InstanceCallComp
srdjan 2012/06/13 18:34:24 Yes, next CL.
404 if (op_kind != Token::kILLEGAL) { 435 if ((op_kind != Token::kILLEGAL) && TryReplaceWithBinaryOp(comp, op_kind)) {
405 TryReplaceWithBinaryOp(comp, op_kind);
406 return; 436 return;
407 } 437 }
408 op_kind = Token::GetUnaryOp(function_name); 438 op_kind = Token::GetUnaryOp(function_name);
409 if (op_kind != Token::kILLEGAL) { 439 if ((op_kind != Token::kILLEGAL) && TryReplaceWithUnaryOp(comp, op_kind)) {
410 TryReplaceWithUnaryOp(comp, op_kind);
411 return; 440 return;
412 } 441 }
413 if (Field::IsGetterName(function_name)) { 442 if ((Field::IsGetterName(function_name)) && TryInlineInstanceGetter(comp)) {
414 TryInlineInstanceGetter(comp);
415 return; 443 return;
416 } 444 }
417 TryInlineInstanceMethod(comp); 445 if (TryInlineInstanceMethod(comp)) {
446 return;
447 }
448 const intptr_t kMaxChecks = 4;
449 if (comp->ic_data()->num_args_tested() <= kMaxChecks) {
450 ZoneGrowableArray<intptr_t>* class_ids =
451 new ZoneGrowableArray<intptr_t>();
452 ZoneGrowableArray<Function*>* targets =
453 new ZoneGrowableArray<Function*>();
454 ExtractClassIdsAndTargets(*comp->ic_data(), class_ids, targets);
455 CheckedInstanceCallComp* call =
456 new CheckedInstanceCallComp(comp, *class_ids, *targets);
457 comp->ReplaceWith(call);
458 }
418 } 459 }
419 } 460 }
420 461
421 462
422 void FlowGraphOptimizer::VisitStaticCall(StaticCallComp* comp) { 463 void FlowGraphOptimizer::VisitStaticCall(StaticCallComp* comp) {
423 MethodRecognizer::Kind recognized_kind = 464 MethodRecognizer::Kind recognized_kind =
424 MethodRecognizer::RecognizeKind(comp->function()); 465 MethodRecognizer::RecognizeKind(comp->function());
425 if (recognized_kind == MethodRecognizer::kMathSqrt) { 466 if (recognized_kind == MethodRecognizer::kMathSqrt) {
426 // TODO(srdjan): Implement this. 467 // TODO(srdjan): Implement this.
427 } 468 }
428 } 469 }
429 470
430 471
431 void FlowGraphOptimizer::TryInlineInstanceSetter(InstanceSetterComp* comp) { 472 bool FlowGraphOptimizer::TryInlineInstanceSetter(InstanceSetterComp* comp) {
432 ASSERT(comp->HasICData()); 473 ASSERT(comp->HasICData());
433 const ICData& ic_data = *comp->ic_data(); 474 const ICData& ic_data = *comp->ic_data();
434 if (ic_data.NumberOfChecks() == 0) { 475 if (ic_data.NumberOfChecks() == 0) {
435 // No type feedback collected. 476 // No type feedback collected.
436 return; 477 return false;
437 } 478 }
438 if (!HasOneTarget(ic_data)) { 479 if (!HasOneTarget(ic_data)) {
439 // TODO(srdjan): Implement when not all targets are the sa,e. 480 // TODO(srdjan): Implement when not all targets are the sa,e.
440 return; 481 return false;
441 } 482 }
442 Function& target = Function::Handle(); 483 Function& target = Function::Handle();
443 Class& cls = Class::Handle(); 484 Class& cls = Class::Handle();
444 ic_data.GetOneClassCheckAt(0, &cls, &target); 485 ic_data.GetOneClassCheckAt(0, &cls, &target);
445 if (target.kind() != RawFunction::kImplicitSetter) { 486 if (target.kind() != RawFunction::kImplicitSetter) {
446 // Not an implicit setter. 487 // Not an implicit setter.
447 // TODO(srdjan): Inline special setters. 488 // TODO(srdjan): Inline special setters.
448 return; 489 return false;
449 } 490 }
450 // Inline implicit instance setter. 491 // Inline implicit instance setter.
451 const Field& field = Field::Handle(GetField(cls, comp->field_name())); 492 const Field& field = Field::Handle(GetField(cls, comp->field_name()));
452 ASSERT(!field.IsNull()); 493 ASSERT(!field.IsNull());
453 StoreInstanceFieldComp* store = new StoreInstanceFieldComp( 494 StoreInstanceFieldComp* store = new StoreInstanceFieldComp(
454 field, 495 field,
455 comp->InputAt(0), 496 comp->InputAt(0),
456 comp->InputAt(1), 497 comp->InputAt(1),
457 comp, 498 comp,
458 ExtractClassIds(ic_data)); 499 ExtractClassIds(ic_data));
459 // Replace 'comp' with 'store'. 500 comp->ReplaceWith(store);
460 store->set_instr(comp->instr()); 501 return true;
461 comp->instr()->replace_computation(store);
462 } 502 }
463 503
464 504
465 505
466 void FlowGraphOptimizer::VisitInstanceSetter(InstanceSetterComp* comp) { 506 void FlowGraphOptimizer::VisitInstanceSetter(InstanceSetterComp* comp) {
467 // TODO(srdjan): Add assigneable check node if --enable_type_checks. 507 // TODO(srdjan): Add assigneable check node if --enable_type_checks.
468 if (comp->HasICData() && !FLAG_enable_type_checks) { 508 if (comp->HasICData() && !FLAG_enable_type_checks) {
469 TryInlineInstanceSetter(comp); 509 TryInlineInstanceSetter(comp);
470 } 510 }
471 } 511 }
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
503 ASSERT(HasOneTarget(ic_data)); 543 ASSERT(HasOneTarget(ic_data));
504 544
505 if (HasTwoSmi(ic_data)) { 545 if (HasTwoSmi(ic_data)) {
506 comp->set_operands_class_id(kSmi); 546 comp->set_operands_class_id(kSmi);
507 } else if (HasTwoDouble(ic_data)) { 547 } else if (HasTwoDouble(ic_data)) {
508 comp->set_operands_class_id(kDouble); 548 comp->set_operands_class_id(kDouble);
509 } 549 }
510 } 550 }
511 551
512 552
553 void FlowGraphOptimizer::VisitEqualityCompare(EqualityCompareComp* comp) {
554 if (!comp->HasICData()) return;
555 const ICData& ic_data = *comp->ic_data();
556 if (ic_data.NumberOfChecks() != 1) return;
557 ASSERT(HasOneTarget(ic_data));
558 if (HasTwoSmi(ic_data)) {
559 comp->set_operands_class_id(kSmi);
560 }
561 }
562
563
513 void FlowGraphOptimizer::VisitDo(DoInstr* instr) { 564 void FlowGraphOptimizer::VisitDo(DoInstr* instr) {
514 instr->computation()->Accept(this); 565 instr->computation()->Accept(this);
515 } 566 }
516 567
517 568
518 void FlowGraphOptimizer::VisitBind(BindInstr* instr) { 569 void FlowGraphOptimizer::VisitBind(BindInstr* instr) {
519 instr->computation()->Accept(this); 570 instr->computation()->Accept(this);
520 } 571 }
521 572
522 573
523 } // namespace dart 574 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698