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

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

Issue 12114008: Avoid re-tagging of the index register in optimized byte array access. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 10 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/intermediate_language_ia32.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language_ia32.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698