OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
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 1181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1192 } | 1192 } |
1193 break; | 1193 break; |
1194 default: | 1194 default: |
1195 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); | 1195 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); |
1196 __ movl(result, element_address); | 1196 __ movl(result, element_address); |
1197 break; | 1197 break; |
1198 } | 1198 } |
1199 } | 1199 } |
1200 | 1200 |
1201 | 1201 |
1202 Representation LoadCodeUnitsInstr::representation() const { | |
1203 switch (class_id()) { | |
1204 case kOneByteStringCid: | |
1205 case kExternalOneByteStringCid: | |
1206 case kTwoByteStringCid: | |
1207 case kExternalTwoByteStringCid: | |
1208 // TODO(zerny): kUnboxedUint32 could be a better choice. | |
1209 return can_pack_into_smi() ? kTagged : kUnboxedMint; | |
1210 default: | |
1211 UNIMPLEMENTED(); | |
1212 return kTagged; | |
1213 } | |
1214 } | |
1215 | |
1216 | |
1217 LocationSummary* LoadCodeUnitsInstr::MakeLocationSummary(Isolate* isolate, | |
1218 bool opt) const { | |
1219 const intptr_t kNumInputs = 2; | |
1220 const intptr_t kNumTemps = 0; | |
1221 LocationSummary* summary = new(isolate) LocationSummary( | |
1222 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
1223 summary->set_in(0, Location::RequiresRegister()); | |
1224 // The smi index is either untagged (element size == 1), or it is left smi | |
1225 // tagged (for all element sizes > 1). | |
1226 summary->set_in(1, (index_scale() == 1) ? Location::WritableRegister() | |
1227 : Location::RequiresRegister()); | |
1228 | |
1229 if (representation() == kUnboxedMint) { | |
1230 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | |
1231 Location::RequiresRegister())); | |
1232 } else { | |
1233 ASSERT(representation() == kTagged); | |
1234 summary->set_out(0, Location::RequiresRegister()); | |
1235 } | |
1236 | |
1237 return summary; | |
1238 } | |
1239 | |
1240 | |
1241 void LoadCodeUnitsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
1242 const Register array = locs()->in(0).reg(); | |
1243 const Location index = locs()->in(1); | |
1244 | |
1245 Address element_address = Assembler::ElementAddressForRegIndex( | |
1246 IsExternal(), class_id(), index_scale(), array, index.reg()); | |
1247 | |
1248 if ((index_scale() == 1)) { | |
1249 __ SmiUntag(index.reg()); | |
1250 } | |
1251 | |
1252 if (representation() == kUnboxedMint) { | |
1253 ASSERT(locs()->out(0).IsPairLocation()); | |
1254 PairLocation* result_pair = locs()->out(0).AsPairLocation(); | |
1255 Register result1 = result_pair->At(0).reg(); | |
1256 Register result2 = result_pair->At(1).reg(); | |
1257 switch (class_id()) { | |
1258 case kOneByteStringCid: | |
1259 case kExternalOneByteStringCid: | |
1260 ASSERT(element_count() == 4); | |
1261 __ movl(result1, element_address); | |
1262 __ xorl(result2, result2); | |
1263 break; | |
1264 case kTwoByteStringCid: | |
1265 case kExternalTwoByteStringCid: | |
1266 ASSERT(element_count() == 2); | |
1267 __ movl(result1, element_address); | |
1268 __ xorl(result2, result2); | |
1269 break; | |
1270 default: | |
1271 UNREACHABLE(); | |
1272 } | |
1273 } else { | |
1274 ASSERT(representation() == kTagged); | |
1275 Register result = locs()->out(0).reg(); | |
1276 switch (class_id()) { | |
1277 case kOneByteStringCid: | |
1278 case kExternalOneByteStringCid: | |
1279 switch (element_count()) { | |
1280 case 1: __ movzxb(result, element_address); break; | |
1281 case 2: __ movzxw(result, element_address); break; | |
1282 default: UNREACHABLE(); | |
1283 } | |
1284 __ SmiTag(result); | |
1285 break; | |
1286 case kTwoByteStringCid: | |
1287 case kExternalTwoByteStringCid: | |
1288 switch (element_count()) { | |
1289 case 1: __ movzxw(result, element_address); break; | |
1290 default: UNREACHABLE(); | |
1291 } | |
1292 __ SmiTag(result); | |
1293 break; | |
1294 default: | |
1295 UNREACHABLE(); | |
1296 break; | |
1297 } | |
1298 } | |
1299 } | |
1300 | |
1301 | |
1302 Representation StoreIndexedInstr::RequiredInputRepresentation( | 1202 Representation StoreIndexedInstr::RequiredInputRepresentation( |
1303 intptr_t idx) const { | 1203 intptr_t idx) const { |
1304 // Array can be a Dart object or a pointer to external data. | 1204 // Array can be a Dart object or a pointer to external data. |
1305 if (idx == 0) return kNoRepresentation; // Flexible input representation. | 1205 if (idx == 0) return kNoRepresentation; // Flexible input representation. |
1306 if (idx == 1) return kTagged; // Index is a smi. | 1206 if (idx == 1) return kTagged; // Index is a smi. |
1307 ASSERT(idx == 2); | 1207 ASSERT(idx == 2); |
1308 switch (class_id_) { | 1208 switch (class_id_) { |
1309 case kArrayCid: | 1209 case kArrayCid: |
1310 case kOneByteStringCid: | 1210 case kOneByteStringCid: |
1311 case kTypedDataInt8ArrayCid: | 1211 case kTypedDataInt8ArrayCid: |
(...skipping 2476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3788 result, | 3688 result, |
3789 Address(value, TIMES_2, lo_offset), | 3689 Address(value, TIMES_2, lo_offset), |
3790 Address(value, TIMES_2, hi_offset), | 3690 Address(value, TIMES_2, hi_offset), |
3791 temp, | 3691 temp, |
3792 out_of_range); | 3692 out_of_range); |
3793 __ Bind(&done); | 3693 __ Bind(&done); |
3794 } | 3694 } |
3795 } | 3695 } |
3796 | 3696 |
3797 | 3697 |
| 3698 LocationSummary* LoadCodeUnitsInstr::MakeLocationSummary(Isolate* isolate, |
| 3699 bool opt) const { |
| 3700 const bool might_box = (representation() == kTagged) && !can_pack_into_smi(); |
| 3701 const intptr_t kNumInputs = 2; |
| 3702 const intptr_t kNumTemps = might_box ? 1 : 0; |
| 3703 LocationSummary* summary = new(isolate) LocationSummary( |
| 3704 isolate, kNumInputs, kNumTemps, |
| 3705 might_box ? LocationSummary::kCallOnSlowPath : LocationSummary::kNoCall); |
| 3706 summary->set_in(0, Location::RequiresRegister()); |
| 3707 // The smi index is either untagged (element size == 1), or it is left smi |
| 3708 // tagged (for all element sizes > 1). |
| 3709 summary->set_in(1, (index_scale() == 1) ? Location::WritableRegister() |
| 3710 : Location::RequiresRegister()); |
| 3711 if (might_box) { |
| 3712 summary->set_temp(0, Location::RequiresRegister()); |
| 3713 } |
| 3714 |
| 3715 if (representation() == kUnboxedMint) { |
| 3716 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
| 3717 Location::RequiresRegister())); |
| 3718 } else { |
| 3719 ASSERT(representation() == kTagged); |
| 3720 summary->set_out(0, Location::RequiresRegister()); |
| 3721 } |
| 3722 |
| 3723 return summary; |
| 3724 } |
| 3725 |
| 3726 |
| 3727 void LoadCodeUnitsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3728 const Register array = locs()->in(0).reg(); |
| 3729 const Location index = locs()->in(1); |
| 3730 |
| 3731 Address element_address = Assembler::ElementAddressForRegIndex( |
| 3732 IsExternal(), class_id(), index_scale(), array, index.reg()); |
| 3733 |
| 3734 if ((index_scale() == 1)) { |
| 3735 __ SmiUntag(index.reg()); |
| 3736 } |
| 3737 |
| 3738 if (representation() == kUnboxedMint) { |
| 3739 ASSERT(compiler->is_optimizing()); |
| 3740 ASSERT(locs()->out(0).IsPairLocation()); |
| 3741 PairLocation* result_pair = locs()->out(0).AsPairLocation(); |
| 3742 Register result1 = result_pair->At(0).reg(); |
| 3743 Register result2 = result_pair->At(1).reg(); |
| 3744 |
| 3745 switch (class_id()) { |
| 3746 case kOneByteStringCid: |
| 3747 case kExternalOneByteStringCid: |
| 3748 ASSERT(element_count() == 4); |
| 3749 __ movl(result1, element_address); |
| 3750 __ xorl(result2, result2); |
| 3751 break; |
| 3752 case kTwoByteStringCid: |
| 3753 case kExternalTwoByteStringCid: |
| 3754 ASSERT(element_count() == 2); |
| 3755 __ movl(result1, element_address); |
| 3756 __ xorl(result2, result2); |
| 3757 break; |
| 3758 default: |
| 3759 UNREACHABLE(); |
| 3760 } |
| 3761 } else { |
| 3762 ASSERT(representation() == kTagged); |
| 3763 Register result = locs()->out(0).reg(); |
| 3764 switch (class_id()) { |
| 3765 case kOneByteStringCid: |
| 3766 case kExternalOneByteStringCid: |
| 3767 switch (element_count()) { |
| 3768 case 1: __ movzxb(result, element_address); break; |
| 3769 case 2: __ movzxw(result, element_address); break; |
| 3770 case 4: __ movl(result, element_address); break; |
| 3771 default: UNREACHABLE(); |
| 3772 } |
| 3773 break; |
| 3774 case kTwoByteStringCid: |
| 3775 case kExternalTwoByteStringCid: |
| 3776 switch (element_count()) { |
| 3777 case 1: __ movzxw(result, element_address); break; |
| 3778 case 2: __ movl(result, element_address); break; |
| 3779 default: UNREACHABLE(); |
| 3780 } |
| 3781 break; |
| 3782 default: |
| 3783 UNREACHABLE(); |
| 3784 break; |
| 3785 } |
| 3786 if (can_pack_into_smi()) { |
| 3787 __ SmiTag(result); |
| 3788 } else { |
| 3789 // If the value cannot fit in a smi then allocate a mint box for it. |
| 3790 Register temp = locs()->temp(0).reg(); |
| 3791 ASSERT(temp != result); |
| 3792 __ MoveRegister(temp, result); |
| 3793 __ SmiTag(result); |
| 3794 |
| 3795 Label done; |
| 3796 __ testl(temp, Immediate(0xC0000000)); |
| 3797 __ j(ZERO, &done); |
| 3798 BoxAllocationSlowPath::Allocate( |
| 3799 compiler, this, compiler->mint_class(), result, kNoRegister); |
| 3800 __ movl(FieldAddress(result, Mint::value_offset()), temp); |
| 3801 __ movl(FieldAddress(result, Mint::value_offset() + kWordSize), |
| 3802 Immediate(0)); |
| 3803 __ Bind(&done); |
| 3804 } |
| 3805 } |
| 3806 } |
| 3807 |
| 3808 |
3798 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Isolate* isolate, | 3809 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Isolate* isolate, |
3799 bool opt) const { | 3810 bool opt) const { |
3800 const intptr_t kNumInputs = 2; | 3811 const intptr_t kNumInputs = 2; |
3801 const intptr_t kNumTemps = 0; | 3812 const intptr_t kNumTemps = 0; |
3802 LocationSummary* summary = new(isolate) LocationSummary( | 3813 LocationSummary* summary = new(isolate) LocationSummary( |
3803 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3814 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3804 summary->set_in(0, Location::RequiresFpuRegister()); | 3815 summary->set_in(0, Location::RequiresFpuRegister()); |
3805 summary->set_in(1, Location::RequiresFpuRegister()); | 3816 summary->set_in(1, Location::RequiresFpuRegister()); |
3806 summary->set_out(0, Location::SameAsFirstInput()); | 3817 summary->set_out(0, Location::SameAsFirstInput()); |
3807 return summary; | 3818 return summary; |
(...skipping 2967 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6775 #if defined(DEBUG) | 6786 #if defined(DEBUG) |
6776 __ movl(EDX, Immediate(kInvalidObjectPointer)); | 6787 __ movl(EDX, Immediate(kInvalidObjectPointer)); |
6777 #endif | 6788 #endif |
6778 } | 6789 } |
6779 | 6790 |
6780 } // namespace dart | 6791 } // namespace dart |
6781 | 6792 |
6782 #undef __ | 6793 #undef __ |
6783 | 6794 |
6784 #endif // defined TARGET_ARCH_IA32 | 6795 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |