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

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

Issue 12871010: Replace scalarlist optimizations and split external array loads into two IL instructions. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 9 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/flow_graph_type_propagator.cc » ('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) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/cha.h" 8 #include "vm/cha.h"
9 #include "vm/flow_graph_builder.h" 9 #include "vm/flow_graph_builder.h"
10 #include "vm/flow_graph_compiler.h" 10 #include "vm/flow_graph_compiler.h"
(...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after
368 368
369 void FlowGraphOptimizer::InsertConversionsFor(Definition* def) { 369 void FlowGraphOptimizer::InsertConversionsFor(Definition* def) {
370 const Representation from_rep = def->representation(); 370 const Representation from_rep = def->representation();
371 371
372 for (Value::Iterator it(def->input_use_list()); 372 for (Value::Iterator it(def->input_use_list());
373 !it.Done(); 373 !it.Done();
374 it.Advance()) { 374 it.Advance()) {
375 Value* use = it.Current(); 375 Value* use = it.Current();
376 const Representation to_rep = 376 const Representation to_rep =
377 use->instruction()->RequiredInputRepresentation(use->use_index()); 377 use->instruction()->RequiredInputRepresentation(use->use_index());
378 if (from_rep == to_rep) { 378 if (from_rep == to_rep || to_rep == kNoRepresentation) {
379 continue; 379 continue;
380 } 380 }
381 381
382 Instruction* insert_before; 382 Instruction* insert_before;
383 Instruction* deopt_target; 383 Instruction* deopt_target;
384 PhiInstr* phi = use->instruction()->AsPhi(); 384 PhiInstr* phi = use->instruction()->AsPhi();
385 if (phi != NULL) { 385 if (phi != NULL) {
386 ASSERT(phi->is_alive()); 386 ASSERT(phi->is_alive());
387 // For phis conversions have to be inserted in the predecessor. 387 // For phis conversions have to be inserted in the predecessor.
388 insert_before = 388 insert_before =
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after
681 // Insert data elements load. 681 // Insert data elements load.
682 LoadFieldInstr* elements = 682 LoadFieldInstr* elements =
683 new LoadFieldInstr(new Value(*array), 683 new LoadFieldInstr(new Value(*array),
684 GrowableObjectArray::data_offset(), 684 GrowableObjectArray::data_offset(),
685 Type::ZoneHandle(Type::DynamicType())); 685 Type::ZoneHandle(Type::DynamicType()));
686 elements->set_result_cid(kArrayCid); 686 elements->set_result_cid(kArrayCid);
687 InsertBefore(call, elements, NULL, Definition::kValue); 687 InsertBefore(call, elements, NULL, Definition::kValue);
688 *array = elements; 688 *array = elements;
689 return kArrayCid; 689 return kArrayCid;
690 } 690 }
691 if (RawObject::IsExternalTypedDataClassId(class_id)) {
692 LoadUntaggedInstr* elements =
693 new LoadUntaggedInstr(new Value(*array),
694 ExternalTypedData::data_offset());
695 InsertBefore(call, elements, NULL, Definition::kValue);
696 *array = elements;
697 }
691 return class_id; 698 return class_id;
692 } 699 }
693 700
694 701
695 static bool CanUnboxInt32() { 702 static bool CanUnboxInt32() {
696 // Int32/Uint32 can be unboxed if it fits into a smi or the platform 703 // Int32/Uint32 can be unboxed if it fits into a smi or the platform
697 // supports unboxed mints. 704 // supports unboxed mints.
698 return (kSmiBits >= 32) || FlowGraphCompiler::SupportsUnboxedMints(); 705 return (kSmiBits >= 32) || FlowGraphCompiler::SupportsUnboxedMints();
699 } 706 }
700 707
701 708
702 bool FlowGraphOptimizer::TryReplaceWithStoreIndexed(InstanceCallInstr* call) { 709 bool FlowGraphOptimizer::TryReplaceWithStoreIndexed(InstanceCallInstr* call) {
703 const intptr_t class_id = ReceiverClassId(call); 710 const intptr_t class_id = ReceiverClassId(call);
704 ICData& value_check = ICData::ZoneHandle(); 711 ICData& value_check = ICData::ZoneHandle();
705 switch (class_id) { 712 switch (class_id) {
706 case kArrayCid: 713 case kArrayCid:
707 case kGrowableObjectArrayCid: 714 case kGrowableObjectArrayCid:
708 if (ArgIsAlwaysSmi(*call->ic_data(), 2)) { 715 if (ArgIsAlwaysSmi(*call->ic_data(), 2)) {
709 value_check = call->ic_data()->AsUnaryClassChecksForArgNr(2); 716 value_check = call->ic_data()->AsUnaryClassChecksForArgNr(2);
710 } 717 }
711 break; 718 break;
712 case kInt8ArrayCid:
713 case kUint8ArrayCid:
714 case kUint8ClampedArrayCid:
715 case kExternalUint8ArrayCid:
716 case kExternalUint8ClampedArrayCid:
717 case kInt16ArrayCid:
718 case kUint16ArrayCid:
719 case kTypedDataInt8ArrayCid: 719 case kTypedDataInt8ArrayCid:
720 case kTypedDataUint8ArrayCid: 720 case kTypedDataUint8ArrayCid:
721 case kTypedDataUint8ClampedArrayCid: 721 case kTypedDataUint8ClampedArrayCid:
722 case kExternalTypedDataUint8ArrayCid: 722 case kExternalTypedDataUint8ArrayCid:
723 case kExternalTypedDataUint8ClampedArrayCid: 723 case kExternalTypedDataUint8ClampedArrayCid:
724 case kTypedDataInt16ArrayCid: 724 case kTypedDataInt16ArrayCid:
725 case kTypedDataUint16ArrayCid: 725 case kTypedDataUint16ArrayCid:
726 // Check that value is always smi. 726 // Check that value is always smi.
727 value_check = call->ic_data()->AsUnaryClassChecksForArgNr(2); 727 value_check = call->ic_data()->AsUnaryClassChecksForArgNr(2);
728 if ((value_check.NumberOfChecks() != 1) || 728 if ((value_check.NumberOfChecks() != 1) ||
729 (value_check.GetReceiverClassIdAt(0) != kSmiCid)) { 729 (value_check.GetReceiverClassIdAt(0) != kSmiCid)) {
730 return false; 730 return false;
731 } 731 }
732 break; 732 break;
733 case kInt32ArrayCid:
734 case kUint32ArrayCid:
735 case kTypedDataInt32ArrayCid: 733 case kTypedDataInt32ArrayCid:
736 case kTypedDataUint32ArrayCid: { 734 case kTypedDataUint32ArrayCid: {
737 if (!CanUnboxInt32()) return false; 735 if (!CanUnboxInt32()) return false;
738 // Check that value is always smi or mint, if the platform has unboxed 736 // Check that value is always smi or mint, if the platform has unboxed
739 // mints (ia32 with at least SSE 4.1). 737 // mints (ia32 with at least SSE 4.1).
740 value_check = call->ic_data()->AsUnaryClassChecksForArgNr(2); 738 value_check = call->ic_data()->AsUnaryClassChecksForArgNr(2);
741 for (intptr_t i = 0; i < value_check.NumberOfChecks(); i++) { 739 for (intptr_t i = 0; i < value_check.NumberOfChecks(); i++) {
742 intptr_t cid = value_check.GetReceiverClassIdAt(i); 740 intptr_t cid = value_check.GetReceiverClassIdAt(i);
743 if (FlowGraphCompiler::SupportsUnboxedMints()) { 741 if (FlowGraphCompiler::SupportsUnboxedMints()) {
744 if ((cid != kSmiCid) && (cid != kMintCid)) { 742 if ((cid != kSmiCid) && (cid != kMintCid)) {
745 return false; 743 return false;
746 } 744 }
747 } else if (cid != kSmiCid) { 745 } else if (cid != kSmiCid) {
748 return false; 746 return false;
749 } 747 }
750 } 748 }
751 break; 749 break;
752 } 750 }
753 case kFloat32ArrayCid:
754 case kFloat64ArrayCid:
755 case kTypedDataFloat32ArrayCid: 751 case kTypedDataFloat32ArrayCid:
756 case kTypedDataFloat64ArrayCid: { 752 case kTypedDataFloat64ArrayCid: {
757 // Check that value is always double. 753 // Check that value is always double.
758 value_check = call->ic_data()->AsUnaryClassChecksForArgNr(2); 754 value_check = call->ic_data()->AsUnaryClassChecksForArgNr(2);
759 if ((value_check.NumberOfChecks() != 1) || 755 if ((value_check.NumberOfChecks() != 1) ||
760 (value_check.GetReceiverClassIdAt(0) != kDoubleCid)) { 756 (value_check.GetReceiverClassIdAt(0) != kDoubleCid)) {
761 return false; 757 return false;
762 } 758 }
763 break; 759 break;
764 } 760 }
765 default: 761 default:
766 // TODO(fschneider): Add support for other array types. 762 // TODO(fschneider): Add support for other array types.
767 return false; 763 return false;
768 } 764 }
769 765
770 BuildStoreIndexed(call, value_check, class_id); 766 BuildStoreIndexed(call, value_check, class_id);
771 return true; 767 return true;
772 } 768 }
773 769
774 770
775 bool FlowGraphOptimizer::TryInlineByteArraySetIndexed(InstanceCallInstr* call) {
776 const intptr_t class_id = ReceiverClassId(call);
777 ICData& value_check = ICData::ZoneHandle();
778 switch (class_id) {
779 case kInt8ArrayCid:
780 case kUint8ArrayCid:
781 case kUint8ClampedArrayCid:
782 case kExternalUint8ArrayCid:
783 case kExternalUint8ClampedArrayCid:
784 case kInt16ArrayCid:
785 case kUint16ArrayCid: {
786 // Check that value is always smi.
787 value_check = ICData::New(Function::Handle(),
788 String::Handle(),
789 Isolate::kNoDeoptId,
790 1);
791 value_check.AddReceiverCheck(kSmiCid, Function::Handle());
792 break;
793 }
794 case kInt32ArrayCid:
795 case kUint32ArrayCid:
796 if (!CanUnboxInt32()) return false;
797
798 // We don't have ICData for the value stored, so we optimistically assume
799 // smis first. If we ever deoptimized here, we require to unbox the value
800 // before storing to handle the mint case, too.
801 if (call->ic_data()->deopt_reason() == kDeoptUnknown) {
802 value_check = ICData::New(Function::Handle(),
803 String::Handle(),
804 Isolate::kNoDeoptId,
805 1);
806 value_check.AddReceiverCheck(kSmiCid, Function::Handle());
807 }
808 break;
809 case kFloat32ArrayCid:
810 case kFloat64ArrayCid: {
811 // Check that value is always double.
812 value_check = ICData::New(Function::Handle(),
813 String::Handle(),
814 Isolate::kNoDeoptId,
815 1);
816 value_check.AddReceiverCheck(kDoubleCid, Function::Handle());
817 break;
818 }
819 default:
820 return false;
821 }
822 BuildStoreIndexed(call, value_check, class_id);
823 return true;
824 }
825
826
827 void FlowGraphOptimizer::BuildStoreIndexed(InstanceCallInstr* call, 771 void FlowGraphOptimizer::BuildStoreIndexed(InstanceCallInstr* call,
828 const ICData& value_check, 772 const ICData& value_check,
829 intptr_t class_id) { 773 intptr_t class_id) {
830 Definition* array = call->ArgumentAt(0); 774 Definition* array = call->ArgumentAt(0);
831 Definition* index = call->ArgumentAt(1); 775 Definition* index = call->ArgumentAt(1);
832 Definition* stored_value = call->ArgumentAt(2); 776 Definition* stored_value = call->ArgumentAt(2);
833 if (FLAG_enable_type_checks) { 777 if (FLAG_enable_type_checks) {
834 // Only type check for the value. A type check for the index is not 778 // Only type check for the value. A type check for the index is not
835 // needed here because we insert a deoptimizing smi-check for the case 779 // needed here because we insert a deoptimizing smi-check for the case
836 // the index is not a smi. 780 // the index is not a smi.
(...skipping 11 matching lines...) Expand all
848 instantiator_class.type_arguments_field_offset(); 792 instantiator_class.type_arguments_field_offset();
849 LoadFieldInstr* load_type_args = 793 LoadFieldInstr* load_type_args =
850 new LoadFieldInstr(new Value(array), 794 new LoadFieldInstr(new Value(array),
851 type_arguments_field_offset, 795 type_arguments_field_offset,
852 Type::ZoneHandle()); // No type. 796 Type::ZoneHandle()); // No type.
853 InsertBefore(call, load_type_args, NULL, Definition::kValue); 797 InsertBefore(call, load_type_args, NULL, Definition::kValue);
854 instantiator = array; 798 instantiator = array;
855 type_args = load_type_args; 799 type_args = load_type_args;
856 break; 800 break;
857 } 801 }
858 case kInt8ArrayCid:
859 case kUint8ArrayCid:
860 case kUint8ClampedArrayCid:
861 case kExternalUint8ArrayCid:
862 case kExternalUint8ClampedArrayCid:
863 case kInt16ArrayCid:
864 case kUint16ArrayCid:
865 case kInt32ArrayCid:
866 case kUint32ArrayCid:
867 case kTypedDataInt8ArrayCid: 802 case kTypedDataInt8ArrayCid:
868 case kTypedDataUint8ArrayCid: 803 case kTypedDataUint8ArrayCid:
869 case kTypedDataUint8ClampedArrayCid: 804 case kTypedDataUint8ClampedArrayCid:
870 case kExternalTypedDataUint8ArrayCid: 805 case kExternalTypedDataUint8ArrayCid:
871 case kExternalTypedDataUint8ClampedArrayCid: 806 case kExternalTypedDataUint8ClampedArrayCid:
872 case kTypedDataInt16ArrayCid: 807 case kTypedDataInt16ArrayCid:
873 case kTypedDataUint16ArrayCid: 808 case kTypedDataUint16ArrayCid:
874 case kTypedDataInt32ArrayCid: 809 case kTypedDataInt32ArrayCid:
875 case kTypedDataUint32ArrayCid: 810 case kTypedDataUint32ArrayCid:
876 ASSERT(value_type.IsIntType()); 811 ASSERT(value_type.IsIntType());
877 // Fall through. 812 // Fall through.
878 case kFloat32ArrayCid:
879 case kFloat64ArrayCid:
880 case kTypedDataFloat32ArrayCid: 813 case kTypedDataFloat32ArrayCid:
881 case kTypedDataFloat64ArrayCid: { 814 case kTypedDataFloat64ArrayCid: {
882 type_args = instantiator = flow_graph_->constant_null(); 815 type_args = instantiator = flow_graph_->constant_null();
883 ASSERT((class_id != kFloat32ArrayCid && 816 ASSERT((class_id != kFloat32ArrayCid &&
884 class_id != kFloat64ArrayCid && 817 class_id != kFloat64ArrayCid &&
885 class_id != kTypedDataFloat32ArrayCid && 818 class_id != kTypedDataFloat32ArrayCid &&
886 class_id != kTypedDataFloat64ArrayCid) || 819 class_id != kTypedDataFloat64ArrayCid) ||
887 value_type.IsDoubleType()); 820 value_type.IsDoubleType());
888 ASSERT(value_type.IsInstantiated()); 821 ASSERT(value_type.IsInstantiated());
889 break; 822 break;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
934 867
935 868
936 bool FlowGraphOptimizer::TryReplaceWithLoadIndexed(InstanceCallInstr* call) { 869 bool FlowGraphOptimizer::TryReplaceWithLoadIndexed(InstanceCallInstr* call) {
937 const intptr_t class_id = ReceiverClassId(call); 870 const intptr_t class_id = ReceiverClassId(call);
938 // Set deopt_id to a valid id if the LoadIndexedInstr can cause deopt. 871 // Set deopt_id to a valid id if the LoadIndexedInstr can cause deopt.
939 intptr_t deopt_id = Isolate::kNoDeoptId; 872 intptr_t deopt_id = Isolate::kNoDeoptId;
940 switch (class_id) { 873 switch (class_id) {
941 case kArrayCid: 874 case kArrayCid:
942 case kImmutableArrayCid: 875 case kImmutableArrayCid:
943 case kGrowableObjectArrayCid: 876 case kGrowableObjectArrayCid:
944 case kFloat32ArrayCid:
945 case kFloat64ArrayCid:
946 case kInt8ArrayCid:
947 case kUint8ArrayCid:
948 case kUint8ClampedArrayCid:
949 case kExternalUint8ArrayCid:
950 case kExternalUint8ClampedArrayCid:
951 case kInt16ArrayCid:
952 case kUint16ArrayCid:
953 case kTypedDataFloat32ArrayCid: 877 case kTypedDataFloat32ArrayCid:
954 case kTypedDataFloat64ArrayCid: 878 case kTypedDataFloat64ArrayCid:
955 case kTypedDataInt8ArrayCid: 879 case kTypedDataInt8ArrayCid:
956 case kTypedDataUint8ArrayCid: 880 case kTypedDataUint8ArrayCid:
957 case kTypedDataUint8ClampedArrayCid: 881 case kTypedDataUint8ClampedArrayCid:
958 case kExternalTypedDataUint8ArrayCid: 882 case kExternalTypedDataUint8ArrayCid:
959 case kExternalTypedDataUint8ClampedArrayCid: 883 case kExternalTypedDataUint8ClampedArrayCid:
960 case kTypedDataInt16ArrayCid: 884 case kTypedDataInt16ArrayCid:
961 case kTypedDataUint16ArrayCid: 885 case kTypedDataUint16ArrayCid:
962 break; 886 break;
963 case kInt32ArrayCid:
964 case kUint32ArrayCid:
965 case kTypedDataInt32ArrayCid: 887 case kTypedDataInt32ArrayCid:
966 case kTypedDataUint32ArrayCid: { 888 case kTypedDataUint32ArrayCid: {
967 if (!CanUnboxInt32()) return false; 889 if (!CanUnboxInt32()) return false;
968 890
969 // Set deopt_id if we can optimistically assume that the result is Smi. 891 // Set deopt_id if we can optimistically assume that the result is Smi.
970 // Assume mixed Mint/Smi if this instruction caused deoptimization once. 892 // Assume mixed Mint/Smi if this instruction caused deoptimization once.
971 ASSERT(call->HasICData()); 893 ASSERT(call->HasICData());
972 const ICData& ic_data = *call->ic_data(); 894 const ICData& ic_data = *call->ic_data();
973 deopt_id = (ic_data.deopt_reason() == kDeoptUnknown) ? 895 deopt_id = (ic_data.deopt_reason() == kDeoptUnknown) ?
974 call->deopt_id() : Isolate::kNoDeoptId; 896 call->deopt_id() : Isolate::kNoDeoptId;
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after
1354 new Value(zero)); 1276 new Value(zero));
1355 ReplaceCall(call, compare); 1277 ReplaceCall(call, compare);
1356 } 1278 }
1357 1279
1358 1280
1359 static intptr_t OffsetForLengthGetter(MethodRecognizer::Kind kind) { 1281 static intptr_t OffsetForLengthGetter(MethodRecognizer::Kind kind) {
1360 switch (kind) { 1282 switch (kind) {
1361 case MethodRecognizer::kObjectArrayLength: 1283 case MethodRecognizer::kObjectArrayLength:
1362 case MethodRecognizer::kImmutableArrayLength: 1284 case MethodRecognizer::kImmutableArrayLength:
1363 return Array::length_offset(); 1285 return Array::length_offset();
1364 case MethodRecognizer::kByteArrayBaseLength:
1365 return ByteArray::length_offset();
1366 case MethodRecognizer::kTypedDataLength: 1286 case MethodRecognizer::kTypedDataLength:
1367 // .length is defined in _TypedList which is the base class for internal 1287 // .length is defined in _TypedList which is the base class for internal
1368 // and external typed data. 1288 // and external typed data.
1369 ASSERT(TypedData::length_offset() == ExternalTypedData::length_offset()); 1289 ASSERT(TypedData::length_offset() == ExternalTypedData::length_offset());
1370 return TypedData::length_offset(); 1290 return TypedData::length_offset();
1371 case MethodRecognizer::kGrowableArrayLength: 1291 case MethodRecognizer::kGrowableArrayLength:
1372 return GrowableObjectArray::length_offset(); 1292 return GrowableObjectArray::length_offset();
1373 default: 1293 default:
1374 UNREACHABLE(); 1294 UNREACHABLE();
1375 return 0; 1295 return 0;
(...skipping 22 matching lines...) Expand all
1398 } 1318 }
1399 1319
1400 // Not an implicit getter. 1320 // Not an implicit getter.
1401 MethodRecognizer::Kind recognized_kind = 1321 MethodRecognizer::Kind recognized_kind =
1402 MethodRecognizer::RecognizeKind(target); 1322 MethodRecognizer::RecognizeKind(target);
1403 1323
1404 // VM objects length getter. 1324 // VM objects length getter.
1405 switch (recognized_kind) { 1325 switch (recognized_kind) {
1406 case MethodRecognizer::kObjectArrayLength: 1326 case MethodRecognizer::kObjectArrayLength:
1407 case MethodRecognizer::kImmutableArrayLength: 1327 case MethodRecognizer::kImmutableArrayLength:
1408 case MethodRecognizer::kByteArrayBaseLength:
1409 case MethodRecognizer::kTypedDataLength: 1328 case MethodRecognizer::kTypedDataLength:
1410 case MethodRecognizer::kGrowableArrayLength: { 1329 case MethodRecognizer::kGrowableArrayLength: {
1411 if (!ic_data.HasOneTarget()) { 1330 if (!ic_data.HasOneTarget()) {
1412 // TODO(srdjan): Implement for mutiple targets. 1331 // TODO(srdjan): Implement for mutiple targets.
1413 return false; 1332 return false;
1414 } 1333 }
1415 const bool is_immutable = 1334 const bool is_immutable =
1416 (recognized_kind == MethodRecognizer::kObjectArrayLength) || 1335 (recognized_kind == MethodRecognizer::kObjectArrayLength) ||
1417 (recognized_kind == MethodRecognizer::kImmutableArrayLength) || 1336 (recognized_kind == MethodRecognizer::kImmutableArrayLength) ||
1418 (recognized_kind == MethodRecognizer::kByteArrayBaseLength) ||
1419 (recognized_kind == MethodRecognizer::kTypedDataLength); 1337 (recognized_kind == MethodRecognizer::kTypedDataLength);
1420 InlineArrayLengthGetter(call, 1338 InlineArrayLengthGetter(call,
1421 OffsetForLengthGetter(recognized_kind), 1339 OffsetForLengthGetter(recognized_kind),
1422 is_immutable, 1340 is_immutable,
1423 recognized_kind); 1341 recognized_kind);
1424 return true; 1342 return true;
1425 } 1343 }
1426 case MethodRecognizer::kGrowableArrayCapacity: 1344 case MethodRecognizer::kGrowableArrayCapacity:
1427 InlineGrowableArrayCapacityGetter(call); 1345 InlineGrowableArrayCapacityGetter(call);
1428 return true; 1346 return true;
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
1497 args->Add(new Value(call->ArgumentAt(i))); 1415 args->Add(new Value(call->ArgumentAt(i)));
1498 } 1416 }
1499 InvokeMathCFunctionInstr* invoke = 1417 InvokeMathCFunctionInstr* invoke =
1500 new InvokeMathCFunctionInstr(args, call, recognized_kind); 1418 new InvokeMathCFunctionInstr(args, call, recognized_kind);
1501 ReplaceCall(call, invoke); 1419 ReplaceCall(call, invoke);
1502 } 1420 }
1503 1421
1504 1422
1505 static bool IsSupportedByteArrayViewCid(intptr_t cid) { 1423 static bool IsSupportedByteArrayViewCid(intptr_t cid) {
1506 switch (cid) { 1424 switch (cid) {
1507 case kInt8ArrayCid: 1425 case kTypedDataInt8ArrayCid:
1508 case kUint8ArrayCid: 1426 case kTypedDataUint8ArrayCid:
1509 case kUint8ClampedArrayCid: 1427 case kExternalTypedDataUint8ArrayCid:
1510 case kInt16ArrayCid: 1428 case kTypedDataUint8ClampedArrayCid:
1511 case kUint16ArrayCid: 1429 case kExternalTypedDataUint8ClampedArrayCid:
1512 case kInt32ArrayCid: 1430 case kTypedDataInt16ArrayCid:
1513 case kUint32ArrayCid: 1431 case kTypedDataUint16ArrayCid:
1514 case kFloat32ArrayCid: 1432 case kTypedDataInt32ArrayCid:
1515 case kFloat64ArrayCid: 1433 case kTypedDataUint32ArrayCid:
1434 case kTypedDataFloat32ArrayCid:
1435 case kTypedDataFloat64ArrayCid:
1516 return true; 1436 return true;
1517 default: 1437 default:
1518 return false; 1438 return false;
1519 } 1439 }
1520 } 1440 }
1521 1441
1522 1442
1523 // Inline only simple, frequently called core library methods. 1443 // Inline only simple, frequently called core library methods.
1524 bool FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) { 1444 bool FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) {
1525 ASSERT(call->HasICData()); 1445 ASSERT(call->HasICData());
1526 const ICData& ic_data = *call->ic_data(); 1446 const ICData& ic_data = *call->ic_data();
1527 if ((ic_data.NumberOfChecks() == 0) || !ic_data.HasOneTarget()) { 1447 if ((ic_data.NumberOfChecks() == 0) || !ic_data.HasOneTarget()) {
1528 // No type feedback collected or multiple targets found. 1448 // No type feedback collected or multiple targets found.
1529 return false; 1449 return false;
1530 } 1450 }
1531 1451
1532 Function& target = Function::Handle(); 1452 Function& target = Function::Handle();
1533 GrowableArray<intptr_t> class_ids; 1453 GrowableArray<intptr_t> class_ids;
1534 ic_data.GetCheckAt(0, &class_ids, &target); 1454 ic_data.GetCheckAt(0, &class_ids, &target);
1535 MethodRecognizer::Kind recognized_kind = 1455 MethodRecognizer::Kind recognized_kind =
1536 MethodRecognizer::RecognizeKind(target); 1456 MethodRecognizer::RecognizeKind(target);
1537 1457
1538 // Byte array access.
1539 switch (recognized_kind) {
1540 case MethodRecognizer::kFloat32ArrayGetIndexed:
1541 case MethodRecognizer::kFloat64ArrayGetIndexed:
1542 case MethodRecognizer::kInt8ArrayGetIndexed:
1543 case MethodRecognizer::kUint8ArrayGetIndexed:
1544 case MethodRecognizer::kUint8ClampedArrayGetIndexed:
1545 case MethodRecognizer::kExternalUint8ArrayGetIndexed:
1546 case MethodRecognizer::kExternalUint8ClampedArrayGetIndexed:
1547 case MethodRecognizer::kInt16ArrayGetIndexed:
1548 case MethodRecognizer::kUint16ArrayGetIndexed:
1549 case MethodRecognizer::kInt32ArrayGetIndexed:
1550 case MethodRecognizer::kUint32ArrayGetIndexed:
1551 return TryReplaceWithLoadIndexed(call);
1552
1553 case MethodRecognizer::kFloat32ArraySetIndexed:
1554 case MethodRecognizer::kFloat64ArraySetIndexed:
1555 case MethodRecognizer::kInt8ArraySetIndexed:
1556 case MethodRecognizer::kUint8ArraySetIndexed:
1557 case MethodRecognizer::kUint8ClampedArraySetIndexed:
1558 case MethodRecognizer::kExternalUint8ArraySetIndexed:
1559 case MethodRecognizer::kExternalUint8ClampedArraySetIndexed:
1560 case MethodRecognizer::kInt16ArraySetIndexed:
1561 case MethodRecognizer::kUint16ArraySetIndexed:
1562 case MethodRecognizer::kInt32ArraySetIndexed:
1563 case MethodRecognizer::kUint32ArraySetIndexed:
1564 return TryInlineByteArraySetIndexed(call);
1565
1566 default:
1567 break;
1568 }
1569
1570 if ((recognized_kind == MethodRecognizer::kStringBaseCodeUnitAt) && 1458 if ((recognized_kind == MethodRecognizer::kStringBaseCodeUnitAt) &&
1571 (ic_data.NumberOfChecks() == 1) && 1459 (ic_data.NumberOfChecks() == 1) &&
1572 ((class_ids[0] == kOneByteStringCid) || 1460 ((class_ids[0] == kOneByteStringCid) ||
1573 (class_ids[0] == kTwoByteStringCid))) { 1461 (class_ids[0] == kTwoByteStringCid))) {
1574 LoadIndexedInstr* instr = BuildStringCodeUnitAt(call, class_ids[0]); 1462 LoadIndexedInstr* instr = BuildStringCodeUnitAt(call, class_ids[0]);
1575 ReplaceCall(call, instr); 1463 ReplaceCall(call, instr);
1576 return true; 1464 return true;
1577 } 1465 }
1578 if ((recognized_kind == MethodRecognizer::kStringBaseCharAt) && 1466 if ((recognized_kind == MethodRecognizer::kStringBaseCharAt) &&
1579 (ic_data.NumberOfChecks() == 1) && 1467 (ic_data.NumberOfChecks() == 1) &&
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
1648 if ((recognized_kind == MethodRecognizer::kByteArrayBaseGetInt32) || 1536 if ((recognized_kind == MethodRecognizer::kByteArrayBaseGetInt32) ||
1649 (recognized_kind == MethodRecognizer::kByteArrayBaseGetUint32) || 1537 (recognized_kind == MethodRecognizer::kByteArrayBaseGetUint32) ||
1650 (recognized_kind == MethodRecognizer::kByteArrayBaseSetInt32) || 1538 (recognized_kind == MethodRecognizer::kByteArrayBaseSetInt32) ||
1651 (recognized_kind == MethodRecognizer::kByteArrayBaseSetUint32)) { 1539 (recognized_kind == MethodRecognizer::kByteArrayBaseSetUint32)) {
1652 if (!CanUnboxInt32()) return false; 1540 if (!CanUnboxInt32()) return false;
1653 } 1541 }
1654 1542
1655 switch (recognized_kind) { 1543 switch (recognized_kind) {
1656 // ByteArray getters. 1544 // ByteArray getters.
1657 case MethodRecognizer::kByteArrayBaseGetInt8: 1545 case MethodRecognizer::kByteArrayBaseGetInt8:
1658 return BuildByteArrayViewLoad(call, class_ids[0], kInt8ArrayCid); 1546 return BuildByteArrayViewLoad(
1547 call, class_ids[0], kTypedDataInt8ArrayCid);
1659 case MethodRecognizer::kByteArrayBaseGetUint8: 1548 case MethodRecognizer::kByteArrayBaseGetUint8:
1660 return BuildByteArrayViewLoad(call, class_ids[0], kUint8ArrayCid); 1549 return BuildByteArrayViewLoad(
1550 call, class_ids[0], kTypedDataUint8ArrayCid);
1661 case MethodRecognizer::kByteArrayBaseGetInt16: 1551 case MethodRecognizer::kByteArrayBaseGetInt16:
1662 return BuildByteArrayViewLoad(call, class_ids[0], kInt16ArrayCid); 1552 return BuildByteArrayViewLoad(
1553 call, class_ids[0], kTypedDataInt16ArrayCid);
1663 case MethodRecognizer::kByteArrayBaseGetUint16: 1554 case MethodRecognizer::kByteArrayBaseGetUint16:
1664 return BuildByteArrayViewLoad(call, class_ids[0], kUint16ArrayCid); 1555 return BuildByteArrayViewLoad(
1556 call, class_ids[0], kTypedDataUint16ArrayCid);
1665 case MethodRecognizer::kByteArrayBaseGetInt32: 1557 case MethodRecognizer::kByteArrayBaseGetInt32:
1666 return BuildByteArrayViewLoad(call, class_ids[0], kInt32ArrayCid); 1558 return BuildByteArrayViewLoad(
1559 call, class_ids[0], kTypedDataInt32ArrayCid);
1667 case MethodRecognizer::kByteArrayBaseGetUint32: 1560 case MethodRecognizer::kByteArrayBaseGetUint32:
1668 return BuildByteArrayViewLoad(call, class_ids[0], kUint32ArrayCid); 1561 return BuildByteArrayViewLoad(
1562 call, class_ids[0], kTypedDataUint32ArrayCid);
1669 case MethodRecognizer::kByteArrayBaseGetFloat32: 1563 case MethodRecognizer::kByteArrayBaseGetFloat32:
1670 return BuildByteArrayViewLoad(call, class_ids[0], kFloat32ArrayCid); 1564 return BuildByteArrayViewLoad(
1565 call, class_ids[0], kTypedDataFloat32ArrayCid);
1671 case MethodRecognizer::kByteArrayBaseGetFloat64: 1566 case MethodRecognizer::kByteArrayBaseGetFloat64:
1672 return BuildByteArrayViewLoad(call, class_ids[0], kFloat64ArrayCid); 1567 return BuildByteArrayViewLoad(
1568 call, class_ids[0], kTypedDataFloat64ArrayCid);
1673 1569
1674 // ByteArray setters. 1570 // ByteArray setters.
1675 case MethodRecognizer::kByteArrayBaseSetInt8: 1571 case MethodRecognizer::kByteArrayBaseSetInt8:
1676 return BuildByteArrayViewStore(call, class_ids[0], kInt8ArrayCid); 1572 return BuildByteArrayViewStore(
1573 call, class_ids[0], kTypedDataInt8ArrayCid);
1677 case MethodRecognizer::kByteArrayBaseSetUint8: 1574 case MethodRecognizer::kByteArrayBaseSetUint8:
1678 return BuildByteArrayViewStore(call, class_ids[0], kUint8ArrayCid); 1575 return BuildByteArrayViewStore(
1576 call, class_ids[0], kTypedDataUint8ArrayCid);
1679 case MethodRecognizer::kByteArrayBaseSetInt16: 1577 case MethodRecognizer::kByteArrayBaseSetInt16:
1680 return BuildByteArrayViewStore(call, class_ids[0], kInt16ArrayCid); 1578 return BuildByteArrayViewStore(
1579 call, class_ids[0], kTypedDataInt16ArrayCid);
1681 case MethodRecognizer::kByteArrayBaseSetUint16: 1580 case MethodRecognizer::kByteArrayBaseSetUint16:
1682 return BuildByteArrayViewStore(call, class_ids[0], kUint16ArrayCid); 1581 return BuildByteArrayViewStore(
1582 call, class_ids[0], kTypedDataUint16ArrayCid);
1683 case MethodRecognizer::kByteArrayBaseSetInt32: 1583 case MethodRecognizer::kByteArrayBaseSetInt32:
1684 return BuildByteArrayViewStore(call, class_ids[0], kInt32ArrayCid); 1584 return BuildByteArrayViewStore(
1585 call, class_ids[0], kTypedDataInt32ArrayCid);
1685 case MethodRecognizer::kByteArrayBaseSetUint32: 1586 case MethodRecognizer::kByteArrayBaseSetUint32:
1686 return BuildByteArrayViewStore(call, class_ids[0], kUint32ArrayCid); 1587 return BuildByteArrayViewStore(
1588 call, class_ids[0], kTypedDataUint32ArrayCid);
1687 case MethodRecognizer::kByteArrayBaseSetFloat32: 1589 case MethodRecognizer::kByteArrayBaseSetFloat32:
1688 return BuildByteArrayViewStore(call, class_ids[0], kFloat32ArrayCid); 1590 return BuildByteArrayViewStore(
1591 call, class_ids[0], kTypedDataFloat32ArrayCid);
1689 case MethodRecognizer::kByteArrayBaseSetFloat64: 1592 case MethodRecognizer::kByteArrayBaseSetFloat64:
1690 return BuildByteArrayViewStore(call, class_ids[0], kFloat64ArrayCid); 1593 return BuildByteArrayViewStore(
1594 call, class_ids[0], kTypedDataFloat64ArrayCid);
1691 default: 1595 default:
1692 // Unsupported method. 1596 // Unsupported method.
1693 return false; 1597 return false;
1694 } 1598 }
1695 } 1599 }
1696 return false; 1600 return false;
1697 } 1601 }
1698 1602
1699 1603
1700 bool FlowGraphOptimizer::BuildByteArrayViewLoad( 1604 bool FlowGraphOptimizer::BuildByteArrayViewLoad(
1701 InstanceCallInstr* call, 1605 InstanceCallInstr* call,
1702 intptr_t receiver_cid, 1606 intptr_t receiver_cid,
1703 intptr_t view_cid) { 1607 intptr_t view_cid) {
1704 PrepareByteArrayViewOp(call, receiver_cid, view_cid);
1705
1706 Definition* array = call->ArgumentAt(0); 1608 Definition* array = call->ArgumentAt(0);
1707 Definition* byte_index = call->ArgumentAt(1); 1609 PrepareByteArrayViewOp(call, receiver_cid, view_cid, &array);
1708 1610
1709 // Optimistically build a smi-checked load for Int32 and Uint32 1611 // Optimistically build a smi-checked load for Int32 and Uint32
1710 // loads on ia32 like we do for normal array loads, and only revert to 1612 // loads on ia32 like we do for normal array loads, and only revert to
1711 // mint case after deoptimizing here. 1613 // mint case after deoptimizing here.
1712 intptr_t deopt_id = Isolate::kNoDeoptId; 1614 intptr_t deopt_id = Isolate::kNoDeoptId;
1713 if ((view_cid == kInt32ArrayCid || view_cid == kUint32ArrayCid) && 1615 if ((view_cid == kInt32ArrayCid || view_cid == kUint32ArrayCid) &&
1714 call->ic_data()->deopt_reason() == kDeoptUnknown) { 1616 call->ic_data()->deopt_reason() == kDeoptUnknown) {
1715 deopt_id = call->deopt_id(); 1617 deopt_id = call->deopt_id();
1716 } 1618 }
1619 Definition* byte_index = call->ArgumentAt(1);
1717 LoadIndexedInstr* array_op = new LoadIndexedInstr(new Value(array), 1620 LoadIndexedInstr* array_op = new LoadIndexedInstr(new Value(array),
1718 new Value(byte_index), 1621 new Value(byte_index),
1719 1, // Index scale. 1622 1, // Index scale.
1720 view_cid, 1623 view_cid,
1721 deopt_id); 1624 deopt_id);
1722 ReplaceCall(call, array_op); 1625 ReplaceCall(call, array_op);
1723 return true; 1626 return true;
1724 } 1627 }
1725 1628
1726 1629
1727 bool FlowGraphOptimizer::BuildByteArrayViewStore( 1630 bool FlowGraphOptimizer::BuildByteArrayViewStore(
1728 InstanceCallInstr* call, 1631 InstanceCallInstr* call,
1729 intptr_t receiver_cid, 1632 intptr_t receiver_cid,
1730 intptr_t view_cid) { 1633 intptr_t view_cid) {
1731 PrepareByteArrayViewOp(call, receiver_cid, view_cid); 1634 Definition* array = call->ArgumentAt(0);
1635 PrepareByteArrayViewOp(call, receiver_cid, view_cid, &array);
1732 ICData& value_check = ICData::ZoneHandle(); 1636 ICData& value_check = ICData::ZoneHandle();
1733 switch (view_cid) { 1637 switch (view_cid) {
1734 case kInt8ArrayCid: 1638 case kTypedDataInt8ArrayCid:
1735 case kUint8ArrayCid: 1639 case kTypedDataUint8ArrayCid:
1736 case kUint8ClampedArrayCid: 1640 case kTypedDataUint8ClampedArrayCid:
1737 case kExternalUint8ArrayCid: 1641 case kExternalTypedDataUint8ArrayCid:
1738 case kExternalUint8ClampedArrayCid: 1642 case kExternalTypedDataUint8ClampedArrayCid:
1739 case kInt16ArrayCid: 1643 case kTypedDataInt16ArrayCid:
1740 case kUint16ArrayCid: { 1644 case kTypedDataUint16ArrayCid: {
1741 // Check that value is always smi. 1645 // Check that value is always smi.
1742 value_check = ICData::New(Function::Handle(), 1646 value_check = ICData::New(Function::Handle(),
1743 String::Handle(), 1647 String::Handle(),
1744 Isolate::kNoDeoptId, 1648 Isolate::kNoDeoptId,
1745 1); 1649 1);
1746 value_check.AddReceiverCheck(kSmiCid, Function::Handle()); 1650 value_check.AddReceiverCheck(kSmiCid, Function::Handle());
1747 break; 1651 break;
1748 } 1652 }
1749 case kInt32ArrayCid: 1653 case kTypedDataInt32ArrayCid:
1750 case kUint32ArrayCid: 1654 case kTypedDataUint32ArrayCid:
1751 // We don't have ICData for the value stored, so we optimistically assume 1655 // We don't have ICData for the value stored, so we optimistically assume
1752 // smis first. If we ever deoptimized here, we require to unbox the value 1656 // smis first. If we ever deoptimized here, we require to unbox the value
1753 // before storing to handle the mint case, too. 1657 // before storing to handle the mint case, too.
1754 if (call->ic_data()->deopt_reason() == kDeoptUnknown) { 1658 if (call->ic_data()->deopt_reason() == kDeoptUnknown) {
1755 value_check = ICData::New(Function::Handle(), 1659 value_check = ICData::New(Function::Handle(),
1756 String::Handle(), 1660 String::Handle(),
1757 Isolate::kNoDeoptId, 1661 Isolate::kNoDeoptId,
1758 1); 1662 1);
1759 value_check.AddReceiverCheck(kSmiCid, Function::Handle()); 1663 value_check.AddReceiverCheck(kSmiCid, Function::Handle());
1760 } 1664 }
1761 break; 1665 break;
1762 case kFloat32ArrayCid: 1666 case kTypedDataFloat32ArrayCid:
1763 case kFloat64ArrayCid: { 1667 case kTypedDataFloat64ArrayCid: {
1764 // Check that value is always double. 1668 // Check that value is always double.
1765 value_check = ICData::New(Function::Handle(), 1669 value_check = ICData::New(Function::Handle(),
1766 String::Handle(), 1670 String::Handle(),
1767 Isolate::kNoDeoptId, 1671 Isolate::kNoDeoptId,
1768 1); 1672 1);
1769 value_check.AddReceiverCheck(kDoubleCid, Function::Handle()); 1673 value_check.AddReceiverCheck(kDoubleCid, Function::Handle());
1770 break; 1674 break;
1771 } 1675 }
1772 default: 1676 default:
1773 // Array cids are already checked in the caller. 1677 // Array cids are already checked in the caller.
1774 UNREACHABLE(); 1678 UNREACHABLE();
1775 return NULL; 1679 return NULL;
1776 } 1680 }
1777 1681
1778 Definition* array = call->ArgumentAt(0);
1779 Definition* index = call->ArgumentAt(1); 1682 Definition* index = call->ArgumentAt(1);
1780 Definition* stored_value = call->ArgumentAt(2); 1683 Definition* stored_value = call->ArgumentAt(2);
1781 if (!value_check.IsNull()) { 1684 if (!value_check.IsNull()) {
1782 AddCheckClass(stored_value, value_check, call->deopt_id(), call->env(), 1685 AddCheckClass(stored_value, value_check, call->deopt_id(), call->env(),
1783 call); 1686 call);
1784 } 1687 }
1785 StoreBarrierType needs_store_barrier = kNoStoreBarrier; 1688 StoreBarrierType needs_store_barrier = kNoStoreBarrier;
1786
1787
1788 // result = index + bytesPerElement.
1789 intptr_t element_size = FlowGraphCompiler::ElementSizeFor(receiver_cid);
1790 ConstantInstr* bytes_per_element =
1791 new ConstantInstr(Smi::Handle(Smi::New(element_size)));
1792 InsertBefore(call, bytes_per_element, NULL, Definition::kValue);
1793 BinarySmiOpInstr* result =
1794 new BinarySmiOpInstr(Token::kADD,
1795 call,
1796 new Value(index),
1797 new Value(bytes_per_element));
1798 InsertBefore(call, result, call->env(), Definition::kValue);
1799
1800 StoreIndexedInstr* array_op = new StoreIndexedInstr(new Value(array), 1689 StoreIndexedInstr* array_op = new StoreIndexedInstr(new Value(array),
1801 new Value(index), 1690 new Value(index),
1802 new Value(stored_value), 1691 new Value(stored_value),
1803 needs_store_barrier, 1692 needs_store_barrier,
1804 1, // Index scale 1693 1, // Index scale
1805 view_cid, 1694 view_cid,
1806 call->deopt_id()); 1695 call->deopt_id());
1807 call->ReplaceUsesWith(result); // Fix uses of the call's return value.
1808 ReplaceCall(call, array_op); 1696 ReplaceCall(call, array_op);
1809 array_op->ClearSSATempIndex(); // Store has no uses.
1810 return true; 1697 return true;
1811 } 1698 }
1812 1699
1813 1700
1814 void FlowGraphOptimizer::PrepareByteArrayViewOp( 1701 void FlowGraphOptimizer::PrepareByteArrayViewOp(
1815 InstanceCallInstr* call, 1702 InstanceCallInstr* call,
1816 intptr_t receiver_cid, 1703 intptr_t receiver_cid,
1817 intptr_t view_cid) { 1704 intptr_t view_cid,
1818 Definition* array = call->ArgumentAt(0); 1705 Definition** array) {
1819 Definition* byte_index = call->ArgumentAt(1); 1706 Definition* byte_index = call->ArgumentAt(1);
1820 1707
1821 AddReceiverCheck(call); 1708 AddReceiverCheck(call);
1822 const bool is_immutable = true; 1709 const bool is_immutable = true;
1823 LoadFieldInstr* length = new LoadFieldInstr( 1710 LoadFieldInstr* length = new LoadFieldInstr(
1824 new Value(array), 1711 new Value(*array),
1825 CheckArrayBoundInstr::LengthOffsetFor(receiver_cid), 1712 CheckArrayBoundInstr::LengthOffsetFor(receiver_cid),
1826 Type::ZoneHandle(Type::SmiType()), 1713 Type::ZoneHandle(Type::SmiType()),
1827 is_immutable); 1714 is_immutable);
1828 length->set_result_cid(kSmiCid); 1715 length->set_result_cid(kSmiCid);
1829 length->set_recognized_kind( 1716 length->set_recognized_kind(
1830 LoadFieldInstr::RecognizedKindFromArrayCid(receiver_cid)); 1717 LoadFieldInstr::RecognizedKindFromArrayCid(receiver_cid));
1831 InsertBefore(call, length, NULL, Definition::kValue); 1718 InsertBefore(call, length, NULL, Definition::kValue);
1832 1719
1833 // len_in_bytes = length * kBytesPerElement(receiver) 1720 // len_in_bytes = length * kBytesPerElement(receiver)
1834 intptr_t element_size = FlowGraphCompiler::ElementSizeFor(receiver_cid); 1721 intptr_t element_size = FlowGraphCompiler::ElementSizeFor(receiver_cid);
1835 ConstantInstr* bytes_per_element = 1722 ConstantInstr* bytes_per_element =
1836 new ConstantInstr(Smi::Handle(Smi::New(element_size))); 1723 new ConstantInstr(Smi::Handle(Smi::New(element_size)));
1837 InsertBefore(call, bytes_per_element, NULL, Definition::kValue); 1724 InsertBefore(call, bytes_per_element, NULL, Definition::kValue);
1838 BinarySmiOpInstr* len_in_bytes = 1725 BinarySmiOpInstr* len_in_bytes =
1839 new BinarySmiOpInstr(Token::kMUL, 1726 new BinarySmiOpInstr(Token::kMUL,
1840 call, 1727 call,
1841 new Value(length), 1728 new Value(length),
1842 new Value(bytes_per_element)); 1729 new Value(bytes_per_element));
1843 InsertBefore(call, len_in_bytes, call->env(), Definition::kValue); 1730 InsertBefore(call, len_in_bytes, call->env(), Definition::kValue);
1844 1731
1845 // Check byte_index < len_in_bytes. 1732 // Check byte_index < len_in_bytes.
1846 InsertBefore(call, 1733 InsertBefore(call,
1847 new CheckArrayBoundInstr(new Value(len_in_bytes), 1734 new CheckArrayBoundInstr(new Value(len_in_bytes),
1848 new Value(byte_index), 1735 new Value(byte_index),
1849 receiver_cid, 1736 receiver_cid,
1850 call), 1737 call),
1851 call->env(), 1738 call->env(),
1852 Definition::kEffect); 1739 Definition::kEffect);
1740
1741 // Insert load of elements for external typed arrays.
1742 if (RawObject::IsExternalTypedDataClassId(receiver_cid)) {
1743 LoadUntaggedInstr* elements =
1744 new LoadUntaggedInstr(new Value(*array),
1745 ExternalTypedData::data_offset());
1746 InsertBefore(call, elements, NULL, Definition::kValue);
1747 *array = elements;
1748 }
1853 } 1749 }
1854 1750
1855 1751
1856 // Returns a Boolean constant if all classes in ic_data yield the same type-test 1752 // Returns a Boolean constant if all classes in ic_data yield the same type-test
1857 // result and the type tests do not depend on type arguments. Otherwise return 1753 // result and the type tests do not depend on type arguments. Otherwise return
1858 // Bool::null(). 1754 // Bool::null().
1859 RawBool* FlowGraphOptimizer::InstanceOfAsBool(const ICData& ic_data, 1755 RawBool* FlowGraphOptimizer::InstanceOfAsBool(const ICData& ic_data,
1860 const AbstractType& type) const { 1756 const AbstractType& type) const {
1861 ASSERT(ic_data.num_args_tested() == 1); // Unary checks only. 1757 ASSERT(ic_data.num_args_tested() == 1); // Unary checks only.
1862 if (!type.IsInstantiated() || type.IsMalformed()) return Bool::null(); 1758 if (!type.IsInstantiated() || type.IsMalformed()) return Bool::null();
(...skipping 2220 matching lines...) Expand 10 before | Expand all | Expand 10 after
4083 SetValue(instr, non_constant_); 3979 SetValue(instr, non_constant_);
4084 } 3980 }
4085 3981
4086 3982
4087 void ConstantPropagator::VisitAllocateObjectWithBoundsCheck( 3983 void ConstantPropagator::VisitAllocateObjectWithBoundsCheck(
4088 AllocateObjectWithBoundsCheckInstr* instr) { 3984 AllocateObjectWithBoundsCheckInstr* instr) {
4089 SetValue(instr, non_constant_); 3985 SetValue(instr, non_constant_);
4090 } 3986 }
4091 3987
4092 3988
3989 void ConstantPropagator::VisitLoadUntagged(LoadUntaggedInstr* instr) {
3990 SetValue(instr, non_constant_);
3991 }
3992
3993
4093 void ConstantPropagator::VisitLoadField(LoadFieldInstr* instr) { 3994 void ConstantPropagator::VisitLoadField(LoadFieldInstr* instr) {
4094 if ((instr->recognized_kind() == MethodRecognizer::kObjectArrayLength) && 3995 if ((instr->recognized_kind() == MethodRecognizer::kObjectArrayLength) &&
4095 (instr->value()->definition()->IsCreateArray())) { 3996 (instr->value()->definition()->IsCreateArray())) {
4096 const intptr_t length = 3997 const intptr_t length =
4097 instr->value()->definition()->AsCreateArray()->num_elements(); 3998 instr->value()->definition()->AsCreateArray()->num_elements();
4098 const Object& result = Smi::ZoneHandle(Smi::New(length)); 3999 const Object& result = Smi::ZoneHandle(Smi::New(length));
4099 SetValue(instr, result); 4000 SetValue(instr, result);
4100 return; 4001 return;
4101 } 4002 }
4102 4003
(...skipping 603 matching lines...) Expand 10 before | Expand all | Expand 10 after
4706 if (changed) { 4607 if (changed) {
4707 // We may have changed the block order and the dominator tree. 4608 // We may have changed the block order and the dominator tree.
4708 flow_graph->DiscoverBlocks(); 4609 flow_graph->DiscoverBlocks();
4709 GrowableArray<BitVector*> dominance_frontier; 4610 GrowableArray<BitVector*> dominance_frontier;
4710 flow_graph->ComputeDominators(&dominance_frontier); 4611 flow_graph->ComputeDominators(&dominance_frontier);
4711 } 4612 }
4712 } 4613 }
4713 4614
4714 4615
4715 } // namespace dart 4616 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/flow_graph_type_propagator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698