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

Side by Side Diff: src/ia32/fast-codegen-ia32.cc

Issue 496009: Added pre- and postfix count operations to top-level compiler.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 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 | « src/fast-codegen.cc ('k') | src/x64/fast-codegen-x64.cc » ('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 2009 the V8 project authors. All rights reserved. 1 // Copyright 2009 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 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 __ push(source); 220 __ push(source);
221 TestAndBranch(source, &discard, false_label_); 221 TestAndBranch(source, &discard, false_label_);
222 __ bind(&discard); 222 __ bind(&discard);
223 __ add(Operand(esp), Immediate(kPointerSize)); 223 __ add(Operand(esp), Immediate(kPointerSize));
224 __ jmp(true_label_); 224 __ jmp(true_label_);
225 } 225 }
226 } 226 }
227 } 227 }
228 228
229 229
230 void FastCodeGenerator::MoveTOS(Expression::Context context) {
231 switch (context) {
232 case Expression::kUninitialized:
233 UNREACHABLE();
234 case Expression::kEffect:
235 __ Drop(1);
236 break;
237 case Expression::kValue:
238 break;
239 case Expression::kTest:
240 __ pop(eax);
241 TestAndBranch(eax, true_label_, false_label_);
242 break;
243 case Expression::kValueTest: {
244 Label discard;
245 __ mov(eax, Operand(esp, 0));
246 TestAndBranch(eax, true_label_, &discard);
247 __ bind(&discard);
248 __ Drop(1);
249 __ jmp(false_label_);
250 break;
251 }
252 case Expression::kTestValue: {
253 Label discard;
254 __ mov(eax, Operand(esp, 0));
255 TestAndBranch(eax, &discard, false_label_);
256 __ bind(&discard);
257 __ Drop(1);
258 __ jmp(true_label_);
259 }
260 }
261 }
262
263
230 template <> 264 template <>
231 Operand FastCodeGenerator::CreateSlotOperand<Operand>(Slot* source, 265 Operand FastCodeGenerator::CreateSlotOperand<Operand>(Slot* source,
232 Register scratch) { 266 Register scratch) {
233 switch (source->type()) { 267 switch (source->type()) {
234 case Slot::PARAMETER: 268 case Slot::PARAMETER:
235 case Slot::LOCAL: 269 case Slot::LOCAL:
236 return Operand(ebp, SlotOffset(source)); 270 return Operand(ebp, SlotOffset(source));
237 case Slot::CONTEXT: { 271 case Slot::CONTEXT: {
238 int context_chain_length = 272 int context_chain_length =
239 function_->scope()->ContextChainLength(source->var()->scope()); 273 function_->scope()->ContextChainLength(source->var()->scope());
(...skipping 581 matching lines...) Expand 10 before | Expand all | Expand 10 after
821 __ add(Operand(esp), Immediate(kPointerSize)); 855 __ add(Operand(esp), Immediate(kPointerSize));
822 __ jmp(true_label_); 856 __ jmp(true_label_);
823 break; 857 break;
824 } 858 }
825 } 859 }
826 } 860 }
827 861
828 862
829 void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop, 863 void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop,
830 Expression::Context context) { 864 Expression::Context context) {
865 SetSourcePosition(prop->position());
831 Literal* key = prop->key()->AsLiteral(); 866 Literal* key = prop->key()->AsLiteral();
832 __ mov(ecx, Immediate(key->handle())); 867 __ mov(ecx, Immediate(key->handle()));
833 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 868 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
834 __ call(ic, RelocInfo::CODE_TARGET); 869 __ call(ic, RelocInfo::CODE_TARGET);
835 Move(context, eax); 870 Move(context, eax);
836 } 871 }
837 872
838 873
839 void FastCodeGenerator::EmitKeyedPropertyLoad(Expression::Context context) { 874 void FastCodeGenerator::EmitKeyedPropertyLoad(Property* prop,
875 Expression::Context context) {
876 SetSourcePosition(prop->position());
840 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 877 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
841 __ call(ic, RelocInfo::CODE_TARGET); 878 __ call(ic, RelocInfo::CODE_TARGET);
842 Move(context, eax); 879 Move(context, eax);
843 } 880 }
844 881
845 882
846 void FastCodeGenerator::EmitCompoundAssignmentOp(Token::Value op, 883 void FastCodeGenerator::EmitCompoundAssignmentOp(Token::Value op,
847 Expression::Context context) { 884 Expression::Context context) {
848 GenericBinaryOpStub stub(op, 885 GenericBinaryOpStub stub(op,
849 NO_OVERWRITE, 886 NO_OVERWRITE,
850 NO_GENERIC_BINARY_FLAGS); 887 NO_GENERIC_BINARY_FLAGS);
851 __ CallStub(&stub); 888 __ CallStub(&stub);
852 Move(context, eax); 889 Move(context, eax);
853 } 890 }
854 891
855 892
856 void FastCodeGenerator::EmitVariableAssignment(Assignment* expr) { 893 void FastCodeGenerator::EmitVariableAssignment(Variable* var,
857 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); 894 Expression::Context context) {
858 ASSERT(var != NULL); 895 ASSERT(var != NULL);
859 ASSERT(var->is_global() || var->slot() != NULL); 896 ASSERT(var->is_global() || var->slot() != NULL);
860 if (var->is_global()) { 897 if (var->is_global()) {
861 // Assignment to a global variable. Use inline caching for the 898 // Assignment to a global variable. Use inline caching for the
862 // assignment. Right-hand-side value is passed in eax, variable name in 899 // assignment. Right-hand-side value is passed in eax, variable name in
863 // ecx, and the global object on the stack. 900 // ecx, and the global object on the stack.
864 __ pop(eax); 901 __ pop(eax);
865 __ mov(ecx, var->name()); 902 __ mov(ecx, var->name());
866 __ push(CodeGenerator::GlobalObject()); 903 __ push(CodeGenerator::GlobalObject());
867 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 904 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
868 __ call(ic, RelocInfo::CODE_TARGET); 905 __ call(ic, RelocInfo::CODE_TARGET);
869 // Overwrite the receiver on the stack with the result if needed. 906 // Overwrite the receiver on the stack with the result if needed.
870 DropAndMove(expr->context(), eax); 907 DropAndMove(context, eax);
871 908
872 } else if (var->slot() != NULL) { 909 } else if (var->slot() != NULL) {
873 Slot* slot = var->slot(); 910 Slot* slot = var->slot();
874 switch (slot->type()) { 911 switch (slot->type()) {
875 case Slot::LOCAL: 912 case Slot::LOCAL:
876 case Slot::PARAMETER: { 913 case Slot::PARAMETER: {
877 Operand target = Operand(ebp, SlotOffset(var->slot())); 914 Operand target = Operand(ebp, SlotOffset(var->slot()));
878 switch (expr->context()) { 915 switch (context) {
879 case Expression::kUninitialized: 916 case Expression::kUninitialized:
880 UNREACHABLE(); 917 UNREACHABLE();
881 case Expression::kEffect: 918 case Expression::kEffect:
882 // Perform assignment and discard value. 919 // Perform assignment and discard value.
883 __ pop(target); 920 __ pop(target);
884 break; 921 break;
885 case Expression::kValue: 922 case Expression::kValue:
886 // Perform assignment and preserve value. 923 // Perform assignment and preserve value.
887 __ mov(eax, Operand(esp, 0)); 924 __ mov(eax, Operand(esp, 0));
888 __ mov(target, eax); 925 __ mov(target, eax);
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
936 } 973 }
937 if (FLAG_debug_code) { 974 if (FLAG_debug_code) {
938 __ cmp(eax, 975 __ cmp(eax,
939 Operand(eax, Context::SlotOffset(Context::FCONTEXT_INDEX))); 976 Operand(eax, Context::SlotOffset(Context::FCONTEXT_INDEX)));
940 __ Check(equal, "Context Slot chain length wrong."); 977 __ Check(equal, "Context Slot chain length wrong.");
941 } 978 }
942 __ pop(ecx); 979 __ pop(ecx);
943 __ mov(Operand(eax, Context::SlotOffset(slot->index())), ecx); 980 __ mov(Operand(eax, Context::SlotOffset(slot->index())), ecx);
944 981
945 // RecordWrite may destroy all its register arguments. 982 // RecordWrite may destroy all its register arguments.
946 if (expr->context() == Expression::kValue) { 983 if (context == Expression::kValue) {
947 __ push(ecx); 984 __ push(ecx);
948 } else if (expr->context() != Expression::kEffect) { 985 } else if (context != Expression::kEffect) {
949 __ mov(edx, ecx); 986 __ mov(edx, ecx);
950 } 987 }
951 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; 988 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
952 __ RecordWrite(eax, offset, ecx, ebx); 989 __ RecordWrite(eax, offset, ecx, ebx);
953 if (expr->context() != Expression::kEffect && 990 if (context != Expression::kEffect &&
954 expr->context() != Expression::kValue) { 991 context != Expression::kValue) {
955 Move(expr->context(), edx); 992 Move(context, edx);
956 } 993 }
957 break; 994 break;
958 } 995 }
959 996
960 case Slot::LOOKUP: 997 case Slot::LOOKUP:
961 UNREACHABLE(); 998 UNREACHABLE();
962 break; 999 break;
963 } 1000 }
964 } 1001 }
965 } 1002 }
(...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after
1370 } 1407 }
1371 1408
1372 default: 1409 default:
1373 UNREACHABLE(); 1410 UNREACHABLE();
1374 } 1411 }
1375 } 1412 }
1376 1413
1377 1414
1378 void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { 1415 void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
1379 Comment cmnt(masm_, "[ CountOperation"); 1416 Comment cmnt(masm_, "[ CountOperation");
1380 VariableProxy* proxy = expr->expression()->AsVariableProxy();
1381 ASSERT(proxy->AsVariable() != NULL);
1382 ASSERT(proxy->AsVariable()->is_global());
1383 1417
1384 Visit(proxy); 1418 // Expression can only be a property, a global or a (parameter or local)
1419 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
1420 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1421 LhsKind assign_type = VARIABLE;
1422 Property* prop = expr->expression()->AsProperty();
1423 // In case of a property we use the uninitialized expression context
1424 // of the key to detect a named property.
1425 if (prop != NULL) {
1426 assign_type = (prop->key()->context() == Expression::kUninitialized)
1427 ? NAMED_PROPERTY
1428 : KEYED_PROPERTY;
1429 }
1430
1431 // Evaluate expression and get value.
1432 if (assign_type == VARIABLE) {
1433 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL);
1434 EmitVariableLoad(expr->expression()->AsVariableProxy()->var(),
1435 Expression::kValue);
1436 } else {
1437 // Reserve space for result of postfix operation.
1438 if (expr->is_postfix() && expr->context() != Expression::kEffect) {
1439 ASSERT(expr->context() != Expression::kUninitialized);
1440 __ push(Immediate(Smi::FromInt(0)));
1441 }
1442 Visit(prop->obj());
1443 ASSERT_EQ(Expression::kValue, prop->obj()->context());
1444 if (assign_type == NAMED_PROPERTY) {
1445 EmitNamedPropertyLoad(prop, Expression::kValue);
1446 } else {
1447 Visit(prop->key());
1448 ASSERT_EQ(Expression::kValue, prop->key()->context());
1449 EmitKeyedPropertyLoad(prop, Expression::kValue);
1450 }
1451 }
1452
1453 // Convert to number.
1385 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); 1454 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION);
1386 1455
1387 switch (expr->context()) { 1456 // Save result for postfix expressions.
1388 case Expression::kUninitialized: 1457 if (expr->is_postfix()) {
1389 UNREACHABLE(); 1458 switch (expr->context()) {
1390 case Expression::kValue: // Fall through 1459 case Expression::kUninitialized:
1391 case Expression::kTest: // Fall through 1460 UNREACHABLE();
1392 case Expression::kTestValue: // Fall through 1461 case Expression::kEffect:
1393 case Expression::kValueTest: 1462 // Do not save result.
1394 // Duplicate the result on the stack. 1463 break;
1395 __ push(eax); 1464 case Expression::kValue: // Fall through
1396 break; 1465 case Expression::kTest: // Fall through
1397 case Expression::kEffect: 1466 case Expression::kTestValue: // Fall through
1398 // Do not save result. 1467 case Expression::kValueTest:
1399 break; 1468 // Save the result on the stack. If we have a named or keyed property
1469 // we store the result under the receiver that is currently on top
1470 // of the stack.
1471 switch (assign_type) {
1472 case VARIABLE:
1473 __ push(eax);
1474 break;
1475 case NAMED_PROPERTY:
1476 __ mov(Operand(esp, kPointerSize), eax);
1477 break;
1478 case KEYED_PROPERTY:
1479 __ mov(Operand(esp, 2 * kPointerSize), eax);
1480 break;
1481 }
1482 break;
1483 }
1400 } 1484 }
1485
1401 // Call runtime for +1/-1. 1486 // Call runtime for +1/-1.
1402 __ push(eax); 1487 __ push(eax);
1403 __ push(Immediate(Smi::FromInt(1))); 1488 __ push(Immediate(Smi::FromInt(1)));
1404 if (expr->op() == Token::INC) { 1489 if (expr->op() == Token::INC) {
1405 __ CallRuntime(Runtime::kNumberAdd, 2); 1490 __ CallRuntime(Runtime::kNumberAdd, 2);
1406 } else { 1491 } else {
1407 __ CallRuntime(Runtime::kNumberSub, 2); 1492 __ CallRuntime(Runtime::kNumberSub, 2);
1408 } 1493 }
1409 // Call Store IC.
1410 __ mov(ecx, proxy->AsVariable()->name());
1411 __ push(CodeGenerator::GlobalObject());
1412 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
1413 __ call(ic, RelocInfo::CODE_TARGET);
1414 // Restore up stack after store IC.
1415 __ add(Operand(esp), Immediate(kPointerSize));
1416 1494
1417 switch (expr->context()) { 1495 // Store the value returned in eax.
1418 case Expression::kUninitialized: 1496 switch (assign_type) {
1419 UNREACHABLE(); 1497 case VARIABLE:
1420 case Expression::kEffect: // Fall through 1498 __ push(eax);
1421 case Expression::kValue: 1499 if (expr->is_postfix()) {
1422 // Do nothing. Result in either on the stack for value context 1500 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
1423 // or discarded for effect context. 1501 Expression::kEffect);
1502 // For all contexts except kEffect: We have the result on
1503 // top of the stack.
1504 if (expr->context() != Expression::kEffect) {
1505 MoveTOS(expr->context());
1506 }
1507 } else {
1508 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
1509 expr->context());
1510 }
1424 break; 1511 break;
1425 case Expression::kTest: 1512 case NAMED_PROPERTY: {
1426 __ pop(eax); 1513 __ mov(ecx, prop->key()->AsLiteral()->handle());
1427 TestAndBranch(eax, true_label_, false_label_); 1514 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
1428 break; 1515 __ call(ic, RelocInfo::CODE_TARGET);
1429 case Expression::kValueTest: { 1516 // This nop signals to the IC that there is no inlined code at the call
1430 Label discard; 1517 // site for it to patch.
1431 __ mov(eax, Operand(esp, 0)); 1518 __ nop();
1432 TestAndBranch(eax, true_label_, &discard); 1519 if (expr->is_postfix()) {
1433 __ bind(&discard); 1520 __ Drop(1); // Result is on the stack under the receiver.
1434 __ add(Operand(esp), Immediate(kPointerSize)); 1521 if (expr->context() != Expression::kEffect) {
1435 __ jmp(false_label_); 1522 MoveTOS(expr->context());
1523 }
1524 } else {
1525 DropAndMove(expr->context(), eax);
1526 }
1436 break; 1527 break;
1437 } 1528 }
1438 case Expression::kTestValue: { 1529 case KEYED_PROPERTY: {
1439 Label discard; 1530 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
1440 __ mov(eax, Operand(esp, 0)); 1531 __ call(ic, RelocInfo::CODE_TARGET);
1441 TestAndBranch(eax, &discard, false_label_); 1532 // This nop signals to the IC that there is no inlined code at the call
1442 __ bind(&discard); 1533 // site for it to patch.
1443 __ add(Operand(esp), Immediate(kPointerSize)); 1534 __ nop();
1444 __ jmp(true_label_); 1535 if (expr->is_postfix()) {
1536 __ Drop(2); // Result is on the stack under the key and the receiver.
1537 if (expr->context() != Expression::kEffect) {
1538 MoveTOS(expr->context());
1539 }
1540 } else {
1541 DropAndMove(expr->context(), eax, 2);
1542 }
1445 break; 1543 break;
1446 } 1544 }
1447 } 1545 }
1448 } 1546 }
1449 1547
1450 1548
1451 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { 1549 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
1452 Comment cmnt(masm_, "[ BinaryOperation"); 1550 Comment cmnt(masm_, "[ BinaryOperation");
1453 switch (expr->op()) { 1551 switch (expr->op()) {
1454 case Token::COMMA: 1552 case Token::COMMA:
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
1702 __ add(Operand(edx), Immediate(masm_->CodeObject())); 1800 __ add(Operand(edx), Immediate(masm_->CodeObject()));
1703 __ mov(Operand(esp, 0), edx); 1801 __ mov(Operand(esp, 0), edx);
1704 // And return. 1802 // And return.
1705 __ ret(0); 1803 __ ret(0);
1706 } 1804 }
1707 1805
1708 1806
1709 #undef __ 1807 #undef __
1710 1808
1711 } } // namespace v8::internal 1809 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/fast-codegen.cc ('k') | src/x64/fast-codegen-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698