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

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

Issue 8835: Track whether a node or variable are likely to be a Smi value. Propagate that... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 12 years, 1 month 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/codegen-ia32.h ('k') | src/compiler.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 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 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 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 bool is_eval) 168 bool is_eval)
169 : is_eval_(is_eval), 169 : is_eval_(is_eval),
170 script_(script), 170 script_(script),
171 deferred_(8), 171 deferred_(8),
172 masm_(new MacroAssembler(NULL, buffer_size)), 172 masm_(new MacroAssembler(NULL, buffer_size)),
173 scope_(NULL), 173 scope_(NULL),
174 frame_(NULL), 174 frame_(NULL),
175 cc_reg_(no_condition), 175 cc_reg_(no_condition),
176 state_(NULL), 176 state_(NULL),
177 is_inside_try_(false), 177 is_inside_try_(false),
178 break_stack_height_(0) { 178 break_stack_height_(0),
179 loop_nesting_(0) {
179 } 180 }
180 181
181 182
182 // Calling conventions: 183 // Calling conventions:
183 // ebp: frame pointer 184 // ebp: frame pointer
184 // esp: stack pointer 185 // esp: stack pointer
185 // edi: caller's parameter pointer 186 // edi: caller's parameter pointer
186 // esi: callee's context 187 // esi: callee's context
187 188
188 void CodeGenerator::GenCode(FunctionLiteral* fun) { 189 void CodeGenerator::GenCode(FunctionLiteral* fun) {
(...skipping 590 matching lines...) Expand 10 before | Expand all | Expand 10 after
779 // deferred->exit() is bound. 780 // deferred->exit() is bound.
780 __ push(eax); 781 __ push(eax);
781 } 782 }
782 783
783 private: 784 private:
784 GenericBinaryOpStub stub_; 785 GenericBinaryOpStub stub_;
785 }; 786 };
786 787
787 788
788 void CodeGenerator::GenericBinaryOperation(Token::Value op, 789 void CodeGenerator::GenericBinaryOperation(Token::Value op,
790 StaticType* type,
789 OverwriteMode overwrite_mode) { 791 OverwriteMode overwrite_mode) {
790 Comment cmnt(masm_, "[ BinaryOperation"); 792 Comment cmnt(masm_, "[ BinaryOperation");
791 Comment cmnt_token(masm_, Token::String(op)); 793 Comment cmnt_token(masm_, Token::String(op));
792 794
793 if (op == Token::COMMA) { 795 if (op == Token::COMMA) {
794 // Simply discard left value. 796 // Simply discard left value.
795 frame_->Pop(eax); 797 frame_->Pop(eax);
796 frame_->Pop(); 798 frame_->Pop();
797 frame_->Push(eax); 799 frame_->Push(eax);
798 return; 800 return;
799 } 801 }
800 802
801 // For now, we keep the old behavior and only inline the smi code 803 // For now, we keep the old behavior and only inline the smi code
802 // for the bitwise operations. 804 // for the bitwise operations.
803 GenericBinaryFlags flags; 805 GenericBinaryFlags flags;
804 switch (op) { 806 switch (op) {
805 case Token::BIT_OR: 807 case Token::BIT_OR:
806 case Token::BIT_AND: 808 case Token::BIT_AND:
807 case Token::BIT_XOR: 809 case Token::BIT_XOR:
808 case Token::SHL: 810 case Token::SHL:
809 case Token::SHR: 811 case Token::SHR:
810 case Token::SAR: 812 case Token::SAR:
811 flags = SMI_CODE_INLINED; 813 // Bit operations always assume they likely operate on Smis. Still only
814 // generate the inline Smi check code if this operation is part of a loop.
815 flags = (loop_nesting() > 0)
816 ? SMI_CODE_INLINED
817 : SMI_CODE_IN_STUB;
812 break; 818 break;
813 819
814 default: 820 default:
815 flags = SMI_CODE_IN_STUB; 821 // By default only inline the Smi check code for likely smis if this
822 // operation is part of a loop.
823 flags = ((loop_nesting() > 0) && type->IsLikelySmi())
824 ? SMI_CODE_INLINED
825 : SMI_CODE_IN_STUB;
816 break; 826 break;
817 } 827 }
818 828
819 if (flags == SMI_CODE_INLINED) { 829 if (flags == SMI_CODE_INLINED) {
820 // Create a new deferred code for the slow-case part. 830 // Create a new deferred code for the slow-case part.
821 DeferredInlineBinaryOperation* deferred = 831 DeferredInlineBinaryOperation* deferred =
822 new DeferredInlineBinaryOperation(this, op, overwrite_mode, flags); 832 new DeferredInlineBinaryOperation(this, op, overwrite_mode, flags);
823 // Fetch the operands from the stack. 833 // Fetch the operands from the stack.
824 frame_->Pop(ebx); // get y 834 frame_->Pop(ebx); // get y
825 __ mov(eax, frame_->Top()); // get x 835 __ mov(eax, frame_->Top()); // get x
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
978 __ CallStub(&igostub); 988 __ CallStub(&igostub);
979 } 989 }
980 990
981 private: 991 private:
982 Register tos_reg_; 992 Register tos_reg_;
983 OverwriteMode overwrite_mode_; 993 OverwriteMode overwrite_mode_;
984 }; 994 };
985 995
986 996
987 void CodeGenerator::SmiOperation(Token::Value op, 997 void CodeGenerator::SmiOperation(Token::Value op,
998 StaticType* type,
988 Handle<Object> value, 999 Handle<Object> value,
989 bool reversed, 1000 bool reversed,
990 OverwriteMode overwrite_mode) { 1001 OverwriteMode overwrite_mode) {
991 // NOTE: This is an attempt to inline (a bit) more of the code for 1002 // NOTE: This is an attempt to inline (a bit) more of the code for
992 // some possible smi operations (like + and -) when (at least) one 1003 // some possible smi operations (like + and -) when (at least) one
993 // of the operands is a literal smi. With this optimization, the 1004 // of the operands is a literal smi. With this optimization, the
994 // performance of the system is increased by ~15%, and the generated 1005 // performance of the system is increased by ~15%, and the generated
995 // code size is increased by ~1% (measured on a combination of 1006 // code size is increased by ~1% (measured on a combination of
996 // different benchmarks). 1007 // different benchmarks).
997 1008
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1039 __ bind(deferred->exit()); 1050 __ bind(deferred->exit());
1040 frame_->Push(eax); 1051 frame_->Push(eax);
1041 break; 1052 break;
1042 } 1053 }
1043 1054
1044 case Token::SAR: { 1055 case Token::SAR: {
1045 if (reversed) { 1056 if (reversed) {
1046 frame_->Pop(eax); 1057 frame_->Pop(eax);
1047 frame_->Push(Immediate(value)); 1058 frame_->Push(Immediate(value));
1048 frame_->Push(eax); 1059 frame_->Push(eax);
1049 GenericBinaryOperation(op, overwrite_mode); 1060 GenericBinaryOperation(op, type, overwrite_mode);
1050 } else { 1061 } else {
1051 int shift_value = int_value & 0x1f; // only least significant 5 bits 1062 int shift_value = int_value & 0x1f; // only least significant 5 bits
1052 DeferredCode* deferred = 1063 DeferredCode* deferred =
1053 new DeferredInlinedSmiOperation(this, Token::SAR, shift_value, 1064 new DeferredInlinedSmiOperation(this, Token::SAR, shift_value,
1054 overwrite_mode); 1065 overwrite_mode);
1055 frame_->Pop(eax); 1066 frame_->Pop(eax);
1056 __ test(eax, Immediate(kSmiTagMask)); 1067 __ test(eax, Immediate(kSmiTagMask));
1057 __ j(not_zero, deferred->enter(), not_taken); 1068 __ j(not_zero, deferred->enter(), not_taken);
1058 __ sar(eax, shift_value); 1069 __ sar(eax, shift_value);
1059 __ and_(eax, ~kSmiTagMask); 1070 __ and_(eax, ~kSmiTagMask);
1060 __ bind(deferred->exit()); 1071 __ bind(deferred->exit());
1061 frame_->Push(eax); 1072 frame_->Push(eax);
1062 } 1073 }
1063 break; 1074 break;
1064 } 1075 }
1065 1076
1066 case Token::SHR: { 1077 case Token::SHR: {
1067 if (reversed) { 1078 if (reversed) {
1068 frame_->Pop(eax); 1079 frame_->Pop(eax);
1069 frame_->Push(Immediate(value)); 1080 frame_->Push(Immediate(value));
1070 frame_->Push(eax); 1081 frame_->Push(eax);
1071 GenericBinaryOperation(op, overwrite_mode); 1082 GenericBinaryOperation(op, type, overwrite_mode);
1072 } else { 1083 } else {
1073 int shift_value = int_value & 0x1f; // only least significant 5 bits 1084 int shift_value = int_value & 0x1f; // only least significant 5 bits
1074 DeferredCode* deferred = 1085 DeferredCode* deferred =
1075 new DeferredInlinedSmiOperation(this, Token::SHR, shift_value, 1086 new DeferredInlinedSmiOperation(this, Token::SHR, shift_value,
1076 overwrite_mode); 1087 overwrite_mode);
1077 frame_->Pop(eax); 1088 frame_->Pop(eax);
1078 __ test(eax, Immediate(kSmiTagMask)); 1089 __ test(eax, Immediate(kSmiTagMask));
1079 __ mov(ebx, Operand(eax)); 1090 __ mov(ebx, Operand(eax));
1080 __ j(not_zero, deferred->enter(), not_taken); 1091 __ j(not_zero, deferred->enter(), not_taken);
1081 __ sar(ebx, kSmiTagSize); 1092 __ sar(ebx, kSmiTagSize);
1082 __ shr(ebx, shift_value); 1093 __ shr(ebx, shift_value);
1083 __ test(ebx, Immediate(0xc0000000)); 1094 __ test(ebx, Immediate(0xc0000000));
1084 __ j(not_zero, deferred->enter(), not_taken); 1095 __ j(not_zero, deferred->enter(), not_taken);
1085 // tag result and store it in TOS (eax) 1096 // tag result and store it in TOS (eax)
1086 ASSERT(kSmiTagSize == times_2); // adjust code if not the case 1097 ASSERT(kSmiTagSize == times_2); // adjust code if not the case
1087 __ lea(eax, Operand(ebx, times_2, kSmiTag)); 1098 __ lea(eax, Operand(ebx, times_2, kSmiTag));
1088 __ bind(deferred->exit()); 1099 __ bind(deferred->exit());
1089 frame_->Push(eax); 1100 frame_->Push(eax);
1090 } 1101 }
1091 break; 1102 break;
1092 } 1103 }
1093 1104
1094 case Token::SHL: { 1105 case Token::SHL: {
1095 if (reversed) { 1106 if (reversed) {
1096 frame_->Pop(eax); 1107 frame_->Pop(eax);
1097 frame_->Push(Immediate(value)); 1108 frame_->Push(Immediate(value));
1098 frame_->Push(eax); 1109 frame_->Push(eax);
1099 GenericBinaryOperation(op, overwrite_mode); 1110 GenericBinaryOperation(op, type, overwrite_mode);
1100 } else { 1111 } else {
1101 int shift_value = int_value & 0x1f; // only least significant 5 bits 1112 int shift_value = int_value & 0x1f; // only least significant 5 bits
1102 DeferredCode* deferred = 1113 DeferredCode* deferred =
1103 new DeferredInlinedSmiOperation(this, Token::SHL, shift_value, 1114 new DeferredInlinedSmiOperation(this, Token::SHL, shift_value,
1104 overwrite_mode); 1115 overwrite_mode);
1105 frame_->Pop(eax); 1116 frame_->Pop(eax);
1106 __ test(eax, Immediate(kSmiTagMask)); 1117 __ test(eax, Immediate(kSmiTagMask));
1107 __ mov(ebx, Operand(eax)); 1118 __ mov(ebx, Operand(eax));
1108 __ j(not_zero, deferred->enter(), not_taken); 1119 __ j(not_zero, deferred->enter(), not_taken);
1109 __ sar(ebx, kSmiTagSize); 1120 __ sar(ebx, kSmiTagSize);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1148 } 1159 }
1149 1160
1150 default: { 1161 default: {
1151 if (!reversed) { 1162 if (!reversed) {
1152 frame_->Push(Immediate(value)); 1163 frame_->Push(Immediate(value));
1153 } else { 1164 } else {
1154 frame_->Pop(eax); 1165 frame_->Pop(eax);
1155 frame_->Push(Immediate(value)); 1166 frame_->Push(Immediate(value));
1156 frame_->Push(eax); 1167 frame_->Push(eax);
1157 } 1168 }
1158 GenericBinaryOperation(op, overwrite_mode); 1169 GenericBinaryOperation(op, type, overwrite_mode);
1159 break; 1170 break;
1160 } 1171 }
1161 } 1172 }
1162 } 1173 }
1163 1174
1164 1175
1165 class CompareStub: public CodeStub { 1176 class CompareStub: public CodeStub {
1166 public: 1177 public:
1167 CompareStub(Condition cc, bool strict) : cc_(cc), strict_(strict) { } 1178 CompareStub(Condition cc, bool strict) : cc_(cc), strict_(strict) { }
1168 1179
(...skipping 571 matching lines...) Expand 10 before | Expand all | Expand 10 after
1740 1751
1741 // init 1752 // init
1742 if (node->init() != NULL) { 1753 if (node->init() != NULL) {
1743 ASSERT(node->type() == LoopStatement::FOR_LOOP); 1754 ASSERT(node->type() == LoopStatement::FOR_LOOP);
1744 Visit(node->init()); 1755 Visit(node->init());
1745 } 1756 }
1746 if (node->type() != LoopStatement::DO_LOOP && info != ALWAYS_TRUE) { 1757 if (node->type() != LoopStatement::DO_LOOP && info != ALWAYS_TRUE) {
1747 __ jmp(&entry); 1758 __ jmp(&entry);
1748 } 1759 }
1749 1760
1761 IncrementLoopNesting();
1762
1750 // body 1763 // body
1751 __ bind(&loop); 1764 __ bind(&loop);
1752 CheckStack(); // TODO(1222600): ignore if body contains calls. 1765 CheckStack(); // TODO(1222600): ignore if body contains calls.
1753 Visit(node->body()); 1766 Visit(node->body());
1754 1767
1755 // next 1768 // next
1756 __ bind(node->continue_target()); 1769 __ bind(node->continue_target());
1757 if (node->next() != NULL) { 1770 if (node->next() != NULL) {
1758 // Record source position of the statement as this code which is after the 1771 // Record source position of the statement as this code which is after the
1759 // code for the body actually belongs to the loop statement and not the 1772 // code for the body actually belongs to the loop statement and not the
(...skipping 12 matching lines...) Expand all
1772 break; 1785 break;
1773 case ALWAYS_FALSE: 1786 case ALWAYS_FALSE:
1774 break; 1787 break;
1775 case DONT_KNOW: 1788 case DONT_KNOW:
1776 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &loop, 1789 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &loop,
1777 node->break_target(), true); 1790 node->break_target(), true);
1778 Branch(true, &loop); 1791 Branch(true, &loop);
1779 break; 1792 break;
1780 } 1793 }
1781 1794
1795 DecrementLoopNesting();
1796
1782 // exit 1797 // exit
1783 __ bind(node->break_target()); 1798 __ bind(node->break_target());
1784 } 1799 }
1785 1800
1786 1801
1787 void CodeGenerator::VisitForInStatement(ForInStatement* node) { 1802 void CodeGenerator::VisitForInStatement(ForInStatement* node) {
1788 Comment cmnt(masm_, "[ ForInStatement"); 1803 Comment cmnt(masm_, "[ ForInStatement");
1789 RecordStatementPosition(node); 1804 RecordStatementPosition(node);
1790 1805
1791 // We keep stuff on the stack while the body is executing. 1806 // We keep stuff on the stack while the body is executing.
(...skipping 788 matching lines...) Expand 10 before | Expand all | Expand 10 after
2580 2595
2581 if (node->op() == Token::ASSIGN || 2596 if (node->op() == Token::ASSIGN ||
2582 node->op() == Token::INIT_VAR || 2597 node->op() == Token::INIT_VAR ||
2583 node->op() == Token::INIT_CONST) { 2598 node->op() == Token::INIT_CONST) {
2584 Load(node->value()); 2599 Load(node->value());
2585 2600
2586 } else { 2601 } else {
2587 target.GetValue(NOT_INSIDE_TYPEOF); 2602 target.GetValue(NOT_INSIDE_TYPEOF);
2588 Literal* literal = node->value()->AsLiteral(); 2603 Literal* literal = node->value()->AsLiteral();
2589 if (IsInlineSmi(literal)) { 2604 if (IsInlineSmi(literal)) {
2590 SmiOperation(node->binary_op(), literal->handle(), false, NO_OVERWRITE); 2605 SmiOperation(node->binary_op(), node->type(), literal->handle(), false,
2606 NO_OVERWRITE);
2591 } else { 2607 } else {
2592 Load(node->value()); 2608 Load(node->value());
2593 GenericBinaryOperation(node->binary_op()); 2609 GenericBinaryOperation(node->binary_op(), node->type());
2594 } 2610 }
2595 } 2611 }
2596 2612
2597 Variable* var = node->target()->AsVariableProxy()->AsVariable(); 2613 Variable* var = node->target()->AsVariableProxy()->AsVariable();
2598 if (var != NULL && 2614 if (var != NULL &&
2599 var->mode() == Variable::CONST && 2615 var->mode() == Variable::CONST &&
2600 node->op() != Token::INIT_VAR && node->op() != Token::INIT_CONST) { 2616 node->op() != Token::INIT_VAR && node->op() != Token::INIT_CONST) {
2601 // Assignment ignored - leave the value on the stack. 2617 // Assignment ignored - leave the value on the stack.
2602 } else { 2618 } else {
2603 __ RecordPosition(node->position()); 2619 __ RecordPosition(node->position());
(...skipping 841 matching lines...) Expand 10 before | Expand all | Expand 10 after
3445 overwrite_mode = OVERWRITE_RIGHT; 3461 overwrite_mode = OVERWRITE_RIGHT;
3446 } 3462 }
3447 3463
3448 // Optimize for the case where (at least) one of the expressions 3464 // Optimize for the case where (at least) one of the expressions
3449 // is a literal small integer. 3465 // is a literal small integer.
3450 Literal* lliteral = node->left()->AsLiteral(); 3466 Literal* lliteral = node->left()->AsLiteral();
3451 Literal* rliteral = node->right()->AsLiteral(); 3467 Literal* rliteral = node->right()->AsLiteral();
3452 3468
3453 if (IsInlineSmi(rliteral)) { 3469 if (IsInlineSmi(rliteral)) {
3454 Load(node->left()); 3470 Load(node->left());
3455 SmiOperation(node->op(), rliteral->handle(), false, overwrite_mode); 3471 SmiOperation(node->op(), node->type(), rliteral->handle(), false,
3456 3472 overwrite_mode);
3457 } else if (IsInlineSmi(lliteral)) { 3473 } else if (IsInlineSmi(lliteral)) {
3458 Load(node->right()); 3474 Load(node->right());
3459 SmiOperation(node->op(), lliteral->handle(), true, overwrite_mode); 3475 SmiOperation(node->op(), node->type(), lliteral->handle(), true,
3460 3476 overwrite_mode);
3461 } else { 3477 } else {
3462 Load(node->left()); 3478 Load(node->left());
3463 Load(node->right()); 3479 Load(node->right());
3464 GenericBinaryOperation(node->op(), overwrite_mode); 3480 GenericBinaryOperation(node->op(), node->type(), overwrite_mode);
3465 } 3481 }
3466 } 3482 }
3467 } 3483 }
3468 3484
3469 3485
3470 void CodeGenerator::VisitThisFunction(ThisFunction* node) { 3486 void CodeGenerator::VisitThisFunction(ThisFunction* node) {
3471 frame_->Push(frame_->Function()); 3487 frame_->Push(frame_->Function());
3472 } 3488 }
3473 3489
3474 3490
(...skipping 1626 matching lines...) Expand 10 before | Expand all | Expand 10 after
5101 5117
5102 // Slow-case: Go through the JavaScript implementation. 5118 // Slow-case: Go through the JavaScript implementation.
5103 __ bind(&slow); 5119 __ bind(&slow);
5104 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 5120 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
5105 } 5121 }
5106 5122
5107 5123
5108 #undef __ 5124 #undef __
5109 5125
5110 } } // namespace v8::internal 5126 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/codegen-ia32.h ('k') | src/compiler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698