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

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

Issue 11967012: Optimized loads/stores for scalar list: Uint8Clamped, Int8, Int16, Uint16. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: addressed comments Created 7 years, 11 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') | tests/standalone/int_array_test.dart » ('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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 918 matching lines...) Expand 10 before | Expand all | Expand 10 after
929 return Utils::IsInt(32, disp); 929 return Utils::IsInt(32, disp);
930 } 930 }
931 931
932 932
933 LocationSummary* StringCharCodeAtInstr::MakeLocationSummary() const { 933 LocationSummary* StringCharCodeAtInstr::MakeLocationSummary() const {
934 const intptr_t kNumInputs = 2; 934 const intptr_t kNumInputs = 2;
935 const intptr_t kNumTemps = 0; 935 const intptr_t kNumTemps = 0;
936 LocationSummary* locs = 936 LocationSummary* locs =
937 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 937 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
938 locs->set_in(0, Location::RequiresRegister()); 938 locs->set_in(0, Location::RequiresRegister());
939 // The smi index is either untagged and tagged again at the end of the
940 // operation (element size == 1), or it is left smi tagged (for all element
941 // sizes > 1).
939 locs->set_in(1, CanBeImmediateIndex(index(), class_id()) 942 locs->set_in(1, CanBeImmediateIndex(index(), class_id())
940 ? Location::RegisterOrSmiConstant(index()) 943 ? Location::RegisterOrSmiConstant(index())
941 : Location::RequiresRegister()); 944 : Location::RequiresRegister());
942 locs->set_out(Location::RequiresRegister()); 945 locs->set_out(Location::RequiresRegister());
943 return locs; 946 return locs;
944 } 947 }
945 948
946 949
947 void StringCharCodeAtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 950 void StringCharCodeAtInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
948 Register str = locs()->in(0).reg(); 951 Register str = locs()->in(0).reg();
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
998 Symbols::kNullCharCodeSymbolOffset * kWordSize)); 1001 Symbols::kNullCharCodeSymbolOffset * kWordSize));
999 } 1002 }
1000 1003
1001 1004
1002 LocationSummary* LoadIndexedInstr::MakeLocationSummary() const { 1005 LocationSummary* LoadIndexedInstr::MakeLocationSummary() const {
1003 const intptr_t kNumInputs = 2; 1006 const intptr_t kNumInputs = 2;
1004 const intptr_t kNumTemps = 0; 1007 const intptr_t kNumTemps = 0;
1005 LocationSummary* locs = 1008 LocationSummary* locs =
1006 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 1009 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
1007 locs->set_in(0, Location::RequiresRegister()); 1010 locs->set_in(0, Location::RequiresRegister());
1011 // The smi index is either untagged and tagged again at the end of the
1012 // operation (element size == 1), or it is left smi tagged (for all element
1013 // sizes > 1).
1008 locs->set_in(1, CanBeImmediateIndex(index(), class_id()) 1014 locs->set_in(1, CanBeImmediateIndex(index(), class_id())
1009 ? Location::RegisterOrSmiConstant(index()) 1015 ? Location::RegisterOrSmiConstant(index())
1010 : Location::RequiresRegister()); 1016 : Location::RequiresRegister());
1011 if (representation() == kUnboxedDouble) { 1017 if (representation() == kUnboxedDouble) {
1012 locs->set_out(Location::RequiresXmmRegister()); 1018 locs->set_out(Location::RequiresXmmRegister());
1013 } else { 1019 } else {
1014 locs->set_out(Location::RequiresRegister()); 1020 locs->set_out(Location::RequiresRegister());
1015 } 1021 }
1016 return locs; 1022 return locs;
1017 } 1023 }
1018 1024
1019 1025
1020 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1026 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1021 Register array = locs()->in(0).reg(); 1027 Register array = locs()->in(0).reg();
1022 Location index = locs()->in(1); 1028 Location index = locs()->in(1);
1023 1029
1024 if (class_id() == kExternalUint8ArrayCid) { 1030 if (class_id() == kExternalUint8ArrayCid) {
1025 Register result = locs()->out().reg(); 1031 Register result = locs()->out().reg();
1026 Address element_address = index.IsRegister() 1032 Address element_address = index.IsRegister()
1027 ? Address(result, index.reg(), TIMES_1, 0) 1033 ? FlowGraphCompiler::ExternalElementAddressForRegIndex(
1028 : Address(result, Smi::Cast(index.constant()).Value()); 1034 class_id(), result, index.reg())
1035 : FlowGraphCompiler::ExternalElementAddressForIntIndex(
1036 class_id(), result, Smi::Cast(index.constant()).Value());
1029 if (index.IsRegister()) { 1037 if (index.IsRegister()) {
1030 __ SmiUntag(index.reg()); 1038 __ SmiUntag(index.reg());
1031 } 1039 }
1032 __ movq(result, 1040 __ movq(result,
1033 FieldAddress(array, ExternalUint8Array::external_data_offset())); 1041 FieldAddress(array, ExternalUint8Array::external_data_offset()));
1034 __ movq(result, 1042 __ movq(result,
1035 Address(result, ExternalByteArrayData<uint8_t>::data_offset())); 1043 Address(result, ExternalByteArrayData<uint8_t>::data_offset()));
1036 __ movzxb(result, element_address); 1044 __ movzxb(result, element_address);
1037 __ SmiTag(result); 1045 __ SmiTag(result);
1038 if (index.IsRegister()) { 1046 if (index.IsRegister()) {
(...skipping 16 matching lines...) Expand all
1055 // Promote to double. 1063 // Promote to double.
1056 __ cvtss2sd(result, locs()->out().xmm_reg()); 1064 __ cvtss2sd(result, locs()->out().xmm_reg());
1057 } else { 1065 } else {
1058 ASSERT(class_id() == kFloat64ArrayCid); 1066 ASSERT(class_id() == kFloat64ArrayCid);
1059 __ movsd(result, element_address); 1067 __ movsd(result, element_address);
1060 } 1068 }
1061 return; 1069 return;
1062 } 1070 }
1063 1071
1064 Register result = locs()->out().reg(); 1072 Register result = locs()->out().reg();
1065 if ((class_id() == kUint8ArrayCid) || 1073 switch (class_id()) {
1066 (class_id() == kUint8ClampedArrayCid)) { 1074 case kInt8ArrayCid:
1067 if (index.IsRegister()) { 1075 case kUint8ArrayCid:
1068 __ SmiUntag(index.reg()); 1076 case kUint8ClampedArrayCid:
1069 } 1077 if (index.IsRegister()) {
1070 __ movzxb(result, element_address); 1078 __ SmiUntag(index.reg());
1071 __ SmiTag(result); 1079 }
1072 if (index.IsRegister()) { 1080 if (class_id() == kInt8ArrayCid) {
1073 __ SmiTag(index.reg()); // Re-tag. 1081 __ movsxb(result, element_address);
1074 } 1082 } else {
1075 return; 1083 __ movzxb(result, element_address);
1084 }
1085 __ SmiTag(result);
1086 if (index.IsRegister()) {
1087 __ SmiTag(index.reg()); // Re-tag.
1088 }
1089 break;
1090 case kInt16ArrayCid:
1091 __ movsxw(result, element_address);
1092 __ SmiTag(result);
1093 break;
1094 case kUint16ArrayCid:
1095 __ movzxw(result, element_address);
1096 __ SmiTag(result);
1097 break;
1098 default:
1099 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid));
1100 __ movq(result, element_address);
1101 break;
1076 } 1102 }
1077
1078 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid));
1079 __ movq(result, element_address);
1080 } 1103 }
1081 1104
1082 1105
1083 LocationSummary* StoreIndexedInstr::MakeLocationSummary() const { 1106 LocationSummary* StoreIndexedInstr::MakeLocationSummary() const {
1084 const intptr_t kNumInputs = 3; 1107 const intptr_t kNumInputs = 3;
1085 const intptr_t numTemps = 0; 1108 const intptr_t kNumTemps = 0;
1086 LocationSummary* locs = 1109 LocationSummary* locs =
1087 new LocationSummary(kNumInputs, numTemps, LocationSummary::kNoCall); 1110 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
1111 // The smi index is either untagged and tagged again at the end of the
1112 // operation (element size == 1), or it is left smi tagged (for all element
1113 // sizes > 1).
1088 locs->set_in(0, Location::RequiresRegister()); 1114 locs->set_in(0, Location::RequiresRegister());
1089 locs->set_in(1, CanBeImmediateIndex(index(), class_id()) 1115 locs->set_in(1, CanBeImmediateIndex(index(), class_id())
1090 ? Location::RegisterOrSmiConstant(index()) 1116 ? Location::RegisterOrSmiConstant(index())
1091 : Location::RequiresRegister()); 1117 : Location::RequiresRegister());
1092 switch (class_id()) { 1118 switch (class_id()) {
1093 case kArrayCid: 1119 case kArrayCid:
1094 locs->set_in(2, ShouldEmitStoreBarrier() 1120 locs->set_in(2, ShouldEmitStoreBarrier()
1095 ? Location::WritableRegister() 1121 ? Location::WritableRegister()
1096 : Location::RegisterOrConstant(value())); 1122 : Location::RegisterOrConstant(value()));
1097 break; 1123 break;
1124 case kInt8ArrayCid:
1098 case kUint8ArrayCid: 1125 case kUint8ArrayCid:
1126 case kUint8ClampedArrayCid:
1099 // TODO(fschneider): Add location constraint for byte registers (RAX, 1127 // TODO(fschneider): Add location constraint for byte registers (RAX,
1100 // RBX, RCX, RDX) instead of using a fixed register. 1128 // RBX, RCX, RDX) instead of using a fixed register.
1101 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), RAX)); 1129 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), RAX));
1102 break; 1130 break;
1131 case kInt16ArrayCid:
1132 case kUint16ArrayCid:
1133 // Writable register because the value must be untagged before storing.
1134 locs->set_in(2, Location::WritableRegister());
1135 break;
1103 case kFloat32ArrayCid: 1136 case kFloat32ArrayCid:
1104 // Need temp register for float-to-double conversion. 1137 // Need temp register for float-to-double conversion.
1105 locs->AddTemp(Location::RequiresXmmRegister()); 1138 locs->AddTemp(Location::RequiresXmmRegister());
1106 // Fall through. 1139 // Fall through.
1107 case kFloat64ArrayCid: 1140 case kFloat64ArrayCid:
1108 // TODO(srdjan): Support Float64 constants. 1141 // TODO(srdjan): Support Float64 constants.
1109 locs->set_in(2, Location::RequiresXmmRegister()); 1142 locs->set_in(2, Location::RequiresXmmRegister());
1110 break; 1143 break;
1111 default: 1144 default:
1112 UNREACHABLE(); 1145 UNREACHABLE();
(...skipping 19 matching lines...) Expand all
1132 Register value = locs()->in(2).reg(); 1165 Register value = locs()->in(2).reg();
1133 __ StoreIntoObject(array, element_address, value); 1166 __ StoreIntoObject(array, element_address, value);
1134 } else if (locs()->in(2).IsConstant()) { 1167 } else if (locs()->in(2).IsConstant()) {
1135 const Object& constant = locs()->in(2).constant(); 1168 const Object& constant = locs()->in(2).constant();
1136 __ StoreObject(element_address, constant); 1169 __ StoreObject(element_address, constant);
1137 } else { 1170 } else {
1138 Register value = locs()->in(2).reg(); 1171 Register value = locs()->in(2).reg();
1139 __ StoreIntoObjectNoBarrier(array, element_address, value); 1172 __ StoreIntoObjectNoBarrier(array, element_address, value);
1140 } 1173 }
1141 break; 1174 break;
1175 case kInt8ArrayCid:
1142 case kUint8ArrayCid: 1176 case kUint8ArrayCid:
1143 if (index.IsRegister()) { 1177 if (index.IsRegister()) {
1144 __ SmiUntag(index.reg()); 1178 __ SmiUntag(index.reg());
1145 } 1179 }
1146 if (locs()->in(2).IsConstant()) { 1180 if (locs()->in(2).IsConstant()) {
1147 const Smi& constant = Smi::Cast(locs()->in(2).constant()); 1181 const Smi& constant = Smi::Cast(locs()->in(2).constant());
1148 __ movb(element_address, 1182 __ movb(element_address,
1149 Immediate(static_cast<int8_t>(constant.Value()))); 1183 Immediate(static_cast<int8_t>(constant.Value())));
1150 } else { 1184 } else {
1151 ASSERT(locs()->in(2).reg() == RAX); 1185 ASSERT(locs()->in(2).reg() == RAX);
1152 __ SmiUntag(RAX); 1186 __ SmiUntag(RAX);
1153 __ movb(element_address, RAX); 1187 __ movb(element_address, RAX);
1154 } 1188 }
1155 if (index.IsRegister()) { 1189 if (index.IsRegister()) {
1156 __ SmiTag(index.reg()); // Re-tag. 1190 __ SmiTag(index.reg()); // Re-tag.
1157 } 1191 }
1158 break; 1192 break;
1193 case kUint8ClampedArrayCid: {
1194 if (index.IsRegister()) {
1195 __ SmiUntag(index.reg());
1196 }
1197 if (locs()->in(2).IsConstant()) {
1198 const Smi& constant = Smi::Cast(locs()->in(2).constant());
1199 intptr_t value = constant.Value();
1200 // Clamp to 0x0 or 0xFF respectively.
1201 if (value > 0xFF) {
1202 value = 0xFF;
1203 } else if (value < 0) {
1204 value = 0;
1205 }
1206 __ movb(element_address,
1207 Immediate(static_cast<int8_t>(value)));
1208 } else {
1209 ASSERT(locs()->in(2).reg() == RAX);
1210 Label store_value, store_0xff;
1211 __ SmiUntag(RAX);
1212 __ cmpq(RAX, Immediate(0xFF));
1213 __ j(BELOW_EQUAL, &store_value, Assembler::kNearJump);
1214 // Clamp to 0x0 or 0xFF respectively.
1215 __ j(GREATER, &store_0xff);
1216 __ xorq(RAX, RAX);
1217 __ jmp(&store_value, Assembler::kNearJump);
1218 __ Bind(&store_0xff);
1219 __ movq(RAX, Immediate(0xFF));
1220 __ Bind(&store_value);
1221 __ movb(element_address, RAX);
1222 }
1223 if (index.IsRegister()) {
1224 __ SmiTag(index.reg()); // Re-tag.
1225 }
1226 break;
1227 }
1228 case kInt16ArrayCid:
1229 case kUint16ArrayCid: {
1230 Register value = locs()->in(2).reg();
1231 __ SmiUntag(value);
1232 __ movw(element_address, value);
1233 break;
1234 }
1159 case kFloat32ArrayCid: 1235 case kFloat32ArrayCid:
1160 // Convert to single precision. 1236 // Convert to single precision.
1161 __ cvtsd2ss(locs()->temp(0).xmm_reg(), locs()->in(2).xmm_reg()); 1237 __ cvtsd2ss(locs()->temp(0).xmm_reg(), locs()->in(2).xmm_reg());
1162 // Store. 1238 // Store.
1163 __ movss(element_address, locs()->temp(0).xmm_reg()); 1239 __ movss(element_address, locs()->temp(0).xmm_reg());
1164 break; 1240 break;
1165 case kFloat64ArrayCid: 1241 case kFloat64ArrayCid:
1166 __ movsd(element_address, locs()->in(2).xmm_reg()); 1242 __ movsd(element_address, locs()->in(2).xmm_reg());
1167 break; 1243 break;
1168 default: 1244 default:
(...skipping 1335 matching lines...) Expand 10 before | Expand all | Expand 10 after
2504 2580
2505 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2581 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2506 UNIMPLEMENTED(); 2582 UNIMPLEMENTED();
2507 } 2583 }
2508 2584
2509 } // namespace dart 2585 } // namespace dart
2510 2586
2511 #undef __ 2587 #undef __
2512 2588
2513 #endif // defined TARGET_ARCH_X64 2589 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language_ia32.cc ('k') | tests/standalone/int_array_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698