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

Side by Side Diff: src/x64/full-codegen-x64.cc

Issue 3195028: Add inlining of binary smi operations in the full codegens on IA32... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 10 years, 4 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 | « src/token.h ('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 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 } 223 }
224 // Check that the size of the code used for returning matches what is 224 // Check that the size of the code used for returning matches what is
225 // expected by the debugger. 225 // expected by the debugger.
226 ASSERT_EQ(Assembler::kJSReturnSequenceLength, 226 ASSERT_EQ(Assembler::kJSReturnSequenceLength,
227 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); 227 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize));
228 #endif 228 #endif
229 } 229 }
230 } 230 }
231 231
232 232
233 FullCodeGenerator::ConstantOperand FullCodeGenerator::GetConstantOperand(
234 Token::Value op, Expression* left, Expression* right) {
235 ASSERT(ShouldInlineSmiCase(op));
236 return kNoConstants;
237 }
238
239
233 void FullCodeGenerator::Apply(Expression::Context context, Register reg) { 240 void FullCodeGenerator::Apply(Expression::Context context, Register reg) {
234 switch (context) { 241 switch (context) {
235 case Expression::kUninitialized: 242 case Expression::kUninitialized:
236 UNREACHABLE(); 243 UNREACHABLE();
237 244
238 case Expression::kEffect: 245 case Expression::kEffect:
239 // Nothing to do. 246 // Nothing to do.
240 break; 247 break;
241 248
242 case Expression::kValue: 249 case Expression::kValue:
(...skipping 906 matching lines...) Expand 10 before | Expand all | Expand 10 after
1149 // on the left-hand side. 1156 // on the left-hand side.
1150 if (!expr->target()->IsValidLeftHandSide()) { 1157 if (!expr->target()->IsValidLeftHandSide()) {
1151 VisitForEffect(expr->target()); 1158 VisitForEffect(expr->target());
1152 return; 1159 return;
1153 } 1160 }
1154 1161
1155 // Left-hand side can only be a property, a global or a (parameter or local) 1162 // Left-hand side can only be a property, a global or a (parameter or local)
1156 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 1163 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
1157 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1164 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1158 LhsKind assign_type = VARIABLE; 1165 LhsKind assign_type = VARIABLE;
1159 Property* prop = expr->target()->AsProperty(); 1166 Property* property = expr->target()->AsProperty();
1160 if (prop != NULL) { 1167 if (property != NULL) {
1161 assign_type = 1168 assign_type = (property->key()->IsPropertyName())
1162 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; 1169 ? NAMED_PROPERTY
1170 : KEYED_PROPERTY;
1163 } 1171 }
1164 1172
1165 // Evaluate LHS expression. 1173 // Evaluate LHS expression.
1166 switch (assign_type) { 1174 switch (assign_type) {
1167 case VARIABLE: 1175 case VARIABLE:
1168 // Nothing to do here. 1176 // Nothing to do here.
1169 break; 1177 break;
1170 case NAMED_PROPERTY: 1178 case NAMED_PROPERTY:
1171 if (expr->is_compound()) { 1179 if (expr->is_compound()) {
1172 // We need the receiver both on the stack and in the accumulator. 1180 // We need the receiver both on the stack and in the accumulator.
1173 VisitForValue(prop->obj(), kAccumulator); 1181 VisitForValue(property->obj(), kAccumulator);
1174 __ push(result_register()); 1182 __ push(result_register());
1175 } else { 1183 } else {
1176 VisitForValue(prop->obj(), kStack); 1184 VisitForValue(property->obj(), kStack);
1177 } 1185 }
1178 break; 1186 break;
1179 case KEYED_PROPERTY: 1187 case KEYED_PROPERTY:
1180 if (expr->is_compound()) { 1188 if (expr->is_compound()) {
1181 VisitForValue(prop->obj(), kStack); 1189 VisitForValue(property->obj(), kStack);
1182 VisitForValue(prop->key(), kAccumulator); 1190 VisitForValue(property->key(), kAccumulator);
1183 __ movq(rdx, Operand(rsp, 0)); 1191 __ movq(rdx, Operand(rsp, 0));
1184 __ push(rax); 1192 __ push(rax);
1185 } else { 1193 } else {
1186 VisitForValue(prop->obj(), kStack); 1194 VisitForValue(property->obj(), kStack);
1187 VisitForValue(prop->key(), kStack); 1195 VisitForValue(property->key(), kStack);
1188 } 1196 }
1189 break; 1197 break;
1190 } 1198 }
1191 1199
1192 // If we have a compound assignment: Get value of LHS expression and
1193 // store in on top of the stack.
1194 if (expr->is_compound()) { 1200 if (expr->is_compound()) {
1195 Location saved_location = location_; 1201 Location saved_location = location_;
1196 location_ = kStack; 1202 location_ = kAccumulator;
1197 switch (assign_type) { 1203 switch (assign_type) {
1198 case VARIABLE: 1204 case VARIABLE:
1199 EmitVariableLoad(expr->target()->AsVariableProxy()->var(), 1205 EmitVariableLoad(expr->target()->AsVariableProxy()->var(),
1200 Expression::kValue); 1206 Expression::kValue);
1201 break; 1207 break;
1202 case NAMED_PROPERTY: 1208 case NAMED_PROPERTY:
1203 EmitNamedPropertyLoad(prop); 1209 EmitNamedPropertyLoad(property);
1204 __ push(result_register());
1205 break; 1210 break;
1206 case KEYED_PROPERTY: 1211 case KEYED_PROPERTY:
1207 EmitKeyedPropertyLoad(prop); 1212 EmitKeyedPropertyLoad(property);
1208 __ push(result_register());
1209 break; 1213 break;
1210 } 1214 }
1211 location_ = saved_location;
1212 }
1213 1215
1214 // Evaluate RHS expression. 1216 Token::Value op = expr->binary_op();
1215 Expression* rhs = expr->value(); 1217 ConstantOperand constant = ShouldInlineSmiCase(op)
1216 VisitForValue(rhs, kAccumulator); 1218 ? GetConstantOperand(op, expr->target(), expr->value())
1219 : kNoConstants;
1220 ASSERT(constant == kRightConstant || constant == kNoConstants);
1221 if (constant == kNoConstants) {
1222 __ push(rax); // Left operand goes on the stack.
1223 VisitForValue(expr->value(), kAccumulator);
1224 }
1217 1225
1218 // If we have a compound assignment: Apply operator.
1219 if (expr->is_compound()) {
1220 Location saved_location = location_;
1221 location_ = kAccumulator;
1222 OverwriteMode mode = expr->value()->ResultOverwriteAllowed() 1226 OverwriteMode mode = expr->value()->ResultOverwriteAllowed()
1223 ? OVERWRITE_RIGHT 1227 ? OVERWRITE_RIGHT
1224 : NO_OVERWRITE; 1228 : NO_OVERWRITE;
1225 EmitBinaryOp(expr->binary_op(), Expression::kValue, mode); 1229 SetSourcePosition(expr->position() + 1);
1230 if (ShouldInlineSmiCase(op)) {
1231 EmitInlineSmiBinaryOp(expr,
1232 op,
1233 Expression::kValue,
1234 mode,
1235 expr->target(),
1236 expr->value(),
1237 constant);
1238 } else {
1239 EmitBinaryOp(op, Expression::kValue, mode);
1240 }
1226 location_ = saved_location; 1241 location_ = saved_location;
1242
1243 } else {
1244 VisitForValue(expr->value(), kAccumulator);
1227 } 1245 }
1228 1246
1229 // Record source position before possible IC call. 1247 // Record source position before possible IC call.
1230 SetSourcePosition(expr->position()); 1248 SetSourcePosition(expr->position());
1231 1249
1232 // Store the value. 1250 // Store the value.
1233 switch (assign_type) { 1251 switch (assign_type) {
1234 case VARIABLE: 1252 case VARIABLE:
1235 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), 1253 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
1236 expr->op(), 1254 expr->op(),
(...skipping 20 matching lines...) Expand all
1257 1275
1258 1276
1259 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { 1277 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
1260 SetSourcePosition(prop->position()); 1278 SetSourcePosition(prop->position());
1261 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 1279 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
1262 __ Call(ic, RelocInfo::CODE_TARGET); 1280 __ Call(ic, RelocInfo::CODE_TARGET);
1263 __ nop(); 1281 __ nop();
1264 } 1282 }
1265 1283
1266 1284
1285 void FullCodeGenerator::EmitInlineSmiBinaryOp(Expression* expr,
1286 Token::Value op,
1287 Expression::Context context,
1288 OverwriteMode mode,
1289 Expression* left,
1290 Expression* right,
1291 ConstantOperand constant) {
1292 ASSERT(constant == kNoConstants); // Only handled case.
1293
1294 // Do combined smi check of the operands. Left operand is on the
1295 // stack (popped into rdx). Right operand is in rax but moved into
1296 // rcx to make the shifts easier.
1297 Label done, stub_call, smi_case;
1298 __ pop(rdx);
1299 __ movq(rcx, rax);
1300 Condition smi = __ CheckBothSmi(rdx, rax);
1301 __ j(smi, &smi_case);
1302
1303 __ bind(&stub_call);
1304 GenericBinaryOpStub stub(op, mode, NO_SMI_CODE_IN_STUB, TypeInfo::Unknown());
1305 if (stub.ArgsInRegistersSupported()) {
1306 stub.GenerateCall(masm_, rdx, rcx);
1307 } else {
1308 __ push(rdx);
1309 __ push(rcx);
1310 __ CallStub(&stub);
1311 }
1312 __ jmp(&done);
1313
1314 __ bind(&smi_case);
1315 switch (op) {
1316 case Token::SAR:
1317 __ SmiShiftArithmeticRight(rax, rdx, rcx);
1318 break;
1319 case Token::SHL:
1320 __ SmiShiftLeft(rax, rdx, rcx);
1321 break;
1322 case Token::SHR:
1323 __ SmiShiftLogicalRight(rax, rdx, rcx, &stub_call);
1324 break;
1325 case Token::ADD:
1326 __ SmiAdd(rax, rdx, rcx, &stub_call);
1327 break;
1328 case Token::SUB:
1329 __ SmiSub(rax, rdx, rcx, &stub_call);
1330 break;
1331 case Token::MUL:
1332 __ SmiMul(rax, rdx, rcx, &stub_call);
1333 break;
1334 case Token::BIT_OR:
1335 __ SmiOr(rax, rdx, rcx);
1336 break;
1337 case Token::BIT_AND:
1338 __ SmiAnd(rax, rdx, rcx);
1339 break;
1340 case Token::BIT_XOR:
1341 __ SmiXor(rax, rdx, rcx);
1342 break;
1343 default:
1344 UNREACHABLE();
1345 break;
1346 }
1347
1348 __ bind(&done);
1349 Apply(context, rax);
1350 }
1351
1352
1267 void FullCodeGenerator::EmitBinaryOp(Token::Value op, 1353 void FullCodeGenerator::EmitBinaryOp(Token::Value op,
1268 Expression::Context context, 1354 Expression::Context context,
1269 OverwriteMode mode) { 1355 OverwriteMode mode) {
1270 GenericBinaryOpStub stub(op, mode, NO_GENERIC_BINARY_FLAGS); 1356 GenericBinaryOpStub stub(op, mode, NO_GENERIC_BINARY_FLAGS);
1271 if (stub.ArgsInRegistersSupported()) { 1357 if (stub.ArgsInRegistersSupported()) {
1272 __ pop(rdx); 1358 __ pop(rdx);
1273 stub.GenerateCall(masm_, rdx, rax); 1359 stub.GenerateCall(masm_, rdx, rax);
1274 } else { 1360 } else {
1275 __ push(result_register()); 1361 __ push(result_register());
1276 __ CallStub(&stub); 1362 __ CallStub(&stub);
(...skipping 687 matching lines...) Expand 10 before | Expand all | Expand 10 after
1964 __ cmpq(rax, rbx); 2050 __ cmpq(rax, rbx);
1965 Split(equal, if_true, if_false, fall_through); 2051 Split(equal, if_true, if_false, fall_through);
1966 2052
1967 Apply(context_, if_true, if_false); 2053 Apply(context_, if_true, if_false);
1968 } 2054 }
1969 2055
1970 2056
1971 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { 2057 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) {
1972 ASSERT(args->length() == 1); 2058 ASSERT(args->length() == 1);
1973 2059
1974 // ArgumentsAccessStub expects the key in edx and the formal 2060 // ArgumentsAccessStub expects the key in rdx and the formal
1975 // parameter count in eax. 2061 // parameter count in rax.
1976 VisitForValue(args->at(0), kAccumulator); 2062 VisitForValue(args->at(0), kAccumulator);
1977 __ movq(rdx, rax); 2063 __ movq(rdx, rax);
1978 __ Move(rax, Smi::FromInt(scope()->num_parameters())); 2064 __ Move(rax, Smi::FromInt(scope()->num_parameters()));
1979 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); 2065 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
1980 __ CallStub(&stub); 2066 __ CallStub(&stub);
1981 Apply(context_, rax); 2067 Apply(context_, rax);
1982 } 2068 }
1983 2069
1984 2070
1985 void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) { 2071 void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) {
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
2169 __ CallRuntime(Runtime::kMath_pow, 2); 2255 __ CallRuntime(Runtime::kMath_pow, 2);
2170 Apply(context_, rax); 2256 Apply(context_, rax);
2171 } 2257 }
2172 2258
2173 2259
2174 void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) { 2260 void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) {
2175 ASSERT(args->length() == 2); 2261 ASSERT(args->length() == 2);
2176 2262
2177 VisitForValue(args->at(0), kStack); // Load the object. 2263 VisitForValue(args->at(0), kStack); // Load the object.
2178 VisitForValue(args->at(1), kAccumulator); // Load the value. 2264 VisitForValue(args->at(1), kAccumulator); // Load the value.
2179 __ pop(rbx); // rax = value. ebx = object. 2265 __ pop(rbx); // rax = value. rbx = object.
2180 2266
2181 Label done; 2267 Label done;
2182 // If the object is a smi, return the value. 2268 // If the object is a smi, return the value.
2183 __ JumpIfSmi(rbx, &done); 2269 __ JumpIfSmi(rbx, &done);
2184 2270
2185 // If the object is not a value type, return the value. 2271 // If the object is not a value type, return the value.
2186 __ CmpObjectType(rbx, JS_VALUE_TYPE, rcx); 2272 __ CmpObjectType(rbx, JS_VALUE_TYPE, rcx);
2187 __ j(not_equal, &done); 2273 __ j(not_equal, &done);
2188 2274
2189 // Store the value. 2275 // Store the value.
(...skipping 970 matching lines...) Expand 10 before | Expand all | Expand 10 after
3160 __ ret(0); 3246 __ ret(0);
3161 } 3247 }
3162 3248
3163 3249
3164 #undef __ 3250 #undef __
3165 3251
3166 3252
3167 } } // namespace v8::internal 3253 } } // namespace v8::internal
3168 3254
3169 #endif // V8_TARGET_ARCH_X64 3255 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/token.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698