| 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_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 1002 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1013 } | 1013 } |
| 1014 } | 1014 } |
| 1015 | 1015 |
| 1016 | 1016 |
| 1017 LocationSummary* LoadIndexedInstr::MakeLocationSummary() const { | 1017 LocationSummary* LoadIndexedInstr::MakeLocationSummary() const { |
| 1018 const intptr_t kNumInputs = 2; | 1018 const intptr_t kNumInputs = 2; |
| 1019 const intptr_t kNumTemps = 0; | 1019 const intptr_t kNumTemps = 0; |
| 1020 LocationSummary* locs = | 1020 LocationSummary* locs = |
| 1021 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1021 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1022 locs->set_in(0, Location::RequiresRegister()); | 1022 locs->set_in(0, Location::RequiresRegister()); |
| 1023 // The smi index is either untagged and tagged again at the end of the | 1023 // The smi index is either untagged (element size == 1), or it is left smi |
| 1024 // operation (element size == 1), or it is left smi tagged (for all element | 1024 // tagged (for all element sizes > 1). |
| 1025 // sizes > 1). | 1025 if (index_scale() == 1) { |
| 1026 locs->set_in(1, CanBeImmediateIndex(index(), class_id()) | 1026 locs->set_in(1, CanBeImmediateIndex(index(), class_id()) |
| 1027 ? Location::RegisterOrSmiConstant(index()) | 1027 ? Location::Constant( |
| 1028 : Location::RequiresRegister()); | 1028 index()->definition()->AsConstant()->value()) |
| 1029 : Location::WritableRegister()); |
| 1030 } else { |
| 1031 locs->set_in(1, CanBeImmediateIndex(index(), class_id()) |
| 1032 ? Location::Constant( |
| 1033 index()->definition()->AsConstant()->value()) |
| 1034 : Location::RequiresRegister()); |
| 1035 } |
| 1029 if (representation() == kUnboxedDouble) { | 1036 if (representation() == kUnboxedDouble) { |
| 1030 locs->set_out(Location::RequiresFpuRegister()); | 1037 locs->set_out(Location::RequiresFpuRegister()); |
| 1031 } else { | 1038 } else { |
| 1032 locs->set_out(Location::RequiresRegister()); | 1039 locs->set_out(Location::RequiresRegister()); |
| 1033 } | 1040 } |
| 1034 return locs; | 1041 return locs; |
| 1035 } | 1042 } |
| 1036 | 1043 |
| 1037 | 1044 |
| 1038 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1045 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1049 class_id(), index_scale(), result, | 1056 class_id(), index_scale(), result, |
| 1050 Smi::Cast(index.constant()).Value()); | 1057 Smi::Cast(index.constant()).Value()); |
| 1051 ASSERT(index_scale() == 1); | 1058 ASSERT(index_scale() == 1); |
| 1052 if (index.IsRegister()) { | 1059 if (index.IsRegister()) { |
| 1053 __ SmiUntag(index.reg()); | 1060 __ SmiUntag(index.reg()); |
| 1054 } | 1061 } |
| 1055 __ movq(result, | 1062 __ movq(result, |
| 1056 FieldAddress(array, ExternalUint8Array::data_offset())); | 1063 FieldAddress(array, ExternalUint8Array::data_offset())); |
| 1057 __ movzxb(result, element_address); | 1064 __ movzxb(result, element_address); |
| 1058 __ SmiTag(result); | 1065 __ SmiTag(result); |
| 1059 if (index.IsRegister()) { | |
| 1060 __ SmiTag(index.reg()); // Re-tag. | |
| 1061 } | |
| 1062 return; | 1066 return; |
| 1063 } | 1067 } |
| 1064 | 1068 |
| 1065 FieldAddress element_address = index.IsRegister() | 1069 FieldAddress element_address = index.IsRegister() |
| 1066 ? FlowGraphCompiler::ElementAddressForRegIndex( | 1070 ? FlowGraphCompiler::ElementAddressForRegIndex( |
| 1067 class_id(), index_scale(), array, index.reg()) | 1071 class_id(), index_scale(), array, index.reg()) |
| 1068 : FlowGraphCompiler::ElementAddressForIntIndex( | 1072 : FlowGraphCompiler::ElementAddressForIntIndex( |
| 1069 class_id(), index_scale(), array, | 1073 class_id(), index_scale(), array, |
| 1070 Smi::Cast(index.constant()).Value()); | 1074 Smi::Cast(index.constant()).Value()); |
| 1071 | 1075 |
| 1072 if (representation() == kUnboxedDouble) { | 1076 if (representation() == kUnboxedDouble) { |
| 1073 if ((index_scale() == 1) && index.IsRegister()) { | 1077 if ((index_scale() == 1) && index.IsRegister()) { |
| 1074 __ SmiUntag(index.reg()); | 1078 __ SmiUntag(index.reg()); |
| 1075 } | 1079 } |
| 1076 | 1080 |
| 1077 XmmRegister result = locs()->out().fpu_reg(); | 1081 XmmRegister result = locs()->out().fpu_reg(); |
| 1078 if (class_id() == kFloat32ArrayCid) { | 1082 if (class_id() == kFloat32ArrayCid) { |
| 1079 // Load single precision float. | 1083 // Load single precision float. |
| 1080 __ movss(result, element_address); | 1084 __ movss(result, element_address); |
| 1081 // Promote to double. | 1085 // Promote to double. |
| 1082 __ cvtss2sd(result, locs()->out().fpu_reg()); | 1086 __ cvtss2sd(result, locs()->out().fpu_reg()); |
| 1083 } else { | 1087 } else { |
| 1084 ASSERT(class_id() == kFloat64ArrayCid); | 1088 ASSERT(class_id() == kFloat64ArrayCid); |
| 1085 __ movsd(result, element_address); | 1089 __ movsd(result, element_address); |
| 1086 } | 1090 } |
| 1087 | |
| 1088 if ((index_scale() == 1) && index.IsRegister()) { | |
| 1089 __ SmiTag(index.reg()); // Re-tag. | |
| 1090 } | |
| 1091 return; | 1091 return; |
| 1092 } | 1092 } |
| 1093 | 1093 |
| 1094 if ((index_scale() == 1) && index.IsRegister()) { | 1094 if ((index_scale() == 1) && index.IsRegister()) { |
| 1095 __ SmiUntag(index.reg()); | 1095 __ SmiUntag(index.reg()); |
| 1096 } | 1096 } |
| 1097 Register result = locs()->out().reg(); | 1097 Register result = locs()->out().reg(); |
| 1098 switch (class_id()) { | 1098 switch (class_id()) { |
| 1099 case kInt8ArrayCid: | 1099 case kInt8ArrayCid: |
| 1100 case kUint8ArrayCid: | 1100 case kUint8ArrayCid: |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1122 break; | 1122 break; |
| 1123 case kUint32ArrayCid: | 1123 case kUint32ArrayCid: |
| 1124 __ movl(result, element_address); | 1124 __ movl(result, element_address); |
| 1125 __ SmiTag(result); | 1125 __ SmiTag(result); |
| 1126 break; | 1126 break; |
| 1127 default: | 1127 default: |
| 1128 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); | 1128 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); |
| 1129 __ movq(result, element_address); | 1129 __ movq(result, element_address); |
| 1130 break; | 1130 break; |
| 1131 } | 1131 } |
| 1132 if ((index_scale() == 1) && index.IsRegister()) { | |
| 1133 __ SmiTag(index.reg()); // Re-tag. | |
| 1134 } | |
| 1135 } | 1132 } |
| 1136 | 1133 |
| 1137 | 1134 |
| 1138 Representation StoreIndexedInstr::RequiredInputRepresentation( | 1135 Representation StoreIndexedInstr::RequiredInputRepresentation( |
| 1139 intptr_t idx) const { | 1136 intptr_t idx) const { |
| 1140 if ((idx == 0) || (idx == 1)) return kTagged; | 1137 if ((idx == 0) || (idx == 1)) return kTagged; |
| 1141 ASSERT(idx == 2); | 1138 ASSERT(idx == 2); |
| 1142 switch (class_id_) { | 1139 switch (class_id_) { |
| 1143 case kArrayCid: | 1140 case kArrayCid: |
| 1144 case kInt8ArrayCid: | 1141 case kInt8ArrayCid: |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1157 return kTagged; | 1154 return kTagged; |
| 1158 } | 1155 } |
| 1159 } | 1156 } |
| 1160 | 1157 |
| 1161 | 1158 |
| 1162 LocationSummary* StoreIndexedInstr::MakeLocationSummary() const { | 1159 LocationSummary* StoreIndexedInstr::MakeLocationSummary() const { |
| 1163 const intptr_t kNumInputs = 3; | 1160 const intptr_t kNumInputs = 3; |
| 1164 const intptr_t kNumTemps = 0; | 1161 const intptr_t kNumTemps = 0; |
| 1165 LocationSummary* locs = | 1162 LocationSummary* locs = |
| 1166 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1163 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1167 // The smi index is either untagged and tagged again at the end of the | |
| 1168 // operation (element size == 1), or it is left smi tagged (for all element | |
| 1169 // sizes > 1). | |
| 1170 locs->set_in(0, Location::RequiresRegister()); | 1164 locs->set_in(0, Location::RequiresRegister()); |
| 1171 locs->set_in(1, CanBeImmediateIndex(index(), class_id()) | 1165 // The smi index is either untagged (element size == 1), or it is left smi |
| 1172 ? Location::RegisterOrSmiConstant(index()) | 1166 // tagged (for all element sizes > 1). |
| 1173 : Location::RequiresRegister()); | 1167 intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(class_id()); |
| 1168 if (index_scale == 1) { |
| 1169 locs->set_in(1, CanBeImmediateIndex(index(), class_id()) |
| 1170 ? Location::Constant( |
| 1171 index()->definition()->AsConstant()->value()) |
| 1172 : Location::WritableRegister()); |
| 1173 } else { |
| 1174 locs->set_in(1, CanBeImmediateIndex(index(), class_id()) |
| 1175 ? Location::Constant( |
| 1176 index()->definition()->AsConstant()->value()) |
| 1177 : Location::RequiresRegister()); |
| 1178 } |
| 1174 switch (class_id()) { | 1179 switch (class_id()) { |
| 1175 case kArrayCid: | 1180 case kArrayCid: |
| 1176 locs->set_in(2, ShouldEmitStoreBarrier() | 1181 locs->set_in(2, ShouldEmitStoreBarrier() |
| 1177 ? Location::WritableRegister() | 1182 ? Location::WritableRegister() |
| 1178 : Location::RegisterOrConstant(value())); | 1183 : Location::RegisterOrConstant(value())); |
| 1179 break; | 1184 break; |
| 1180 case kInt8ArrayCid: | 1185 case kInt8ArrayCid: |
| 1181 case kUint8ArrayCid: | 1186 case kUint8ArrayCid: |
| 1182 case kUint8ClampedArrayCid: | 1187 case kUint8ClampedArrayCid: |
| 1183 // TODO(fschneider): Add location constraint for byte registers (RAX, | 1188 // TODO(fschneider): Add location constraint for byte registers (RAX, |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1240 } | 1245 } |
| 1241 if (locs()->in(2).IsConstant()) { | 1246 if (locs()->in(2).IsConstant()) { |
| 1242 const Smi& constant = Smi::Cast(locs()->in(2).constant()); | 1247 const Smi& constant = Smi::Cast(locs()->in(2).constant()); |
| 1243 __ movb(element_address, | 1248 __ movb(element_address, |
| 1244 Immediate(static_cast<int8_t>(constant.Value()))); | 1249 Immediate(static_cast<int8_t>(constant.Value()))); |
| 1245 } else { | 1250 } else { |
| 1246 ASSERT(locs()->in(2).reg() == RAX); | 1251 ASSERT(locs()->in(2).reg() == RAX); |
| 1247 __ SmiUntag(RAX); | 1252 __ SmiUntag(RAX); |
| 1248 __ movb(element_address, RAX); | 1253 __ movb(element_address, RAX); |
| 1249 } | 1254 } |
| 1250 if (index.IsRegister()) { | |
| 1251 __ SmiTag(index.reg()); // Re-tag. | |
| 1252 } | |
| 1253 break; | 1255 break; |
| 1254 case kUint8ClampedArrayCid: { | 1256 case kUint8ClampedArrayCid: { |
| 1255 if (index.IsRegister()) { | 1257 if (index.IsRegister()) { |
| 1256 __ SmiUntag(index.reg()); | 1258 __ SmiUntag(index.reg()); |
| 1257 } | 1259 } |
| 1258 if (locs()->in(2).IsConstant()) { | 1260 if (locs()->in(2).IsConstant()) { |
| 1259 const Smi& constant = Smi::Cast(locs()->in(2).constant()); | 1261 const Smi& constant = Smi::Cast(locs()->in(2).constant()); |
| 1260 intptr_t value = constant.Value(); | 1262 intptr_t value = constant.Value(); |
| 1261 // Clamp to 0x0 or 0xFF respectively. | 1263 // Clamp to 0x0 or 0xFF respectively. |
| 1262 if (value > 0xFF) { | 1264 if (value > 0xFF) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1274 __ j(BELOW_EQUAL, &store_value, Assembler::kNearJump); | 1276 __ j(BELOW_EQUAL, &store_value, Assembler::kNearJump); |
| 1275 // Clamp to 0x0 or 0xFF respectively. | 1277 // Clamp to 0x0 or 0xFF respectively. |
| 1276 __ j(GREATER, &store_0xff); | 1278 __ j(GREATER, &store_0xff); |
| 1277 __ xorq(RAX, RAX); | 1279 __ xorq(RAX, RAX); |
| 1278 __ jmp(&store_value, Assembler::kNearJump); | 1280 __ jmp(&store_value, Assembler::kNearJump); |
| 1279 __ Bind(&store_0xff); | 1281 __ Bind(&store_0xff); |
| 1280 __ movq(RAX, Immediate(0xFF)); | 1282 __ movq(RAX, Immediate(0xFF)); |
| 1281 __ Bind(&store_value); | 1283 __ Bind(&store_value); |
| 1282 __ movb(element_address, RAX); | 1284 __ movb(element_address, RAX); |
| 1283 } | 1285 } |
| 1284 if (index.IsRegister()) { | |
| 1285 __ SmiTag(index.reg()); // Re-tag. | |
| 1286 } | |
| 1287 break; | 1286 break; |
| 1288 } | 1287 } |
| 1289 case kInt16ArrayCid: | 1288 case kInt16ArrayCid: |
| 1290 case kUint16ArrayCid: { | 1289 case kUint16ArrayCid: { |
| 1291 Register value = locs()->in(2).reg(); | 1290 Register value = locs()->in(2).reg(); |
| 1292 __ SmiUntag(value); | 1291 __ SmiUntag(value); |
| 1293 __ movw(element_address, value); | 1292 __ movw(element_address, value); |
| 1294 break; | 1293 break; |
| 1295 } | 1294 } |
| 1296 case kInt32ArrayCid: | 1295 case kInt32ArrayCid: |
| (...skipping 910 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2207 slow_path->entry_label(), | 2206 slow_path->entry_label(), |
| 2208 Assembler::kFarJump, | 2207 Assembler::kFarJump, |
| 2209 out_reg); | 2208 out_reg); |
| 2210 __ Bind(slow_path->exit_label()); | 2209 __ Bind(slow_path->exit_label()); |
| 2211 __ movsd(FieldAddress(out_reg, Double::value_offset()), value); | 2210 __ movsd(FieldAddress(out_reg, Double::value_offset()), value); |
| 2212 } | 2211 } |
| 2213 | 2212 |
| 2214 | 2213 |
| 2215 LocationSummary* UnboxDoubleInstr::MakeLocationSummary() const { | 2214 LocationSummary* UnboxDoubleInstr::MakeLocationSummary() const { |
| 2216 const intptr_t kNumInputs = 1; | 2215 const intptr_t kNumInputs = 1; |
| 2217 const intptr_t kNumTemps = CanDeoptimize() ? 1 : 0; | 2216 const intptr_t kNumTemps = 0; |
| 2218 LocationSummary* summary = | 2217 LocationSummary* summary = |
| 2219 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2218 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2220 summary->set_in(0, Location::RequiresRegister()); | 2219 const bool needs_writable_input = (value()->ResultCid() != kDoubleCid); |
| 2221 if (CanDeoptimize()) summary->set_temp(0, Location::RequiresRegister()); | 2220 summary->set_in(0, needs_writable_input |
| 2221 ? Location::WritableRegister() |
| 2222 : Location::RequiresRegister()); |
| 2222 summary->set_out(Location::RequiresFpuRegister()); | 2223 summary->set_out(Location::RequiresFpuRegister()); |
| 2223 return summary; | 2224 return summary; |
| 2224 } | 2225 } |
| 2225 | 2226 |
| 2226 | 2227 |
| 2227 void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2228 void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2228 const intptr_t value_cid = value()->ResultCid(); | 2229 const intptr_t value_cid = value()->ResultCid(); |
| 2229 const Register value = locs()->in(0).reg(); | 2230 const Register value = locs()->in(0).reg(); |
| 2230 const XmmRegister result = locs()->out().fpu_reg(); | 2231 const XmmRegister result = locs()->out().fpu_reg(); |
| 2231 | 2232 |
| 2232 if (value_cid == kDoubleCid) { | 2233 if (value_cid == kDoubleCid) { |
| 2233 __ movsd(result, FieldAddress(value, Double::value_offset())); | 2234 __ movsd(result, FieldAddress(value, Double::value_offset())); |
| 2234 } else if (value_cid == kSmiCid) { | 2235 } else if (value_cid == kSmiCid) { |
| 2235 __ SmiUntag(value); // Untag input before conversion. | 2236 __ SmiUntag(value); // Untag input before conversion. |
| 2236 __ cvtsi2sd(result, value); | 2237 __ cvtsi2sd(result, value); |
| 2237 __ SmiTag(value); // Restore input register. | |
| 2238 } else { | 2238 } else { |
| 2239 Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptBinaryDoubleOp); | 2239 Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptBinaryDoubleOp); |
| 2240 compiler->LoadDoubleOrSmiToFpu(result, | 2240 Label is_smi, done; |
| 2241 value, | 2241 __ testq(value, Immediate(kSmiTagMask)); |
| 2242 locs()->temp(0).reg(), | 2242 __ j(ZERO, &is_smi); |
| 2243 deopt); | 2243 __ CompareClassId(value, kDoubleCid); |
| 2244 __ j(NOT_EQUAL, deopt); |
| 2245 __ movsd(result, FieldAddress(value, Double::value_offset())); |
| 2246 __ jmp(&done); |
| 2247 __ Bind(&is_smi); |
| 2248 __ SmiUntag(value); |
| 2249 __ cvtsi2sd(result, value); |
| 2250 __ Bind(&done); |
| 2244 } | 2251 } |
| 2245 } | 2252 } |
| 2246 | 2253 |
| 2247 | 2254 |
| 2248 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary() const { | 2255 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary() const { |
| 2249 const intptr_t kNumInputs = 2; | 2256 const intptr_t kNumInputs = 2; |
| 2250 const intptr_t kNumTemps = 0; | 2257 const intptr_t kNumTemps = 0; |
| 2251 LocationSummary* summary = | 2258 LocationSummary* summary = |
| 2252 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2259 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2253 summary->set_in(0, Location::RequiresFpuRegister()); | 2260 summary->set_in(0, Location::RequiresFpuRegister()); |
| (...skipping 792 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3046 PcDescriptors::kOther, | 3053 PcDescriptors::kOther, |
| 3047 locs()); | 3054 locs()); |
| 3048 __ Drop(2); // Discard type arguments and receiver. | 3055 __ Drop(2); // Discard type arguments and receiver. |
| 3049 } | 3056 } |
| 3050 | 3057 |
| 3051 } // namespace dart | 3058 } // namespace dart |
| 3052 | 3059 |
| 3053 #undef __ | 3060 #undef __ |
| 3054 | 3061 |
| 3055 #endif // defined TARGET_ARCH_X64 | 3062 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |