| OLD | NEW |
| 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/globals.h" // Needed here to get TARGET_ARCH_ARM. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. |
| 6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 121 return NULL; | 121 return NULL; |
| 122 } | 122 } |
| 123 | 123 |
| 124 | 124 |
| 125 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 125 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 126 UNREACHABLE(); | 126 UNREACHABLE(); |
| 127 } | 127 } |
| 128 | 128 |
| 129 | 129 |
| 130 LocationSummary* ClosureCallInstr::MakeLocationSummary() const { | 130 LocationSummary* ClosureCallInstr::MakeLocationSummary() const { |
| 131 UNIMPLEMENTED(); | 131 const intptr_t kNumInputs = 0; |
| 132 return NULL; | 132 const intptr_t kNumTemps = 1; |
| 133 LocationSummary* result = |
| 134 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 135 result->set_out(Location::RegisterLocation(R0)); |
| 136 result->set_temp(0, Location::RegisterLocation(R4)); // Arg. descriptor. |
| 137 return result; |
| 138 } |
| 139 |
| 140 |
| 141 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 142 // The arguments to the stub include the closure, as does the arguments |
| 143 // descriptor. |
| 144 Register temp_reg = locs()->temp(0).reg(); |
| 145 int argument_count = ArgumentCount(); |
| 146 const Array& arguments_descriptor = |
| 147 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, |
| 148 argument_names())); |
| 149 __ LoadObject(temp_reg, arguments_descriptor); |
| 150 compiler->GenerateDartCall(deopt_id(), |
| 151 token_pos(), |
| 152 &StubCode::CallClosureFunctionLabel(), |
| 153 PcDescriptors::kOther, |
| 154 locs()); |
| 155 __ Drop(argument_count); |
| 133 } | 156 } |
| 134 | 157 |
| 135 | 158 |
| 136 LocationSummary* LoadLocalInstr::MakeLocationSummary() const { | 159 LocationSummary* LoadLocalInstr::MakeLocationSummary() const { |
| 137 return LocationSummary::Make(0, | 160 return LocationSummary::Make(0, |
| 138 Location::RequiresRegister(), | 161 Location::RequiresRegister(), |
| 139 LocationSummary::kNoCall); | 162 LocationSummary::kNoCall); |
| 140 } | 163 } |
| 141 | 164 |
| 142 | 165 |
| (...skipping 692 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 835 | 858 |
| 836 | 859 |
| 837 Representation StoreIndexedInstr::RequiredInputRepresentation( | 860 Representation StoreIndexedInstr::RequiredInputRepresentation( |
| 838 intptr_t idx) const { | 861 intptr_t idx) const { |
| 839 UNIMPLEMENTED(); | 862 UNIMPLEMENTED(); |
| 840 return kTagged; | 863 return kTagged; |
| 841 } | 864 } |
| 842 | 865 |
| 843 | 866 |
| 844 LocationSummary* StoreIndexedInstr::MakeLocationSummary() const { | 867 LocationSummary* StoreIndexedInstr::MakeLocationSummary() const { |
| 845 UNIMPLEMENTED(); | 868 const intptr_t kNumInputs = 3; |
| 846 return NULL; | 869 const intptr_t kNumTemps = 0; |
| 870 LocationSummary* locs = |
| 871 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 872 locs->set_in(0, Location::RequiresRegister()); |
| 873 // The smi index is either untagged (element size == 1), or it is left smi |
| 874 // tagged (for all element sizes > 1). |
| 875 // TODO(regis): Revisit and see if the index can be immediate. |
| 876 locs->set_in(1, Location::WritableRegister()); |
| 877 switch (class_id()) { |
| 878 case kArrayCid: |
| 879 locs->set_in(2, ShouldEmitStoreBarrier() |
| 880 ? Location::WritableRegister() |
| 881 : Location::RegisterOrConstant(value())); |
| 882 break; |
| 883 case kExternalTypedDataUint8ArrayCid: |
| 884 case kExternalTypedDataUint8ClampedArrayCid: |
| 885 case kTypedDataInt8ArrayCid: |
| 886 case kTypedDataUint8ArrayCid: |
| 887 case kTypedDataUint8ClampedArrayCid: |
| 888 case kTypedDataInt16ArrayCid: |
| 889 case kTypedDataUint16ArrayCid: |
| 890 case kTypedDataInt32ArrayCid: |
| 891 case kTypedDataUint32ArrayCid: |
| 892 case kTypedDataFloat32ArrayCid: |
| 893 case kTypedDataFloat64ArrayCid: |
| 894 case kTypedDataFloat32x4ArrayCid: |
| 895 UNIMPLEMENTED(); |
| 896 break; |
| 897 default: |
| 898 UNREACHABLE(); |
| 899 return NULL; |
| 900 } |
| 901 return locs; |
| 847 } | 902 } |
| 848 | 903 |
| 849 | 904 |
| 850 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 905 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 851 UNIMPLEMENTED(); | 906 Register array = locs()->in(0).reg(); |
| 907 Location index = locs()->in(1); |
| 908 |
| 909 Address element_address(kNoRegister, 0); |
| 910 if (IsExternal()) { |
| 911 UNIMPLEMENTED(); |
| 912 } else { |
| 913 ASSERT(this->array()->definition()->representation() == kTagged); |
| 914 ASSERT(index.IsRegister()); // TODO(regis): Revisit. |
| 915 // Note that index is expected smi-tagged, (i.e, times 2) for all arrays |
| 916 // with index scale factor > 1. E.g., for Uint8Array and OneByteString the |
| 917 // index is expected to be untagged before accessing. |
| 918 ASSERT(kSmiTagShift == 1); |
| 919 switch (index_scale()) { |
| 920 case 1: { |
| 921 __ SmiUntag(index.reg()); |
| 922 break; |
| 923 } |
| 924 case 2: { |
| 925 break; |
| 926 } |
| 927 case 4: { |
| 928 __ mov(index.reg(), ShifterOperand(index.reg(), LSL, 1)); |
| 929 break; |
| 930 } |
| 931 case 8: { |
| 932 __ mov(index.reg(), ShifterOperand(index.reg(), LSL, 2)); |
| 933 break; |
| 934 } |
| 935 case 16: { |
| 936 __ mov(index.reg(), ShifterOperand(index.reg(), LSL, 3)); |
| 937 break; |
| 938 } |
| 939 default: |
| 940 UNREACHABLE(); |
| 941 } |
| 942 __ AddImmediate(index.reg(), |
| 943 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag); |
| 944 element_address = Address(array, index.reg(), LSL, 0); |
| 945 } |
| 946 |
| 947 switch (class_id()) { |
| 948 case kArrayCid: |
| 949 if (ShouldEmitStoreBarrier()) { |
| 950 Register value = locs()->in(2).reg(); |
| 951 __ StoreIntoObject(array, element_address, value); |
| 952 } else if (locs()->in(2).IsConstant()) { |
| 953 const Object& constant = locs()->in(2).constant(); |
| 954 __ StoreIntoObjectNoBarrier(array, element_address, constant); |
| 955 } else { |
| 956 Register value = locs()->in(2).reg(); |
| 957 __ StoreIntoObjectNoBarrier(array, element_address, value); |
| 958 } |
| 959 break; |
| 960 case kTypedDataInt8ArrayCid: |
| 961 case kTypedDataUint8ArrayCid: |
| 962 case kExternalTypedDataUint8ArrayCid: |
| 963 case kTypedDataUint8ClampedArrayCid: |
| 964 case kExternalTypedDataUint8ClampedArrayCid: |
| 965 case kTypedDataInt16ArrayCid: |
| 966 case kTypedDataUint16ArrayCid: |
| 967 case kTypedDataInt32ArrayCid: |
| 968 case kTypedDataUint32ArrayCid: |
| 969 case kTypedDataFloat32ArrayCid: |
| 970 case kTypedDataFloat64ArrayCid: |
| 971 case kTypedDataFloat32x4ArrayCid: |
| 972 UNIMPLEMENTED(); |
| 973 break; |
| 974 default: |
| 975 UNREACHABLE(); |
| 976 } |
| 852 } | 977 } |
| 853 | 978 |
| 854 | 979 |
| 855 LocationSummary* GuardFieldInstr::MakeLocationSummary() const { | 980 LocationSummary* GuardFieldInstr::MakeLocationSummary() const { |
| 856 UNIMPLEMENTED(); | 981 const intptr_t kNumInputs = 1; |
| 857 return NULL; | 982 LocationSummary* summary = |
| 983 new LocationSummary(kNumInputs, 0, LocationSummary::kNoCall); |
| 984 summary->set_in(0, Location::RequiresRegister()); |
| 985 if ((value()->Type()->ToCid() == kDynamicCid) && |
| 986 (field().guarded_cid() != kSmiCid)) { |
| 987 summary->AddTemp(Location::RequiresRegister()); |
| 988 } |
| 989 if (field().guarded_cid() == kIllegalCid) { |
| 990 summary->AddTemp(Location::RequiresRegister()); |
| 991 } |
| 992 return summary; |
| 858 } | 993 } |
| 859 | 994 |
| 860 | 995 |
| 861 void GuardFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 996 void GuardFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 862 UNIMPLEMENTED(); | 997 const intptr_t field_cid = field().guarded_cid(); |
| 998 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; |
| 999 |
| 1000 if (field_cid == kDynamicCid) { |
| 1001 ASSERT(!compiler->is_optimizing()); |
| 1002 return; // Nothing to emit. |
| 1003 } |
| 1004 |
| 1005 const intptr_t value_cid = value()->Type()->ToCid(); |
| 1006 |
| 1007 Register value_reg = locs()->in(0).reg(); |
| 1008 |
| 1009 Register value_cid_reg = ((value_cid == kDynamicCid) && |
| 1010 (field_cid != kSmiCid)) ? locs()->temp(0).reg() : kNoRegister; |
| 1011 |
| 1012 Register field_reg = (field_cid == kIllegalCid) ? |
| 1013 locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister; |
| 1014 |
| 1015 Label ok, fail_label; |
| 1016 |
| 1017 Label* deopt = compiler->is_optimizing() ? |
| 1018 compiler->AddDeoptStub(deopt_id(), kDeoptGuardField) : NULL; |
| 1019 |
| 1020 Label* fail = (deopt != NULL) ? deopt : &fail_label; |
| 1021 |
| 1022 const bool ok_is_fall_through = (deopt != NULL); |
| 1023 |
| 1024 if (!compiler->is_optimizing() || (field_cid == kIllegalCid)) { |
| 1025 if (!compiler->is_optimizing()) { |
| 1026 // Currently we can't have different location summaries for optimized |
| 1027 // and non-optimized code. So instead we manually pick up a register |
| 1028 // that is known to be free because we know how non-optimizing compiler |
| 1029 // allocates registers. |
| 1030 field_reg = R2; |
| 1031 ASSERT((field_reg != value_reg) && (field_reg != value_cid_reg)); |
| 1032 } |
| 1033 |
| 1034 __ LoadObject(field_reg, Field::ZoneHandle(field().raw())); |
| 1035 |
| 1036 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset()); |
| 1037 FieldAddress field_nullability_operand( |
| 1038 field_reg, Field::is_nullable_offset()); |
| 1039 |
| 1040 if (value_cid == kDynamicCid) { |
| 1041 if (value_cid_reg == kNoRegister) { |
| 1042 ASSERT(!compiler->is_optimizing()); |
| 1043 value_cid_reg = R3; |
| 1044 ASSERT((value_cid_reg != value_reg) && (field_reg != value_cid_reg)); |
| 1045 } |
| 1046 |
| 1047 LoadValueCid(compiler, value_cid_reg, value_reg); |
| 1048 |
| 1049 __ ldr(IP, field_cid_operand); |
| 1050 __ cmp(value_cid_reg, ShifterOperand(IP)); |
| 1051 __ b(&ok, EQ); |
| 1052 __ ldr(IP, field_nullability_operand); |
| 1053 __ cmp(value_cid_reg, ShifterOperand(IP)); |
| 1054 } else if (value_cid == kNullCid) { |
| 1055 // TODO(regis): IP may conflict. Revisit. |
| 1056 __ ldr(IP, field_nullability_operand); |
| 1057 __ CompareImmediate(IP, value_cid); |
| 1058 } else { |
| 1059 // TODO(regis): IP may conflict. Revisit. |
| 1060 __ ldr(IP, field_cid_operand); |
| 1061 __ CompareImmediate(IP, value_cid); |
| 1062 } |
| 1063 __ b(&ok, EQ); |
| 1064 |
| 1065 __ ldr(IP, field_cid_operand); |
| 1066 __ CompareImmediate(IP, kIllegalCid); |
| 1067 __ b(fail, NE); |
| 1068 |
| 1069 if (value_cid == kDynamicCid) { |
| 1070 __ str(value_cid_reg, field_cid_operand); |
| 1071 __ str(value_cid_reg, field_nullability_operand); |
| 1072 } else { |
| 1073 __ LoadImmediate(IP, value_cid); |
| 1074 __ str(IP, field_cid_operand); |
| 1075 __ str(IP, field_nullability_operand); |
| 1076 } |
| 1077 |
| 1078 if (!ok_is_fall_through) { |
| 1079 __ b(&ok); |
| 1080 } |
| 1081 } else { |
| 1082 if (value_cid == kDynamicCid) { |
| 1083 // Field's guarded class id is fixed by value's class id is not known. |
| 1084 __ tst(value_reg, ShifterOperand(kSmiTagMask)); |
| 1085 |
| 1086 if (field_cid != kSmiCid) { |
| 1087 __ b(fail, EQ); |
| 1088 __ LoadClassId(value_cid_reg, value_reg); |
| 1089 __ CompareImmediate(value_cid_reg, field_cid); |
| 1090 } |
| 1091 |
| 1092 if (field().is_nullable() && (field_cid != kNullCid)) { |
| 1093 __ b(&ok, EQ); |
| 1094 __ CompareImmediate(value_reg, |
| 1095 reinterpret_cast<intptr_t>(Object::null())); |
| 1096 } |
| 1097 |
| 1098 if (ok_is_fall_through) { |
| 1099 __ b(fail, NE); |
| 1100 } else { |
| 1101 __ b(&ok, EQ); |
| 1102 } |
| 1103 } else { |
| 1104 // Both value's and field's class id is known. |
| 1105 if ((value_cid != field_cid) && (value_cid != nullability)) { |
| 1106 if (ok_is_fall_through) { |
| 1107 __ b(fail); |
| 1108 } |
| 1109 } else { |
| 1110 // Nothing to emit. |
| 1111 ASSERT(!compiler->is_optimizing()); |
| 1112 return; |
| 1113 } |
| 1114 } |
| 1115 } |
| 1116 |
| 1117 if (deopt == NULL) { |
| 1118 ASSERT(!compiler->is_optimizing()); |
| 1119 __ Bind(fail); |
| 1120 |
| 1121 __ ldr(IP, FieldAddress(field_reg, Field::guarded_cid_offset())); |
| 1122 __ CompareImmediate(IP, kDynamicCid); |
| 1123 __ b(&ok, EQ); |
| 1124 |
| 1125 __ Push(field_reg); |
| 1126 __ Push(value_reg); |
| 1127 __ CallRuntime(kUpdateFieldCidRuntimeEntry); |
| 1128 __ Drop(2); // Drop the field and the value. |
| 1129 } |
| 1130 |
| 1131 __ Bind(&ok); |
| 863 } | 1132 } |
| 864 | 1133 |
| 865 | 1134 |
| 866 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const { | 1135 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const { |
| 867 UNIMPLEMENTED(); | 1136 const intptr_t kNumInputs = 2; |
| 868 return NULL; | 1137 const intptr_t num_temps = 0; |
| 1138 LocationSummary* summary = |
| 1139 new LocationSummary(kNumInputs, num_temps, LocationSummary::kNoCall); |
| 1140 summary->set_in(0, Location::RequiresRegister()); |
| 1141 summary->set_in(1, ShouldEmitStoreBarrier() |
| 1142 ? Location::WritableRegister() |
| 1143 : Location::RegisterOrConstant(value())); |
| 1144 return summary; |
| 869 } | 1145 } |
| 870 | 1146 |
| 871 | 1147 |
| 872 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1148 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 873 UNIMPLEMENTED(); | 1149 Register instance_reg = locs()->in(0).reg(); |
| 1150 if (ShouldEmitStoreBarrier()) { |
| 1151 Register value_reg = locs()->in(1).reg(); |
| 1152 __ StoreIntoObject(instance_reg, |
| 1153 FieldAddress(instance_reg, field().Offset()), |
| 1154 value_reg, |
| 1155 CanValueBeSmi()); |
| 1156 } else { |
| 1157 if (locs()->in(1).IsConstant()) { |
| 1158 __ StoreIntoObjectNoBarrier( |
| 1159 instance_reg, |
| 1160 FieldAddress(instance_reg, field().Offset()), |
| 1161 locs()->in(1).constant()); |
| 1162 } else { |
| 1163 Register value_reg = locs()->in(1).reg(); |
| 1164 __ StoreIntoObjectNoBarrier(instance_reg, |
| 1165 FieldAddress(instance_reg, field().Offset()), value_reg); |
| 1166 } |
| 1167 } |
| 874 } | 1168 } |
| 875 | 1169 |
| 876 | 1170 |
| 877 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary() const { | 1171 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary() const { |
| 878 UNIMPLEMENTED(); | 1172 return LocationSummary::Make(0, |
| 879 return NULL; | 1173 Location::RequiresRegister(), |
| 1174 LocationSummary::kNoCall); |
| 880 } | 1175 } |
| 881 | 1176 |
| 882 | 1177 |
| 883 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1178 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 884 UNIMPLEMENTED(); | 1179 Register result = locs()->out().reg(); |
| 1180 __ LoadObject(result, field()); |
| 1181 __ LoadFromOffset(kLoadWord, result, |
| 1182 result, Field::value_offset() - kHeapObjectTag); |
| 885 } | 1183 } |
| 886 | 1184 |
| 887 | 1185 |
| 888 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary() const { | 1186 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary() const { |
| 889 UNIMPLEMENTED(); | 1187 LocationSummary* locs = new LocationSummary(1, 1, LocationSummary::kNoCall); |
| 890 return NULL; | 1188 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() |
| 1189 : Location::RequiresRegister()); |
| 1190 locs->set_temp(0, Location::RequiresRegister()); |
| 1191 return locs; |
| 891 } | 1192 } |
| 892 | 1193 |
| 893 | 1194 |
| 894 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1195 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 895 UNIMPLEMENTED(); | 1196 Register value = locs()->in(0).reg(); |
| 896 } | 1197 Register temp = locs()->temp(0).reg(); |
| 897 | 1198 |
| 898 | 1199 __ LoadObject(temp, field()); |
| 1200 if (this->value()->NeedsStoreBuffer()) { |
| 1201 __ StoreIntoObject(temp, |
| 1202 FieldAddress(temp, Field::value_offset()), value, CanValueBeSmi()); |
| 1203 } else { |
| 1204 __ StoreIntoObjectNoBarrier( |
| 1205 temp, FieldAddress(temp, Field::value_offset()), value); |
| 1206 } |
| 1207 } |
| 1208 |
| 1209 |
| 899 LocationSummary* InstanceOfInstr::MakeLocationSummary() const { | 1210 LocationSummary* InstanceOfInstr::MakeLocationSummary() const { |
| 900 UNIMPLEMENTED(); | 1211 UNIMPLEMENTED(); |
| 901 return NULL; | 1212 return NULL; |
| 902 } | 1213 } |
| 903 | 1214 |
| 904 | 1215 |
| 905 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1216 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 906 UNIMPLEMENTED(); | 1217 UNIMPLEMENTED(); |
| 907 } | 1218 } |
| 908 | 1219 |
| 909 | 1220 |
| 910 LocationSummary* CreateArrayInstr::MakeLocationSummary() const { | 1221 LocationSummary* CreateArrayInstr::MakeLocationSummary() const { |
| 911 UNIMPLEMENTED(); | 1222 const intptr_t kNumInputs = 1; |
| 912 return NULL; | 1223 const intptr_t kNumTemps = 0; |
| 1224 LocationSummary* locs = |
| 1225 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 1226 locs->set_in(0, Location::RegisterLocation(R1)); |
| 1227 locs->set_out(Location::RegisterLocation(R0)); |
| 1228 return locs; |
| 913 } | 1229 } |
| 914 | 1230 |
| 915 | 1231 |
| 916 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1232 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 917 UNIMPLEMENTED(); | 1233 // Allocate the array. R2 = length, R1 = element type. |
| 1234 ASSERT(locs()->in(0).reg() == R1); |
| 1235 __ LoadImmediate(R2, Smi::RawValue(num_elements())); |
| 1236 compiler->GenerateCall(token_pos(), |
| 1237 &StubCode::AllocateArrayLabel(), |
| 1238 PcDescriptors::kOther, |
| 1239 locs()); |
| 1240 ASSERT(locs()->out().reg() == R0); |
| 918 } | 1241 } |
| 919 | 1242 |
| 920 | 1243 |
| 921 LocationSummary* | 1244 LocationSummary* |
| 922 AllocateObjectWithBoundsCheckInstr::MakeLocationSummary() const { | 1245 AllocateObjectWithBoundsCheckInstr::MakeLocationSummary() const { |
| 923 UNIMPLEMENTED(); | 1246 UNIMPLEMENTED(); |
| 924 return NULL; | 1247 return NULL; |
| 925 } | 1248 } |
| 926 | 1249 |
| 927 | 1250 |
| 928 void AllocateObjectWithBoundsCheckInstr::EmitNativeCode( | 1251 void AllocateObjectWithBoundsCheckInstr::EmitNativeCode( |
| 929 FlowGraphCompiler* compiler) { | 1252 FlowGraphCompiler* compiler) { |
| 930 UNIMPLEMENTED(); | 1253 UNIMPLEMENTED(); |
| 931 } | 1254 } |
| 932 | 1255 |
| 933 | 1256 |
| 934 LocationSummary* LoadFieldInstr::MakeLocationSummary() const { | 1257 LocationSummary* LoadFieldInstr::MakeLocationSummary() const { |
| 935 UNIMPLEMENTED(); | 1258 return LocationSummary::Make(1, |
| 936 return NULL; | 1259 Location::RequiresRegister(), |
| 1260 LocationSummary::kNoCall); |
| 937 } | 1261 } |
| 938 | 1262 |
| 939 | 1263 |
| 940 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1264 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 941 UNIMPLEMENTED(); | 1265 Register instance_reg = locs()->in(0).reg(); |
| 1266 Register result_reg = locs()->out().reg(); |
| 1267 |
| 1268 __ LoadFromOffset(kLoadWord, result_reg, |
| 1269 instance_reg, offset_in_bytes() - kHeapObjectTag); |
| 942 } | 1270 } |
| 943 | 1271 |
| 944 | 1272 |
| 945 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary() const { | 1273 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary() const { |
| 946 UNIMPLEMENTED(); | 1274 const intptr_t kNumInputs = 1; |
| 947 return NULL; | 1275 const intptr_t kNumTemps = 1; |
| 1276 LocationSummary* locs = |
| 1277 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 1278 locs->set_in(0, Location::RegisterLocation(R0)); |
| 1279 locs->set_temp(0, Location::RegisterLocation(R1)); |
| 1280 locs->set_out(Location::RegisterLocation(R0)); |
| 1281 return locs; |
| 948 } | 1282 } |
| 949 | 1283 |
| 950 | 1284 |
| 951 void InstantiateTypeArgumentsInstr::EmitNativeCode( | 1285 void InstantiateTypeArgumentsInstr::EmitNativeCode( |
| 952 FlowGraphCompiler* compiler) { | 1286 FlowGraphCompiler* compiler) { |
| 953 UNIMPLEMENTED(); | 1287 Register instantiator_reg = locs()->in(0).reg(); |
| 1288 Register temp = locs()->temp(0).reg(); |
| 1289 Register result_reg = locs()->out().reg(); |
| 1290 |
| 1291 // 'instantiator_reg' is the instantiator AbstractTypeArguments object |
| 1292 // (or null). |
| 1293 // If the instantiator is null and if the type argument vector |
| 1294 // instantiated from null becomes a vector of dynamic, then use null as |
| 1295 // the type arguments. |
| 1296 Label type_arguments_instantiated; |
| 1297 const intptr_t len = type_arguments().Length(); |
| 1298 if (type_arguments().IsRawInstantiatedRaw(len)) { |
| 1299 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null())); |
| 1300 __ cmp(instantiator_reg, ShifterOperand(IP)); |
| 1301 __ b(&type_arguments_instantiated, EQ); |
| 1302 } |
| 1303 // Instantiate non-null type arguments. |
| 1304 if (type_arguments().IsUninstantiatedIdentity()) { |
| 1305 // Check if the instantiator type argument vector is a TypeArguments of a |
| 1306 // matching length and, if so, use it as the instantiated type_arguments. |
| 1307 // No need to check the instantiator ('instantiator_reg') for null here, |
| 1308 // because a null instantiator will have the wrong class (Null instead of |
| 1309 // TypeArguments). |
| 1310 Label type_arguments_uninstantiated; |
| 1311 __ CompareClassId(instantiator_reg, kTypeArgumentsCid, temp); |
| 1312 __ b(&type_arguments_uninstantiated, NE); |
| 1313 __ ldr(temp, |
| 1314 FieldAddress(instantiator_reg, TypeArguments::length_offset())); |
| 1315 __ CompareImmediate(temp, Smi::RawValue(len)); |
| 1316 __ b(&type_arguments_instantiated, EQ); |
| 1317 __ Bind(&type_arguments_uninstantiated); |
| 1318 } |
| 1319 // A runtime call to instantiate the type arguments is required. |
| 1320 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 1321 __ PushObject(type_arguments()); |
| 1322 __ Push(instantiator_reg); // Push instantiator type arguments. |
| 1323 compiler->GenerateCallRuntime(token_pos(), |
| 1324 deopt_id(), |
| 1325 kInstantiateTypeArgumentsRuntimeEntry, |
| 1326 locs()); |
| 1327 __ Drop(2); // Drop instantiator and uninstantiated type arguments. |
| 1328 __ Pop(result_reg); // Pop instantiated type arguments. |
| 1329 __ Bind(&type_arguments_instantiated); |
| 1330 ASSERT(instantiator_reg == result_reg); |
| 1331 // 'result_reg': Instantiated type arguments. |
| 954 } | 1332 } |
| 955 | 1333 |
| 956 | 1334 |
| 957 LocationSummary* | 1335 LocationSummary* |
| 958 ExtractConstructorTypeArgumentsInstr::MakeLocationSummary() const { | 1336 ExtractConstructorTypeArgumentsInstr::MakeLocationSummary() const { |
| 959 UNIMPLEMENTED(); | 1337 const intptr_t kNumInputs = 1; |
| 960 return NULL; | 1338 const intptr_t kNumTemps = 1; |
| 1339 LocationSummary* locs = |
| 1340 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1341 locs->set_in(0, Location::RequiresRegister()); |
| 1342 locs->set_out(Location::SameAsFirstInput()); |
| 1343 locs->set_temp(0, Location::RequiresRegister()); |
| 1344 return locs; |
| 961 } | 1345 } |
| 962 | 1346 |
| 963 | 1347 |
| 964 void ExtractConstructorTypeArgumentsInstr::EmitNativeCode( | 1348 void ExtractConstructorTypeArgumentsInstr::EmitNativeCode( |
| 965 FlowGraphCompiler* compiler) { | 1349 FlowGraphCompiler* compiler) { |
| 966 UNIMPLEMENTED(); | 1350 Register instantiator_reg = locs()->in(0).reg(); |
| 1351 Register result_reg = locs()->out().reg(); |
| 1352 ASSERT(instantiator_reg == result_reg); |
| 1353 Register temp_reg = locs()->temp(0).reg(); |
| 1354 |
| 1355 // instantiator_reg is the instantiator type argument vector, i.e. an |
| 1356 // AbstractTypeArguments object (or null). |
| 1357 // If the instantiator is null and if the type argument vector |
| 1358 // instantiated from null becomes a vector of dynamic, then use null as |
| 1359 // the type arguments. |
| 1360 Label type_arguments_instantiated; |
| 1361 const intptr_t len = type_arguments().Length(); |
| 1362 if (type_arguments().IsRawInstantiatedRaw(len)) { |
| 1363 __ CompareImmediate(instantiator_reg, |
| 1364 reinterpret_cast<intptr_t>(Object::null())); |
| 1365 __ b(&type_arguments_instantiated, EQ); |
| 1366 } |
| 1367 // Instantiate non-null type arguments. |
| 1368 if (type_arguments().IsUninstantiatedIdentity()) { |
| 1369 // Check if the instantiator type argument vector is a TypeArguments of a |
| 1370 // matching length and, if so, use it as the instantiated type_arguments. |
| 1371 // No need to check instantiator_reg for null here, because a null |
| 1372 // instantiator will have the wrong class (Null instead of TypeArguments). |
| 1373 Label type_arguments_uninstantiated; |
| 1374 __ CompareClassId(instantiator_reg, kTypeArgumentsCid, temp_reg); |
| 1375 __ b(&type_arguments_uninstantiated, NE); |
| 1376 __ ldr(temp_reg, |
| 1377 FieldAddress(instantiator_reg, TypeArguments::length_offset())); |
| 1378 __ CompareImmediate(temp_reg, Smi::RawValue(type_arguments().Length())); |
| 1379 __ b(&type_arguments_instantiated, EQ); |
| 1380 __ Bind(&type_arguments_uninstantiated); |
| 1381 } |
| 1382 // In the non-factory case, we rely on the allocation stub to |
| 1383 // instantiate the type arguments. |
| 1384 __ LoadObject(result_reg, type_arguments()); |
| 1385 // result_reg: uninstantiated type arguments. |
| 1386 __ Bind(&type_arguments_instantiated); |
| 1387 // result_reg: uninstantiated or instantiated type arguments. |
| 967 } | 1388 } |
| 968 | 1389 |
| 969 | 1390 |
| 970 LocationSummary* | 1391 LocationSummary* |
| 971 ExtractConstructorInstantiatorInstr::MakeLocationSummary() const { | 1392 ExtractConstructorInstantiatorInstr::MakeLocationSummary() const { |
| 972 UNIMPLEMENTED(); | 1393 const intptr_t kNumInputs = 1; |
| 973 return NULL; | 1394 const intptr_t kNumTemps = 1; |
| 1395 LocationSummary* locs = |
| 1396 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1397 locs->set_in(0, Location::RequiresRegister()); |
| 1398 locs->set_out(Location::SameAsFirstInput()); |
| 1399 locs->set_temp(0, Location::RequiresRegister()); |
| 1400 return locs; |
| 974 } | 1401 } |
| 975 | 1402 |
| 976 | 1403 |
| 977 void ExtractConstructorInstantiatorInstr::EmitNativeCode( | 1404 void ExtractConstructorInstantiatorInstr::EmitNativeCode( |
| 978 FlowGraphCompiler* compiler) { | 1405 FlowGraphCompiler* compiler) { |
| 979 UNIMPLEMENTED(); | 1406 Register instantiator_reg = locs()->in(0).reg(); |
| 980 } | 1407 ASSERT(locs()->out().reg() == instantiator_reg); |
| 981 | 1408 Register temp_reg = locs()->temp(0).reg(); |
| 982 | 1409 |
| 1410 // instantiator_reg is the instantiator AbstractTypeArguments object |
| 1411 // (or null). If the instantiator is null and if the type argument vector |
| 1412 // instantiated from null becomes a vector of dynamic, then use null as |
| 1413 // the type arguments and do not pass the instantiator. |
| 1414 Label done; |
| 1415 const intptr_t len = type_arguments().Length(); |
| 1416 if (type_arguments().IsRawInstantiatedRaw(len)) { |
| 1417 Label instantiator_not_null; |
| 1418 __ CompareImmediate(instantiator_reg, |
| 1419 reinterpret_cast<intptr_t>(Object::null())); |
| 1420 __ b(&instantiator_not_null, NE); |
| 1421 // Null was used in VisitExtractConstructorTypeArguments as the |
| 1422 // instantiated type arguments, no proper instantiator needed. |
| 1423 __ LoadImmediate(instantiator_reg, |
| 1424 Smi::RawValue(StubCode::kNoInstantiator)); |
| 1425 __ b(&done); |
| 1426 __ Bind(&instantiator_not_null); |
| 1427 } |
| 1428 // Instantiate non-null type arguments. |
| 1429 if (type_arguments().IsUninstantiatedIdentity()) { |
| 1430 // TODO(regis): The following emitted code is duplicated in |
| 1431 // VisitExtractConstructorTypeArguments above. The reason is that the code |
| 1432 // is split between two computations, so that each one produces a |
| 1433 // single value, rather than producing a pair of values. |
| 1434 // If this becomes an issue, we should expose these tests at the IL level. |
| 1435 |
| 1436 // Check if the instantiator type argument vector is a TypeArguments of a |
| 1437 // matching length and, if so, use it as the instantiated type_arguments. |
| 1438 // No need to check the instantiator ('instantiator_reg') for null here, |
| 1439 // because a null instantiator will have the wrong class (Null instead of |
| 1440 // TypeArguments). |
| 1441 __ CompareClassId(instantiator_reg, kTypeArgumentsCid, temp_reg); |
| 1442 __ b(&done, NE); |
| 1443 __ ldr(temp_reg, |
| 1444 FieldAddress(instantiator_reg, TypeArguments::length_offset())); |
| 1445 __ CompareImmediate(temp_reg, Smi::RawValue(type_arguments().Length())); |
| 1446 __ b(&done, NE); |
| 1447 // The instantiator was used in VisitExtractConstructorTypeArguments as the |
| 1448 // instantiated type arguments, no proper instantiator needed. |
| 1449 __ LoadImmediate(instantiator_reg, |
| 1450 Smi::RawValue(StubCode::kNoInstantiator)); |
| 1451 } |
| 1452 __ Bind(&done); |
| 1453 // instantiator_reg: instantiator or kNoInstantiator. |
| 1454 } |
| 1455 |
| 1456 |
| 983 LocationSummary* AllocateContextInstr::MakeLocationSummary() const { | 1457 LocationSummary* AllocateContextInstr::MakeLocationSummary() const { |
| 984 UNIMPLEMENTED(); | 1458 UNIMPLEMENTED(); |
| 985 return NULL; | 1459 return NULL; |
| 986 } | 1460 } |
| 987 | 1461 |
| 988 | 1462 |
| 989 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1463 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 990 UNIMPLEMENTED(); | 1464 UNIMPLEMENTED(); |
| 991 } | 1465 } |
| 992 | 1466 |
| (...skipping 559 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1552 return NULL; | 2026 return NULL; |
| 1553 } | 2027 } |
| 1554 | 2028 |
| 1555 | 2029 |
| 1556 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2030 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1557 UNIMPLEMENTED(); | 2031 UNIMPLEMENTED(); |
| 1558 } | 2032 } |
| 1559 | 2033 |
| 1560 | 2034 |
| 1561 LocationSummary* ThrowInstr::MakeLocationSummary() const { | 2035 LocationSummary* ThrowInstr::MakeLocationSummary() const { |
| 1562 UNIMPLEMENTED(); | 2036 return new LocationSummary(0, 0, LocationSummary::kCall); |
| 1563 return NULL; | |
| 1564 } | 2037 } |
| 1565 | 2038 |
| 1566 | 2039 |
| 1567 | 2040 |
| 1568 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2041 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1569 UNIMPLEMENTED(); | 2042 compiler->GenerateCallRuntime(token_pos(), |
| 2043 deopt_id(), |
| 2044 kThrowRuntimeEntry, |
| 2045 locs()); |
| 2046 __ bkpt(0); |
| 1570 } | 2047 } |
| 1571 | 2048 |
| 1572 | 2049 |
| 1573 LocationSummary* ReThrowInstr::MakeLocationSummary() const { | 2050 LocationSummary* ReThrowInstr::MakeLocationSummary() const { |
| 1574 UNIMPLEMENTED(); | 2051 UNIMPLEMENTED(); |
| 1575 return NULL; | 2052 return NULL; |
| 1576 } | 2053 } |
| 1577 | 2054 |
| 1578 | 2055 |
| 1579 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2056 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1650 | 2127 |
| 1651 // Fall through or jump to the true successor. | 2128 // Fall through or jump to the true successor. |
| 1652 if (!compiler->CanFallThroughTo(true_successor())) { | 2129 if (!compiler->CanFallThroughTo(true_successor())) { |
| 1653 __ b(compiler->GetJumpLabel(true_successor())); | 2130 __ b(compiler->GetJumpLabel(true_successor())); |
| 1654 } | 2131 } |
| 1655 } | 2132 } |
| 1656 } | 2133 } |
| 1657 | 2134 |
| 1658 | 2135 |
| 1659 LocationSummary* CurrentContextInstr::MakeLocationSummary() const { | 2136 LocationSummary* CurrentContextInstr::MakeLocationSummary() const { |
| 1660 UNIMPLEMENTED(); | 2137 return LocationSummary::Make(0, |
| 1661 return NULL; | 2138 Location::RequiresRegister(), |
| 2139 LocationSummary::kNoCall); |
| 1662 } | 2140 } |
| 1663 | 2141 |
| 1664 | 2142 |
| 1665 void CurrentContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2143 void CurrentContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1666 UNIMPLEMENTED(); | 2144 __ mov(locs()->out().reg(), ShifterOperand(CTX)); |
| 1667 } | 2145 } |
| 1668 | 2146 |
| 1669 | 2147 |
| 1670 LocationSummary* StrictCompareInstr::MakeLocationSummary() const { | 2148 LocationSummary* StrictCompareInstr::MakeLocationSummary() const { |
| 1671 const intptr_t kNumInputs = 2; | 2149 const intptr_t kNumInputs = 2; |
| 1672 const intptr_t kNumTemps = 0; | 2150 const intptr_t kNumTemps = 0; |
| 1673 LocationSummary* locs = | 2151 LocationSummary* locs = |
| 1674 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2152 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1675 locs->set_in(0, Location::RegisterOrConstant(left())); | 2153 locs->set_in(0, Location::RegisterOrConstant(left())); |
| 1676 locs->set_in(1, Location::RegisterOrConstant(right())); | 2154 locs->set_in(1, Location::RegisterOrConstant(right())); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1743 compiler->EmitEqualityRegRegCompare(left.reg(), | 2221 compiler->EmitEqualityRegRegCompare(left.reg(), |
| 1744 right.reg(), | 2222 right.reg(), |
| 1745 needs_number_check()); | 2223 needs_number_check()); |
| 1746 } | 2224 } |
| 1747 | 2225 |
| 1748 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQ : NE; | 2226 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQ : NE; |
| 1749 branch->EmitBranchOnCondition(compiler, true_condition); | 2227 branch->EmitBranchOnCondition(compiler, true_condition); |
| 1750 } | 2228 } |
| 1751 | 2229 |
| 1752 | 2230 |
| 1753 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 1754 UNIMPLEMENTED(); | |
| 1755 } | |
| 1756 | |
| 1757 | |
| 1758 LocationSummary* BooleanNegateInstr::MakeLocationSummary() const { | 2231 LocationSummary* BooleanNegateInstr::MakeLocationSummary() const { |
| 1759 UNIMPLEMENTED(); | 2232 UNIMPLEMENTED(); |
| 1760 return NULL; | 2233 return NULL; |
| 1761 } | 2234 } |
| 1762 | 2235 |
| 1763 | 2236 |
| 1764 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2237 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1765 UNIMPLEMENTED(); | 2238 UNIMPLEMENTED(); |
| 1766 } | 2239 } |
| 1767 | 2240 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1799 const ExternalLabel label(cls.ToCString(), stub.EntryPoint()); | 2272 const ExternalLabel label(cls.ToCString(), stub.EntryPoint()); |
| 1800 compiler->GenerateCall(token_pos(), | 2273 compiler->GenerateCall(token_pos(), |
| 1801 &label, | 2274 &label, |
| 1802 PcDescriptors::kOther, | 2275 PcDescriptors::kOther, |
| 1803 locs()); | 2276 locs()); |
| 1804 __ Drop(ArgumentCount()); // Discard arguments. | 2277 __ Drop(ArgumentCount()); // Discard arguments. |
| 1805 } | 2278 } |
| 1806 | 2279 |
| 1807 | 2280 |
| 1808 LocationSummary* CreateClosureInstr::MakeLocationSummary() const { | 2281 LocationSummary* CreateClosureInstr::MakeLocationSummary() const { |
| 1809 UNIMPLEMENTED(); | 2282 return MakeCallSummary(); |
| 1810 return NULL; | |
| 1811 } | 2283 } |
| 1812 | 2284 |
| 1813 | 2285 |
| 1814 void CreateClosureInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2286 void CreateClosureInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1815 UNIMPLEMENTED(); | 2287 const Function& closure_function = function(); |
| 2288 ASSERT(!closure_function.IsImplicitStaticClosureFunction()); |
| 2289 const Code& stub = Code::Handle( |
| 2290 StubCode::GetAllocationStubForClosure(closure_function)); |
| 2291 const ExternalLabel label(closure_function.ToCString(), stub.EntryPoint()); |
| 2292 compiler->GenerateCall(token_pos(), |
| 2293 &label, |
| 2294 PcDescriptors::kOther, |
| 2295 locs()); |
| 2296 __ Drop(2); // Discard type arguments and receiver. |
| 1816 } | 2297 } |
| 1817 | 2298 |
| 1818 } // namespace dart | 2299 } // namespace dart |
| 1819 | 2300 |
| 1820 #endif // defined TARGET_ARCH_ARM | 2301 #endif // defined TARGET_ARCH_ARM |
| 1821 | 2302 |
| OLD | NEW |