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

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

Issue 269343010: Adds single-precision and SIMD load/store to arm64. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 7 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_arm64.cc ('k') | runtime/vm/simulator_arm64.h » ('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) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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_ARM64. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64.
6 #if defined(TARGET_ARCH_ARM64) 6 #if defined(TARGET_ARCH_ARM64)
7 7
8 #include "vm/intermediate_language.h" 8 #include "vm/intermediate_language.h"
9 9
10 #include "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
48 // where PushArgument is handled by BindInstr::EmitNativeCode. 48 // where PushArgument is handled by BindInstr::EmitNativeCode.
49 if (compiler->is_optimizing()) { 49 if (compiler->is_optimizing()) {
50 Location value = locs()->in(0); 50 Location value = locs()->in(0);
51 if (value.IsRegister()) { 51 if (value.IsRegister()) {
52 __ Push(value.reg()); 52 __ Push(value.reg());
53 } else if (value.IsConstant()) { 53 } else if (value.IsConstant()) {
54 __ PushObject(value.constant(), PP); 54 __ PushObject(value.constant(), PP);
55 } else { 55 } else {
56 ASSERT(value.IsStackSlot()); 56 ASSERT(value.IsStackSlot());
57 const intptr_t value_offset = value.ToStackSlotOffset(); 57 const intptr_t value_offset = value.ToStackSlotOffset();
58 __ LoadFromOffset(TMP, FP, value_offset); 58 __ LoadFromOffset(TMP, FP, value_offset, PP);
59 __ Push(TMP); 59 __ Push(TMP);
60 } 60 }
61 } 61 }
62 } 62 }
63 63
64 64
65 LocationSummary* ReturnInstr::MakeLocationSummary(bool opt) const { 65 LocationSummary* ReturnInstr::MakeLocationSummary(bool opt) const {
66 const intptr_t kNumInputs = 1; 66 const intptr_t kNumInputs = 1;
67 const intptr_t kNumTemps = 0; 67 const intptr_t kNumTemps = 0;
68 LocationSummary* locs = 68 LocationSummary* locs =
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
194 // Load arguments descriptor in R4. 194 // Load arguments descriptor in R4.
195 int argument_count = ArgumentCount(); 195 int argument_count = ArgumentCount();
196 const Array& arguments_descriptor = 196 const Array& arguments_descriptor =
197 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, 197 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count,
198 argument_names())); 198 argument_names()));
199 __ LoadObject(R4, arguments_descriptor, PP); 199 __ LoadObject(R4, arguments_descriptor, PP);
200 200
201 // R4: Arguments descriptor. 201 // R4: Arguments descriptor.
202 // R0: Function. 202 // R0: Function.
203 ASSERT(locs()->in(0).reg() == R0); 203 ASSERT(locs()->in(0).reg() == R0);
204 __ LoadFieldFromOffset(R2, R0, Function::code_offset()); 204 __ LoadFieldFromOffset(R2, R0, Function::code_offset(), PP);
205 205
206 // R2: code. 206 // R2: code.
207 // R5: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value). 207 // R5: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value).
208 __ LoadImmediate(R5, 0, PP); 208 __ LoadImmediate(R5, 0, PP);
209 __ LoadFieldFromOffset(R2, R2, Code::instructions_offset()); 209 __ LoadFieldFromOffset(R2, R2, Code::instructions_offset(), PP);
210 __ AddImmediate(R2, R2, Instructions::HeaderSize() - kHeapObjectTag, PP); 210 __ AddImmediate(R2, R2, Instructions::HeaderSize() - kHeapObjectTag, PP);
211 __ blr(R2); 211 __ blr(R2);
212 compiler->AddCurrentDescriptor(PcDescriptors::kClosureCall, 212 compiler->AddCurrentDescriptor(PcDescriptors::kClosureCall,
213 deopt_id(), 213 deopt_id(),
214 token_pos()); 214 token_pos());
215 compiler->RecordSafepoint(locs()); 215 compiler->RecordSafepoint(locs());
216 // Marks either the continuation point in unoptimized code or the 216 // Marks either the continuation point in unoptimized code or the
217 // deoptimization point in optimized code, after call. 217 // deoptimization point in optimized code, after call.
218 const intptr_t deopt_id_after = Isolate::ToDeoptAfter(deopt_id()); 218 const intptr_t deopt_id_after = Isolate::ToDeoptAfter(deopt_id());
219 if (compiler->is_optimizing()) { 219 if (compiler->is_optimizing()) {
(...skipping 11 matching lines...) Expand all
231 231
232 LocationSummary* LoadLocalInstr::MakeLocationSummary(bool opt) const { 232 LocationSummary* LoadLocalInstr::MakeLocationSummary(bool opt) const {
233 return LocationSummary::Make(0, 233 return LocationSummary::Make(0,
234 Location::RequiresRegister(), 234 Location::RequiresRegister(),
235 LocationSummary::kNoCall); 235 LocationSummary::kNoCall);
236 } 236 }
237 237
238 238
239 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 239 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
240 Register result = locs()->out(0).reg(); 240 Register result = locs()->out(0).reg();
241 __ LoadFromOffset(result, FP, local().index() * kWordSize); 241 __ LoadFromOffset(result, FP, local().index() * kWordSize, PP);
242 } 242 }
243 243
244 244
245 LocationSummary* StoreLocalInstr::MakeLocationSummary(bool opt) const { 245 LocationSummary* StoreLocalInstr::MakeLocationSummary(bool opt) const {
246 return LocationSummary::Make(1, 246 return LocationSummary::Make(1,
247 Location::SameAsFirstInput(), 247 Location::SameAsFirstInput(),
248 LocationSummary::kNoCall); 248 LocationSummary::kNoCall);
249 } 249 }
250 250
251 251
252 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 252 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
253 Register value = locs()->in(0).reg(); 253 Register value = locs()->in(0).reg();
254 Register result = locs()->out(0).reg(); 254 Register result = locs()->out(0).reg();
255 ASSERT(result == value); // Assert that register assignment is correct. 255 ASSERT(result == value); // Assert that register assignment is correct.
256 __ StoreToOffset(value, FP, local().index() * kWordSize); 256 __ StoreToOffset(value, FP, local().index() * kWordSize, PP);
257 } 257 }
258 258
259 259
260 LocationSummary* ConstantInstr::MakeLocationSummary(bool opt) const { 260 LocationSummary* ConstantInstr::MakeLocationSummary(bool opt) const {
261 return LocationSummary::Make(0, 261 return LocationSummary::Make(0,
262 Location::RequiresRegister(), 262 Location::RequiresRegister(),
263 LocationSummary::kNoCall); 263 LocationSummary::kNoCall);
264 } 264 }
265 265
266 266
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after
584 584
585 Label* deopt = CanDeoptimize() ? 585 Label* deopt = CanDeoptimize() ?
586 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptTestCids) : NULL; 586 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptTestCids) : NULL;
587 587
588 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; 588 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0;
589 const ZoneGrowableArray<intptr_t>& data = cid_results(); 589 const ZoneGrowableArray<intptr_t>& data = cid_results();
590 ASSERT(data[0] == kSmiCid); 590 ASSERT(data[0] == kSmiCid);
591 bool result = data[1] == true_result; 591 bool result = data[1] == true_result;
592 __ tsti(val_reg, kSmiTagMask); 592 __ tsti(val_reg, kSmiTagMask);
593 __ b(result ? labels.true_label : labels.false_label, EQ); 593 __ b(result ? labels.true_label : labels.false_label, EQ);
594 __ LoadClassId(cid_reg, val_reg); 594 __ LoadClassId(cid_reg, val_reg, PP);
595 595
596 for (intptr_t i = 2; i < data.length(); i += 2) { 596 for (intptr_t i = 2; i < data.length(); i += 2) {
597 const intptr_t test_cid = data[i]; 597 const intptr_t test_cid = data[i];
598 ASSERT(test_cid != kSmiCid); 598 ASSERT(test_cid != kSmiCid);
599 result = data[i + 1] == true_result; 599 result = data[i + 1] == true_result;
600 __ CompareImmediate(cid_reg, test_cid, PP); 600 __ CompareImmediate(cid_reg, test_cid, PP);
601 __ b(result ? labels.true_label : labels.false_label, EQ); 601 __ b(result ? labels.true_label : labels.false_label, EQ);
602 } 602 }
603 // No match found, deoptimize or false. 603 // No match found, deoptimize or false.
604 if (deopt == NULL) { 604 if (deopt == NULL) {
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
787 return LocationSummary::Make(kNumInputs, 787 return LocationSummary::Make(kNumInputs,
788 Location::RequiresRegister(), 788 Location::RequiresRegister(),
789 LocationSummary::kNoCall); 789 LocationSummary::kNoCall);
790 } 790 }
791 791
792 792
793 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 793 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
794 ASSERT(cid_ == kOneByteStringCid); 794 ASSERT(cid_ == kOneByteStringCid);
795 Register str = locs()->in(0).reg(); 795 Register str = locs()->in(0).reg();
796 Register result = locs()->out(0).reg(); 796 Register result = locs()->out(0).reg();
797 __ LoadFieldFromOffset(result, str, String::length_offset()); 797 __ LoadFieldFromOffset(result, str, String::length_offset(), PP);
798 __ CompareImmediate(result, Smi::RawValue(1), PP); 798 __ CompareImmediate(result, Smi::RawValue(1), PP);
799 __ LoadImmediate(TMP, Smi::RawValue(-1), PP); 799 __ LoadImmediate(TMP, Smi::RawValue(-1), PP);
800 __ ldr(TMP2, FieldAddress(str, OneByteString::data_offset()), kUnsignedByte); 800 __ ldr(TMP2, FieldAddress(str, OneByteString::data_offset()), kUnsignedByte);
801 __ csel(result, TMP, result, NE); 801 __ csel(result, TMP, result, NE);
802 __ csel(result, TMP2, result, EQ); 802 __ csel(result, TMP2, result, EQ);
803 __ SmiTag(result); 803 __ SmiTag(result);
804 } 804 }
805 805
806 806
807 LocationSummary* StringInterpolateInstr::MakeLocationSummary(bool opt) const { 807 LocationSummary* StringInterpolateInstr::MakeLocationSummary(bool opt) const {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
851 851
852 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 852 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
853 Register object = locs()->in(0).reg(); 853 Register object = locs()->in(0).reg();
854 Register result = locs()->out(0).reg(); 854 Register result = locs()->out(0).reg();
855 Label load, done; 855 Label load, done;
856 __ tsti(object, kSmiTagMask); 856 __ tsti(object, kSmiTagMask);
857 __ b(&load, NE); 857 __ b(&load, NE);
858 __ LoadImmediate(result, Smi::RawValue(kSmiCid), PP); 858 __ LoadImmediate(result, Smi::RawValue(kSmiCid), PP);
859 __ b(&done); 859 __ b(&done);
860 __ Bind(&load); 860 __ Bind(&load);
861 __ LoadClassId(result, object); 861 __ LoadClassId(result, object, PP);
862 __ SmiTag(result); 862 __ SmiTag(result);
863 __ Bind(&done); 863 __ Bind(&done);
864 } 864 }
865 865
866 866
867 CompileType LoadIndexedInstr::ComputeType() const { 867 CompileType LoadIndexedInstr::ComputeType() const {
868 switch (class_id_) { 868 switch (class_id_) {
869 case kArrayCid: 869 case kArrayCid:
870 case kImmutableArrayCid: 870 case kImmutableArrayCid:
871 return CompileType::Dynamic(); 871 return CompileType::Dynamic();
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
1002 (representation() == kUnboxedFloat64x2)) { 1002 (representation() == kUnboxedFloat64x2)) {
1003 const VRegister result = locs()->out(0).fpu_reg(); 1003 const VRegister result = locs()->out(0).fpu_reg();
1004 switch (class_id()) { 1004 switch (class_id()) {
1005 case kTypedDataInt32ArrayCid: 1005 case kTypedDataInt32ArrayCid:
1006 case kTypedDataUint32ArrayCid: 1006 case kTypedDataUint32ArrayCid:
1007 // TODO(zra): Add when we have simd. 1007 // TODO(zra): Add when we have simd.
1008 UNIMPLEMENTED(); 1008 UNIMPLEMENTED();
1009 break; 1009 break;
1010 case kTypedDataFloat32ArrayCid: 1010 case kTypedDataFloat32ArrayCid:
1011 // Load single precision float. 1011 // Load single precision float.
1012 // TODO(zra): Add when we add single precision floats. 1012 __ fldrs(result, element_address);
1013 UNIMPLEMENTED();
1014 break; 1013 break;
1015 case kTypedDataFloat64ArrayCid: 1014 case kTypedDataFloat64ArrayCid:
1016 // Load double precision float. 1015 // Load double precision float.
1017 __ fldrd(result, element_address); 1016 __ fldrd(result, element_address);
1018 break; 1017 break;
1019 case kTypedDataFloat64x2ArrayCid: 1018 case kTypedDataFloat64x2ArrayCid:
1020 case kTypedDataInt32x4ArrayCid: 1019 case kTypedDataInt32x4ArrayCid:
1021 case kTypedDataFloat32x4ArrayCid: 1020 case kTypedDataFloat32x4ArrayCid:
1022 // TODO(zra): Add when we have simd. 1021 // TODO(zra): Add when we have simd.
1023 UNIMPLEMENTED(); 1022 UNIMPLEMENTED();
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
1134 // Mints are stored in Q registers. For smis, use a writable register 1133 // Mints are stored in Q registers. For smis, use a writable register
1135 // because the value must be untagged before storing. 1134 // because the value must be untagged before storing.
1136 if (value()->IsSmiValue()) { 1135 if (value()->IsSmiValue()) {
1137 locs->set_in(2, Location::WritableRegister()); 1136 locs->set_in(2, Location::WritableRegister());
1138 } else { 1137 } else {
1139 // TODO(zra): Implement when we add simd loads and stores. 1138 // TODO(zra): Implement when we add simd loads and stores.
1140 UNIMPLEMENTED(); 1139 UNIMPLEMENTED();
1141 } 1140 }
1142 break; 1141 break;
1143 case kTypedDataFloat32ArrayCid: 1142 case kTypedDataFloat32ArrayCid:
1144 // TODO(zra): Implement when we add float store.
1145 UNIMPLEMENTED();
1146 break;
1147 case kTypedDataFloat64ArrayCid: // TODO(srdjan): Support Float64 constants. 1143 case kTypedDataFloat64ArrayCid: // TODO(srdjan): Support Float64 constants.
1148 locs->set_in(2, Location::RequiresFpuRegister()); 1144 locs->set_in(2, Location::RequiresFpuRegister());
1149 break; 1145 break;
1150 case kTypedDataInt32x4ArrayCid: 1146 case kTypedDataInt32x4ArrayCid:
1151 case kTypedDataFloat32x4ArrayCid: 1147 case kTypedDataFloat32x4ArrayCid:
1152 case kTypedDataFloat64x2ArrayCid: 1148 case kTypedDataFloat64x2ArrayCid:
1153 // TODO(zra): Implement when we add simd loads and stores. 1149 // TODO(zra): Implement when we add simd loads and stores.
1154 UNIMPLEMENTED(); 1150 UNIMPLEMENTED();
1155 break; 1151 break;
1156 default: 1152 default:
1157 UNREACHABLE(); 1153 UNREACHABLE();
1158 return NULL; 1154 return NULL;
1159 } 1155 }
1160 return locs; 1156 return locs;
1161 } 1157 }
1162 1158
1163 1159
1164 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1160 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1165 Register array = locs()->in(0).reg(); 1161 const Register array = locs()->in(0).reg();
1166 Location index = locs()->in(1); 1162 Location index = locs()->in(1);
1167 1163
1168 Address element_address(kNoRegister, 0); 1164 Address element_address(kNoRegister, 0);
1169 ASSERT(index.IsRegister()); // TODO(regis): Revisit. 1165 ASSERT(index.IsRegister()); // TODO(regis): Revisit.
1170 // Note that index is expected smi-tagged, (i.e, times 2) for all arrays 1166 // Note that index is expected smi-tagged, (i.e, times 2) for all arrays
1171 // with index scale factor > 1. E.g., for Uint8Array and OneByteString the 1167 // with index scale factor > 1. E.g., for Uint8Array and OneByteString the
1172 // index is expected to be untagged before accessing. 1168 // index is expected to be untagged before accessing.
1173 ASSERT(kSmiTagShift == 1); 1169 ASSERT(kSmiTagShift == 1);
1174 switch (index_scale()) { 1170 switch (index_scale()) {
1175 case 1: { 1171 case 1: {
(...skipping 21 matching lines...) Expand all
1197 if (!IsExternal()) { 1193 if (!IsExternal()) {
1198 ASSERT(this->array()->definition()->representation() == kTagged); 1194 ASSERT(this->array()->definition()->representation() == kTagged);
1199 __ AddImmediate(index.reg(), index.reg(), 1195 __ AddImmediate(index.reg(), index.reg(),
1200 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag, PP); 1196 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag, PP);
1201 } 1197 }
1202 element_address = Address(array, index.reg(), UXTX, Address::Unscaled); 1198 element_address = Address(array, index.reg(), UXTX, Address::Unscaled);
1203 1199
1204 switch (class_id()) { 1200 switch (class_id()) {
1205 case kArrayCid: 1201 case kArrayCid:
1206 if (ShouldEmitStoreBarrier()) { 1202 if (ShouldEmitStoreBarrier()) {
1207 Register value = locs()->in(2).reg(); 1203 const Register value = locs()->in(2).reg();
1208 __ StoreIntoObject(array, element_address, value); 1204 __ StoreIntoObject(array, element_address, value);
1209 } else if (locs()->in(2).IsConstant()) { 1205 } else if (locs()->in(2).IsConstant()) {
1210 const Object& constant = locs()->in(2).constant(); 1206 const Object& constant = locs()->in(2).constant();
1211 __ StoreIntoObjectNoBarrier(array, element_address, constant); 1207 __ StoreIntoObjectNoBarrier(array, element_address, constant);
1212 } else { 1208 } else {
1213 Register value = locs()->in(2).reg(); 1209 const Register value = locs()->in(2).reg();
1214 __ StoreIntoObjectNoBarrier(array, element_address, value); 1210 __ StoreIntoObjectNoBarrier(array, element_address, value);
1215 } 1211 }
1216 break; 1212 break;
1217 case kTypedDataInt8ArrayCid: 1213 case kTypedDataInt8ArrayCid:
1218 case kTypedDataUint8ArrayCid: 1214 case kTypedDataUint8ArrayCid:
1219 case kExternalTypedDataUint8ArrayCid: 1215 case kExternalTypedDataUint8ArrayCid:
1220 case kOneByteStringCid: { 1216 case kOneByteStringCid: {
1221 if (locs()->in(2).IsConstant()) { 1217 if (locs()->in(2).IsConstant()) {
1222 const Smi& constant = Smi::Cast(locs()->in(2).constant()); 1218 const Smi& constant = Smi::Cast(locs()->in(2).constant());
1223 __ LoadImmediate(TMP, static_cast<int8_t>(constant.Value()), PP); 1219 __ LoadImmediate(TMP, static_cast<int8_t>(constant.Value()), PP);
1224 __ str(TMP, element_address, kUnsignedByte); 1220 __ str(TMP, element_address, kUnsignedByte);
1225 } else { 1221 } else {
1226 Register value = locs()->in(2).reg(); 1222 const Register value = locs()->in(2).reg();
1227 __ SmiUntag(value); 1223 __ SmiUntag(value);
1228 __ str(value, element_address, kUnsignedByte); 1224 __ str(value, element_address, kUnsignedByte);
1229 } 1225 }
1230 break; 1226 break;
1231 } 1227 }
1232 case kTypedDataUint8ClampedArrayCid: 1228 case kTypedDataUint8ClampedArrayCid:
1233 case kExternalTypedDataUint8ClampedArrayCid: { 1229 case kExternalTypedDataUint8ClampedArrayCid: {
1234 if (locs()->in(2).IsConstant()) { 1230 if (locs()->in(2).IsConstant()) {
1235 const Smi& constant = Smi::Cast(locs()->in(2).constant()); 1231 const Smi& constant = Smi::Cast(locs()->in(2).constant());
1236 intptr_t value = constant.Value(); 1232 intptr_t value = constant.Value();
1237 // Clamp to 0x0 or 0xFF respectively. 1233 // Clamp to 0x0 or 0xFF respectively.
1238 if (value > 0xFF) { 1234 if (value > 0xFF) {
1239 value = 0xFF; 1235 value = 0xFF;
1240 } else if (value < 0) { 1236 } else if (value < 0) {
1241 value = 0; 1237 value = 0;
1242 } 1238 }
1243 __ LoadImmediate(TMP, static_cast<int8_t>(value), PP); 1239 __ LoadImmediate(TMP, static_cast<int8_t>(value), PP);
1244 __ str(TMP, element_address, kUnsignedByte); 1240 __ str(TMP, element_address, kUnsignedByte);
1245 } else { 1241 } else {
1246 Register value = locs()->in(2).reg(); 1242 const Register value = locs()->in(2).reg();
1247 Label store_value; 1243 Label store_value;
1248 __ SmiUntag(value); 1244 __ SmiUntag(value);
1249 __ CompareImmediate(value, 0xFF, PP); 1245 __ CompareImmediate(value, 0xFF, PP);
1250 // Clamp to 0x00 or 0xFF respectively. 1246 // Clamp to 0x00 or 0xFF respectively.
1251 __ b(&store_value, LS); 1247 __ b(&store_value, LS);
1252 __ LoadImmediate(TMP, 0x00, PP); 1248 __ LoadImmediate(TMP, 0x00, PP);
1253 __ LoadImmediate(TMP2, 0xFF, PP); 1249 __ LoadImmediate(TMP2, 0xFF, PP);
1254 __ csel(value, TMP, value, LE); 1250 __ csel(value, TMP, value, LE);
1255 __ csel(value, TMP2, value, GT); 1251 __ csel(value, TMP2, value, GT);
1256 __ Bind(&store_value); 1252 __ Bind(&store_value);
1257 __ str(value, element_address, kUnsignedByte); 1253 __ str(value, element_address, kUnsignedByte);
1258 } 1254 }
1259 break; 1255 break;
1260 } 1256 }
1261 case kTypedDataInt16ArrayCid: 1257 case kTypedDataInt16ArrayCid:
1262 case kTypedDataUint16ArrayCid: { 1258 case kTypedDataUint16ArrayCid: {
1263 Register value = locs()->in(2).reg(); 1259 const Register value = locs()->in(2).reg();
1264 __ SmiUntag(value); 1260 __ SmiUntag(value);
1265 __ str(value, element_address, kUnsignedHalfword); 1261 __ str(value, element_address, kUnsignedHalfword);
1266 break; 1262 break;
1267 } 1263 }
1268 case kTypedDataInt32ArrayCid: 1264 case kTypedDataInt32ArrayCid:
1269 case kTypedDataUint32ArrayCid: { 1265 case kTypedDataUint32ArrayCid: {
1270 if (value()->IsSmiValue()) { 1266 if (value()->IsSmiValue()) {
1271 ASSERT(RequiredInputRepresentation(2) == kTagged); 1267 ASSERT(RequiredInputRepresentation(2) == kTagged);
1272 Register value = locs()->in(2).reg(); 1268 const Register value = locs()->in(2).reg();
1273 __ SmiUntag(value); 1269 __ SmiUntag(value);
1274 __ str(value, element_address); 1270 __ str(value, element_address, kUnsignedWord);
1275 } else { 1271 } else {
1276 // TODO(zra): Implement when we add simd loads and stores. 1272 // TODO(zra): Implement when we add simd loads and stores.
1277 UNIMPLEMENTED(); 1273 UNIMPLEMENTED();
1278 } 1274 }
1279 break; 1275 break;
1280 } 1276 }
1281 case kTypedDataFloat32ArrayCid: 1277 case kTypedDataFloat32ArrayCid: {
1282 // TODO(zra): Implement when we add float store. 1278 const VRegister in2 = locs()->in(2).fpu_reg();
1283 UNIMPLEMENTED(); 1279 __ add(index.reg(), index.reg(), Operand(array));
1280 __ fstrs(in2, Address(index.reg()));
1284 break; 1281 break;
1282 }
1285 case kTypedDataFloat64ArrayCid: { 1283 case kTypedDataFloat64ArrayCid: {
1286 VRegister in2 = locs()->in(2).fpu_reg(); 1284 const VRegister in2 = locs()->in(2).fpu_reg();
1287 __ add(index.reg(), index.reg(), Operand(array)); 1285 __ add(index.reg(), index.reg(), Operand(array));
1288 __ StoreDToOffset(in2, index.reg(), 0); 1286 __ StoreDToOffset(in2, index.reg(), 0, PP);
1289 break; 1287 break;
1290 } 1288 }
1291 case kTypedDataFloat64x2ArrayCid: 1289 case kTypedDataFloat64x2ArrayCid:
1292 case kTypedDataInt32x4ArrayCid: 1290 case kTypedDataInt32x4ArrayCid:
1293 case kTypedDataFloat32x4ArrayCid: { 1291 case kTypedDataFloat32x4ArrayCid: {
1294 // TODO(zra): Implement when we add simd loads and stores. 1292 // TODO(zra): Implement when we add simd loads and stores.
1295 UNIMPLEMENTED(); 1293 UNIMPLEMENTED();
1296 break; 1294 break;
1297 } 1295 }
1298 default: 1296 default:
1299 UNREACHABLE(); 1297 UNREACHABLE();
1300 } 1298 }
1301 } 1299 }
1302 1300
1303 1301
1304 static void LoadValueCid(FlowGraphCompiler* compiler, 1302 static void LoadValueCid(FlowGraphCompiler* compiler,
1305 Register value_cid_reg, 1303 Register value_cid_reg,
1306 Register value_reg, 1304 Register value_reg,
1307 Label* value_is_smi = NULL) { 1305 Label* value_is_smi = NULL) {
1308 Label done; 1306 Label done;
1309 if (value_is_smi == NULL) { 1307 if (value_is_smi == NULL) {
1310 __ LoadImmediate(value_cid_reg, kSmiCid, PP); 1308 __ LoadImmediate(value_cid_reg, kSmiCid, PP);
1311 } 1309 }
1312 __ tsti(value_reg, kSmiTagMask); 1310 __ tsti(value_reg, kSmiTagMask);
1313 if (value_is_smi == NULL) { 1311 if (value_is_smi == NULL) {
1314 __ b(&done, EQ); 1312 __ b(&done, EQ);
1315 } else { 1313 } else {
1316 __ b(value_is_smi, EQ); 1314 __ b(value_is_smi, EQ);
1317 } 1315 }
1318 __ LoadClassId(value_cid_reg, value_reg); 1316 __ LoadClassId(value_cid_reg, value_reg, PP);
1319 __ Bind(&done); 1317 __ Bind(&done);
1320 } 1318 }
1321 1319
1322 1320
1323 LocationSummary* GuardFieldInstr::MakeLocationSummary(bool opt) const { 1321 LocationSummary* GuardFieldInstr::MakeLocationSummary(bool opt) const {
1324 const intptr_t kNumInputs = 1; 1322 const intptr_t kNumInputs = 1;
1325 LocationSummary* summary = 1323 LocationSummary* summary =
1326 new LocationSummary(kNumInputs, 0, LocationSummary::kNoCall); 1324 new LocationSummary(kNumInputs, 0, LocationSummary::kNoCall);
1327 summary->set_in(0, Location::RequiresRegister()); 1325 summary->set_in(0, Location::RequiresRegister());
1328 const bool field_has_length = field().needs_length_check(); 1326 const bool field_has_length = field().needs_length_check();
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
1396 if (value_cid == kDynamicCid) { 1394 if (value_cid == kDynamicCid) {
1397 LoadValueCid(compiler, value_cid_reg, value_reg); 1395 LoadValueCid(compiler, value_cid_reg, value_reg);
1398 Label skip_length_check; 1396 Label skip_length_check;
1399 __ ldr(TMP, field_cid_operand); 1397 __ ldr(TMP, field_cid_operand);
1400 __ CompareRegisters(value_cid_reg, TMP); 1398 __ CompareRegisters(value_cid_reg, TMP);
1401 __ b(&skip_length_check, NE); 1399 __ b(&skip_length_check, NE);
1402 if (field_has_length) { 1400 if (field_has_length) {
1403 ASSERT(temp_reg != kNoRegister); 1401 ASSERT(temp_reg != kNoRegister);
1404 // Field guard may have remembered list length, check it. 1402 // Field guard may have remembered list length, check it.
1405 if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) { 1403 if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) {
1406 __ LoadFieldFromOffset(temp_reg, value_reg, Array::length_offset()); 1404 __ LoadFieldFromOffset(
1405 temp_reg, value_reg, Array::length_offset(), PP);
1407 __ CompareImmediate(temp_reg, Smi::RawValue(field_length), PP); 1406 __ CompareImmediate(temp_reg, Smi::RawValue(field_length), PP);
1408 } else if (RawObject::IsTypedDataClassId(field_cid)) { 1407 } else if (RawObject::IsTypedDataClassId(field_cid)) {
1409 __ LoadFieldFromOffset( 1408 __ LoadFieldFromOffset(
1410 temp_reg, value_reg, TypedData::length_offset()); 1409 temp_reg, value_reg, TypedData::length_offset(), PP);
1411 __ CompareImmediate(temp_reg, Smi::RawValue(field_length), PP); 1410 __ CompareImmediate(temp_reg, Smi::RawValue(field_length), PP);
1412 } else { 1411 } else {
1413 ASSERT(field_cid == kIllegalCid); 1412 ASSERT(field_cid == kIllegalCid);
1414 ASSERT(field_length == Field::kUnknownFixedLength); 1413 ASSERT(field_length == Field::kUnknownFixedLength);
1415 // At compile time we do not know the type of the field nor its 1414 // At compile time we do not know the type of the field nor its
1416 // length. At execution time we may have set the class id and 1415 // length. At execution time we may have set the class id and
1417 // list length so we compare the guarded length with the 1416 // list length so we compare the guarded length with the
1418 // list length here, without this check the list length could change 1417 // list length here, without this check the list length could change
1419 // without triggering a deoptimization. 1418 // without triggering a deoptimization.
1420 Label check_array, length_compared, no_fixed_length; 1419 Label check_array, length_compared, no_fixed_length;
1421 // If length is negative the length guard is either disabled or 1420 // If length is negative the length guard is either disabled or
1422 // has not been initialized, either way it is safe to skip the 1421 // has not been initialized, either way it is safe to skip the
1423 // length check. 1422 // length check.
1424 __ ldr(TMP, field_length_operand); 1423 __ ldr(TMP, field_length_operand);
1425 __ CompareImmediate(TMP, 0, PP); 1424 __ CompareImmediate(TMP, 0, PP);
1426 __ b(&skip_length_check, LT); 1425 __ b(&skip_length_check, LT);
1427 __ CompareImmediate(value_cid_reg, kNullCid, PP); 1426 __ CompareImmediate(value_cid_reg, kNullCid, PP);
1428 __ b(&no_fixed_length, EQ); 1427 __ b(&no_fixed_length, EQ);
1429 // Check for typed data array. 1428 // Check for typed data array.
1430 __ CompareImmediate(value_cid_reg, kTypedDataInt32x4ArrayCid, PP); 1429 __ CompareImmediate(value_cid_reg, kTypedDataInt32x4ArrayCid, PP);
1431 __ b(&no_fixed_length, GT); 1430 __ b(&no_fixed_length, GT);
1432 __ CompareImmediate(value_cid_reg, kTypedDataInt8ArrayCid, PP); 1431 __ CompareImmediate(value_cid_reg, kTypedDataInt8ArrayCid, PP);
1433 // Could still be a regular array. 1432 // Could still be a regular array.
1434 __ b(&check_array, LT); 1433 __ b(&check_array, LT);
1435 __ LoadFieldFromOffset( 1434 __ LoadFieldFromOffset(
1436 temp_reg, value_reg, TypedData::length_offset()); 1435 temp_reg, value_reg, TypedData::length_offset(), PP);
1437 __ ldr(TMP, field_length_operand); 1436 __ ldr(TMP, field_length_operand);
1438 __ CompareRegisters(temp_reg, TMP); 1437 __ CompareRegisters(temp_reg, TMP);
1439 __ b(&length_compared); 1438 __ b(&length_compared);
1440 // Check for regular array. 1439 // Check for regular array.
1441 __ Bind(&check_array); 1440 __ Bind(&check_array);
1442 __ CompareImmediate(value_cid_reg, kImmutableArrayCid, PP); 1441 __ CompareImmediate(value_cid_reg, kImmutableArrayCid, PP);
1443 __ b(&no_fixed_length, GT); 1442 __ b(&no_fixed_length, GT);
1444 __ CompareImmediate(value_cid_reg, kArrayCid, PP); 1443 __ CompareImmediate(value_cid_reg, kArrayCid, PP);
1445 __ b(&no_fixed_length, LT); 1444 __ b(&no_fixed_length, LT);
1446 __ LoadFieldFromOffset(temp_reg, value_reg, Array::length_offset()); 1445 __ LoadFieldFromOffset(
1446 temp_reg, value_reg, Array::length_offset(), PP);
1447 __ ldr(TMP, field_length_operand); 1447 __ ldr(TMP, field_length_operand);
1448 __ CompareRegisters(temp_reg, TMP); 1448 __ CompareRegisters(temp_reg, TMP);
1449 __ b(&length_compared); 1449 __ b(&length_compared);
1450 __ Bind(&no_fixed_length); 1450 __ Bind(&no_fixed_length);
1451 __ b(fail); 1451 __ b(fail);
1452 __ Bind(&length_compared); 1452 __ Bind(&length_compared);
1453 // Following branch cannot not occur, fall through. 1453 // Following branch cannot not occur, fall through.
1454 } 1454 }
1455 __ b(fail, NE); 1455 __ b(fail, NE);
1456 } 1456 }
1457 __ Bind(&skip_length_check); 1457 __ Bind(&skip_length_check);
1458 __ ldr(TMP, field_nullability_operand); 1458 __ ldr(TMP, field_nullability_operand);
1459 __ CompareRegisters(value_cid_reg, TMP); 1459 __ CompareRegisters(value_cid_reg, TMP);
1460 } else if (value_cid == kNullCid) { 1460 } else if (value_cid == kNullCid) {
1461 __ ldr(value_cid_reg, field_nullability_operand); 1461 __ ldr(value_cid_reg, field_nullability_operand);
1462 __ CompareImmediate(value_cid_reg, value_cid, PP); 1462 __ CompareImmediate(value_cid_reg, value_cid, PP);
1463 } else { 1463 } else {
1464 Label skip_length_check; 1464 Label skip_length_check;
1465 __ ldr(value_cid_reg, field_cid_operand); 1465 __ ldr(value_cid_reg, field_cid_operand);
1466 __ CompareImmediate(value_cid_reg, value_cid, PP); 1466 __ CompareImmediate(value_cid_reg, value_cid, PP);
1467 __ b(&skip_length_check, NE); 1467 __ b(&skip_length_check, NE);
1468 if (field_has_length) { 1468 if (field_has_length) {
1469 ASSERT(value_cid_reg != kNoRegister); 1469 ASSERT(value_cid_reg != kNoRegister);
1470 ASSERT(temp_reg != kNoRegister); 1470 ASSERT(temp_reg != kNoRegister);
1471 if ((value_cid == kArrayCid) || (value_cid == kImmutableArrayCid)) { 1471 if ((value_cid == kArrayCid) || (value_cid == kImmutableArrayCid)) {
1472 __ LoadFieldFromOffset(temp_reg, value_reg, Array::length_offset()); 1472 __ LoadFieldFromOffset(
1473 temp_reg, value_reg, Array::length_offset(), PP);
1473 __ CompareImmediate(temp_reg, Smi::RawValue(field_length), PP); 1474 __ CompareImmediate(temp_reg, Smi::RawValue(field_length), PP);
1474 } else if (RawObject::IsTypedDataClassId(value_cid)) { 1475 } else if (RawObject::IsTypedDataClassId(value_cid)) {
1475 __ LoadFieldFromOffset( 1476 __ LoadFieldFromOffset(
1476 temp_reg, value_reg, TypedData::length_offset()); 1477 temp_reg, value_reg, TypedData::length_offset(), PP);
1477 __ CompareImmediate(temp_reg, Smi::RawValue(field_length), PP); 1478 __ CompareImmediate(temp_reg, Smi::RawValue(field_length), PP);
1478 } else if (field_cid != kIllegalCid) { 1479 } else if (field_cid != kIllegalCid) {
1479 ASSERT(field_cid != value_cid); 1480 ASSERT(field_cid != value_cid);
1480 ASSERT(field_length >= 0); 1481 ASSERT(field_length >= 0);
1481 // Field has a known class id and length. At compile time it is 1482 // Field has a known class id and length. At compile time it is
1482 // known that the value's class id is not a fixed length list. 1483 // known that the value's class id is not a fixed length list.
1483 __ b(fail); 1484 __ b(fail);
1484 } else { 1485 } else {
1485 ASSERT(field_cid == kIllegalCid); 1486 ASSERT(field_cid == kIllegalCid);
1486 ASSERT(field_length == Field::kUnknownFixedLength); 1487 ASSERT(field_length == Field::kUnknownFixedLength);
(...skipping 18 matching lines...) Expand all
1505 __ CompareImmediate(value_cid_reg, kNullCid, PP); 1506 __ CompareImmediate(value_cid_reg, kNullCid, PP);
1506 __ b(&no_fixed_length, EQ); 1507 __ b(&no_fixed_length, EQ);
1507 // Check for typed data array. 1508 // Check for typed data array.
1508 __ CompareImmediate(value_cid_reg, kTypedDataInt32x4ArrayCid, PP); 1509 __ CompareImmediate(value_cid_reg, kTypedDataInt32x4ArrayCid, PP);
1509 __ b(&no_fixed_length, GT); 1510 __ b(&no_fixed_length, GT);
1510 __ CompareImmediate(value_cid_reg, kTypedDataInt8ArrayCid, PP); 1511 __ CompareImmediate(value_cid_reg, kTypedDataInt8ArrayCid, PP);
1511 // Could still be a regular array. 1512 // Could still be a regular array.
1512 __ b(&check_array, LT); 1513 __ b(&check_array, LT);
1513 // Destroy value_cid_reg (safe because we are finished with it). 1514 // Destroy value_cid_reg (safe because we are finished with it).
1514 __ LoadFieldFromOffset( 1515 __ LoadFieldFromOffset(
1515 value_cid_reg, value_reg, TypedData::length_offset()); 1516 value_cid_reg, value_reg, TypedData::length_offset(), PP);
1516 __ str(value_cid_reg, field_length_operand); 1517 __ str(value_cid_reg, field_length_operand);
1517 __ b(&length_set); // Updated field length typed data array. 1518 __ b(&length_set); // Updated field length typed data array.
1518 // Check for regular array. 1519 // Check for regular array.
1519 __ Bind(&check_array); 1520 __ Bind(&check_array);
1520 __ CompareImmediate(value_cid_reg, kImmutableArrayCid, PP); 1521 __ CompareImmediate(value_cid_reg, kImmutableArrayCid, PP);
1521 __ b(&no_fixed_length, GT); 1522 __ b(&no_fixed_length, GT);
1522 __ CompareImmediate(value_cid_reg, kArrayCid, PP); 1523 __ CompareImmediate(value_cid_reg, kArrayCid, PP);
1523 __ b(&no_fixed_length, LT); 1524 __ b(&no_fixed_length, LT);
1524 // Destroy value_cid_reg (safe because we are finished with it). 1525 // Destroy value_cid_reg (safe because we are finished with it).
1525 __ LoadFieldFromOffset( 1526 __ LoadFieldFromOffset(
1526 value_cid_reg, value_reg, Array::length_offset()); 1527 value_cid_reg, value_reg, Array::length_offset(), PP);
1527 __ str(value_cid_reg, field_length_operand); 1528 __ str(value_cid_reg, field_length_operand);
1528 // Updated field length from regular array. 1529 // Updated field length from regular array.
1529 __ b(&length_set); 1530 __ b(&length_set);
1530 __ Bind(&no_fixed_length); 1531 __ Bind(&no_fixed_length);
1531 __ LoadImmediate(TMP, Smi::RawValue(Field::kNoFixedLength), PP); 1532 __ LoadImmediate(TMP, Smi::RawValue(Field::kNoFixedLength), PP);
1532 __ str(TMP, field_length_operand); 1533 __ str(TMP, field_length_operand);
1533 __ Bind(&length_set); 1534 __ Bind(&length_set);
1534 } 1535 }
1535 } else { 1536 } else {
1536 __ LoadImmediate(TMP, value_cid, PP); 1537 __ LoadImmediate(TMP, value_cid, PP);
1537 __ str(TMP, field_cid_operand); 1538 __ str(TMP, field_cid_operand);
1538 __ str(TMP, field_nullability_operand); 1539 __ str(TMP, field_nullability_operand);
1539 if (field_has_length) { 1540 if (field_has_length) {
1540 if ((value_cid == kArrayCid) || (value_cid == kImmutableArrayCid)) { 1541 if ((value_cid == kArrayCid) || (value_cid == kImmutableArrayCid)) {
1541 // Destroy value_cid_reg (safe because we are finished with it). 1542 // Destroy value_cid_reg (safe because we are finished with it).
1542 __ LoadFieldFromOffset( 1543 __ LoadFieldFromOffset(
1543 value_cid_reg, value_reg, Array::length_offset()); 1544 value_cid_reg, value_reg, Array::length_offset(), PP);
1544 __ str(value_cid_reg, field_length_operand); 1545 __ str(value_cid_reg, field_length_operand);
1545 } else if (RawObject::IsTypedDataClassId(value_cid)) { 1546 } else if (RawObject::IsTypedDataClassId(value_cid)) {
1546 // Destroy value_cid_reg (safe because we are finished with it). 1547 // Destroy value_cid_reg (safe because we are finished with it).
1547 __ LoadFieldFromOffset( 1548 __ LoadFieldFromOffset(
1548 value_cid_reg, value_reg, TypedData::length_offset()); 1549 value_cid_reg, value_reg, TypedData::length_offset(), PP);
1549 __ str(value_cid_reg, field_length_operand); 1550 __ str(value_cid_reg, field_length_operand);
1550 } else { 1551 } else {
1551 __ LoadImmediate(TMP, Smi::RawValue(Field::kNoFixedLength), PP); 1552 __ LoadImmediate(TMP, Smi::RawValue(Field::kNoFixedLength), PP);
1552 __ str(TMP, field_length_operand); 1553 __ str(TMP, field_length_operand);
1553 } 1554 }
1554 } 1555 }
1555 } 1556 }
1556 1557
1557 if (deopt == NULL) { 1558 if (deopt == NULL) {
1558 ASSERT(!compiler->is_optimizing()); 1559 ASSERT(!compiler->is_optimizing());
1559 __ b(&ok); 1560 __ b(&ok);
1560 __ Bind(fail); 1561 __ Bind(fail);
1561 1562
1562 __ LoadFieldFromOffset(TMP, field_reg, Field::guarded_cid_offset()); 1563 __ LoadFieldFromOffset(TMP, field_reg, Field::guarded_cid_offset(), PP);
1563 __ CompareImmediate(TMP, kDynamicCid, PP); 1564 __ CompareImmediate(TMP, kDynamicCid, PP);
1564 __ b(&ok, EQ); 1565 __ b(&ok, EQ);
1565 1566
1566 __ Push(field_reg); 1567 __ Push(field_reg);
1567 __ Push(value_reg); 1568 __ Push(value_reg);
1568 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2); 1569 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2);
1569 __ Drop(2); // Drop the field and the value. 1570 __ Drop(2); // Drop the field and the value.
1570 } 1571 }
1571 } else { 1572 } else {
1572 ASSERT(compiler->is_optimizing()); 1573 ASSERT(compiler->is_optimizing());
1573 ASSERT(deopt != NULL); 1574 ASSERT(deopt != NULL);
1574 // Field guard class has been initialized and is known. 1575 // Field guard class has been initialized and is known.
1575 if (field_reg != kNoRegister) { 1576 if (field_reg != kNoRegister) {
1576 __ LoadObject(field_reg, Field::ZoneHandle(field().raw()), PP); 1577 __ LoadObject(field_reg, Field::ZoneHandle(field().raw()), PP);
1577 } 1578 }
1578 if (value_cid == kDynamicCid) { 1579 if (value_cid == kDynamicCid) {
1579 // Field's guarded class id is fixed by value's class id is not known. 1580 // Field's guarded class id is fixed by value's class id is not known.
1580 __ tsti(value_reg, kSmiTagMask); 1581 __ tsti(value_reg, kSmiTagMask);
1581 1582
1582 if (field_cid != kSmiCid) { 1583 if (field_cid != kSmiCid) {
1583 __ b(fail, EQ); 1584 __ b(fail, EQ);
1584 __ LoadClassId(value_cid_reg, value_reg); 1585 __ LoadClassId(value_cid_reg, value_reg, PP);
1585 __ CompareImmediate(value_cid_reg, field_cid, PP); 1586 __ CompareImmediate(value_cid_reg, field_cid, PP);
1586 } 1587 }
1587 1588
1588 if (field_has_length) { 1589 if (field_has_length) {
1589 __ b(fail, NE); 1590 __ b(fail, NE);
1590 // Classes are same, perform guarded list length check. 1591 // Classes are same, perform guarded list length check.
1591 ASSERT(field_reg != kNoRegister); 1592 ASSERT(field_reg != kNoRegister);
1592 ASSERT(value_cid_reg != kNoRegister); 1593 ASSERT(value_cid_reg != kNoRegister);
1593 FieldAddress field_length_operand( 1594 FieldAddress field_length_operand(
1594 field_reg, Field::guarded_list_length_offset()); 1595 field_reg, Field::guarded_list_length_offset());
1595 if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) { 1596 if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) {
1596 // Destroy value_cid_reg (safe because we are finished with it). 1597 // Destroy value_cid_reg (safe because we are finished with it).
1597 __ LoadFieldFromOffset( 1598 __ LoadFieldFromOffset(
1598 value_cid_reg, value_reg, Array::length_offset()); 1599 value_cid_reg, value_reg, Array::length_offset(), PP);
1599 } else if (RawObject::IsTypedDataClassId(field_cid)) { 1600 } else if (RawObject::IsTypedDataClassId(field_cid)) {
1600 // Destroy value_cid_reg (safe because we are finished with it). 1601 // Destroy value_cid_reg (safe because we are finished with it).
1601 __ LoadFieldFromOffset( 1602 __ LoadFieldFromOffset(
1602 value_cid_reg, value_reg, TypedData::length_offset()); 1603 value_cid_reg, value_reg, TypedData::length_offset(), PP);
1603 } 1604 }
1604 __ ldr(TMP, field_length_operand); 1605 __ ldr(TMP, field_length_operand);
1605 __ CompareRegisters(value_cid_reg, TMP); 1606 __ CompareRegisters(value_cid_reg, TMP);
1606 } 1607 }
1607 1608
1608 if (field().is_nullable() && (field_cid != kNullCid)) { 1609 if (field().is_nullable() && (field_cid != kNullCid)) {
1609 __ b(&ok, EQ); 1610 __ b(&ok, EQ);
1610 __ CompareObject(value_reg, Object::null_object(), PP); 1611 __ CompareObject(value_reg, Object::null_object(), PP);
1611 } 1612 }
1612 __ b(fail, NE); 1613 __ b(fail, NE);
1613 } else { 1614 } else {
1614 // Both value's and field's class id is known. 1615 // Both value's and field's class id is known.
1615 if ((value_cid != field_cid) && (value_cid != nullability)) { 1616 if ((value_cid != field_cid) && (value_cid != nullability)) {
1616 __ b(fail); 1617 __ b(fail);
1617 } else if (field_has_length && (value_cid == field_cid)) { 1618 } else if (field_has_length && (value_cid == field_cid)) {
1618 ASSERT(value_cid_reg != kNoRegister); 1619 ASSERT(value_cid_reg != kNoRegister);
1619 if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) { 1620 if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) {
1620 // Destroy value_cid_reg (safe because we are finished with it). 1621 // Destroy value_cid_reg (safe because we are finished with it).
1621 __ LoadFieldFromOffset( 1622 __ LoadFieldFromOffset(
1622 value_cid_reg, value_reg, Array::length_offset()); 1623 value_cid_reg, value_reg, Array::length_offset(), PP);
1623 } else if (RawObject::IsTypedDataClassId(field_cid)) { 1624 } else if (RawObject::IsTypedDataClassId(field_cid)) {
1624 // Destroy value_cid_reg (safe because we are finished with it). 1625 // Destroy value_cid_reg (safe because we are finished with it).
1625 __ LoadFieldFromOffset( 1626 __ LoadFieldFromOffset(
1626 value_cid_reg, value_reg, TypedData::length_offset()); 1627 value_cid_reg, value_reg, TypedData::length_offset(), PP);
1627 } 1628 }
1628 __ CompareImmediate(value_cid_reg, field_length, PP); 1629 __ CompareImmediate(value_cid_reg, field_length, PP);
1629 __ b(fail, NE); 1630 __ b(fail, NE);
1630 } else { 1631 } else {
1631 UNREACHABLE(); 1632 UNREACHABLE();
1632 } 1633 }
1633 } 1634 }
1634 } 1635 }
1635 __ Bind(&ok); 1636 __ Bind(&ok);
1636 } 1637 }
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
1712 const Register temp = locs()->temp(0).reg(); 1713 const Register temp = locs()->temp(0).reg();
1713 const Register temp2 = locs()->temp(1).reg(); 1714 const Register temp2 = locs()->temp(1).reg();
1714 const intptr_t cid = field().UnboxedFieldCid(); 1715 const intptr_t cid = field().UnboxedFieldCid();
1715 1716
1716 if (is_initialization_) { 1717 if (is_initialization_) {
1717 const Class* cls = NULL; 1718 const Class* cls = NULL;
1718 switch (cid) { 1719 switch (cid) {
1719 case kDoubleCid: 1720 case kDoubleCid:
1720 cls = &compiler->double_class(); 1721 cls = &compiler->double_class();
1721 break; 1722 break;
1722 // TODO(zra): Implement these when we add fpu loads and stores.
1723 case kFloat32x4Cid: 1723 case kFloat32x4Cid:
1724 cls = &compiler->float32x4_class();
1725 break;
1724 case kFloat64x2Cid: 1726 case kFloat64x2Cid:
1725 UNIMPLEMENTED(); 1727 cls = &compiler->float64x2_class();
1726 break; 1728 break;
1727 default: 1729 default:
1728 UNREACHABLE(); 1730 UNREACHABLE();
1729 } 1731 }
1730 1732
1731 StoreInstanceFieldSlowPath* slow_path = 1733 StoreInstanceFieldSlowPath* slow_path =
1732 new StoreInstanceFieldSlowPath(this, *cls); 1734 new StoreInstanceFieldSlowPath(this, *cls);
1733 compiler->AddSlowPathCode(slow_path); 1735 compiler->AddSlowPathCode(slow_path);
1734 1736
1735 __ TryAllocate(*cls, 1737 __ TryAllocate(*cls,
1736 slow_path->entry_label(), 1738 slow_path->entry_label(),
1737 temp, 1739 temp,
1738 temp2, 1740 temp2,
1739 PP); 1741 PP);
1740 __ Bind(slow_path->exit_label()); 1742 __ Bind(slow_path->exit_label());
1741 __ mov(temp2, temp); 1743 __ mov(temp2, temp);
1742 __ StoreIntoObject(instance_reg, 1744 __ StoreIntoObjectOffset(instance_reg, offset_in_bytes_, temp2, PP);
1743 FieldAddress(instance_reg, offset_in_bytes_),
1744 temp2);
1745 } else { 1745 } else {
1746 __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes_); 1746 __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes_, PP);
1747 } 1747 }
1748 switch (cid) { 1748 switch (cid) {
1749 case kDoubleCid: 1749 case kDoubleCid:
1750 __ Comment("UnboxedDoubleStoreInstanceFieldInstr"); 1750 __ Comment("UnboxedDoubleStoreInstanceFieldInstr");
1751 __ StoreDFieldToOffset(value, temp, Double::value_offset()); 1751 __ StoreDFieldToOffset(value, temp, Double::value_offset(), PP);
1752 break; 1752 break;
1753 case kFloat32x4Cid: 1753 case kFloat32x4Cid:
1754 __ Comment("UnboxedFloat32x4StoreInstanceFieldInstr");
1755 __ StoreQFieldToOffset(value, temp, Float32x4::value_offset(), PP);
1756 break;
1754 case kFloat64x2Cid: 1757 case kFloat64x2Cid:
1755 UNIMPLEMENTED(); 1758 __ Comment("UnboxedFloat64x2StoreInstanceFieldInstr");
1759 __ StoreQFieldToOffset(value, temp, Float64x2::value_offset(), PP);
1756 break; 1760 break;
1757 default: 1761 default:
1758 UNREACHABLE(); 1762 UNREACHABLE();
1759 } 1763 }
1760 1764
1761 return; 1765 return;
1762 } 1766 }
1763 1767
1764 if (IsPotentialUnboxedStore()) { 1768 if (IsPotentialUnboxedStore()) {
1765 const Register value_reg = locs()->in(1).reg(); 1769 const Register value_reg = locs()->in(1).reg();
1766 const Register temp = locs()->temp(0).reg(); 1770 const Register temp = locs()->temp(0).reg();
1767 const Register temp2 = locs()->temp(1).reg(); 1771 const Register temp2 = locs()->temp(1).reg();
1768 const VRegister fpu_temp = locs()->temp(2).fpu_reg(); 1772 const VRegister fpu_temp = locs()->temp(2).fpu_reg();
1769 1773
1770 Label store_pointer; 1774 Label store_pointer;
1771 Label store_double; 1775 Label store_double;
1772 Label store_float32x4; 1776 Label store_float32x4;
1773 Label store_float64x2; 1777 Label store_float64x2;
1774 1778
1775 __ LoadObject(temp, Field::ZoneHandle(field().raw()), PP); 1779 __ LoadObject(temp, Field::ZoneHandle(field().raw()), PP);
1776 1780
1777 __ LoadFieldFromOffset(temp2, temp, Field::is_nullable_offset()); 1781 __ LoadFieldFromOffset(temp2, temp, Field::is_nullable_offset(), PP);
1778 __ CompareImmediate(temp2, kNullCid, PP); 1782 __ CompareImmediate(temp2, kNullCid, PP);
1779 __ b(&store_pointer, EQ); 1783 __ b(&store_pointer, EQ);
1780 1784
1781 __ LoadFromOffset( 1785 __ LoadFromOffset(
1782 temp2, temp, Field::kind_bits_offset() - kHeapObjectTag, kUnsignedByte); 1786 temp2, temp, Field::kind_bits_offset() - kHeapObjectTag,
1787 PP, kUnsignedByte);
1783 __ tsti(temp2, 1 << Field::kUnboxingCandidateBit); 1788 __ tsti(temp2, 1 << Field::kUnboxingCandidateBit);
1784 __ b(&store_pointer, EQ); 1789 __ b(&store_pointer, EQ);
1785 1790
1786 __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset()); 1791 __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(), PP);
1787 __ CompareImmediate(temp2, kDoubleCid, PP); 1792 __ CompareImmediate(temp2, kDoubleCid, PP);
1788 __ b(&store_double, EQ); 1793 __ b(&store_double, EQ);
1789 1794
1790 __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset()); 1795 __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(), PP);
1791 __ CompareImmediate(temp2, kFloat32x4Cid, PP); 1796 __ CompareImmediate(temp2, kFloat32x4Cid, PP);
1792 __ b(&store_float32x4, EQ); 1797 __ b(&store_float32x4, EQ);
1793 1798
1794 __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset()); 1799 __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(), PP);
1795 __ CompareImmediate(temp2, kFloat64x2Cid, PP); 1800 __ CompareImmediate(temp2, kFloat64x2Cid, PP);
1796 __ b(&store_float64x2, EQ); 1801 __ b(&store_float64x2, EQ);
1797 1802
1798 // Fall through. 1803 // Fall through.
1799 __ b(&store_pointer); 1804 __ b(&store_pointer);
1800 1805
1801 if (!compiler->is_optimizing()) { 1806 if (!compiler->is_optimizing()) {
1802 locs()->live_registers()->Add(locs()->in(0)); 1807 locs()->live_registers()->Add(locs()->in(0));
1803 locs()->live_registers()->Add(locs()->in(1)); 1808 locs()->live_registers()->Add(locs()->in(1));
1804 } 1809 }
1805 1810
1806 { 1811 {
1807 __ Bind(&store_double); 1812 __ Bind(&store_double);
1808 Label copy_double; 1813 Label copy_double;
1809 StoreInstanceFieldSlowPath* slow_path = 1814 StoreInstanceFieldSlowPath* slow_path =
1810 new StoreInstanceFieldSlowPath(this, compiler->double_class()); 1815 new StoreInstanceFieldSlowPath(this, compiler->double_class());
1811 compiler->AddSlowPathCode(slow_path); 1816 compiler->AddSlowPathCode(slow_path);
1812 1817
1813 __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes_); 1818 __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes_, PP);
1814 __ CompareObject(temp, Object::null_object(), PP); 1819 __ CompareObject(temp, Object::null_object(), PP);
1815 __ b(&copy_double, NE); 1820 __ b(&copy_double, NE);
1816 1821
1817 __ TryAllocate(compiler->double_class(), 1822 __ TryAllocate(compiler->double_class(),
1818 slow_path->entry_label(), 1823 slow_path->entry_label(),
1819 temp, 1824 temp,
1820 temp2, 1825 temp2,
1821 PP); 1826 PP);
1822 __ Bind(slow_path->exit_label()); 1827 __ Bind(slow_path->exit_label());
1823 __ mov(temp2, temp); 1828 __ mov(temp2, temp);
1824 __ StoreIntoObject(instance_reg, 1829 __ StoreIntoObjectOffset(instance_reg, offset_in_bytes_, temp2, PP);
1825 FieldAddress(instance_reg, offset_in_bytes_),
1826 temp2);
1827 __ Bind(&copy_double); 1830 __ Bind(&copy_double);
1828 __ LoadDFieldFromOffset(fpu_temp, value_reg, Double::value_offset()); 1831 __ LoadDFieldFromOffset(fpu_temp, value_reg, Double::value_offset(), PP);
1829 __ StoreDFieldToOffset(fpu_temp, temp, Double::value_offset()); 1832 __ StoreDFieldToOffset(fpu_temp, temp, Double::value_offset(), PP);
1830 __ b(&skip_store); 1833 __ b(&skip_store);
1831 } 1834 }
1832 1835
1833 // TODO(zra): Implement these when we add simd loads and stores.
1834 { 1836 {
1835 __ Bind(&store_float32x4); 1837 __ Bind(&store_float32x4);
1836 __ Stop("Float32x4 Unimplemented"); 1838 Label copy_float32x4;
1839 StoreInstanceFieldSlowPath* slow_path =
1840 new StoreInstanceFieldSlowPath(this, compiler->float32x4_class());
1841 compiler->AddSlowPathCode(slow_path);
1842
1843 __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes_, PP);
1844 __ CompareObject(temp, Object::null_object(), PP);
1845 __ b(&copy_float32x4, NE);
1846
1847 __ TryAllocate(compiler->float32x4_class(),
1848 slow_path->entry_label(),
1849 temp,
1850 temp2,
1851 PP);
1852 __ Bind(slow_path->exit_label());
1853 __ mov(temp2, temp);
1854 __ StoreIntoObjectOffset(instance_reg, offset_in_bytes_, temp2, PP);
1855 __ Bind(&copy_float32x4);
1856 __ LoadQFieldFromOffset(
1857 fpu_temp, value_reg, Float32x4::value_offset(), PP);
1858 __ StoreQFieldToOffset(
1859 fpu_temp, value_reg, Float32x4::value_offset(), PP);
1860 __ b(&skip_store);
1837 } 1861 }
1838 1862
1839 { 1863 {
1840 __ Bind(&store_float64x2); 1864 __ Bind(&store_float64x2);
1841 __ Stop("Float64x2 Unimplemented"); 1865 Label copy_float64x2;
1866 StoreInstanceFieldSlowPath* slow_path =
1867 new StoreInstanceFieldSlowPath(this, compiler->float64x2_class());
1868 compiler->AddSlowPathCode(slow_path);
1869
1870 __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes_, PP);
1871 __ CompareObject(temp, Object::null_object(), PP);
1872 __ b(&copy_float64x2, NE);
1873
1874 __ TryAllocate(compiler->float64x2_class(),
1875 slow_path->entry_label(),
1876 temp,
1877 temp2,
1878 PP);
1879 __ Bind(slow_path->exit_label());
1880 __ mov(temp2, temp);
1881 __ StoreIntoObjectOffset(instance_reg, offset_in_bytes_, temp2, PP);
1882 __ Bind(&copy_float64x2);
1883 __ LoadQFieldFromOffset(
1884 fpu_temp, value_reg, Float64x2::value_offset(), PP);
1885 __ StoreQFieldToOffset(
1886 fpu_temp, value_reg, Float64x2::value_offset(), PP);
1887 __ b(&skip_store);
1842 } 1888 }
1843 1889
1844 __ Bind(&store_pointer); 1890 __ Bind(&store_pointer);
1845 } 1891 }
1846 1892
1847 if (ShouldEmitStoreBarrier()) { 1893 if (ShouldEmitStoreBarrier()) {
1848 Register value_reg = locs()->in(1).reg(); 1894 const Register value_reg = locs()->in(1).reg();
1849 __ StoreIntoObject(instance_reg, 1895 __ StoreIntoObjectOffset(
1850 FieldAddress(instance_reg, offset_in_bytes_), 1896 instance_reg, offset_in_bytes_, value_reg, PP, CanValueBeSmi());
1851 value_reg,
1852 CanValueBeSmi());
1853 } else { 1897 } else {
1854 if (locs()->in(1).IsConstant()) { 1898 if (locs()->in(1).IsConstant()) {
1855 __ StoreIntoObjectNoBarrier( 1899 __ StoreIntoObjectOffsetNoBarrier(
1856 instance_reg, 1900 instance_reg,
1857 FieldAddress(instance_reg, offset_in_bytes_), 1901 offset_in_bytes_,
1858 locs()->in(1).constant()); 1902 locs()->in(1).constant(),
1903 PP);
1859 } else { 1904 } else {
1860 Register value_reg = locs()->in(1).reg(); 1905 const Register value_reg = locs()->in(1).reg();
1861 __ StoreIntoObjectNoBarrier(instance_reg, 1906 __ StoreIntoObjectOffsetNoBarrier(
1862 FieldAddress(instance_reg, offset_in_bytes_), value_reg); 1907 instance_reg,
1908 offset_in_bytes_,
1909 value_reg,
1910 PP);
1863 } 1911 }
1864 } 1912 }
1865 __ Bind(&skip_store); 1913 __ Bind(&skip_store);
1866 } 1914 }
1867 1915
1868 1916
1869 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(bool opt) const { 1917 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(bool opt) const {
1870 const intptr_t kNumInputs = 1; 1918 const intptr_t kNumInputs = 1;
1871 const intptr_t kNumTemps = 0; 1919 const intptr_t kNumTemps = 0;
1872 LocationSummary* summary = 1920 LocationSummary* summary =
1873 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 1921 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
1874 summary->set_in(0, Location::RequiresRegister()); 1922 summary->set_in(0, Location::RequiresRegister());
1875 summary->set_out(0, Location::RequiresRegister()); 1923 summary->set_out(0, Location::RequiresRegister());
1876 return summary; 1924 return summary;
1877 } 1925 }
1878 1926
1879 1927
1880 // When the parser is building an implicit static getter for optimization, 1928 // When the parser is building an implicit static getter for optimization,
1881 // it can generate a function body where deoptimization ids do not line up 1929 // it can generate a function body where deoptimization ids do not line up
1882 // with the unoptimized code. 1930 // with the unoptimized code.
1883 // 1931 //
1884 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. 1932 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize.
1885 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1933 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1886 Register field = locs()->in(0).reg(); 1934 Register field = locs()->in(0).reg();
1887 Register result = locs()->out(0).reg(); 1935 Register result = locs()->out(0).reg();
1888 __ LoadFieldFromOffset(result, field, Field::value_offset()); 1936 __ LoadFieldFromOffset(result, field, Field::value_offset(), PP);
1889 } 1937 }
1890 1938
1891 1939
1892 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(bool opt) const { 1940 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(bool opt) const {
1893 LocationSummary* locs = new LocationSummary(1, 1, LocationSummary::kNoCall); 1941 LocationSummary* locs = new LocationSummary(1, 1, LocationSummary::kNoCall);
1894 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() 1942 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister()
1895 : Location::RequiresRegister()); 1943 : Location::RequiresRegister());
1896 locs->set_temp(0, Location::RequiresRegister()); 1944 locs->set_temp(0, Location::RequiresRegister());
1897 return locs; 1945 return locs;
1898 } 1946 }
1899 1947
1900 1948
1901 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1949 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1902 Register value = locs()->in(0).reg(); 1950 Register value = locs()->in(0).reg();
1903 Register temp = locs()->temp(0).reg(); 1951 Register temp = locs()->temp(0).reg();
1904 1952
1905 __ LoadObject(temp, field(), PP); 1953 __ LoadObject(temp, field(), PP);
1906 if (this->value()->NeedsStoreBuffer()) { 1954 if (this->value()->NeedsStoreBuffer()) {
1907 __ StoreIntoObject(temp, 1955 __ StoreIntoObjectOffset(
1908 FieldAddress(temp, Field::value_offset()), value, CanValueBeSmi()); 1956 temp, Field::value_offset(), value, PP, CanValueBeSmi());
1909 } else { 1957 } else {
1910 __ StoreIntoObjectNoBarrier( 1958 __ StoreIntoObjectOffsetNoBarrier(temp, Field::value_offset(), value, PP);
1911 temp, FieldAddress(temp, Field::value_offset()), value);
1912 } 1959 }
1913 } 1960 }
1914 1961
1915 1962
1916 LocationSummary* InstanceOfInstr::MakeLocationSummary(bool opt) const { 1963 LocationSummary* InstanceOfInstr::MakeLocationSummary(bool opt) const {
1917 const intptr_t kNumInputs = 3; 1964 const intptr_t kNumInputs = 3;
1918 const intptr_t kNumTemps = 0; 1965 const intptr_t kNumTemps = 0;
1919 LocationSummary* summary = 1966 LocationSummary* summary =
1920 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); 1967 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
1921 summary->set_in(0, Location::RegisterLocation(R0)); 1968 summary->set_in(0, Location::RegisterLocation(R0));
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
2018 locs->set_out(0, Location::RequiresRegister()); 2065 locs->set_out(0, Location::RequiresRegister());
2019 return locs; 2066 return locs;
2020 } 2067 }
2021 2068
2022 2069
2023 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2070 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2024 Register instance_reg = locs()->in(0).reg(); 2071 Register instance_reg = locs()->in(0).reg();
2025 if (IsUnboxedLoad() && compiler->is_optimizing()) { 2072 if (IsUnboxedLoad() && compiler->is_optimizing()) {
2026 const VRegister result = locs()->out(0).fpu_reg(); 2073 const VRegister result = locs()->out(0).fpu_reg();
2027 const Register temp = locs()->temp(0).reg(); 2074 const Register temp = locs()->temp(0).reg();
2028 __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes()); 2075 __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes(), PP);
2029 const intptr_t cid = field()->UnboxedFieldCid(); 2076 const intptr_t cid = field()->UnboxedFieldCid();
2030 switch (cid) { 2077 switch (cid) {
2031 case kDoubleCid: 2078 case kDoubleCid:
2032 __ Comment("UnboxedDoubleLoadFieldInstr"); 2079 __ Comment("UnboxedDoubleLoadFieldInstr");
2033 __ LoadDFieldFromOffset(result, temp, Double::value_offset()); 2080 __ LoadDFieldFromOffset(result, temp, Double::value_offset(), PP);
2034 break; 2081 break;
2035 case kFloat32x4Cid: 2082 case kFloat32x4Cid:
2036 case kFloat64x2Cid: 2083 case kFloat64x2Cid:
2037 UNIMPLEMENTED(); 2084 UNIMPLEMENTED();
2038 break; 2085 break;
2039 default: 2086 default:
2040 UNREACHABLE(); 2087 UNREACHABLE();
2041 } 2088 }
2042 return; 2089 return;
2043 } 2090 }
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
2086 __ Bind(&load_double); 2133 __ Bind(&load_double);
2087 BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this); 2134 BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this);
2088 compiler->AddSlowPathCode(slow_path); 2135 compiler->AddSlowPathCode(slow_path);
2089 2136
2090 __ TryAllocate(compiler->double_class(), 2137 __ TryAllocate(compiler->double_class(),
2091 slow_path->entry_label(), 2138 slow_path->entry_label(),
2092 result_reg, 2139 result_reg,
2093 temp, 2140 temp,
2094 PP); 2141 PP);
2095 __ Bind(slow_path->exit_label()); 2142 __ Bind(slow_path->exit_label());
2096 __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes()); 2143 __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes(), PP);
2097 __ LoadDFieldFromOffset(value, temp, Double::value_offset()); 2144 __ LoadDFieldFromOffset(value, temp, Double::value_offset(), PP);
2098 __ StoreDFieldToOffset(value, result_reg, Double::value_offset()); 2145 __ StoreDFieldToOffset(value, result_reg, Double::value_offset(), PP);
2099 __ b(&done); 2146 __ b(&done);
2100 } 2147 }
2101 2148
2102 // TODO(zra): Implement these when we add simd loads and stores. 2149 // TODO(zra): Implement these when we add simd loads and stores.
2103 { 2150 {
2104 __ Bind(&load_float32x4); 2151 __ Bind(&load_float32x4);
2105 __ Stop("Float32x4 Unimplemented"); 2152 __ Stop("Float32x4 Unimplemented");
2106 } 2153 }
2107 2154
2108 { 2155 {
2109 __ Bind(&load_float64x2); 2156 __ Bind(&load_float64x2);
2110 __ Stop("Float64x2 Unimplemented"); 2157 __ Stop("Float64x2 Unimplemented");
2111 } 2158 }
2112 2159
2113 __ Bind(&load_pointer); 2160 __ Bind(&load_pointer);
2114 } 2161 }
2115 __ LoadFieldFromOffset(result_reg, instance_reg, offset_in_bytes()); 2162 __ LoadFieldFromOffset(result_reg, instance_reg, offset_in_bytes(), PP);
2116 __ Bind(&done); 2163 __ Bind(&done);
2117 } 2164 }
2118 2165
2119 2166
2120 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(bool opt) const { 2167 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(bool opt) const {
2121 const intptr_t kNumInputs = 1; 2168 const intptr_t kNumInputs = 1;
2122 const intptr_t kNumTemps = 0; 2169 const intptr_t kNumTemps = 0;
2123 LocationSummary* locs = 2170 LocationSummary* locs =
2124 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); 2171 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
2125 locs->set_in(0, Location::RegisterLocation(R0)); 2172 locs->set_in(0, Location::RegisterLocation(R0));
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
2175 // instantiated from null becomes a vector of dynamic, then use null as 2222 // instantiated from null becomes a vector of dynamic, then use null as
2176 // the type arguments. 2223 // the type arguments.
2177 Label type_arguments_instantiated; 2224 Label type_arguments_instantiated;
2178 const intptr_t len = type_arguments().Length(); 2225 const intptr_t len = type_arguments().Length();
2179 if (type_arguments().IsRawInstantiatedRaw(len)) { 2226 if (type_arguments().IsRawInstantiatedRaw(len)) {
2180 __ CompareObject(instantiator_reg, Object::null_object(), PP); 2227 __ CompareObject(instantiator_reg, Object::null_object(), PP);
2181 __ b(&type_arguments_instantiated, EQ); 2228 __ b(&type_arguments_instantiated, EQ);
2182 } 2229 }
2183 2230
2184 __ LoadObject(R2, type_arguments(), PP); 2231 __ LoadObject(R2, type_arguments(), PP);
2185 __ LoadFieldFromOffset(R2, R2, TypeArguments::instantiations_offset()); 2232 __ LoadFieldFromOffset(R2, R2, TypeArguments::instantiations_offset(), PP);
2186 __ AddImmediate(R2, R2, Array::data_offset() - kHeapObjectTag, PP); 2233 __ AddImmediate(R2, R2, Array::data_offset() - kHeapObjectTag, PP);
2187 // The instantiations cache is initialized with Object::zero_array() and is 2234 // The instantiations cache is initialized with Object::zero_array() and is
2188 // therefore guaranteed to contain kNoInstantiator. No length check needed. 2235 // therefore guaranteed to contain kNoInstantiator. No length check needed.
2189 Label loop, found, slow_case; 2236 Label loop, found, slow_case;
2190 __ Bind(&loop); 2237 __ Bind(&loop);
2191 __ LoadFromOffset(R1, R2, 0 * kWordSize); // Cached instantiator. 2238 __ LoadFromOffset(R1, R2, 0 * kWordSize, PP); // Cached instantiator.
2192 __ CompareRegisters(R1, R0); 2239 __ CompareRegisters(R1, R0);
2193 __ b(&found, EQ); 2240 __ b(&found, EQ);
2194 __ AddImmediate(R2, R2, 2 * kWordSize, PP); 2241 __ AddImmediate(R2, R2, 2 * kWordSize, PP);
2195 __ CompareImmediate(R1, Smi::RawValue(StubCode::kNoInstantiator), PP); 2242 __ CompareImmediate(R1, Smi::RawValue(StubCode::kNoInstantiator), PP);
2196 __ b(&loop, NE); 2243 __ b(&loop, NE);
2197 __ b(&slow_case); 2244 __ b(&slow_case);
2198 __ Bind(&found); 2245 __ Bind(&found);
2199 __ LoadFromOffset(R0, R2, 1 * kWordSize); // Cached instantiated args. 2246 __ LoadFromOffset(R0, R2, 1 * kWordSize, PP); // Cached instantiated args.
2200 __ b(&type_arguments_instantiated); 2247 __ b(&type_arguments_instantiated);
2201 2248
2202 __ Bind(&slow_case); 2249 __ Bind(&slow_case);
2203 // Instantiate non-null type arguments. 2250 // Instantiate non-null type arguments.
2204 // A runtime call to instantiate the type arguments is required. 2251 // A runtime call to instantiate the type arguments is required.
2205 __ PushObject(Object::ZoneHandle(), PP); // Make room for the result. 2252 __ PushObject(Object::ZoneHandle(), PP); // Make room for the result.
2206 __ PushObject(type_arguments(), PP); 2253 __ PushObject(type_arguments(), PP);
2207 __ Push(instantiator_reg); // Push instantiator type arguments. 2254 __ Push(instantiator_reg); // Push instantiator type arguments.
2208 compiler->GenerateRuntimeCall(token_pos(), 2255 compiler->GenerateRuntimeCall(token_pos(),
2209 deopt_id(), 2256 deopt_id(),
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
2292 // Restore SP from FP as we are coming from a throw and the code for 2339 // Restore SP from FP as we are coming from a throw and the code for
2293 // popping arguments has not been run. 2340 // popping arguments has not been run.
2294 const intptr_t fp_sp_dist = 2341 const intptr_t fp_sp_dist =
2295 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; 2342 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize;
2296 ASSERT(fp_sp_dist <= 0); 2343 ASSERT(fp_sp_dist <= 0);
2297 __ AddImmediate(SP, FP, fp_sp_dist, PP); 2344 __ AddImmediate(SP, FP, fp_sp_dist, PP);
2298 2345
2299 // Restore stack and initialize the two exception variables: 2346 // Restore stack and initialize the two exception variables:
2300 // exception and stack trace variables. 2347 // exception and stack trace variables.
2301 __ StoreToOffset(kExceptionObjectReg, 2348 __ StoreToOffset(kExceptionObjectReg,
2302 FP, exception_var().index() * kWordSize); 2349 FP, exception_var().index() * kWordSize, PP);
2303 __ StoreToOffset(kStackTraceObjectReg, 2350 __ StoreToOffset(kStackTraceObjectReg,
2304 FP, stacktrace_var().index() * kWordSize); 2351 FP, stacktrace_var().index() * kWordSize, PP);
2305 } 2352 }
2306 2353
2307 2354
2308 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(bool opt) const { 2355 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(bool opt) const {
2309 const intptr_t kNumInputs = 0; 2356 const intptr_t kNumInputs = 0;
2310 const intptr_t kNumTemps = 1; 2357 const intptr_t kNumTemps = 1;
2311 LocationSummary* summary = 2358 LocationSummary* summary =
2312 new LocationSummary(kNumInputs, 2359 new LocationSummary(kNumInputs,
2313 kNumTemps, 2360 kNumTemps,
2314 LocationSummary::kCallOnSlowPath); 2361 LocationSummary::kCallOnSlowPath);
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
2377 __ CompareRegisters(SP, TMP); 2424 __ CompareRegisters(SP, TMP);
2378 __ b(slow_path->entry_label(), LS); 2425 __ b(slow_path->entry_label(), LS);
2379 if (compiler->CanOSRFunction() && in_loop()) { 2426 if (compiler->CanOSRFunction() && in_loop()) {
2380 Register temp = locs()->temp(0).reg(); 2427 Register temp = locs()->temp(0).reg();
2381 // In unoptimized code check the usage counter to trigger OSR at loop 2428 // In unoptimized code check the usage counter to trigger OSR at loop
2382 // stack checks. Use progressively higher thresholds for more deeply 2429 // stack checks. Use progressively higher thresholds for more deeply
2383 // nested loops to attempt to hit outer loops with OSR when possible. 2430 // nested loops to attempt to hit outer loops with OSR when possible.
2384 __ LoadObject(temp, compiler->parsed_function().function(), PP); 2431 __ LoadObject(temp, compiler->parsed_function().function(), PP);
2385 intptr_t threshold = 2432 intptr_t threshold =
2386 FLAG_optimization_counter_threshold * (loop_depth() + 1); 2433 FLAG_optimization_counter_threshold * (loop_depth() + 1);
2387 __ LoadFieldFromOffset(temp, temp, Function::usage_counter_offset()); 2434 __ LoadFieldFromOffset(temp, temp, Function::usage_counter_offset(), PP);
2388 __ CompareImmediate(temp, threshold, PP); 2435 __ CompareImmediate(temp, threshold, PP);
2389 __ b(slow_path->osr_entry_label(), GE); 2436 __ b(slow_path->osr_entry_label(), GE);
2390 } 2437 }
2391 if (compiler->ForceSlowPathForStackOverflow()) { 2438 if (compiler->ForceSlowPathForStackOverflow()) {
2392 __ b(slow_path->entry_label()); 2439 __ b(slow_path->entry_label());
2393 } 2440 }
2394 __ Bind(slow_path->exit_label()); 2441 __ Bind(slow_path->exit_label());
2395 } 2442 }
2396 2443
2397 2444
(...skipping 472 matching lines...) Expand 10 before | Expand all | Expand 10 after
2870 2917
2871 const Register out_reg = locs()->out(0).reg(); 2918 const Register out_reg = locs()->out(0).reg();
2872 const VRegister value = locs()->in(0).fpu_reg(); 2919 const VRegister value = locs()->in(0).fpu_reg();
2873 2920
2874 __ TryAllocate(compiler->double_class(), 2921 __ TryAllocate(compiler->double_class(),
2875 slow_path->entry_label(), 2922 slow_path->entry_label(),
2876 out_reg, 2923 out_reg,
2877 locs()->temp(0).reg(), 2924 locs()->temp(0).reg(),
2878 PP); 2925 PP);
2879 __ Bind(slow_path->exit_label()); 2926 __ Bind(slow_path->exit_label());
2880 __ StoreDFieldToOffset(value, out_reg, Double::value_offset()); 2927 __ StoreDFieldToOffset(value, out_reg, Double::value_offset(), PP);
2881 } 2928 }
2882 2929
2883 2930
2884 LocationSummary* UnboxDoubleInstr::MakeLocationSummary(bool opt) const { 2931 LocationSummary* UnboxDoubleInstr::MakeLocationSummary(bool opt) const {
2885 const intptr_t kNumInputs = 1; 2932 const intptr_t kNumInputs = 1;
2886 const intptr_t kNumTemps = 0; 2933 const intptr_t kNumTemps = 0;
2887 LocationSummary* summary = 2934 LocationSummary* summary =
2888 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 2935 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2889 summary->set_in(0, Location::RequiresRegister()); 2936 summary->set_in(0, Location::RequiresRegister());
2890 summary->set_out(0, Location::RequiresFpuRegister()); 2937 summary->set_out(0, Location::RequiresFpuRegister());
2891 return summary; 2938 return summary;
2892 } 2939 }
2893 2940
2894 2941
2895 void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2942 void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2896 CompileType* value_type = value()->Type(); 2943 CompileType* value_type = value()->Type();
2897 const intptr_t value_cid = value_type->ToCid(); 2944 const intptr_t value_cid = value_type->ToCid();
2898 const Register value = locs()->in(0).reg(); 2945 const Register value = locs()->in(0).reg();
2899 const VRegister result = locs()->out(0).fpu_reg(); 2946 const VRegister result = locs()->out(0).fpu_reg();
2900 2947
2901 if (value_cid == kDoubleCid) { 2948 if (value_cid == kDoubleCid) {
2902 __ LoadDFieldFromOffset(result, value, Double::value_offset()); 2949 __ LoadDFieldFromOffset(result, value, Double::value_offset(), PP);
2903 } else if (value_cid == kSmiCid) { 2950 } else if (value_cid == kSmiCid) {
2904 __ Asr(TMP, value, kSmiTagSize); // Untag input before conversion. 2951 __ Asr(TMP, value, kSmiTagSize); // Untag input before conversion.
2905 __ scvtfd(result, TMP); 2952 __ scvtfd(result, TMP);
2906 } else { 2953 } else {
2907 Label* deopt = compiler->AddDeoptStub(deopt_id_, 2954 Label* deopt = compiler->AddDeoptStub(deopt_id_,
2908 ICData::kDeoptBinaryDoubleOp); 2955 ICData::kDeoptBinaryDoubleOp);
2909 if (value_type->is_nullable() && 2956 if (value_type->is_nullable() &&
2910 (value_type->ToNullableCid() == kDoubleCid)) { 2957 (value_type->ToNullableCid() == kDoubleCid)) {
2911 __ CompareObject(value, Object::null_object(), PP); 2958 __ CompareObject(value, Object::null_object(), PP);
2912 __ b(deopt, EQ); 2959 __ b(deopt, EQ);
2913 // It must be double now. 2960 // It must be double now.
2914 __ LoadDFieldFromOffset(result, value, Double::value_offset()); 2961 __ LoadDFieldFromOffset(result, value, Double::value_offset(), PP);
2915 } else { 2962 } else {
2916 Label is_smi, done; 2963 Label is_smi, done;
2917 __ tsti(value, kSmiTagMask); 2964 __ tsti(value, kSmiTagMask);
2918 __ b(&is_smi, EQ); 2965 __ b(&is_smi, EQ);
2919 __ CompareClassId(value, kDoubleCid); 2966 __ CompareClassId(value, kDoubleCid, PP);
2920 __ b(deopt, NE); 2967 __ b(deopt, NE);
2921 __ LoadDFieldFromOffset(result, value, Double::value_offset()); 2968 __ LoadDFieldFromOffset(result, value, Double::value_offset(), PP);
2922 __ b(&done); 2969 __ b(&done);
2923 __ Bind(&is_smi); 2970 __ Bind(&is_smi);
2924 __ Asr(TMP, value, kSmiTagSize); // Copy and untag. 2971 __ Asr(TMP, value, kSmiTagSize); // Copy and untag.
2925 __ scvtfd(result, TMP); 2972 __ scvtfd(result, TMP);
2926 __ Bind(&done); 2973 __ Bind(&done);
2927 } 2974 }
2928 } 2975 }
2929 } 2976 }
2930 2977
2931 2978
(...skipping 554 matching lines...) Expand 10 before | Expand all | Expand 10 after
3486 result->set_out(0, Location::RegisterLocation(R0)); 3533 result->set_out(0, Location::RegisterLocation(R0));
3487 return result; 3534 return result;
3488 } 3535 }
3489 3536
3490 3537
3491 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3538 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3492 const Register result = locs()->out(0).reg(); 3539 const Register result = locs()->out(0).reg();
3493 const Register value_obj = locs()->in(0).reg(); 3540 const Register value_obj = locs()->in(0).reg();
3494 ASSERT(result == R0); 3541 ASSERT(result == R0);
3495 ASSERT(result != value_obj); 3542 ASSERT(result != value_obj);
3496 __ LoadDFieldFromOffset(VTMP, value_obj, Double::value_offset()); 3543 __ LoadDFieldFromOffset(VTMP, value_obj, Double::value_offset(), PP);
3497 3544
3498 Label do_call, done; 3545 Label do_call, done;
3499 // First check for NaN. Checking for minint after the conversion doesn't work 3546 // First check for NaN. Checking for minint after the conversion doesn't work
3500 // on ARM64 because fcvtzds gives 0 for NaN. 3547 // on ARM64 because fcvtzds gives 0 for NaN.
3501 __ fcmpd(VTMP, VTMP); 3548 __ fcmpd(VTMP, VTMP);
3502 __ b(&do_call, VS); 3549 __ b(&do_call, VS);
3503 3550
3504 __ fcvtzds(result, VTMP); 3551 __ fcvtzds(result, VTMP);
3505 // Overflow is signaled with minint. 3552 // Overflow is signaled with minint.
3506 3553
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
3561 return NULL; 3608 return NULL;
3562 } 3609 }
3563 3610
3564 3611
3565 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3612 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3566 UNIMPLEMENTED(); 3613 UNIMPLEMENTED();
3567 } 3614 }
3568 3615
3569 3616
3570 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(bool opt) const { 3617 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(bool opt) const {
3571 UNIMPLEMENTED(); 3618 const intptr_t kNumInputs = 1;
3572 return NULL; 3619 const intptr_t kNumTemps = 0;
3620 LocationSummary* result =
3621 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
3622 result->set_in(0, Location::RequiresFpuRegister());
3623 result->set_out(0, Location::RequiresFpuRegister());
3624 return result;
3573 } 3625 }
3574 3626
3575 3627
3576 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3628 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3577 UNIMPLEMENTED(); 3629 const VRegister value = locs()->in(0).fpu_reg();
3630 const VRegister result = locs()->out(0).fpu_reg();
3631 __ fcvtsd(result, value);
3578 } 3632 }
3579 3633
3580 3634
3581 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(bool opt) const { 3635 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(bool opt) const {
3582 UNIMPLEMENTED(); 3636 const intptr_t kNumInputs = 1;
3583 return NULL; 3637 const intptr_t kNumTemps = 0;
3638 LocationSummary* result =
3639 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
3640 result->set_in(0, Location::RequiresFpuRegister());
3641 result->set_out(0, Location::RequiresFpuRegister());
3642 return result;
3584 } 3643 }
3585 3644
3586 3645
3587 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3646 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3588 UNIMPLEMENTED(); 3647 const VRegister value = locs()->in(0).fpu_reg();
3648 const VRegister result = locs()->out(0).fpu_reg();
3649 __ fcvtds(result, value);
3589 } 3650 }
3590 3651
3591 3652
3592 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(bool opt) const { 3653 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(bool opt) const {
3593 ASSERT((InputCount() == 1) || (InputCount() == 2)); 3654 ASSERT((InputCount() == 1) || (InputCount() == 2));
3594 const intptr_t kNumTemps = 0; 3655 const intptr_t kNumTemps = 0;
3595 LocationSummary* result = 3656 LocationSummary* result =
3596 new LocationSummary(InputCount(), kNumTemps, LocationSummary::kCall); 3657 new LocationSummary(InputCount(), kNumTemps, LocationSummary::kCall);
3597 result->set_in(0, Location::FpuRegisterLocation(V0)); 3658 result->set_in(0, Location::FpuRegisterLocation(V0));
3598 if (InputCount() == 2) { 3659 if (InputCount() == 2) {
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
3832 instance_call()->token_pos(), 3893 instance_call()->token_pos(),
3833 target, 3894 target,
3834 instance_call()->ArgumentCount(), 3895 instance_call()->ArgumentCount(),
3835 instance_call()->argument_names(), 3896 instance_call()->argument_names(),
3836 locs()); 3897 locs());
3837 return; 3898 return;
3838 } 3899 }
3839 3900
3840 // Load receiver into R0. 3901 // Load receiver into R0.
3841 __ LoadFromOffset( 3902 __ LoadFromOffset(
3842 R0, SP, (instance_call()->ArgumentCount() - 1) * kWordSize); 3903 R0, SP, (instance_call()->ArgumentCount() - 1) * kWordSize, PP);
3843 3904
3844 LoadValueCid(compiler, R2, R0, 3905 LoadValueCid(compiler, R2, R0,
3845 (ic_data().GetReceiverClassIdAt(0) == kSmiCid) ? NULL : deopt); 3906 (ic_data().GetReceiverClassIdAt(0) == kSmiCid) ? NULL : deopt);
3846 3907
3847 compiler->EmitTestAndCall(ic_data(), 3908 compiler->EmitTestAndCall(ic_data(),
3848 R2, // Class id register. 3909 R2, // Class id register.
3849 instance_call()->ArgumentCount(), 3910 instance_call()->ArgumentCount(),
3850 instance_call()->argument_names(), 3911 instance_call()->argument_names(),
3851 deopt, 3912 deopt,
3852 deopt_id(), 3913 deopt_id(),
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
3899 Label is_ok; 3960 Label is_ok;
3900 intptr_t cix = 0; 3961 intptr_t cix = 0;
3901 if (unary_checks().GetReceiverClassIdAt(cix) == kSmiCid) { 3962 if (unary_checks().GetReceiverClassIdAt(cix) == kSmiCid) {
3902 __ tsti(value, kSmiTagMask); 3963 __ tsti(value, kSmiTagMask);
3903 __ b(&is_ok, EQ); 3964 __ b(&is_ok, EQ);
3904 cix++; // Skip first check. 3965 cix++; // Skip first check.
3905 } else { 3966 } else {
3906 __ tsti(value, kSmiTagMask); 3967 __ tsti(value, kSmiTagMask);
3907 __ b(deopt, EQ); 3968 __ b(deopt, EQ);
3908 } 3969 }
3909 __ LoadClassId(temp, value); 3970 __ LoadClassId(temp, value, PP);
3910 const intptr_t num_checks = unary_checks().NumberOfChecks(); 3971 const intptr_t num_checks = unary_checks().NumberOfChecks();
3911 for (intptr_t i = cix; i < num_checks; i++) { 3972 for (intptr_t i = cix; i < num_checks; i++) {
3912 ASSERT(unary_checks().GetReceiverClassIdAt(i) != kSmiCid); 3973 ASSERT(unary_checks().GetReceiverClassIdAt(i) != kSmiCid);
3913 __ CompareImmediate(temp, unary_checks().GetReceiverClassIdAt(i), PP); 3974 __ CompareImmediate(temp, unary_checks().GetReceiverClassIdAt(i), PP);
3914 if (i == (num_checks - 1)) { 3975 if (i == (num_checks - 1)) {
3915 __ b(deopt, NE); 3976 __ b(deopt, NE);
3916 } else { 3977 } else {
3917 __ b(&is_ok, EQ); 3978 __ b(&is_ok, EQ);
3918 } 3979 }
3919 } 3980 }
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after
4254 compiler->GenerateCall(token_pos(), 4315 compiler->GenerateCall(token_pos(),
4255 &label, 4316 &label,
4256 PcDescriptors::kOther, 4317 PcDescriptors::kOther,
4257 locs()); 4318 locs());
4258 __ Drop(ArgumentCount()); // Discard arguments. 4319 __ Drop(ArgumentCount()); // Discard arguments.
4259 } 4320 }
4260 4321
4261 } // namespace dart 4322 } // namespace dart
4262 4323
4263 #endif // defined TARGET_ARCH_ARM64 4324 #endif // defined TARGET_ARCH_ARM64
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_compiler_arm64.cc ('k') | runtime/vm/simulator_arm64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698