| 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 27 matching lines...) Expand all Loading... |
| 246 return AddToInitialDefinitions( | 246 return AddToInitialDefinitions( |
| 247 new ParameterInstr(adjustment + index, | 247 new ParameterInstr(adjustment + index, |
| 248 flow_graph_->graph_entry(), | 248 flow_graph_->graph_entry(), |
| 249 SPREG)); | 249 SPREG)); |
| 250 } | 250 } |
| 251 | 251 |
| 252 intptr_t TokenPos() { | 252 intptr_t TokenPos() { |
| 253 return flow_graph_->parsed_function()->function().token_pos(); | 253 return flow_graph_->parsed_function()->function().token_pos(); |
| 254 } | 254 } |
| 255 | 255 |
| 256 Definition* AddNullDefinition() { |
| 257 return AddDefinition( |
| 258 new ConstantInstr(Object::ZoneHandle(Object::null()))); |
| 259 } |
| 260 |
| 256 private: | 261 private: |
| 257 FlowGraph* flow_graph_; | 262 FlowGraph* flow_graph_; |
| 258 BlockEntryInstr* entry_; | 263 BlockEntryInstr* entry_; |
| 259 Instruction* current_; | 264 Instruction* current_; |
| 260 }; | 265 }; |
| 261 | 266 |
| 262 | 267 |
| 263 static void PrepareIndexedOp(BlockBuilder* builder, | 268 static void PrepareIndexedOp(BlockBuilder* builder, |
| 264 Definition* array, | 269 Definition* array, |
| 265 Definition* index, | 270 Definition* index, |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 375 builder.AddInstruction( | 380 builder.AddInstruction( |
| 376 new StoreIndexedInstr(new Value(array), | 381 new StoreIndexedInstr(new Value(array), |
| 377 new Value(index), | 382 new Value(index), |
| 378 new Value(value), | 383 new Value(value), |
| 379 kNoStoreBarrier, | 384 kNoStoreBarrier, |
| 380 1, // index scale | 385 1, // index scale |
| 381 kTypedDataUint8ArrayCid, | 386 kTypedDataUint8ArrayCid, |
| 382 Isolate::kNoDeoptId, | 387 Isolate::kNoDeoptId, |
| 383 builder.TokenPos())); | 388 builder.TokenPos())); |
| 384 // Return null. | 389 // Return null. |
| 385 Definition* null_def = builder.AddDefinition( | 390 Definition* null_def = builder.AddNullDefinition(); |
| 386 new ConstantInstr(Object::ZoneHandle(Object::null()))); | |
| 387 builder.AddIntrinsicReturn(new Value(null_def)); | 391 builder.AddIntrinsicReturn(new Value(null_def)); |
| 388 return true; | 392 return true; |
| 389 } | 393 } |
| 390 | 394 |
| 391 | 395 |
| 392 bool Intrinsifier::Build_ExternalUint8ArraySetIndexed(FlowGraph* flow_graph) { | 396 bool Intrinsifier::Build_ExternalUint8ArraySetIndexed(FlowGraph* flow_graph) { |
| 393 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 397 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 394 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 398 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 395 BlockBuilder builder(flow_graph, normal_entry); | 399 BlockBuilder builder(flow_graph, normal_entry); |
| 396 | 400 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 410 builder.AddInstruction( | 414 builder.AddInstruction( |
| 411 new StoreIndexedInstr(new Value(elements), | 415 new StoreIndexedInstr(new Value(elements), |
| 412 new Value(index), | 416 new Value(index), |
| 413 new Value(value), | 417 new Value(value), |
| 414 kNoStoreBarrier, | 418 kNoStoreBarrier, |
| 415 1, // index scale | 419 1, // index scale |
| 416 kExternalTypedDataUint8ArrayCid, | 420 kExternalTypedDataUint8ArrayCid, |
| 417 Isolate::kNoDeoptId, | 421 Isolate::kNoDeoptId, |
| 418 builder.TokenPos())); | 422 builder.TokenPos())); |
| 419 // Return null. | 423 // Return null. |
| 420 Definition* null_def = builder.AddDefinition( | 424 Definition* null_def = builder.AddNullDefinition(); |
| 421 new ConstantInstr(Object::ZoneHandle(Object::null()))); | |
| 422 builder.AddIntrinsicReturn(new Value(null_def)); | 425 builder.AddIntrinsicReturn(new Value(null_def)); |
| 423 return true; | 426 return true; |
| 424 } | 427 } |
| 425 | 428 |
| 426 | 429 |
| 427 bool Intrinsifier::Build_Float64ArraySetIndexed(FlowGraph* flow_graph) { | 430 bool Intrinsifier::Build_Float64ArraySetIndexed(FlowGraph* flow_graph) { |
| 428 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; | 431 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; |
| 429 | 432 |
| 430 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 433 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 431 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 434 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 462 builder.AddInstruction( | 465 builder.AddInstruction( |
| 463 new StoreIndexedInstr(new Value(array), | 466 new StoreIndexedInstr(new Value(array), |
| 464 new Value(index), | 467 new Value(index), |
| 465 new Value(double_value), | 468 new Value(double_value), |
| 466 kNoStoreBarrier, | 469 kNoStoreBarrier, |
| 467 8, // index scale | 470 8, // index scale |
| 468 kTypedDataFloat64ArrayCid, | 471 kTypedDataFloat64ArrayCid, |
| 469 Isolate::kNoDeoptId, | 472 Isolate::kNoDeoptId, |
| 470 builder.TokenPos())); | 473 builder.TokenPos())); |
| 471 // Return null. | 474 // Return null. |
| 472 Definition* null_def = builder.AddDefinition( | 475 Definition* null_def = builder.AddNullDefinition(); |
| 473 new ConstantInstr(Object::ZoneHandle(Object::null()))); | |
| 474 builder.AddIntrinsicReturn(new Value(null_def)); | 476 builder.AddIntrinsicReturn(new Value(null_def)); |
| 475 return true; | 477 return true; |
| 476 } | 478 } |
| 477 | 479 |
| 478 | 480 |
| 479 bool Intrinsifier::Build_Float64ArrayGetIndexed(FlowGraph* flow_graph) { | 481 bool Intrinsifier::Build_Float64ArrayGetIndexed(FlowGraph* flow_graph) { |
| 480 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; | 482 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; |
| 481 | 483 |
| 482 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 484 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 483 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 485 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 559 Definition* capacity = builder.AddDefinition( | 561 Definition* capacity = builder.AddDefinition( |
| 560 new LoadFieldInstr(new Value(backing_store), | 562 new LoadFieldInstr(new Value(backing_store), |
| 561 Array::length_offset(), | 563 Array::length_offset(), |
| 562 Type::ZoneHandle(), | 564 Type::ZoneHandle(), |
| 563 builder.TokenPos())); | 565 builder.TokenPos())); |
| 564 builder.AddIntrinsicReturn(new Value(capacity)); | 566 builder.AddIntrinsicReturn(new Value(capacity)); |
| 565 return true; | 567 return true; |
| 566 } | 568 } |
| 567 | 569 |
| 568 | 570 |
| 571 bool Intrinsifier::Build_GrowableArrayGetIndexed(FlowGraph* flow_graph) { |
| 572 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 573 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 574 BlockBuilder builder(flow_graph, normal_entry); |
| 575 |
| 576 Definition* index = builder.AddParameter(1); |
| 577 Definition* growable_array = builder.AddParameter(2); |
| 578 |
| 579 PrepareIndexedOp( |
| 580 &builder, growable_array, index, GrowableObjectArray::length_offset()); |
| 581 |
| 582 Definition* backing_store = builder.AddDefinition( |
| 583 new LoadFieldInstr(new Value(growable_array), |
| 584 GrowableObjectArray::data_offset(), |
| 585 Type::ZoneHandle(), |
| 586 builder.TokenPos())); |
| 587 Definition* result = builder.AddDefinition( |
| 588 new LoadIndexedInstr(new Value(backing_store), |
| 589 new Value(index), |
| 590 Instance::ElementSizeFor(kArrayCid), // index scale |
| 591 kArrayCid, |
| 592 Isolate::kNoDeoptId, |
| 593 builder.TokenPos())); |
| 594 builder.AddIntrinsicReturn(new Value(result)); |
| 595 return true; |
| 596 } |
| 597 |
| 598 |
| 599 bool Intrinsifier::Build_GrowableArraySetIndexed(FlowGraph* flow_graph) { |
| 600 if (FLAG_enable_type_checks) return false; |
| 601 |
| 602 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 603 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 604 BlockBuilder builder(flow_graph, normal_entry); |
| 605 |
| 606 Definition* value = builder.AddParameter(1); |
| 607 Definition* index = builder.AddParameter(2); |
| 608 Definition* array = builder.AddParameter(3); |
| 609 |
| 610 PrepareIndexedOp( |
| 611 &builder, array, index, GrowableObjectArray::length_offset()); |
| 612 |
| 613 Definition* backing_store = builder.AddDefinition( |
| 614 new LoadFieldInstr(new Value(array), |
| 615 GrowableObjectArray::data_offset(), |
| 616 Type::ZoneHandle(), |
| 617 builder.TokenPos())); |
| 618 |
| 619 builder.AddInstruction( |
| 620 new StoreIndexedInstr(new Value(backing_store), |
| 621 new Value(index), |
| 622 new Value(value), |
| 623 kEmitStoreBarrier, |
| 624 Instance::ElementSizeFor(kArrayCid), // index scale |
| 625 kArrayCid, |
| 626 Isolate::kNoDeoptId, |
| 627 builder.TokenPos())); |
| 628 // Return null. |
| 629 Definition* null_def = builder.AddNullDefinition(); |
| 630 builder.AddIntrinsicReturn(new Value(null_def)); |
| 631 return true; |
| 632 } |
| 633 |
| 634 |
| 635 bool Intrinsifier::Build_GrowableArraySetData(FlowGraph* flow_graph) { |
| 636 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 637 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 638 BlockBuilder builder(flow_graph, normal_entry); |
| 639 |
| 640 Definition* data = builder.AddParameter(1); |
| 641 Definition* growable_array = builder.AddParameter(2); |
| 642 |
| 643 const ICData& value_check = ICData::ZoneHandle(ICData::New( |
| 644 flow_graph->parsed_function()->function(), |
| 645 String::Handle(flow_graph->parsed_function()->function().name()), |
| 646 Object::empty_array(), // Dummy args. descr. |
| 647 Isolate::kNoDeoptId, |
| 648 1)); |
| 649 value_check.AddReceiverCheck(kArrayCid, |
| 650 flow_graph->parsed_function()->function()); |
| 651 builder.AddInstruction( |
| 652 new CheckClassInstr(new Value(data), |
| 653 Isolate::kNoDeoptId, |
| 654 value_check, |
| 655 builder.TokenPos())); |
| 656 |
| 657 builder.AddInstruction( |
| 658 new StoreInstanceFieldInstr(GrowableObjectArray::data_offset(), |
| 659 new Value(growable_array), |
| 660 new Value(data), |
| 661 kEmitStoreBarrier, |
| 662 builder.TokenPos())); |
| 663 // Return null. |
| 664 Definition* null_def = builder.AddNullDefinition(); |
| 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.AddNullDefinition(); |
| 689 builder.AddIntrinsicReturn(new Value(null_def)); |
| 690 return true; |
| 691 } |
| 692 |
| 569 } // namespace dart | 693 } // namespace dart |
| OLD | NEW |