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

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

Issue 14153004: Implement missing features to run Hello world! on simulated ARM. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 8 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_compiler_arm.cc ('k') | runtime/vm/intermediate_language_ia32.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/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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_compiler_arm.cc ('k') | runtime/vm/intermediate_language_ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698