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

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

Issue 8733: Merged bleeding_edge r599:645 into regexp2000. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/regexp2000/
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 // Set the flags based on the operation, type and loop nesting level.
802 // for the bitwise operations.
803 GenericBinaryFlags flags; 804 GenericBinaryFlags flags;
804 switch (op) { 805 switch (op) {
805 case Token::BIT_OR: 806 case Token::BIT_OR:
806 case Token::BIT_AND: 807 case Token::BIT_AND:
807 case Token::BIT_XOR: 808 case Token::BIT_XOR:
808 case Token::SHL: 809 case Token::SHL:
809 case Token::SHR: 810 case Token::SHR:
810 case Token::SAR: 811 case Token::SAR:
811 flags = SMI_CODE_INLINED; 812 // Bit operations always assume they likely operate on Smis. Still only
813 // generate the inline Smi check code if this operation is part of a loop.
814 flags = (loop_nesting() > 0)
815 ? SMI_CODE_INLINED
816 : SMI_CODE_IN_STUB;
812 break; 817 break;
813 818
814 default: 819 default:
815 flags = SMI_CODE_IN_STUB; 820 // By default only inline the Smi check code for likely smis if this
821 // operation is part of a loop.
822 flags = ((loop_nesting() > 0) && type->IsLikelySmi())
823 ? SMI_CODE_INLINED
824 : SMI_CODE_IN_STUB;
816 break; 825 break;
817 } 826 }
818 827
819 if (flags == SMI_CODE_INLINED) { 828 if (flags == SMI_CODE_INLINED) {
820 // Create a new deferred code for the slow-case part. 829 // Create a new deferred code for the slow-case part.
821 DeferredInlineBinaryOperation* deferred = 830 DeferredInlineBinaryOperation* deferred =
822 new DeferredInlineBinaryOperation(this, op, overwrite_mode, flags); 831 new DeferredInlineBinaryOperation(this, op, overwrite_mode, flags);
823 // Fetch the operands from the stack. 832 // Fetch the operands from the stack.
824 frame_->Pop(ebx); // get y 833 frame_->Pop(ebx); // get y
825 __ mov(eax, frame_->Top()); // get x 834 __ mov(eax, frame_->Top()); // get x
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
978 __ CallStub(&igostub); 987 __ CallStub(&igostub);
979 } 988 }
980 989
981 private: 990 private:
982 Register tos_reg_; 991 Register tos_reg_;
983 OverwriteMode overwrite_mode_; 992 OverwriteMode overwrite_mode_;
984 }; 993 };
985 994
986 995
987 void CodeGenerator::SmiOperation(Token::Value op, 996 void CodeGenerator::SmiOperation(Token::Value op,
997 StaticType* type,
988 Handle<Object> value, 998 Handle<Object> value,
989 bool reversed, 999 bool reversed,
990 OverwriteMode overwrite_mode) { 1000 OverwriteMode overwrite_mode) {
991 // NOTE: This is an attempt to inline (a bit) more of the code for 1001 // 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 1002 // some possible smi operations (like + and -) when (at least) one
993 // of the operands is a literal smi. With this optimization, the 1003 // of the operands is a literal smi. With this optimization, the
994 // performance of the system is increased by ~15%, and the generated 1004 // performance of the system is increased by ~15%, and the generated
995 // code size is increased by ~1% (measured on a combination of 1005 // code size is increased by ~1% (measured on a combination of
996 // different benchmarks). 1006 // different benchmarks).
997 1007
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1039 __ bind(deferred->exit()); 1049 __ bind(deferred->exit());
1040 frame_->Push(eax); 1050 frame_->Push(eax);
1041 break; 1051 break;
1042 } 1052 }
1043 1053
1044 case Token::SAR: { 1054 case Token::SAR: {
1045 if (reversed) { 1055 if (reversed) {
1046 frame_->Pop(eax); 1056 frame_->Pop(eax);
1047 frame_->Push(Immediate(value)); 1057 frame_->Push(Immediate(value));
1048 frame_->Push(eax); 1058 frame_->Push(eax);
1049 GenericBinaryOperation(op, overwrite_mode); 1059 GenericBinaryOperation(op, type, overwrite_mode);
1050 } else { 1060 } else {
1051 int shift_value = int_value & 0x1f; // only least significant 5 bits 1061 int shift_value = int_value & 0x1f; // only least significant 5 bits
1052 DeferredCode* deferred = 1062 DeferredCode* deferred =
1053 new DeferredInlinedSmiOperation(this, Token::SAR, shift_value, 1063 new DeferredInlinedSmiOperation(this, Token::SAR, shift_value,
1054 overwrite_mode); 1064 overwrite_mode);
1055 frame_->Pop(eax); 1065 frame_->Pop(eax);
1056 __ test(eax, Immediate(kSmiTagMask)); 1066 __ test(eax, Immediate(kSmiTagMask));
1057 __ j(not_zero, deferred->enter(), not_taken); 1067 __ j(not_zero, deferred->enter(), not_taken);
1058 __ sar(eax, shift_value); 1068 __ sar(eax, shift_value);
1059 __ and_(eax, ~kSmiTagMask); 1069 __ and_(eax, ~kSmiTagMask);
1060 __ bind(deferred->exit()); 1070 __ bind(deferred->exit());
1061 frame_->Push(eax); 1071 frame_->Push(eax);
1062 } 1072 }
1063 break; 1073 break;
1064 } 1074 }
1065 1075
1066 case Token::SHR: { 1076 case Token::SHR: {
1067 if (reversed) { 1077 if (reversed) {
1068 frame_->Pop(eax); 1078 frame_->Pop(eax);
1069 frame_->Push(Immediate(value)); 1079 frame_->Push(Immediate(value));
1070 frame_->Push(eax); 1080 frame_->Push(eax);
1071 GenericBinaryOperation(op, overwrite_mode); 1081 GenericBinaryOperation(op, type, overwrite_mode);
1072 } else { 1082 } else {
1073 int shift_value = int_value & 0x1f; // only least significant 5 bits 1083 int shift_value = int_value & 0x1f; // only least significant 5 bits
1074 DeferredCode* deferred = 1084 DeferredCode* deferred =
1075 new DeferredInlinedSmiOperation(this, Token::SHR, shift_value, 1085 new DeferredInlinedSmiOperation(this, Token::SHR, shift_value,
1076 overwrite_mode); 1086 overwrite_mode);
1077 frame_->Pop(eax); 1087 frame_->Pop(eax);
1078 __ test(eax, Immediate(kSmiTagMask)); 1088 __ test(eax, Immediate(kSmiTagMask));
1079 __ mov(ebx, Operand(eax)); 1089 __ mov(ebx, Operand(eax));
1080 __ j(not_zero, deferred->enter(), not_taken); 1090 __ j(not_zero, deferred->enter(), not_taken);
1081 __ sar(ebx, kSmiTagSize); 1091 __ sar(ebx, kSmiTagSize);
1082 __ shr(ebx, shift_value); 1092 __ shr(ebx, shift_value);
1083 __ test(ebx, Immediate(0xc0000000)); 1093 __ test(ebx, Immediate(0xc0000000));
1084 __ j(not_zero, deferred->enter(), not_taken); 1094 __ j(not_zero, deferred->enter(), not_taken);
1085 // tag result and store it in TOS (eax) 1095 // tag result and store it in TOS (eax)
1086 ASSERT(kSmiTagSize == times_2); // adjust code if not the case 1096 ASSERT(kSmiTagSize == times_2); // adjust code if not the case
1087 __ lea(eax, Operand(ebx, times_2, kSmiTag)); 1097 __ lea(eax, Operand(ebx, times_2, kSmiTag));
1088 __ bind(deferred->exit()); 1098 __ bind(deferred->exit());
1089 frame_->Push(eax); 1099 frame_->Push(eax);
1090 } 1100 }
1091 break; 1101 break;
1092 } 1102 }
1093 1103
1094 case Token::SHL: { 1104 case Token::SHL: {
1095 if (reversed) { 1105 if (reversed) {
1096 frame_->Pop(eax); 1106 frame_->Pop(eax);
1097 frame_->Push(Immediate(value)); 1107 frame_->Push(Immediate(value));
1098 frame_->Push(eax); 1108 frame_->Push(eax);
1099 GenericBinaryOperation(op, overwrite_mode); 1109 GenericBinaryOperation(op, type, overwrite_mode);
1100 } else { 1110 } else {
1101 int shift_value = int_value & 0x1f; // only least significant 5 bits 1111 int shift_value = int_value & 0x1f; // only least significant 5 bits
1102 DeferredCode* deferred = 1112 DeferredCode* deferred =
1103 new DeferredInlinedSmiOperation(this, Token::SHL, shift_value, 1113 new DeferredInlinedSmiOperation(this, Token::SHL, shift_value,
1104 overwrite_mode); 1114 overwrite_mode);
1105 frame_->Pop(eax); 1115 frame_->Pop(eax);
1106 __ test(eax, Immediate(kSmiTagMask)); 1116 __ test(eax, Immediate(kSmiTagMask));
1107 __ mov(ebx, Operand(eax)); 1117 __ mov(ebx, Operand(eax));
1108 __ j(not_zero, deferred->enter(), not_taken); 1118 __ j(not_zero, deferred->enter(), not_taken);
1109 __ sar(ebx, kSmiTagSize); 1119 __ sar(ebx, kSmiTagSize);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1148 } 1158 }
1149 1159
1150 default: { 1160 default: {
1151 if (!reversed) { 1161 if (!reversed) {
1152 frame_->Push(Immediate(value)); 1162 frame_->Push(Immediate(value));
1153 } else { 1163 } else {
1154 frame_->Pop(eax); 1164 frame_->Pop(eax);
1155 frame_->Push(Immediate(value)); 1165 frame_->Push(Immediate(value));
1156 frame_->Push(eax); 1166 frame_->Push(eax);
1157 } 1167 }
1158 GenericBinaryOperation(op, overwrite_mode); 1168 GenericBinaryOperation(op, type, overwrite_mode);
1159 break; 1169 break;
1160 } 1170 }
1161 } 1171 }
1162 } 1172 }
1163 1173
1164 1174
1165 class CompareStub: public CodeStub { 1175 class CompareStub: public CodeStub {
1166 public: 1176 public:
1167 CompareStub(Condition cc, bool strict) : cc_(cc), strict_(strict) { } 1177 CompareStub(Condition cc, bool strict) : cc_(cc), strict_(strict) { }
1168 1178
(...skipping 571 matching lines...) Expand 10 before | Expand all | Expand 10 after
1740 1750
1741 // init 1751 // init
1742 if (node->init() != NULL) { 1752 if (node->init() != NULL) {
1743 ASSERT(node->type() == LoopStatement::FOR_LOOP); 1753 ASSERT(node->type() == LoopStatement::FOR_LOOP);
1744 Visit(node->init()); 1754 Visit(node->init());
1745 } 1755 }
1746 if (node->type() != LoopStatement::DO_LOOP && info != ALWAYS_TRUE) { 1756 if (node->type() != LoopStatement::DO_LOOP && info != ALWAYS_TRUE) {
1747 __ jmp(&entry); 1757 __ jmp(&entry);
1748 } 1758 }
1749 1759
1760 IncrementLoopNesting();
1761
1750 // body 1762 // body
1751 __ bind(&loop); 1763 __ bind(&loop);
1752 CheckStack(); // TODO(1222600): ignore if body contains calls. 1764 CheckStack(); // TODO(1222600): ignore if body contains calls.
1753 Visit(node->body()); 1765 Visit(node->body());
1754 1766
1755 // next 1767 // next
1756 __ bind(node->continue_target()); 1768 __ bind(node->continue_target());
1757 if (node->next() != NULL) { 1769 if (node->next() != NULL) {
1758 // Record source position of the statement as this code which is after the 1770 // 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 1771 // code for the body actually belongs to the loop statement and not the
(...skipping 12 matching lines...) Expand all
1772 break; 1784 break;
1773 case ALWAYS_FALSE: 1785 case ALWAYS_FALSE:
1774 break; 1786 break;
1775 case DONT_KNOW: 1787 case DONT_KNOW:
1776 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &loop, 1788 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &loop,
1777 node->break_target(), true); 1789 node->break_target(), true);
1778 Branch(true, &loop); 1790 Branch(true, &loop);
1779 break; 1791 break;
1780 } 1792 }
1781 1793
1794 DecrementLoopNesting();
1795
1782 // exit 1796 // exit
1783 __ bind(node->break_target()); 1797 __ bind(node->break_target());
1784 } 1798 }
1785 1799
1786 1800
1787 void CodeGenerator::VisitForInStatement(ForInStatement* node) { 1801 void CodeGenerator::VisitForInStatement(ForInStatement* node) {
1788 Comment cmnt(masm_, "[ ForInStatement"); 1802 Comment cmnt(masm_, "[ ForInStatement");
1789 RecordStatementPosition(node); 1803 RecordStatementPosition(node);
1790 1804
1791 // We keep stuff on the stack while the body is executing. 1805 // We keep stuff on the stack while the body is executing.
(...skipping 788 matching lines...) Expand 10 before | Expand all | Expand 10 after
2580 2594
2581 if (node->op() == Token::ASSIGN || 2595 if (node->op() == Token::ASSIGN ||
2582 node->op() == Token::INIT_VAR || 2596 node->op() == Token::INIT_VAR ||
2583 node->op() == Token::INIT_CONST) { 2597 node->op() == Token::INIT_CONST) {
2584 Load(node->value()); 2598 Load(node->value());
2585 2599
2586 } else { 2600 } else {
2587 target.GetValue(NOT_INSIDE_TYPEOF); 2601 target.GetValue(NOT_INSIDE_TYPEOF);
2588 Literal* literal = node->value()->AsLiteral(); 2602 Literal* literal = node->value()->AsLiteral();
2589 if (IsInlineSmi(literal)) { 2603 if (IsInlineSmi(literal)) {
2590 SmiOperation(node->binary_op(), literal->handle(), false, NO_OVERWRITE); 2604 SmiOperation(node->binary_op(), node->type(), literal->handle(), false,
2605 NO_OVERWRITE);
2591 } else { 2606 } else {
2592 Load(node->value()); 2607 Load(node->value());
2593 GenericBinaryOperation(node->binary_op()); 2608 GenericBinaryOperation(node->binary_op(), node->type());
2594 } 2609 }
2595 } 2610 }
2596 2611
2597 Variable* var = node->target()->AsVariableProxy()->AsVariable(); 2612 Variable* var = node->target()->AsVariableProxy()->AsVariable();
2598 if (var != NULL && 2613 if (var != NULL &&
2599 var->mode() == Variable::CONST && 2614 var->mode() == Variable::CONST &&
2600 node->op() != Token::INIT_VAR && node->op() != Token::INIT_CONST) { 2615 node->op() != Token::INIT_VAR && node->op() != Token::INIT_CONST) {
2601 // Assignment ignored - leave the value on the stack. 2616 // Assignment ignored - leave the value on the stack.
2602 } else { 2617 } else {
2603 __ RecordPosition(node->position()); 2618 __ RecordPosition(node->position());
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
2653 // ------------------------------------------------------------------------ 2668 // ------------------------------------------------------------------------
2654 2669
2655 if (var != NULL && !var->is_this() && var->is_global()) { 2670 if (var != NULL && !var->is_this() && var->is_global()) {
2656 // ---------------------------------- 2671 // ----------------------------------
2657 // JavaScript example: 'foo(1, 2, 3)' // foo is global 2672 // JavaScript example: 'foo(1, 2, 3)' // foo is global
2658 // ---------------------------------- 2673 // ----------------------------------
2659 2674
2660 // Push the name of the function and the receiver onto the stack. 2675 // Push the name of the function and the receiver onto the stack.
2661 frame_->Push(Immediate(var->name())); 2676 frame_->Push(Immediate(var->name()));
2662 2677
2663 // TODO(120): Use global object for function lookup and inline 2678 // Pass the global object as the receiver and let the IC stub
2664 // cache, and use global proxy as 'this' for invocation. 2679 // patch the stack to use the global proxy as 'this' in the
2665 LoadGlobalReceiver(eax); 2680 // invoked function.
2681 LoadGlobal();
2666 2682
2667 // Load the arguments. 2683 // Load the arguments.
2668 for (int i = 0; i < args->length(); i++) { 2684 for (int i = 0; i < args->length(); i++) {
2669 Load(args->at(i)); 2685 Load(args->at(i));
2670 } 2686 }
2671 2687
2672 // Setup the receiver register and call the IC initialization code. 2688 // Setup the receiver register and call the IC initialization code.
2673 Handle<Code> stub = ComputeCallInitialize(args->length()); 2689 Handle<Code> stub = ComputeCallInitialize(args->length());
2674 __ RecordPosition(node->position()); 2690 __ RecordPosition(node->position());
2675 __ call(stub, RelocInfo::CODE_TARGET_CONTEXT); 2691 __ call(stub, RelocInfo::CODE_TARGET_CONTEXT);
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
2842 frame_->Pop(ebx); 2858 frame_->Pop(ebx);
2843 2859
2844 // Check for negative or non-smi index. 2860 // Check for negative or non-smi index.
2845 ASSERT(kSmiTag == 0); 2861 ASSERT(kSmiTag == 0);
2846 __ test(ebx, Immediate(kSmiTagMask | 0x80000000)); 2862 __ test(ebx, Immediate(kSmiTagMask | 0x80000000));
2847 __ j(not_zero, &slow_case, not_taken); 2863 __ j(not_zero, &slow_case, not_taken);
2848 // Get rid of the smi tag on the index. 2864 // Get rid of the smi tag on the index.
2849 __ sar(ebx, kSmiTagSize); 2865 __ sar(ebx, kSmiTagSize);
2850 2866
2851 __ bind(&try_again_with_new_string); 2867 __ bind(&try_again_with_new_string);
2852 // Get the type of the heap object into ecx. 2868 // Get the type of the heap object into edi.
2853 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); 2869 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
2854 __ movzx_b(ecx, FieldOperand(edx, Map::kInstanceTypeOffset)); 2870 __ movzx_b(edi, FieldOperand(edx, Map::kInstanceTypeOffset));
2855 // We don't handle non-strings. 2871 // We don't handle non-strings.
2856 __ test(ecx, Immediate(kIsNotStringMask)); 2872 __ test(edi, Immediate(kIsNotStringMask));
2857 __ j(not_zero, &slow_case, not_taken); 2873 __ j(not_zero, &slow_case, not_taken);
2858 2874
2875 // Here we make assumptions about the tag values and the shifts needed.
2876 // See the comment in objects.h.
2877 ASSERT(kLongStringTag == 0);
2878 ASSERT(kMediumStringTag + String::kLongLengthShift ==
2879 String::kMediumLengthShift);
2880 ASSERT(kShortStringTag + String::kLongLengthShift ==
2881 String::kShortLengthShift);
2882 __ mov(ecx, Operand(edi));
2883 __ and_(ecx, kStringSizeMask);
2884 __ add(Operand(ecx), Immediate(String::kLongLengthShift));
2859 // Get the length field. 2885 // Get the length field.
2860 __ mov(edx, FieldOperand(eax, String::kLengthOffset)); 2886 __ mov(edx, FieldOperand(eax, String::kLengthOffset));
2861 Label long_string; 2887 __ shr(edx); // ecx is implicit operand.
2862 Label medium_string;
2863 Label string_length_shifted;
2864 // The code assumes the tags are disjoint.
2865 ASSERT((kLongStringTag & kMediumStringTag) == 0);
2866 ASSERT(kShortStringTag == 0);
2867 __ test(ecx, Immediate(kLongStringTag));
2868 __ j(not_zero, &long_string, not_taken);
2869 __ test(ecx, Immediate(kMediumStringTag));
2870 __ j(not_zero, &medium_string, taken);
2871 // Short string.
2872 __ shr(edx, String::kShortLengthShift);
2873 __ jmp(&string_length_shifted);
2874
2875 // Medium string.
2876 __ bind(&medium_string);
2877 __ shr(edx, String::kMediumLengthShift - String::kLongLengthShift);
2878 // Fall through to long string.
2879 __ bind(&long_string);
2880 __ shr(edx, String::kLongLengthShift);
2881
2882 __ bind(&string_length_shifted);
2883 ASSERT(kSmiTag == 0);
2884 // edx is now the length of the string. 2888 // edx is now the length of the string.
2885 2889
2886 // Check for index out of range. 2890 // Check for index out of range.
2887 __ cmp(ebx, Operand(edx)); 2891 __ cmp(ebx, Operand(edx));
2888 __ j(greater_equal, &slow_case, not_taken); 2892 __ j(greater_equal, &slow_case, not_taken);
2889 2893
2890 // We need special handling for non-flat strings. 2894 // We need special handling for non-flat strings.
2891 ASSERT(kSeqStringTag == 0); 2895 ASSERT(kSeqStringTag == 0);
2892 __ test(ecx, Immediate(kStringRepresentationMask)); 2896 __ test(edi, Immediate(kStringRepresentationMask));
2893 __ j(not_zero, &not_a_flat_string, not_taken); 2897 __ j(not_zero, &not_a_flat_string, not_taken);
2894 2898
2895 // Check for 1-byte or 2-byte string. 2899 // Check for 1-byte or 2-byte string.
2896 __ test(ecx, Immediate(kStringEncodingMask)); 2900 __ test(edi, Immediate(kStringEncodingMask));
2897 __ j(not_zero, &ascii_string, taken); 2901 __ j(not_zero, &ascii_string, taken);
2898 2902
2899 // 2-byte string. 2903 // 2-byte string.
2900 // Load the 2-byte character code. 2904 // Load the 2-byte character code.
2901 __ movzx_w(eax, 2905 __ movzx_w(eax,
2902 FieldOperand(eax, ebx, times_2, SeqTwoByteString::kHeaderSize)); 2906 FieldOperand(eax, ebx, times_2, SeqTwoByteString::kHeaderSize));
2903 __ jmp(&got_char_code); 2907 __ jmp(&got_char_code);
2904 2908
2905 // ASCII string. 2909 // ASCII string.
2906 __ bind(&ascii_string); 2910 __ bind(&ascii_string);
2907 // Load the byte. 2911 // Load the byte.
2908 __ movzx_b(eax, FieldOperand(eax, ebx, times_1, SeqAsciiString::kHeaderSize)); 2912 __ movzx_b(eax, FieldOperand(eax, ebx, times_1, SeqAsciiString::kHeaderSize));
2909 2913
2910 __ bind(&got_char_code); 2914 __ bind(&got_char_code);
2911 ASSERT(kSmiTag == 0); 2915 ASSERT(kSmiTag == 0);
2912 __ shl(eax, kSmiTagSize); 2916 __ shl(eax, kSmiTagSize);
2913 frame_->Push(eax); 2917 frame_->Push(eax);
2914 __ jmp(&end); 2918 __ jmp(&end);
2915 2919
2916
2917 // Handle non-flat strings. 2920 // Handle non-flat strings.
2918 __ bind(&not_a_flat_string); 2921 __ bind(&not_a_flat_string);
2919 __ and_(ecx, kStringRepresentationMask); 2922 __ and_(edi, kStringRepresentationMask);
2920 __ cmp(ecx, kConsStringTag); 2923 __ cmp(edi, kConsStringTag);
2921 __ j(not_equal, &not_a_cons_string_either, not_taken); 2924 __ j(not_equal, &not_a_cons_string_either, not_taken);
2922 2925
2923 // ConsString. 2926 // ConsString.
2924 // Get the first of the two strings. 2927 // Get the first of the two strings.
2925 __ mov(eax, FieldOperand(eax, ConsString::kFirstOffset)); 2928 __ mov(eax, FieldOperand(eax, ConsString::kFirstOffset));
2926 __ jmp(&try_again_with_new_string); 2929 __ jmp(&try_again_with_new_string);
2927 2930
2928 __ bind(&not_a_cons_string_either); 2931 __ bind(&not_a_cons_string_either);
2929 __ cmp(ecx, kSlicedStringTag); 2932 __ cmp(edi, kSlicedStringTag);
2930 __ j(not_equal, &slow_case, not_taken); 2933 __ j(not_equal, &slow_case, not_taken);
2931 2934
2932 // SlicedString. 2935 // SlicedString.
2933 // Add the offset to the index. 2936 // Add the offset to the index.
2934 __ add(ebx, FieldOperand(eax, SlicedString::kStartOffset)); 2937 __ add(ebx, FieldOperand(eax, SlicedString::kStartOffset));
2935 __ j(overflow, &slow_case); 2938 __ j(overflow, &slow_case);
2936 // Get the underlying string. 2939 // Get the underlying string.
2937 __ mov(eax, FieldOperand(eax, SlicedString::kBufferOffset)); 2940 __ mov(eax, FieldOperand(eax, SlicedString::kBufferOffset));
2938 __ jmp(&try_again_with_new_string); 2941 __ jmp(&try_again_with_new_string);
2939 2942
(...skipping 517 matching lines...) Expand 10 before | Expand all | Expand 10 after
3457 overwrite_mode = OVERWRITE_RIGHT; 3460 overwrite_mode = OVERWRITE_RIGHT;
3458 } 3461 }
3459 3462
3460 // Optimize for the case where (at least) one of the expressions 3463 // Optimize for the case where (at least) one of the expressions
3461 // is a literal small integer. 3464 // is a literal small integer.
3462 Literal* lliteral = node->left()->AsLiteral(); 3465 Literal* lliteral = node->left()->AsLiteral();
3463 Literal* rliteral = node->right()->AsLiteral(); 3466 Literal* rliteral = node->right()->AsLiteral();
3464 3467
3465 if (IsInlineSmi(rliteral)) { 3468 if (IsInlineSmi(rliteral)) {
3466 Load(node->left()); 3469 Load(node->left());
3467 SmiOperation(node->op(), rliteral->handle(), false, overwrite_mode); 3470 SmiOperation(node->op(), node->type(), rliteral->handle(), false,
3468 3471 overwrite_mode);
3469 } else if (IsInlineSmi(lliteral)) { 3472 } else if (IsInlineSmi(lliteral)) {
3470 Load(node->right()); 3473 Load(node->right());
3471 SmiOperation(node->op(), lliteral->handle(), true, overwrite_mode); 3474 SmiOperation(node->op(), node->type(), lliteral->handle(), true,
3472 3475 overwrite_mode);
3473 } else { 3476 } else {
3474 Load(node->left()); 3477 Load(node->left());
3475 Load(node->right()); 3478 Load(node->right());
3476 GenericBinaryOperation(node->op(), overwrite_mode); 3479 GenericBinaryOperation(node->op(), node->type(), overwrite_mode);
3477 } 3480 }
3478 } 3481 }
3479 } 3482 }
3480 3483
3481 3484
3482 void CodeGenerator::VisitThisFunction(ThisFunction* node) { 3485 void CodeGenerator::VisitThisFunction(ThisFunction* node) {
3483 frame_->Push(frame_->Function()); 3486 frame_->Push(frame_->Function());
3484 } 3487 }
3485 3488
3486 3489
(...skipping 1457 matching lines...) Expand 10 before | Expand all | Expand 10 after
4944 // eax: result parameter for PerformGC, if any (setup below) 4947 // eax: result parameter for PerformGC, if any (setup below)
4945 // ebx: pointer to builtin function (C callee-saved) 4948 // ebx: pointer to builtin function (C callee-saved)
4946 // ebp: frame pointer (restored after C call) 4949 // ebp: frame pointer (restored after C call)
4947 // esp: stack pointer (restored after C call) 4950 // esp: stack pointer (restored after C call)
4948 // edi: number of arguments including receiver (C callee-saved) 4951 // edi: number of arguments including receiver (C callee-saved)
4949 // esi: argv pointer (C callee-saved) 4952 // esi: argv pointer (C callee-saved)
4950 4953
4951 Label throw_out_of_memory_exception; 4954 Label throw_out_of_memory_exception;
4952 Label throw_normal_exception; 4955 Label throw_normal_exception;
4953 4956
4954 #ifdef DEBUG 4957 // Call into the runtime system. Collect garbage before the call if
4958 // running with --gc-greedy set.
4955 if (FLAG_gc_greedy) { 4959 if (FLAG_gc_greedy) {
4956 Failure* failure = Failure::RetryAfterGC(0); 4960 Failure* failure = Failure::RetryAfterGC(0);
4957 __ mov(Operand(eax), Immediate(reinterpret_cast<int32_t>(failure))); 4961 __ mov(Operand(eax), Immediate(reinterpret_cast<int32_t>(failure)));
4958 } 4962 }
4959 GenerateCore(masm, &throw_normal_exception, 4963 GenerateCore(masm, &throw_normal_exception,
4960 &throw_out_of_memory_exception, 4964 &throw_out_of_memory_exception,
4961 frame_type, 4965 frame_type,
4962 FLAG_gc_greedy); 4966 FLAG_gc_greedy);
4963 #else 4967
4968 // Do space-specific GC and retry runtime call.
4964 GenerateCore(masm, 4969 GenerateCore(masm,
4965 &throw_normal_exception, 4970 &throw_normal_exception,
4966 &throw_out_of_memory_exception, 4971 &throw_out_of_memory_exception,
4967 frame_type, 4972 frame_type,
4968 false); 4973 true);
4969 #endif
4970 4974
4975 // Do full GC and retry runtime call one final time.
4976 Failure* failure = Failure::InternalError();
4977 __ mov(Operand(eax), Immediate(reinterpret_cast<int32_t>(failure)));
4971 GenerateCore(masm, 4978 GenerateCore(masm,
4972 &throw_normal_exception, 4979 &throw_normal_exception,
4973 &throw_out_of_memory_exception, 4980 &throw_out_of_memory_exception,
4974 frame_type, 4981 frame_type,
4975 true); 4982 true);
4976 4983
4977 __ bind(&throw_out_of_memory_exception); 4984 __ bind(&throw_out_of_memory_exception);
4978 GenerateThrowOutOfMemory(masm); 4985 GenerateThrowOutOfMemory(masm);
4979 // control flow for generated will not return. 4986 // control flow for generated will not return.
4980 4987
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
5113 5120
5114 // Slow-case: Go through the JavaScript implementation. 5121 // Slow-case: Go through the JavaScript implementation.
5115 __ bind(&slow); 5122 __ bind(&slow);
5116 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 5123 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
5117 } 5124 }
5118 5125
5119 5126
5120 #undef __ 5127 #undef __
5121 5128
5122 } } // namespace v8::internal 5129 } } // 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