Chromium Code Reviews| 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/intrinsifier.h" | 7 #include "vm/intrinsifier.h" |
| 8 #include "vm/flags.h" | 8 #include "vm/flags.h" |
| 9 #include "vm/object.h" | 9 #include "vm/object.h" |
| 10 #include "vm/symbols.h" | 10 #include "vm/symbols.h" |
| 11 | 11 |
| 12 #include "vm/flow_graph.h" | 12 #include "vm/flow_graph.h" |
| 13 #include "vm/flow_graph_compiler.h" | 13 #include "vm/flow_graph_compiler.h" |
| 14 #include "vm/flow_graph_allocator.h" | 14 #include "vm/flow_graph_allocator.h" |
| 15 #include "vm/flow_graph_builder.h" | 15 #include "vm/flow_graph_builder.h" |
| 16 #include "vm/il_printer.h" | 16 #include "vm/il_printer.h" |
| 17 #include "vm/intermediate_language.h" | 17 #include "vm/intermediate_language.h" |
| 18 #include "vm/parser.h" | 18 #include "vm/parser.h" |
| 19 | 19 |
| 20 namespace dart { | 20 namespace dart { |
| 21 | 21 |
| 22 DEFINE_FLAG(bool, intrinsify, true, "Instrinsify when possible"); | 22 DEFINE_FLAG(bool, intrinsify, true, "Instrinsify when possible"); |
| 23 DECLARE_FLAG(bool, throw_on_javascript_int_overflow); | 23 DECLARE_FLAG(bool, throw_on_javascript_int_overflow); |
| 24 DECLARE_FLAG(bool, code_comments); | 24 DECLARE_FLAG(bool, code_comments); |
| 25 DECLARE_FLAG(bool, print_flow_graph); | 25 DECLARE_FLAG(bool, print_flow_graph); |
| 26 DECLARE_FLAG(bool, print_flow_graph_optimized); | 26 DECLARE_FLAG(bool, print_flow_graph_optimized); |
| 27 DECLARE_FLAG(bool, enable_type_checks); | |
| 27 | 28 |
| 28 bool Intrinsifier::CanIntrinsify(const Function& function) { | 29 bool Intrinsifier::CanIntrinsify(const Function& function) { |
| 29 if (!FLAG_intrinsify) return false; | 30 if (!FLAG_intrinsify) return false; |
| 30 if (function.IsClosureFunction()) return false; | 31 if (function.IsClosureFunction()) return false; |
| 31 // Can occur because of compile-all flag. | 32 // Can occur because of compile-all flag. |
| 32 if (function.is_external()) return false; | 33 if (function.is_external()) return false; |
| 33 return function.is_intrinsic(); | 34 return function.is_intrinsic(); |
| 34 } | 35 } |
| 35 | 36 |
| 36 | 37 |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 198 // overflow. | 199 // overflow. |
| 199 switch (function.recognized_kind()) { | 200 switch (function.recognized_kind()) { |
| 200 ALL_INTRINSICS_NO_INTEGER_LIB_LIST(EMIT_CASE); | 201 ALL_INTRINSICS_NO_INTEGER_LIB_LIST(EMIT_CASE); |
| 201 default: | 202 default: |
| 202 break; | 203 break; |
| 203 } | 204 } |
| 204 } else { | 205 } else { |
| 205 switch (function.recognized_kind()) { | 206 switch (function.recognized_kind()) { |
| 206 ALL_INTRINSICS_LIST(EMIT_CASE); | 207 ALL_INTRINSICS_LIST(EMIT_CASE); |
| 207 default: | 208 default: |
| 208 UNREACHABLE(); | |
| 209 break; | 209 break; |
| 210 } | 210 } |
| 211 } | 211 } |
| 212 #undef EMIT_INTRINSIC | 212 #undef EMIT_INTRINSIC |
| 213 } | 213 } |
| 214 | 214 |
| 215 | 215 |
| 216 class BlockBuilder : public ValueObject { | 216 class BlockBuilder : public ValueObject { |
| 217 public: | 217 public: |
| 218 BlockBuilder(FlowGraph* flow_graph, TargetEntryInstr* entry) | 218 BlockBuilder(FlowGraph* flow_graph, TargetEntryInstr* entry) |
| (...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 559 Definition* capacity = builder.AddDefinition( | 559 Definition* capacity = builder.AddDefinition( |
| 560 new LoadFieldInstr(new Value(backing_store), | 560 new LoadFieldInstr(new Value(backing_store), |
| 561 Array::length_offset(), | 561 Array::length_offset(), |
| 562 Type::ZoneHandle(), | 562 Type::ZoneHandle(), |
| 563 builder.TokenPos())); | 563 builder.TokenPos())); |
| 564 builder.AddIntrinsicReturn(new Value(capacity)); | 564 builder.AddIntrinsicReturn(new Value(capacity)); |
| 565 return true; | 565 return true; |
| 566 } | 566 } |
| 567 | 567 |
| 568 | 568 |
| 569 bool Intrinsifier::Build_GrowableArrayGetIndexed(FlowGraph* flow_graph) { | |
| 570 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | |
| 571 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | |
| 572 BlockBuilder builder(flow_graph, normal_entry); | |
| 573 | |
| 574 Definition* index = builder.AddParameter(1); | |
| 575 Definition* growable_array = builder.AddParameter(2); | |
| 576 | |
| 577 PrepareIndexedOp( | |
| 578 &builder, growable_array, index, GrowableObjectArray::length_offset()); | |
| 579 | |
| 580 Definition* backing_store = builder.AddDefinition( | |
| 581 new LoadFieldInstr(new Value(growable_array), | |
| 582 GrowableObjectArray::data_offset(), | |
| 583 Type::ZoneHandle(), | |
| 584 builder.TokenPos())); | |
| 585 Definition* result = builder.AddDefinition( | |
| 586 new LoadIndexedInstr(new Value(backing_store), | |
| 587 new Value(index), | |
| 588 Instance::ElementSizeFor(kArrayCid), // index scale | |
| 589 kArrayCid, | |
| 590 Isolate::kNoDeoptId, | |
| 591 builder.TokenPos())); | |
| 592 builder.AddIntrinsicReturn(new Value(result)); | |
| 593 return true; | |
| 594 } | |
| 595 | |
| 596 | |
| 597 bool Intrinsifier::Build_GrowableArraySetIndexed(FlowGraph* flow_graph) { | |
| 598 if (FLAG_enable_type_checks) return false; | |
| 599 | |
| 600 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | |
| 601 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | |
| 602 BlockBuilder builder(flow_graph, normal_entry); | |
| 603 | |
| 604 Definition* value = builder.AddParameter(1); | |
| 605 Definition* index = builder.AddParameter(2); | |
| 606 Definition* array = builder.AddParameter(3); | |
| 607 | |
| 608 PrepareIndexedOp( | |
| 609 &builder, array, index, GrowableObjectArray::length_offset()); | |
| 610 | |
| 611 Definition* backing_store = builder.AddDefinition( | |
| 612 new LoadFieldInstr(new Value(array), | |
| 613 GrowableObjectArray::data_offset(), | |
| 614 Type::ZoneHandle(), | |
| 615 builder.TokenPos())); | |
| 616 | |
| 617 builder.AddInstruction( | |
| 618 new StoreIndexedInstr(new Value(backing_store), | |
| 619 new Value(index), | |
| 620 new Value(value), | |
| 621 kEmitStoreBarrier, | |
| 622 Instance::ElementSizeFor(kArrayCid), // index scale | |
| 623 kArrayCid, | |
| 624 Isolate::kNoDeoptId, | |
| 625 builder.TokenPos())); | |
| 626 // Return null. | |
| 627 Definition* null_def = builder.AddDefinition( | |
| 628 new ConstantInstr(Object::ZoneHandle(Object::null()))); | |
| 629 builder.AddIntrinsicReturn(new Value(null_def)); | |
| 630 return true; | |
| 631 } | |
| 632 | |
| 633 | |
| 634 bool Intrinsifier::Build_GrowableArraySetData(FlowGraph* flow_graph) { | |
| 635 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | |
| 636 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | |
| 637 BlockBuilder builder(flow_graph, normal_entry); | |
| 638 | |
| 639 Definition* data = builder.AddParameter(1); | |
| 640 Definition* growable_array = builder.AddParameter(2); | |
| 641 | |
| 642 const ICData& value_check = ICData::ZoneHandle(ICData::New( | |
| 643 flow_graph->parsed_function()->function(), | |
| 644 String::Handle(flow_graph->parsed_function()->function().name()), | |
| 645 Object::empty_array(), // Dummy args. descr. | |
| 646 Isolate::kNoDeoptId, | |
| 647 1)); | |
| 648 value_check.AddReceiverCheck(kArrayCid, | |
| 649 flow_graph->parsed_function()->function()); | |
| 650 builder.AddInstruction( | |
| 651 new CheckClassInstr(new Value(data), | |
| 652 Isolate::kNoDeoptId, | |
| 653 value_check, | |
| 654 builder.TokenPos())); | |
| 655 | |
| 656 builder.AddInstruction( | |
| 657 new StoreInstanceFieldInstr(GrowableObjectArray::data_offset(), | |
| 658 new Value(growable_array), | |
| 659 new Value(data), | |
| 660 kEmitStoreBarrier, | |
| 661 builder.TokenPos())); | |
| 662 // Return null. | |
| 663 Definition* null_def = builder.AddDefinition( | |
| 664 new ConstantInstr(Object::ZoneHandle(Object::null()))); | |
| 665 builder.AddIntrinsicReturn(new Value(null_def)); | |
| 666 return true; | |
| 667 } | |
| 668 | |
| 669 | |
| 670 bool Intrinsifier::Build_GrowableArraySetLength(FlowGraph* flow_graph) { | |
| 671 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | |
| 672 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | |
| 673 BlockBuilder builder(flow_graph, normal_entry); | |
| 674 | |
| 675 Definition* length = builder.AddParameter(1); | |
| 676 Definition* growable_array = builder.AddParameter(2); | |
| 677 | |
| 678 builder.AddInstruction( | |
| 679 new CheckSmiInstr(new Value(length), | |
| 680 Isolate::kNoDeoptId, | |
| 681 builder.TokenPos())); | |
| 682 builder.AddInstruction( | |
| 683 new StoreInstanceFieldInstr(GrowableObjectArray::length_offset(), | |
| 684 new Value(growable_array), | |
| 685 new Value(length), | |
| 686 kNoStoreBarrier, | |
| 687 builder.TokenPos())); | |
| 688 Definition* null_def = builder.AddDefinition( | |
|
zerny-google
2015/01/28 14:33:10
Should we abstract this in BlockBuilder::AddNullDe
Florian Schneider
2015/01/29 12:48:14
Done.
| |
| 689 new ConstantInstr(Object::ZoneHandle(Object::null()))); | |
| 690 builder.AddIntrinsicReturn(new Value(null_def)); | |
| 691 return true; | |
| 692 } | |
| 693 | |
| 569 } // namespace dart | 694 } // namespace dart |
| OLD | NEW |