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

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
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 // 'targets' can be NULL in which case it is not collected,
271 static void ExtractClassIdsAndTargets(const ICData& ic_data,
272 ZoneGrowableArray<intptr_t>* class_ids,
273 ZoneGrowableArray<Function*>* targets) {
274 ASSERT(class_ids != NULL);
275 class_ids->Clear();
276 if (targets != NULL) {
277 targets->Clear();
278 }
279 intptr_t smi_index = -1;
280 Function& target = Function::Handle();
281 GrowableArray<const Class*> classes;
282 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) {
283 ic_data.GetCheckAt(i, &classes, &target);
284 // Collect receiver class only.
285 const intptr_t class_id = (*classes[0]).id();
286 if (ic_data.num_args_tested() > 1) {
287 // Check if we have not already entered the class-id.
288 intptr_t duplicate_class_id = -1;
289 for (intptr_t k = 0; k < class_ids->length(); k++) {
290 if ((*class_ids)[k] == class_id) {
291 duplicate_class_id = k;
292 break;
293 }
294 }
295 if (duplicate_class_id >= 0) {
296 ASSERT((targets == NULL) ||
297 ((*targets)[duplicate_class_id]->raw() == target.raw()));
298 continue;
299 }
300 }
301 if (class_id == kSmi) {
302 ASSERT(smi_index < 0); // Classes entered only once in ic_data.
303 smi_index = class_ids->length();
304 }
305 class_ids->Add(class_id);
306 if (targets != NULL) {
307 targets->Add(&Function::ZoneHandle(target.raw()));
308 }
309 }
310 if (smi_index >= 0) {
311 // Smi class id must be at index 0.
312 intptr_t temp_id = (*class_ids)[0];
313 (*class_ids)[0] = (*class_ids)[smi_index];
314 (*class_ids)[smi_index] = temp_id;
315 if (targets != NULL) {
316 Function* temp_func = (*targets)[0];
317 (*targets)[0] = (*targets)[smi_index];
318 (*targets)[smi_index] = temp_func;
319 }
320 }
321 }
322
323
269 // Returns array of all class ids that are in ic_data. The result is 324 // 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. 325 // 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) { 326 static ZoneGrowableArray<intptr_t>* ExtractClassIds(const ICData& ic_data) {
272 if (ic_data.NumberOfChecks() == 0) return NULL; 327 if (ic_data.NumberOfChecks() == 0) return NULL;
273 ZoneGrowableArray<intptr_t>* result = 328 ZoneGrowableArray<intptr_t>* result =
274 new ZoneGrowableArray<intptr_t>(ic_data.NumberOfChecks()); 329 new ZoneGrowableArray<intptr_t>(ic_data.NumberOfChecks());
275 intptr_t smi_index = -1; 330 ExtractClassIdsAndTargets(ic_data, result, NULL);
276 Function& target = Function::Handle();
277 Class& cls = Class::Handle();
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; 331 return result;
293 } 332 }
294 333
295 334
296 // Only unique implicit instance getters can be currently handled. 335 // Only unique implicit instance getters can be currently handled.
297 void FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallComp* comp) { 336 bool FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallComp* comp) {
298 ASSERT(comp->HasICData()); 337 ASSERT(comp->HasICData());
299 const ICData& ic_data = *comp->ic_data(); 338 const ICData& ic_data = *comp->ic_data();
300 if (ic_data.NumberOfChecks() == 0) { 339 if (ic_data.NumberOfChecks() == 0) {
301 // No type feedback collected. 340 // No type feedback collected.
302 return; 341 return false;
303 } 342 }
304 Function& target = Function::Handle(); 343 Function& target = Function::Handle();
305 GrowableArray<const Class*> classes; 344 GrowableArray<const Class*> classes;
306 ic_data.GetCheckAt(0, &classes, &target); 345 ic_data.GetCheckAt(0, &classes, &target);
307 ASSERT(classes.length() == 1); 346 ASSERT(classes.length() == 1);
308 347
309 if (target.kind() == RawFunction::kImplicitGetter) { 348 if (target.kind() == RawFunction::kImplicitGetter) {
310 if (!HasOneTarget(ic_data)) { 349 if (!HasOneTarget(ic_data)) {
311 // TODO(srdjan): Implement for mutiple targets. 350 // TODO(srdjan): Implement for mutiple targets.
312 return; 351 return false;
313 } 352 }
314 // Inline implicit instance getter. 353 // Inline implicit instance getter.
315 const String& field_name = 354 const String& field_name =
316 String::Handle(Field::NameFromGetter(comp->function_name())); 355 String::Handle(Field::NameFromGetter(comp->function_name()));
317 const Field& field = Field::Handle(GetField(*classes[0], field_name)); 356 const Field& field = Field::Handle(GetField(*classes[0], field_name));
318 ASSERT(!field.IsNull()); 357 ASSERT(!field.IsNull());
319 LoadInstanceFieldComp* load = new LoadInstanceFieldComp( 358 LoadInstanceFieldComp* load = new LoadInstanceFieldComp(
320 field, comp->InputAt(0), comp, ExtractClassIds(ic_data)); 359 field, comp->InputAt(0), comp, ExtractClassIds(ic_data));
321 // Replace 'comp' with 'load'. 360 comp->ReplaceWith(load);
322 load->set_instr(comp->instr()); 361 return true;
323 comp->instr()->replace_computation(load);
324 return;
325 } 362 }
326 363
327 // Not an implicit getter. 364 // Not an implicit getter.
328 MethodRecognizer::Kind recognized_kind = 365 MethodRecognizer::Kind recognized_kind =
329 MethodRecognizer::RecognizeKind(target); 366 MethodRecognizer::RecognizeKind(target);
330 367
331 // VM objects length getter. 368 // VM objects length getter.
332 if ((recognized_kind == MethodRecognizer::kObjectArrayLength) || 369 if ((recognized_kind == MethodRecognizer::kObjectArrayLength) ||
333 (recognized_kind == MethodRecognizer::kImmutableArrayLength) || 370 (recognized_kind == MethodRecognizer::kImmutableArrayLength) ||
334 (recognized_kind == MethodRecognizer::kGrowableArrayLength)) { 371 (recognized_kind == MethodRecognizer::kGrowableArrayLength)) {
335 if (!HasOneTarget(ic_data)) { 372 if (!HasOneTarget(ic_data)) {
336 // TODO(srdjan): Implement for mutiple targets. 373 // TODO(srdjan): Implement for mutiple targets.
337 return; 374 return false;
338 } 375 }
339 intptr_t length_offset = -1; 376 intptr_t length_offset = -1;
340 switch (recognized_kind) { 377 switch (recognized_kind) {
341 case MethodRecognizer::kObjectArrayLength: 378 case MethodRecognizer::kObjectArrayLength:
342 case MethodRecognizer::kImmutableArrayLength: 379 case MethodRecognizer::kImmutableArrayLength:
343 length_offset = Array::length_offset(); 380 length_offset = Array::length_offset();
344 break; 381 break;
345 case MethodRecognizer::kGrowableArrayLength: 382 case MethodRecognizer::kGrowableArrayLength:
346 length_offset = GrowableObjectArray::length_offset(); 383 length_offset = GrowableObjectArray::length_offset();
347 break; 384 break;
348 default: 385 default:
349 UNREACHABLE(); 386 UNREACHABLE();
350 } 387 }
351 LoadVMFieldComp* load = new LoadVMFieldComp( 388 LoadVMFieldComp* load = new LoadVMFieldComp(
352 comp->InputAt(0), 389 comp->InputAt(0),
353 length_offset, 390 length_offset,
354 Type::ZoneHandle(Type::IntInterface()), 391 Type::ZoneHandle(Type::IntInterface()),
355 comp, 392 comp,
356 ExtractClassIds(ic_data)); 393 ExtractClassIds(ic_data));
357 load->set_instr(comp->instr()); 394 comp->ReplaceWith(load);
358 comp->instr()->replace_computation(load); 395 return true;
359 return;
360 } 396 }
361 397
362 if (recognized_kind == MethodRecognizer::kStringBaseLength) { 398 if (recognized_kind == MethodRecognizer::kStringBaseLength) {
363 ASSERT(HasOneTarget(ic_data)); 399 ASSERT(HasOneTarget(ic_data));
364 LoadVMFieldComp* load = new LoadVMFieldComp( 400 LoadVMFieldComp* load = new LoadVMFieldComp(
365 comp->InputAt(0), 401 comp->InputAt(0),
366 String::length_offset(), 402 String::length_offset(),
367 Type::ZoneHandle(Type::IntInterface()), 403 Type::ZoneHandle(Type::IntInterface()),
368 comp, 404 comp,
369 ExtractClassIds(ic_data)); 405 ExtractClassIds(ic_data));
370 load->set_instr(comp->instr()); 406 comp->ReplaceWith(load);
371 comp->instr()->replace_computation(load); 407 return true;
372 return;
373 } 408 }
409 return false;
374 } 410 }
375 411
376 412
377 // Inline only simple, frequently called core library methods. 413 // Inline only simple, frequently called core library methods.
378 void FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallComp* comp) { 414 bool FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallComp* comp) {
379 ASSERT(comp->HasICData()); 415 ASSERT(comp->HasICData());
380 const ICData& ic_data = *comp->ic_data(); 416 const ICData& ic_data = *comp->ic_data();
381 if ((ic_data.NumberOfChecks() == 0) || !HasOneTarget(ic_data)) { 417 if ((ic_data.NumberOfChecks() == 0) || !HasOneTarget(ic_data)) {
382 // No type feedback collected. 418 // No type feedback collected.
383 return; 419 return false;
384 } 420 }
385 Function& target = Function::Handle(); 421 Function& target = Function::Handle();
386 GrowableArray<const Class*> classes; 422 GrowableArray<const Class*> classes;
387 ic_data.GetCheckAt(0, &classes, &target); 423 ic_data.GetCheckAt(0, &classes, &target);
388 ASSERT(classes.length() == 1);
389 MethodRecognizer::Kind recognized_kind = 424 MethodRecognizer::Kind recognized_kind =
390 MethodRecognizer::RecognizeKind(target); 425 MethodRecognizer::RecognizeKind(target);
391 426
392 ObjectKind from_kind; 427 ObjectKind from_kind;
393 if (recognized_kind == MethodRecognizer::kDoubleToDouble) { 428 if (recognized_kind == MethodRecognizer::kDoubleToDouble) {
394 from_kind = kDouble; 429 from_kind = kDouble;
395 } else if (recognized_kind == MethodRecognizer::kIntegerToDouble) { 430 } else if (recognized_kind == MethodRecognizer::kIntegerToDouble) {
396 from_kind = kSmi; 431 from_kind = kSmi;
397 } else { 432 } else {
398 return; 433 return false;
399 } 434 }
400 435
401 if (classes[0]->id() != from_kind) { 436 if (classes[0]->id() != from_kind) {
402 return; 437 return false;
403 } 438 }
404
405 ToDoubleComp* coerce = new ToDoubleComp( 439 ToDoubleComp* coerce = new ToDoubleComp(
406 comp->InputAt(0), from_kind, comp); 440 comp->InputAt(0), from_kind, comp);
407 coerce->set_instr(comp->instr()); 441 coerce->set_instr(comp->instr());
408 comp->instr()->replace_computation(coerce); 442 comp->instr()->replace_computation(coerce);
443 return true;
409 } 444 }
410 445
411 446
412 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallComp* comp) { 447 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallComp* comp) {
413 if (comp->HasICData()) { 448 if (comp->HasICData() && (comp->ic_data()->NumberOfChecks() > 0)) {
414 const String& function_name = comp->function_name(); 449 const String& function_name = comp->function_name();
415 Token::Kind op_kind = Token::GetBinaryOp(function_name); 450 Token::Kind op_kind = Token::GetBinaryOp(function_name);
416 if (op_kind != Token::kILLEGAL) { 451 if ((op_kind != Token::kILLEGAL) && TryReplaceWithBinaryOp(comp, op_kind)) {
417 TryReplaceWithBinaryOp(comp, op_kind);
418 return; 452 return;
419 } 453 }
420 op_kind = Token::GetUnaryOp(function_name); 454 op_kind = Token::GetUnaryOp(function_name);
421 if (op_kind != Token::kILLEGAL) { 455 if ((op_kind != Token::kILLEGAL) && TryReplaceWithUnaryOp(comp, op_kind)) {
422 TryReplaceWithUnaryOp(comp, op_kind);
423 return; 456 return;
424 } 457 }
425 if (Field::IsGetterName(function_name)) { 458 if ((Field::IsGetterName(function_name)) && TryInlineInstanceGetter(comp)) {
426 TryInlineInstanceGetter(comp);
427 return; 459 return;
428 } 460 }
429 TryInlineInstanceMethod(comp); 461 if (TryInlineInstanceMethod(comp)) {
462 return;
463 }
464 const intptr_t kMaxChecks = 4;
465 if (comp->ic_data()->num_args_tested() <= kMaxChecks) {
466 ZoneGrowableArray<intptr_t>* class_ids =
467 new ZoneGrowableArray<intptr_t>();
468 ZoneGrowableArray<Function*>* targets =
469 new ZoneGrowableArray<Function*>();
470 ExtractClassIdsAndTargets(*comp->ic_data(), class_ids, targets);
471 PolymorphicInstanceCallComp* call =
472 new PolymorphicInstanceCallComp(comp, *class_ids, *targets);
473 comp->ReplaceWith(call);
474 }
430 } 475 }
431 } 476 }
432 477
433 478
434 void FlowGraphOptimizer::VisitStaticCall(StaticCallComp* comp) { 479 void FlowGraphOptimizer::VisitStaticCall(StaticCallComp* comp) {
435 MethodRecognizer::Kind recognized_kind = 480 MethodRecognizer::Kind recognized_kind =
436 MethodRecognizer::RecognizeKind(comp->function()); 481 MethodRecognizer::RecognizeKind(comp->function());
437 if (recognized_kind == MethodRecognizer::kMathSqrt) { 482 if (recognized_kind == MethodRecognizer::kMathSqrt) {
438 // TODO(srdjan): Implement this. 483 // TODO(srdjan): Implement this.
439 } 484 }
440 } 485 }
441 486
442 487
443 void FlowGraphOptimizer::TryInlineInstanceSetter(InstanceSetterComp* comp) { 488 bool FlowGraphOptimizer::TryInlineInstanceSetter(InstanceSetterComp* comp) {
444 ASSERT(comp->HasICData()); 489 ASSERT(comp->HasICData());
445 const ICData& ic_data = *comp->ic_data(); 490 const ICData& ic_data = *comp->ic_data();
446 if (ic_data.NumberOfChecks() == 0) { 491 if (ic_data.NumberOfChecks() == 0) {
447 // No type feedback collected. 492 // No type feedback collected.
448 return; 493 return false;
449 } 494 }
450 if (!HasOneTarget(ic_data)) { 495 if (!HasOneTarget(ic_data)) {
451 // TODO(srdjan): Implement when not all targets are the sa,e. 496 // TODO(srdjan): Implement when not all targets are the sa,e.
452 return; 497 return false;
453 } 498 }
454 Function& target = Function::Handle(); 499 Function& target = Function::Handle();
455 Class& cls = Class::Handle(); 500 Class& cls = Class::Handle();
456 ic_data.GetOneClassCheckAt(0, &cls, &target); 501 ic_data.GetOneClassCheckAt(0, &cls, &target);
457 if (target.kind() != RawFunction::kImplicitSetter) { 502 if (target.kind() != RawFunction::kImplicitSetter) {
458 // Not an implicit setter. 503 // Not an implicit setter.
459 // TODO(srdjan): Inline special setters. 504 // TODO(srdjan): Inline special setters.
460 return; 505 return false;
461 } 506 }
462 // Inline implicit instance setter. 507 // Inline implicit instance setter.
463 const Field& field = Field::Handle(GetField(cls, comp->field_name())); 508 const Field& field = Field::Handle(GetField(cls, comp->field_name()));
464 ASSERT(!field.IsNull()); 509 ASSERT(!field.IsNull());
465 StoreInstanceFieldComp* store = new StoreInstanceFieldComp( 510 StoreInstanceFieldComp* store = new StoreInstanceFieldComp(
466 field, 511 field,
467 comp->InputAt(0), 512 comp->InputAt(0),
468 comp->InputAt(1), 513 comp->InputAt(1),
469 comp, 514 comp,
470 ExtractClassIds(ic_data)); 515 ExtractClassIds(ic_data));
471 // Replace 'comp' with 'store'. 516 comp->ReplaceWith(store);
472 store->set_instr(comp->instr()); 517 return true;
473 comp->instr()->replace_computation(store);
474 } 518 }
475 519
476 520
477 521
478 void FlowGraphOptimizer::VisitInstanceSetter(InstanceSetterComp* comp) { 522 void FlowGraphOptimizer::VisitInstanceSetter(InstanceSetterComp* comp) {
479 // TODO(srdjan): Add assigneable check node if --enable_type_checks. 523 // TODO(srdjan): Add assigneable check node if --enable_type_checks.
480 if (comp->HasICData() && !FLAG_enable_type_checks) { 524 if (comp->HasICData() && !FLAG_enable_type_checks) {
481 TryInlineInstanceSetter(comp); 525 TryInlineInstanceSetter(comp);
482 } 526 }
483 } 527 }
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
588 instr->computation()->Accept(this); 632 instr->computation()->Accept(this);
589 } 633 }
590 634
591 635
592 void FlowGraphOptimizer::VisitBind(BindInstr* instr) { 636 void FlowGraphOptimizer::VisitBind(BindInstr* instr) {
593 instr->computation()->Accept(this); 637 instr->computation()->Accept(this);
594 } 638 }
595 639
596 640
597 } // namespace dart 641 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698