OLD | NEW |
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 // Class for intrinsifying functions. | 4 // Class for intrinsifying functions. |
5 | 5 |
6 #include "vm/assembler.h" | 6 #include "vm/assembler.h" |
7 #include "vm/compiler.h" | 7 #include "vm/compiler.h" |
8 #include "vm/cpu.h" | 8 #include "vm/cpu.h" |
9 #include "vm/flags.h" | 9 #include "vm/flags.h" |
10 #include "vm/flow_graph.h" | 10 #include "vm/flow_graph.h" |
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
377 new LoadFieldInstr(new Value(array), | 377 new LoadFieldInstr(new Value(array), |
378 length_offset, | 378 length_offset, |
379 Type::ZoneHandle(Type::SmiType()), | 379 Type::ZoneHandle(Type::SmiType()), |
380 TokenPosition::kNoSource)); | 380 TokenPosition::kNoSource)); |
381 builder->AddInstruction( | 381 builder->AddInstruction( |
382 new CheckArrayBoundInstr(new Value(length), | 382 new CheckArrayBoundInstr(new Value(length), |
383 new Value(index), | 383 new Value(index), |
384 Thread::kNoDeoptId)); | 384 Thread::kNoDeoptId)); |
385 } | 385 } |
386 | 386 |
387 | 387 static bool IntrinsifyArrayGetIndexed(FlowGraph* flow_graph, |
388 bool Intrinsifier::Build_ObjectArrayGetIndexed(FlowGraph* flow_graph) { | 388 intptr_t array_cid) { |
389 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 389 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
390 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 390 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
391 BlockBuilder builder(flow_graph, normal_entry); | 391 BlockBuilder builder(flow_graph, normal_entry); |
392 | |
393 Definition* index = builder.AddParameter(1); | |
394 Definition* array = builder.AddParameter(2); | |
395 | |
396 PrepareIndexedOp(&builder, array, index, Array::length_offset()); | |
397 | |
398 Definition* result = builder.AddDefinition( | |
399 new LoadIndexedInstr(new Value(array), | |
400 new Value(index), | |
401 Instance::ElementSizeFor(kArrayCid), // index scale | |
402 kArrayCid, | |
403 Thread::kNoDeoptId, | |
404 builder.TokenPos())); | |
405 builder.AddIntrinsicReturn(new Value(result)); | |
406 return true; | |
407 } | |
408 | |
409 | |
410 bool Intrinsifier::Build_ImmutableArrayGetIndexed(FlowGraph* flow_graph) { | |
411 return Build_ObjectArrayGetIndexed(flow_graph); | |
412 } | |
413 | |
414 | |
415 bool Intrinsifier::Build_Uint8ArrayGetIndexed(FlowGraph* flow_graph) { | |
416 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | |
417 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | |
418 BlockBuilder builder(flow_graph, normal_entry); | |
419 | 392 |
420 Definition* index = builder.AddParameter(1); | 393 Definition* index = builder.AddParameter(1); |
421 Definition* array = builder.AddParameter(2); | 394 Definition* array = builder.AddParameter(2); |
422 | 395 |
423 PrepareIndexedOp(&builder, array, index, TypedData::length_offset()); | 396 intptr_t length_offset = Array::length_offset(); |
| 397 if (RawObject::IsTypedDataClassId(array_cid)) { |
| 398 length_offset = TypedData::length_offset(); |
| 399 } else if (RawObject::IsExternalTypedDataClassId(array_cid)) { |
| 400 length_offset = ExternalTypedData::length_offset(); |
| 401 } |
| 402 |
| 403 PrepareIndexedOp(&builder, array, index, length_offset); |
| 404 |
| 405 if (RawObject::IsExternalTypedDataClassId(array_cid)) { |
| 406 array = builder.AddDefinition( |
| 407 new LoadUntaggedInstr(new Value(array), |
| 408 ExternalTypedData::data_offset())); |
| 409 } |
424 | 410 |
425 Definition* result = builder.AddDefinition( | 411 Definition* result = builder.AddDefinition( |
426 new LoadIndexedInstr(new Value(array), | 412 new LoadIndexedInstr(new Value(array), |
427 new Value(index), | 413 new Value(index), |
428 1, // index scale | 414 Instance::ElementSizeFor(array_cid), // index scale |
429 kTypedDataUint8ArrayCid, | 415 array_cid, |
430 Thread::kNoDeoptId, | 416 Thread::kNoDeoptId, |
431 builder.TokenPos())); | 417 builder.TokenPos())); |
| 418 // Box and/or convert result if necessary. |
| 419 switch (array_cid) { |
| 420 case kTypedDataInt32ArrayCid: |
| 421 case kExternalTypedDataInt32ArrayCid: |
| 422 result = builder.AddDefinition( |
| 423 BoxInstr::Create(kUnboxedInt32, new Value(result))); |
| 424 break; |
| 425 case kTypedDataUint32ArrayCid: |
| 426 case kExternalTypedDataUint32ArrayCid: |
| 427 result = builder.AddDefinition( |
| 428 BoxInstr::Create(kUnboxedUint32, new Value(result))); |
| 429 break; |
| 430 case kTypedDataFloat32ArrayCid: |
| 431 result = builder.AddDefinition( |
| 432 new FloatToDoubleInstr(new Value(result), Thread::kNoDeoptId)); |
| 433 // Fall through. |
| 434 case kTypedDataFloat64ArrayCid: |
| 435 result = builder.AddDefinition( |
| 436 BoxInstr::Create(kUnboxedDouble, new Value(result))); |
| 437 break; |
| 438 default: |
| 439 ASSERT(array_cid == kArrayCid || |
| 440 array_cid == kImmutableArrayCid || |
| 441 array_cid == kTypedDataUint8ArrayCid || |
| 442 array_cid == kExternalTypedDataUint8ArrayCid); |
| 443 break; |
| 444 } |
432 builder.AddIntrinsicReturn(new Value(result)); | 445 builder.AddIntrinsicReturn(new Value(result)); |
433 return true; | 446 return true; |
434 } | 447 } |
435 | 448 |
436 | 449 |
437 bool Intrinsifier::Build_ExternalUint8ArrayGetIndexed(FlowGraph* flow_graph) { | 450 static bool IntrinsifyArraySetIndexed(FlowGraph* flow_graph, |
| 451 intptr_t array_cid) { |
438 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 452 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
439 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 453 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
440 BlockBuilder builder(flow_graph, normal_entry); | 454 BlockBuilder builder(flow_graph, normal_entry); |
441 | |
442 Definition* index = builder.AddParameter(1); | |
443 Definition* array = builder.AddParameter(2); | |
444 | |
445 PrepareIndexedOp(&builder, array, index, ExternalTypedData::length_offset()); | |
446 | |
447 Definition* elements = builder.AddDefinition( | |
448 new LoadUntaggedInstr(new Value(array), | |
449 ExternalTypedData::data_offset())); | |
450 Definition* result = builder.AddDefinition( | |
451 new LoadIndexedInstr(new Value(elements), | |
452 new Value(index), | |
453 1, // index scale | |
454 kExternalTypedDataUint8ArrayCid, | |
455 Thread::kNoDeoptId, | |
456 builder.TokenPos())); | |
457 builder.AddIntrinsicReturn(new Value(result)); | |
458 return true; | |
459 } | |
460 | |
461 | |
462 bool Intrinsifier::Build_Uint8ArraySetIndexed(FlowGraph* flow_graph) { | |
463 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | |
464 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | |
465 BlockBuilder builder(flow_graph, normal_entry); | |
466 | 455 |
467 Definition* value = builder.AddParameter(1); | 456 Definition* value = builder.AddParameter(1); |
468 Definition* index = builder.AddParameter(2); | 457 Definition* index = builder.AddParameter(2); |
469 Definition* array = builder.AddParameter(3); | 458 Definition* array = builder.AddParameter(3); |
470 | 459 |
471 PrepareIndexedOp(&builder, array, index, TypedData::length_offset()); | 460 intptr_t length_offset = Array::length_offset(); |
| 461 if (RawObject::IsTypedDataClassId(array_cid)) { |
| 462 length_offset = TypedData::length_offset(); |
| 463 } else if (RawObject::IsExternalTypedDataClassId(array_cid)) { |
| 464 length_offset = ExternalTypedData::length_offset(); |
| 465 } |
472 | 466 |
473 builder.AddInstruction( | 467 PrepareIndexedOp(&builder, array, index, length_offset); |
474 new CheckSmiInstr(new Value(value), | |
475 Thread::kNoDeoptId, | |
476 builder.TokenPos())); | |
477 | 468 |
| 469 // Value check/conversion. |
| 470 switch (array_cid) { |
| 471 case kTypedDataUint8ArrayCid: |
| 472 case kExternalTypedDataUint8ArrayCid: |
| 473 builder.AddInstruction(new CheckSmiInstr(new Value(value), |
| 474 Thread::kNoDeoptId, |
| 475 builder.TokenPos())); |
| 476 break; |
| 477 case kTypedDataInt32ArrayCid: |
| 478 case kExternalTypedDataInt32ArrayCid: |
| 479 // Use same truncating unbox-instruction for int32 and uint32. |
| 480 // Fall-through. |
| 481 case kTypedDataUint32ArrayCid: |
| 482 case kExternalTypedDataUint32ArrayCid: |
| 483 // Supports smi and mint, slow-case for bigints. |
| 484 value = builder.AddUnboxInstr(kUnboxedUint32, |
| 485 new Value(value), |
| 486 /* is_checked = */ false); |
| 487 break; |
| 488 case kTypedDataFloat32ArrayCid: |
| 489 case kTypedDataFloat64ArrayCid: { |
| 490 const ICData& value_check = ICData::ZoneHandle(ICData::New( |
| 491 flow_graph->function(), |
| 492 Symbols::Empty(), // Dummy function name. |
| 493 Object::empty_array(), // Dummy args. descr. |
| 494 Thread::kNoDeoptId, |
| 495 1, |
| 496 false)); |
| 497 value_check.AddReceiverCheck(kDoubleCid, flow_graph->function()); |
| 498 builder.AddInstruction( |
| 499 new CheckClassInstr(new Value(value), |
| 500 Thread::kNoDeoptId, |
| 501 value_check, |
| 502 builder.TokenPos())); |
| 503 value = builder.AddUnboxInstr(kUnboxedDouble, |
| 504 new Value(value), |
| 505 /* is_checked = */ true); |
| 506 if (array_cid == kTypedDataFloat32ArrayCid) { |
| 507 value = builder.AddDefinition( |
| 508 new DoubleToFloatInstr(new Value(value), Thread::kNoDeoptId)); |
| 509 } |
| 510 break; |
| 511 } |
| 512 default: |
| 513 UNREACHABLE(); |
| 514 } |
| 515 |
| 516 if (RawObject::IsExternalTypedDataClassId(array_cid)) { |
| 517 array = builder.AddDefinition( |
| 518 new LoadUntaggedInstr(new Value(array), |
| 519 ExternalTypedData::data_offset())); |
| 520 } |
| 521 // No store barrier. |
| 522 ASSERT(RawObject::IsExternalTypedDataClassId(array_cid) || |
| 523 RawObject::IsTypedDataClassId(array_cid)); |
478 builder.AddInstruction( | 524 builder.AddInstruction( |
479 new StoreIndexedInstr(new Value(array), | 525 new StoreIndexedInstr(new Value(array), |
480 new Value(index), | 526 new Value(index), |
481 new Value(value), | 527 new Value(value), |
482 kNoStoreBarrier, | 528 kNoStoreBarrier, |
483 1, // index scale | 529 Instance::ElementSizeFor(array_cid), // index scale |
484 kTypedDataUint8ArrayCid, | 530 array_cid, |
485 Thread::kNoDeoptId, | 531 Thread::kNoDeoptId, |
486 builder.TokenPos())); | 532 builder.TokenPos())); |
487 // Return null. | 533 // Return null. |
488 Definition* null_def = builder.AddNullDefinition(); | |
489 builder.AddIntrinsicReturn(new Value(null_def)); | |
490 return true; | |
491 } | |
492 | |
493 | |
494 bool Intrinsifier::Build_ExternalUint8ArraySetIndexed(FlowGraph* flow_graph) { | |
495 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | |
496 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | |
497 BlockBuilder builder(flow_graph, normal_entry); | |
498 | |
499 Definition* value = builder.AddParameter(1); | |
500 Definition* index = builder.AddParameter(2); | |
501 Definition* array = builder.AddParameter(3); | |
502 | |
503 PrepareIndexedOp(&builder, array, index, ExternalTypedData::length_offset()); | |
504 | |
505 builder.AddInstruction( | |
506 new CheckSmiInstr(new Value(value), | |
507 Thread::kNoDeoptId, | |
508 builder.TokenPos())); | |
509 Definition* elements = builder.AddDefinition( | |
510 new LoadUntaggedInstr(new Value(array), | |
511 ExternalTypedData::data_offset())); | |
512 builder.AddInstruction( | |
513 new StoreIndexedInstr(new Value(elements), | |
514 new Value(index), | |
515 new Value(value), | |
516 kNoStoreBarrier, | |
517 1, // index scale | |
518 kExternalTypedDataUint8ArrayCid, | |
519 Thread::kNoDeoptId, | |
520 builder.TokenPos())); | |
521 // Return null. | |
522 Definition* null_def = builder.AddNullDefinition(); | 534 Definition* null_def = builder.AddNullDefinition(); |
523 builder.AddIntrinsicReturn(new Value(null_def)); | 535 builder.AddIntrinsicReturn(new Value(null_def)); |
524 return true; | 536 return true; |
525 } | 537 } |
526 | 538 |
527 | 539 |
528 bool Intrinsifier::Build_Uint32ArraySetIndexed(FlowGraph* flow_graph) { | 540 #define DEFINE_ARRAY_GETTER_INTRINSIC(enum_name) \ |
529 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 541 bool Intrinsifier::Build_##enum_name##GetIndexed(FlowGraph* flow_graph) { \ |
530 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 542 return IntrinsifyArrayGetIndexed( \ |
531 BlockBuilder builder(flow_graph, normal_entry); | 543 flow_graph, \ |
532 | 544 MethodRecognizer::MethodKindToCid( \ |
533 Definition* value = builder.AddParameter(1); | 545 MethodRecognizer::k##enum_name##GetIndexed)); \ |
534 Definition* index = builder.AddParameter(2); | |
535 Definition* array = builder.AddParameter(3); | |
536 | |
537 PrepareIndexedOp(&builder, array, index, TypedData::length_offset()); | |
538 | |
539 Definition* unboxed_value = | |
540 builder.AddUnboxInstr(kUnboxedUint32, | |
541 new Value(value), | |
542 /* is_checked = */ true); | |
543 | |
544 builder.AddInstruction( | |
545 new StoreIndexedInstr(new Value(array), | |
546 new Value(index), | |
547 new Value(unboxed_value), | |
548 kNoStoreBarrier, | |
549 4, // index scale | |
550 kTypedDataUint32ArrayCid, | |
551 Thread::kNoDeoptId, | |
552 builder.TokenPos())); | |
553 // Return null. | |
554 Definition* null_def = builder.AddNullDefinition(); | |
555 builder.AddIntrinsicReturn(new Value(null_def)); | |
556 return true; | |
557 } | 546 } |
558 | 547 |
559 | 548 |
560 bool Intrinsifier::Build_Uint32ArrayGetIndexed(FlowGraph* flow_graph) { | 549 #define DEFINE_ARRAY_SETTER_INTRINSIC(enum_name) \ |
561 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 550 bool Intrinsifier::Build_##enum_name##SetIndexed(FlowGraph* flow_graph) { \ |
562 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 551 return IntrinsifyArraySetIndexed( \ |
563 BlockBuilder builder(flow_graph, normal_entry); | 552 flow_graph, \ |
| 553 MethodRecognizer::MethodKindToCid( \ |
| 554 MethodRecognizer::k##enum_name##SetIndexed)); \ |
| 555 } |
564 | 556 |
565 Definition* index = builder.AddParameter(1); | 557 DEFINE_ARRAY_GETTER_INTRINSIC(ObjectArray) // Setter in intrinsifier_<arch>.cc. |
566 Definition* array = builder.AddParameter(2); | 558 DEFINE_ARRAY_GETTER_INTRINSIC(ImmutableArray) |
567 | 559 |
568 PrepareIndexedOp(&builder, array, index, TypedData::length_offset()); | 560 #define DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(enum_name) \ |
| 561 DEFINE_ARRAY_GETTER_INTRINSIC(enum_name) \ |
| 562 DEFINE_ARRAY_SETTER_INTRINSIC(enum_name) |
569 | 563 |
570 Definition* unboxed_value = builder.AddDefinition( | 564 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint8Array) |
571 new LoadIndexedInstr(new Value(array), | 565 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(ExternalUint8Array) |
572 new Value(index), | 566 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Int32Array) |
573 4, // index scale | 567 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint32Array) |
574 kTypedDataUint32ArrayCid, | 568 |
575 Thread::kNoDeoptId, | 569 #undef DEFINE_ARRAY_GETTER_SETTER_INTRINSICS |
576 builder.TokenPos())); | 570 #undef DEFINE_ARRAY_GETTER_INTRINSIC |
577 Definition* result = builder.AddDefinition( | 571 #undef DEFINE_ARRAY_SETTER_INTRINSIC |
578 BoxInstr::Create(kUnboxedUint32, new Value(unboxed_value))); | 572 |
579 builder.AddIntrinsicReturn(new Value(result)); | 573 |
580 return true; | 574 #define DEFINE_FLOAT_ARRAY_GETTER_INTRINSIC(enum_name) \ |
| 575 bool Intrinsifier::Build_##enum_name##GetIndexed(FlowGraph* flow_graph) { \ |
| 576 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) { \ |
| 577 return false; \ |
| 578 } \ |
| 579 return IntrinsifyArrayGetIndexed( \ |
| 580 flow_graph, \ |
| 581 MethodRecognizer::MethodKindToCid( \ |
| 582 MethodRecognizer::k##enum_name##GetIndexed)); \ |
581 } | 583 } |
582 | 584 |
583 | 585 |
584 bool Intrinsifier::Build_Float64ArraySetIndexed(FlowGraph* flow_graph) { | 586 #define DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC(enum_name) \ |
585 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) { | 587 bool Intrinsifier::Build_##enum_name##SetIndexed(FlowGraph* flow_graph) { \ |
586 return false; | 588 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) { \ |
587 } | 589 return false; \ |
588 | 590 } \ |
589 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 591 return IntrinsifyArraySetIndexed( \ |
590 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 592 flow_graph, \ |
591 BlockBuilder builder(flow_graph, normal_entry); | 593 MethodRecognizer::MethodKindToCid( \ |
592 | 594 MethodRecognizer::k##enum_name##SetIndexed)); \ |
593 Definition* value = builder.AddParameter(1); | |
594 Definition* index = builder.AddParameter(2); | |
595 Definition* array = builder.AddParameter(3); | |
596 | |
597 PrepareIndexedOp(&builder, array, index, TypedData::length_offset()); | |
598 | |
599 const ICData& value_check = ICData::ZoneHandle(ICData::New( | |
600 flow_graph->function(), | |
601 String::Handle(flow_graph->function().name()), | |
602 Object::empty_array(), // Dummy args. descr. | |
603 Thread::kNoDeoptId, | |
604 1, | |
605 false)); | |
606 value_check.AddReceiverCheck(kDoubleCid, flow_graph->function()); | |
607 builder.AddInstruction( | |
608 new CheckClassInstr(new Value(value), | |
609 Thread::kNoDeoptId, | |
610 value_check, | |
611 builder.TokenPos())); | |
612 Definition* double_value = | |
613 builder.AddUnboxInstr(kUnboxedDouble, | |
614 new Value(value), | |
615 /* is_checked = */ true); | |
616 | |
617 builder.AddInstruction( | |
618 new StoreIndexedInstr(new Value(array), | |
619 new Value(index), | |
620 new Value(double_value), | |
621 kNoStoreBarrier, | |
622 8, // index scale | |
623 kTypedDataFloat64ArrayCid, | |
624 Thread::kNoDeoptId, | |
625 builder.TokenPos())); | |
626 // Return null. | |
627 Definition* null_def = builder.AddNullDefinition(); | |
628 builder.AddIntrinsicReturn(new Value(null_def)); | |
629 return true; | |
630 } | 595 } |
631 | 596 |
| 597 #define DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS(enum_name) \ |
| 598 DEFINE_FLOAT_ARRAY_GETTER_INTRINSIC(enum_name) \ |
| 599 DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC(enum_name) |
632 | 600 |
633 bool Intrinsifier::Build_Float64ArrayGetIndexed(FlowGraph* flow_graph) { | 601 DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS(Float64Array) |
634 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) { | 602 DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS(Float32Array) |
635 return false; | |
636 } | |
637 | 603 |
638 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 604 #undef DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS |
639 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 605 #undef DEFINE_FLOAT_ARRAY_GETTER_INTRINSIC |
640 BlockBuilder builder(flow_graph, normal_entry); | 606 #undef DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC |
641 | |
642 Definition* index = builder.AddParameter(1); | |
643 Definition* array = builder.AddParameter(2); | |
644 | |
645 PrepareIndexedOp(&builder, array, index, TypedData::length_offset()); | |
646 | |
647 Definition* unboxed_value = builder.AddDefinition( | |
648 new LoadIndexedInstr(new Value(array), | |
649 new Value(index), | |
650 8, // index scale | |
651 kTypedDataFloat64ArrayCid, | |
652 Thread::kNoDeoptId, | |
653 builder.TokenPos())); | |
654 Definition* result = builder.AddDefinition( | |
655 BoxInstr::Create(kUnboxedDouble, new Value(unboxed_value))); | |
656 builder.AddIntrinsicReturn(new Value(result)); | |
657 return true; | |
658 } | |
659 | 607 |
660 | 608 |
661 static bool BuildCodeUnitAt(FlowGraph* flow_graph, intptr_t cid) { | 609 static bool BuildCodeUnitAt(FlowGraph* flow_graph, intptr_t cid) { |
662 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 610 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
663 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 611 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
664 BlockBuilder builder(flow_graph, normal_entry); | 612 BlockBuilder builder(flow_graph, normal_entry); |
665 | 613 |
666 Definition* index = builder.AddParameter(1); | 614 Definition* index = builder.AddParameter(1); |
667 Definition* str = builder.AddParameter(2); | 615 Definition* str = builder.AddParameter(2); |
668 PrepareIndexedOp(&builder, str, index, String::length_offset()); | 616 PrepareIndexedOp(&builder, str, index, String::length_offset()); |
(...skipping 558 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1227 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 1175 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
1228 BlockBuilder builder(flow_graph, normal_entry); | 1176 BlockBuilder builder(flow_graph, normal_entry); |
1229 | 1177 |
1230 return BuildInvokeMathCFunction(&builder, | 1178 return BuildInvokeMathCFunction(&builder, |
1231 MethodRecognizer::kDoubleRound); | 1179 MethodRecognizer::kDoubleRound); |
1232 } | 1180 } |
1233 #endif // !defined(TARGET_ARCH_DBC) | 1181 #endif // !defined(TARGET_ARCH_DBC) |
1234 | 1182 |
1235 | 1183 |
1236 } // namespace dart | 1184 } // namespace dart |
OLD | NEW |