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

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

Issue 113895: Simplify deferred code by removing some unneeded or redundant stuff. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 11 years, 6 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/ia32/codegen-ia32.h ('k') | src/x64/codegen-x64.h » ('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-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-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 300 matching lines...) Expand 10 before | Expand all | Expand 10 after
311 loop_nesting_ -= fun->loop_nesting(); 311 loop_nesting_ -= fun->loop_nesting();
312 312
313 // Code generation state must be reset. 313 // Code generation state must be reset.
314 ASSERT(state_ == NULL); 314 ASSERT(state_ == NULL);
315 ASSERT(loop_nesting() == 0); 315 ASSERT(loop_nesting() == 0);
316 ASSERT(!function_return_is_shadowed_); 316 ASSERT(!function_return_is_shadowed_);
317 function_return_.Unuse(); 317 function_return_.Unuse();
318 DeleteFrame(); 318 DeleteFrame();
319 319
320 // Process any deferred code using the register allocator. 320 // Process any deferred code using the register allocator.
321 if (HasStackOverflow()) { 321 if (!HasStackOverflow()) {
322 ClearDeferred();
323 } else {
324 HistogramTimerScope deferred_timer(&Counters::deferred_code_generation); 322 HistogramTimerScope deferred_timer(&Counters::deferred_code_generation);
325 JumpTarget::set_compiling_deferred_code(true); 323 JumpTarget::set_compiling_deferred_code(true);
326 ProcessDeferred(); 324 ProcessDeferred();
327 JumpTarget::set_compiling_deferred_code(false); 325 JumpTarget::set_compiling_deferred_code(false);
328 } 326 }
329 327
330 // There is no need to delete the register allocator, it is a 328 // There is no need to delete the register allocator, it is a
331 // stack-allocated local. 329 // stack-allocated local.
332 allocator_ = NULL; 330 allocator_ = NULL;
333 scope_ = NULL; 331 scope_ = NULL;
(...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after
777 } 775 }
778 } 776 }
779 777
780 778
781 // A deferred code class implementing binary operations on likely smis. 779 // A deferred code class implementing binary operations on likely smis.
782 // This class generates both inline code and deferred code. 780 // This class generates both inline code and deferred code.
783 // The fastest path is implemented inline. Deferred code calls 781 // The fastest path is implemented inline. Deferred code calls
784 // the GenericBinaryOpStub stub for slow cases. 782 // the GenericBinaryOpStub stub for slow cases.
785 class DeferredInlineBinaryOperation: public DeferredCode { 783 class DeferredInlineBinaryOperation: public DeferredCode {
786 public: 784 public:
787 DeferredInlineBinaryOperation(CodeGenerator* generator, 785 DeferredInlineBinaryOperation(Token::Value op,
788 Token::Value op,
789 OverwriteMode mode, 786 OverwriteMode mode,
790 GenericBinaryFlags flags) 787 GenericBinaryFlags flags)
791 : DeferredCode(generator), stub_(op, mode, flags), op_(op) { 788 : stub_(op, mode, flags), op_(op) {
792 set_comment("[ DeferredInlineBinaryOperation"); 789 set_comment("[ DeferredInlineBinaryOperation");
793 } 790 }
794 791
795 // Consumes its arguments, left and right, leaving them invalid. 792 // Consumes its arguments, left and right, leaving them invalid.
796 Result GenerateInlineCode(Result* left, Result* right); 793 Result GenerateInlineCode(Result* left, Result* right);
797 794
798 virtual void Generate(); 795 virtual void Generate();
799 796
800 private: 797 private:
801 GenericBinaryOpStub stub_; 798 GenericBinaryOpStub stub_;
802 Token::Value op_; 799 Token::Value op_;
803 }; 800 };
804 801
805 802
806 void DeferredInlineBinaryOperation::Generate() { 803 void DeferredInlineBinaryOperation::Generate() {
807 Result left; 804 Result left;
808 Result right; 805 Result right;
809 enter()->Bind(&left, &right); 806 enter()->Bind(&left, &right);
810 generator()->frame()->Push(&left); 807 cgen()->frame()->Push(&left);
811 generator()->frame()->Push(&right); 808 cgen()->frame()->Push(&right);
812 Result answer = generator()->frame()->CallStub(&stub_, 2); 809 Result answer = cgen()->frame()->CallStub(&stub_, 2);
813 exit_.Jump(&answer); 810 exit_.Jump(&answer);
814 } 811 }
815 812
816 813
817 void CodeGenerator::GenericBinaryOperation(Token::Value op, 814 void CodeGenerator::GenericBinaryOperation(Token::Value op,
818 SmiAnalysis* type, 815 SmiAnalysis* type,
819 OverwriteMode overwrite_mode) { 816 OverwriteMode overwrite_mode) {
820 Comment cmnt(masm_, "[ BinaryOperation"); 817 Comment cmnt(masm_, "[ BinaryOperation");
821 Comment cmnt_token(masm_, Token::String(op)); 818 Comment cmnt_token(masm_, Token::String(op));
822 819
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
1006 } 1003 }
1007 1004
1008 1005
1009 void CodeGenerator::LikelySmiBinaryOperation(Token::Value op, 1006 void CodeGenerator::LikelySmiBinaryOperation(Token::Value op,
1010 Result* left, 1007 Result* left,
1011 Result* right, 1008 Result* right,
1012 OverwriteMode overwrite_mode) { 1009 OverwriteMode overwrite_mode) {
1013 // Implements a binary operation using a deferred code object 1010 // Implements a binary operation using a deferred code object
1014 // and some inline code to operate on smis quickly. 1011 // and some inline code to operate on smis quickly.
1015 DeferredInlineBinaryOperation* deferred = 1012 DeferredInlineBinaryOperation* deferred =
1016 new DeferredInlineBinaryOperation(this, op, overwrite_mode, 1013 new DeferredInlineBinaryOperation(op, overwrite_mode, SMI_CODE_INLINED);
1017 SMI_CODE_INLINED);
1018 // Generate the inline code that handles some smi operations, 1014 // Generate the inline code that handles some smi operations,
1019 // and jumps to the deferred code for everything else. 1015 // and jumps to the deferred code for everything else.
1020 Result answer = deferred->GenerateInlineCode(left, right); 1016 Result answer = deferred->GenerateInlineCode(left, right);
1021 deferred->BindExit(&answer); 1017 deferred->BindExit(&answer);
1022 frame_->Push(&answer); 1018 frame_->Push(&answer);
1023 } 1019 }
1024 1020
1025 1021
1026 class DeferredInlineSmiOperation: public DeferredCode { 1022 class DeferredInlineSmiOperation: public DeferredCode {
1027 public: 1023 public:
1028 DeferredInlineSmiOperation(CodeGenerator* generator, 1024 DeferredInlineSmiOperation(Token::Value op,
1029 Token::Value op,
1030 Smi* value, 1025 Smi* value,
1031 OverwriteMode overwrite_mode) 1026 OverwriteMode overwrite_mode)
1032 : DeferredCode(generator), 1027 : op_(op),
1033 op_(op),
1034 value_(value), 1028 value_(value),
1035 overwrite_mode_(overwrite_mode) { 1029 overwrite_mode_(overwrite_mode) {
1036 set_comment("[ DeferredInlineSmiOperation"); 1030 set_comment("[ DeferredInlineSmiOperation");
1037 } 1031 }
1038 1032
1039 virtual void Generate(); 1033 virtual void Generate();
1040 1034
1041 private: 1035 private:
1042 Token::Value op_; 1036 Token::Value op_;
1043 Smi* value_; 1037 Smi* value_;
1044 OverwriteMode overwrite_mode_; 1038 OverwriteMode overwrite_mode_;
1045 }; 1039 };
1046 1040
1047 1041
1048 void DeferredInlineSmiOperation::Generate() { 1042 void DeferredInlineSmiOperation::Generate() {
1049 Result left; 1043 Result left;
1050 enter()->Bind(&left); 1044 enter()->Bind(&left);
1051 generator()->frame()->Push(&left); 1045 cgen()->frame()->Push(&left);
1052 generator()->frame()->Push(value_); 1046 cgen()->frame()->Push(value_);
1053 GenericBinaryOpStub igostub(op_, overwrite_mode_, SMI_CODE_INLINED); 1047 GenericBinaryOpStub igostub(op_, overwrite_mode_, SMI_CODE_INLINED);
1054 Result answer = generator()->frame()->CallStub(&igostub, 2); 1048 Result answer = cgen()->frame()->CallStub(&igostub, 2);
1055 exit_.Jump(&answer); 1049 exit_.Jump(&answer);
1056 } 1050 }
1057 1051
1058 1052
1059 class DeferredInlineSmiOperationReversed: public DeferredCode { 1053 class DeferredInlineSmiOperationReversed: public DeferredCode {
1060 public: 1054 public:
1061 DeferredInlineSmiOperationReversed(CodeGenerator* generator, 1055 DeferredInlineSmiOperationReversed(Token::Value op,
1062 Token::Value op,
1063 Smi* value, 1056 Smi* value,
1064 OverwriteMode overwrite_mode) 1057 OverwriteMode overwrite_mode)
1065 : DeferredCode(generator), 1058 : op_(op),
1066 op_(op),
1067 value_(value), 1059 value_(value),
1068 overwrite_mode_(overwrite_mode) { 1060 overwrite_mode_(overwrite_mode) {
1069 set_comment("[ DeferredInlineSmiOperationReversed"); 1061 set_comment("[ DeferredInlineSmiOperationReversed");
1070 } 1062 }
1071 1063
1072 virtual void Generate(); 1064 virtual void Generate();
1073 1065
1074 private: 1066 private:
1075 Token::Value op_; 1067 Token::Value op_;
1076 Smi* value_; 1068 Smi* value_;
1077 OverwriteMode overwrite_mode_; 1069 OverwriteMode overwrite_mode_;
1078 }; 1070 };
1079 1071
1080 1072
1081 void DeferredInlineSmiOperationReversed::Generate() { 1073 void DeferredInlineSmiOperationReversed::Generate() {
1082 Result right; 1074 Result right;
1083 enter()->Bind(&right); 1075 enter()->Bind(&right);
1084 generator()->frame()->Push(value_); 1076 cgen()->frame()->Push(value_);
1085 generator()->frame()->Push(&right); 1077 cgen()->frame()->Push(&right);
1086 GenericBinaryOpStub igostub(op_, overwrite_mode_, SMI_CODE_INLINED); 1078 GenericBinaryOpStub igostub(op_, overwrite_mode_, SMI_CODE_INLINED);
1087 Result answer = generator()->frame()->CallStub(&igostub, 2); 1079 Result answer = cgen()->frame()->CallStub(&igostub, 2);
1088 exit_.Jump(&answer); 1080 exit_.Jump(&answer);
1089 } 1081 }
1090 1082
1091 1083
1092 class DeferredInlineSmiAdd: public DeferredCode { 1084 class DeferredInlineSmiAdd: public DeferredCode {
1093 public: 1085 public:
1094 DeferredInlineSmiAdd(CodeGenerator* generator, 1086 DeferredInlineSmiAdd(Smi* value,
1095 Smi* value,
1096 OverwriteMode overwrite_mode) 1087 OverwriteMode overwrite_mode)
1097 : DeferredCode(generator), 1088 : value_(value),
1098 value_(value),
1099 overwrite_mode_(overwrite_mode) { 1089 overwrite_mode_(overwrite_mode) {
1100 set_comment("[ DeferredInlineSmiAdd"); 1090 set_comment("[ DeferredInlineSmiAdd");
1101 } 1091 }
1102 1092
1103 virtual void Generate(); 1093 virtual void Generate();
1104 1094
1105 private: 1095 private:
1106 Smi* value_; 1096 Smi* value_;
1107 OverwriteMode overwrite_mode_; 1097 OverwriteMode overwrite_mode_;
1108 }; 1098 };
1109 1099
1110 1100
1111 void DeferredInlineSmiAdd::Generate() {
1112 // Undo the optimistic add operation and call the shared stub.
1113 Result left; // Initially left + value_.
1114 enter()->Bind(&left);
1115 left.ToRegister();
1116 generator()->frame()->Spill(left.reg());
1117 __ sub(Operand(left.reg()), Immediate(value_));
1118 generator()->frame()->Push(&left);
1119 generator()->frame()->Push(value_);
1120 GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED);
1121 Result answer = generator()->frame()->CallStub(&igostub, 2);
1122 exit_.Jump(&answer);
1123 }
1124
1125
1126 class DeferredInlineSmiAddReversed: public DeferredCode { 1101 class DeferredInlineSmiAddReversed: public DeferredCode {
1127 public: 1102 public:
1128 DeferredInlineSmiAddReversed(CodeGenerator* generator, 1103 DeferredInlineSmiAddReversed(Smi* value,
1129 Smi* value,
1130 OverwriteMode overwrite_mode) 1104 OverwriteMode overwrite_mode)
1131 : DeferredCode(generator), 1105 : value_(value),
1132 value_(value),
1133 overwrite_mode_(overwrite_mode) { 1106 overwrite_mode_(overwrite_mode) {
1134 set_comment("[ DeferredInlineSmiAddReversed"); 1107 set_comment("[ DeferredInlineSmiAddReversed");
1135 } 1108 }
1136 1109
1137 virtual void Generate(); 1110 virtual void Generate();
1138 1111
1139 private: 1112 private:
1140 Smi* value_; 1113 Smi* value_;
1141 OverwriteMode overwrite_mode_; 1114 OverwriteMode overwrite_mode_;
1142 }; 1115 };
1143 1116
1144 1117
1145 void DeferredInlineSmiAddReversed::Generate() {
1146 // Undo the optimistic add operation and call the shared stub.
1147 Result right; // Initially value_ + right.
1148 enter()->Bind(&right);
1149 right.ToRegister();
1150 generator()->frame()->Spill(right.reg());
1151 __ sub(Operand(right.reg()), Immediate(value_));
1152 generator()->frame()->Push(value_);
1153 generator()->frame()->Push(&right);
1154 GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED);
1155 Result answer = generator()->frame()->CallStub(&igostub, 2);
1156 exit_.Jump(&answer);
1157 }
1158
1159
1160 class DeferredInlineSmiSub: public DeferredCode { 1118 class DeferredInlineSmiSub: public DeferredCode {
1161 public: 1119 public:
1162 DeferredInlineSmiSub(CodeGenerator* generator, 1120 DeferredInlineSmiSub(Smi* value,
1163 Smi* value,
1164 OverwriteMode overwrite_mode) 1121 OverwriteMode overwrite_mode)
1165 : DeferredCode(generator), 1122 : value_(value),
1166 value_(value),
1167 overwrite_mode_(overwrite_mode) { 1123 overwrite_mode_(overwrite_mode) {
1168 set_comment("[ DeferredInlineSmiSub"); 1124 set_comment("[ DeferredInlineSmiSub");
1169 } 1125 }
1170 1126
1171 virtual void Generate(); 1127 virtual void Generate();
1172 1128
1173 private: 1129 private:
1174 Smi* value_; 1130 Smi* value_;
1175 OverwriteMode overwrite_mode_; 1131 OverwriteMode overwrite_mode_;
1176 }; 1132 };
1177 1133
1178 1134
1135 #undef __
1136 #define __ ACCESS_MASM(cgen()->masm())
1137
1138
1139 void DeferredInlineSmiAdd::Generate() {
1140 // Undo the optimistic add operation and call the shared stub.
1141 Result left; // Initially left + value_.
1142 enter()->Bind(&left);
1143 left.ToRegister();
1144 cgen()->frame()->Spill(left.reg());
1145 __ sub(Operand(left.reg()), Immediate(value_));
1146 cgen()->frame()->Push(&left);
1147 cgen()->frame()->Push(value_);
1148 GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED);
1149 Result answer = cgen()->frame()->CallStub(&igostub, 2);
1150 exit_.Jump(&answer);
1151 }
1152
1153
1154 void DeferredInlineSmiAddReversed::Generate() {
1155 // Undo the optimistic add operation and call the shared stub.
1156 Result right; // Initially value_ + right.
1157 enter()->Bind(&right);
1158 right.ToRegister();
1159 cgen()->frame()->Spill(right.reg());
1160 __ sub(Operand(right.reg()), Immediate(value_));
1161 cgen()->frame()->Push(value_);
1162 cgen()->frame()->Push(&right);
1163 GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED);
1164 Result answer = cgen()->frame()->CallStub(&igostub, 2);
1165 exit_.Jump(&answer);
1166 }
1167
1168
1179 void DeferredInlineSmiSub::Generate() { 1169 void DeferredInlineSmiSub::Generate() {
1180 // Undo the optimistic sub operation and call the shared stub. 1170 // Undo the optimistic sub operation and call the shared stub.
1181 Result left; // Initially left - value_. 1171 Result left; // Initially left - value_.
1182 enter()->Bind(&left); 1172 enter()->Bind(&left);
1183 left.ToRegister(); 1173 left.ToRegister();
1184 generator()->frame()->Spill(left.reg()); 1174 cgen()->frame()->Spill(left.reg());
1185 __ add(Operand(left.reg()), Immediate(value_)); 1175 __ add(Operand(left.reg()), Immediate(value_));
1186 generator()->frame()->Push(&left); 1176 cgen()->frame()->Push(&left);
1187 generator()->frame()->Push(value_); 1177 cgen()->frame()->Push(value_);
1188 GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, SMI_CODE_INLINED); 1178 GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, SMI_CODE_INLINED);
1189 Result answer = generator()->frame()->CallStub(&igostub, 2); 1179 Result answer = cgen()->frame()->CallStub(&igostub, 2);
1190 exit_.Jump(&answer); 1180 exit_.Jump(&answer);
1191 } 1181 }
1192 1182
1193 1183
1184 #undef __
1185 #define __ ACCESS_MASM(masm_)
1186
1187
1194 class DeferredInlineSmiSubReversed: public DeferredCode { 1188 class DeferredInlineSmiSubReversed: public DeferredCode {
1195 public: 1189 public:
1196 DeferredInlineSmiSubReversed(CodeGenerator* generator, 1190 DeferredInlineSmiSubReversed(Smi* value,
1197 Smi* value,
1198 OverwriteMode overwrite_mode) 1191 OverwriteMode overwrite_mode)
1199 : DeferredCode(generator), 1192 : value_(value),
1200 value_(value),
1201 overwrite_mode_(overwrite_mode) { 1193 overwrite_mode_(overwrite_mode) {
1202 set_comment("[ DeferredInlineSmiSubReversed"); 1194 set_comment("[ DeferredInlineSmiSubReversed");
1203 } 1195 }
1204 1196
1205 virtual void Generate(); 1197 virtual void Generate();
1206 1198
1207 private: 1199 private:
1208 Smi* value_; 1200 Smi* value_;
1209 OverwriteMode overwrite_mode_; 1201 OverwriteMode overwrite_mode_;
1210 }; 1202 };
1211 1203
1212 1204
1213 void DeferredInlineSmiSubReversed::Generate() { 1205 void DeferredInlineSmiSubReversed::Generate() {
1214 // Call the shared stub. 1206 // Call the shared stub.
1215 Result right; 1207 Result right;
1216 enter()->Bind(&right); 1208 enter()->Bind(&right);
1217 generator()->frame()->Push(value_); 1209 cgen()->frame()->Push(value_);
1218 generator()->frame()->Push(&right); 1210 cgen()->frame()->Push(&right);
1219 GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, SMI_CODE_INLINED); 1211 GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, SMI_CODE_INLINED);
1220 Result answer = generator()->frame()->CallStub(&igostub, 2); 1212 Result answer = cgen()->frame()->CallStub(&igostub, 2);
1221 exit_.Jump(&answer); 1213 exit_.Jump(&answer);
1222 } 1214 }
1223 1215
1224 1216
1225 void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op, 1217 void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
1226 Result* operand, 1218 Result* operand,
1227 Handle<Object> value, 1219 Handle<Object> value,
1228 SmiAnalysis* type, 1220 SmiAnalysis* type,
1229 bool reversed, 1221 bool reversed,
1230 OverwriteMode overwrite_mode) { 1222 OverwriteMode overwrite_mode) {
(...skipping 22 matching lines...) Expand all
1253 int int_value = smi_value->value(); 1245 int int_value = smi_value->value();
1254 1246
1255 switch (op) { 1247 switch (op) {
1256 case Token::ADD: { 1248 case Token::ADD: {
1257 operand->ToRegister(); 1249 operand->ToRegister();
1258 frame_->Spill(operand->reg()); 1250 frame_->Spill(operand->reg());
1259 __ add(Operand(operand->reg()), Immediate(value)); 1251 __ add(Operand(operand->reg()), Immediate(value));
1260 1252
1261 DeferredCode* deferred = NULL; 1253 DeferredCode* deferred = NULL;
1262 if (reversed) { 1254 if (reversed) {
1263 deferred = new DeferredInlineSmiAddReversed(this, smi_value, 1255 deferred = new DeferredInlineSmiAddReversed(smi_value, overwrite_mode);
1264 overwrite_mode);
1265 } else { 1256 } else {
1266 deferred = new DeferredInlineSmiAdd(this, smi_value, overwrite_mode); 1257 deferred = new DeferredInlineSmiAdd(smi_value, overwrite_mode);
1267 } 1258 }
1268 deferred->SetEntryFrame(operand); 1259 deferred->SetEntryFrame(operand);
1269 deferred->enter()->Branch(overflow, operand, not_taken); 1260 deferred->enter()->Branch(overflow, operand, not_taken);
1270 __ test(operand->reg(), Immediate(kSmiTagMask)); 1261 __ test(operand->reg(), Immediate(kSmiTagMask));
1271 deferred->enter()->Branch(not_zero, operand, not_taken); 1262 deferred->enter()->Branch(not_zero, operand, not_taken);
1272 deferred->BindExit(operand); 1263 deferred->BindExit(operand);
1273 frame_->Push(operand); 1264 frame_->Push(operand);
1274 break; 1265 break;
1275 } 1266 }
1276 1267
1277 case Token::SUB: { 1268 case Token::SUB: {
1278 DeferredCode* deferred = NULL; 1269 DeferredCode* deferred = NULL;
1279 Result answer; // Only allocate a new register if reversed. 1270 Result answer; // Only allocate a new register if reversed.
1280 if (reversed) { 1271 if (reversed) {
1281 answer = allocator()->Allocate(); 1272 answer = allocator()->Allocate();
1282 ASSERT(answer.is_valid()); 1273 ASSERT(answer.is_valid());
1283 deferred = new DeferredInlineSmiSubReversed(this, smi_value, 1274 deferred = new DeferredInlineSmiSubReversed(smi_value, overwrite_mode);
1284 overwrite_mode);
1285 __ Set(answer.reg(), Immediate(value)); 1275 __ Set(answer.reg(), Immediate(value));
1286 // We are in the reversed case so they can't both be Smi constants. 1276 // We are in the reversed case so they can't both be Smi constants.
1287 ASSERT(operand->is_register()); 1277 ASSERT(operand->is_register());
1288 __ sub(answer.reg(), Operand(operand->reg())); 1278 __ sub(answer.reg(), Operand(operand->reg()));
1289 } else { 1279 } else {
1290 operand->ToRegister(); 1280 operand->ToRegister();
1291 frame_->Spill(operand->reg()); 1281 frame_->Spill(operand->reg());
1292 deferred = new DeferredInlineSmiSub(this, smi_value, overwrite_mode); 1282 deferred = new DeferredInlineSmiSub(smi_value, overwrite_mode);
1293 __ sub(Operand(operand->reg()), Immediate(value)); 1283 __ sub(Operand(operand->reg()), Immediate(value));
1294 answer = *operand; 1284 answer = *operand;
1295 } 1285 }
1296 deferred->SetEntryFrame(operand); 1286 deferred->SetEntryFrame(operand);
1297 deferred->enter()->Branch(overflow, operand, not_taken); 1287 deferred->enter()->Branch(overflow, operand, not_taken);
1298 __ test(answer.reg(), Immediate(kSmiTagMask)); 1288 __ test(answer.reg(), Immediate(kSmiTagMask));
1299 deferred->enter()->Branch(not_zero, operand, not_taken); 1289 deferred->enter()->Branch(not_zero, operand, not_taken);
1300 operand->Unuse(); 1290 operand->Unuse();
1301 deferred->BindExit(&answer); 1291 deferred->BindExit(&answer);
1302 frame_->Push(&answer); 1292 frame_->Push(&answer);
1303 break; 1293 break;
1304 } 1294 }
1305 1295
1306 case Token::SAR: { 1296 case Token::SAR: {
1307 if (reversed) { 1297 if (reversed) {
1308 Result constant_operand(value); 1298 Result constant_operand(value);
1309 LikelySmiBinaryOperation(op, &constant_operand, operand, 1299 LikelySmiBinaryOperation(op, &constant_operand, operand,
1310 overwrite_mode); 1300 overwrite_mode);
1311 } else { 1301 } else {
1312 // Only the least significant 5 bits of the shift value are used. 1302 // Only the least significant 5 bits of the shift value are used.
1313 // In the slow case, this masking is done inside the runtime call. 1303 // In the slow case, this masking is done inside the runtime call.
1314 int shift_value = int_value & 0x1f; 1304 int shift_value = int_value & 0x1f;
1315 DeferredCode* deferred = 1305 DeferredCode* deferred =
1316 new DeferredInlineSmiOperation(this, Token::SAR, smi_value, 1306 new DeferredInlineSmiOperation(op, smi_value, overwrite_mode);
1317 overwrite_mode);
1318 operand->ToRegister(); 1307 operand->ToRegister();
1319 __ test(operand->reg(), Immediate(kSmiTagMask)); 1308 __ test(operand->reg(), Immediate(kSmiTagMask));
1320 deferred->enter()->Branch(not_zero, operand, not_taken); 1309 deferred->enter()->Branch(not_zero, operand, not_taken);
1321 if (shift_value > 0) { 1310 if (shift_value > 0) {
1322 frame_->Spill(operand->reg()); 1311 frame_->Spill(operand->reg());
1323 __ sar(operand->reg(), shift_value); 1312 __ sar(operand->reg(), shift_value);
1324 __ and_(operand->reg(), ~kSmiTagMask); 1313 __ and_(operand->reg(), ~kSmiTagMask);
1325 } 1314 }
1326 deferred->BindExit(operand); 1315 deferred->BindExit(operand);
1327 frame_->Push(operand); 1316 frame_->Push(operand);
1328 } 1317 }
1329 break; 1318 break;
1330 } 1319 }
1331 1320
1332 case Token::SHR: { 1321 case Token::SHR: {
1333 if (reversed) { 1322 if (reversed) {
1334 Result constant_operand(value); 1323 Result constant_operand(value);
1335 LikelySmiBinaryOperation(op, &constant_operand, operand, 1324 LikelySmiBinaryOperation(op, &constant_operand, operand,
1336 overwrite_mode); 1325 overwrite_mode);
1337 } else { 1326 } else {
1338 // Only the least significant 5 bits of the shift value are used. 1327 // Only the least significant 5 bits of the shift value are used.
1339 // In the slow case, this masking is done inside the runtime call. 1328 // In the slow case, this masking is done inside the runtime call.
1340 int shift_value = int_value & 0x1f; 1329 int shift_value = int_value & 0x1f;
1341 DeferredCode* deferred = 1330 DeferredCode* deferred =
1342 new DeferredInlineSmiOperation(this, Token::SHR, smi_value, 1331 new DeferredInlineSmiOperation(op, smi_value, overwrite_mode);
1343 overwrite_mode);
1344 operand->ToRegister(); 1332 operand->ToRegister();
1345 __ test(operand->reg(), Immediate(kSmiTagMask)); 1333 __ test(operand->reg(), Immediate(kSmiTagMask));
1346 deferred->enter()->Branch(not_zero, operand, not_taken); 1334 deferred->enter()->Branch(not_zero, operand, not_taken);
1347 Result answer = allocator()->Allocate(); 1335 Result answer = allocator()->Allocate();
1348 ASSERT(answer.is_valid()); 1336 ASSERT(answer.is_valid());
1349 __ mov(answer.reg(), operand->reg()); 1337 __ mov(answer.reg(), operand->reg());
1350 __ sar(answer.reg(), kSmiTagSize); 1338 __ sar(answer.reg(), kSmiTagSize);
1351 __ shr(answer.reg(), shift_value); 1339 __ shr(answer.reg(), shift_value);
1352 // A negative Smi shifted right two is in the positive Smi range. 1340 // A negative Smi shifted right two is in the positive Smi range.
1353 if (shift_value < 2) { 1341 if (shift_value < 2) {
(...skipping 13 matching lines...) Expand all
1367 case Token::SHL: { 1355 case Token::SHL: {
1368 if (reversed) { 1356 if (reversed) {
1369 Result constant_operand(value); 1357 Result constant_operand(value);
1370 LikelySmiBinaryOperation(op, &constant_operand, operand, 1358 LikelySmiBinaryOperation(op, &constant_operand, operand,
1371 overwrite_mode); 1359 overwrite_mode);
1372 } else { 1360 } else {
1373 // Only the least significant 5 bits of the shift value are used. 1361 // Only the least significant 5 bits of the shift value are used.
1374 // In the slow case, this masking is done inside the runtime call. 1362 // In the slow case, this masking is done inside the runtime call.
1375 int shift_value = int_value & 0x1f; 1363 int shift_value = int_value & 0x1f;
1376 DeferredCode* deferred = 1364 DeferredCode* deferred =
1377 new DeferredInlineSmiOperation(this, Token::SHL, smi_value, 1365 new DeferredInlineSmiOperation(op, smi_value, overwrite_mode);
1378 overwrite_mode);
1379 operand->ToRegister(); 1366 operand->ToRegister();
1380 __ test(operand->reg(), Immediate(kSmiTagMask)); 1367 __ test(operand->reg(), Immediate(kSmiTagMask));
1381 deferred->enter()->Branch(not_zero, operand, not_taken); 1368 deferred->enter()->Branch(not_zero, operand, not_taken);
1382 if (shift_value != 0) { 1369 if (shift_value != 0) {
1383 Result answer = allocator()->Allocate(); 1370 Result answer = allocator()->Allocate();
1384 ASSERT(answer.is_valid()); 1371 ASSERT(answer.is_valid());
1385 __ mov(answer.reg(), operand->reg()); 1372 __ mov(answer.reg(), operand->reg());
1386 ASSERT(kSmiTag == 0); // adjust code if not the case 1373 ASSERT(kSmiTag == 0); // adjust code if not the case
1387 // We do no shifts, only the Smi conversion, if shift_value is 1. 1374 // We do no shifts, only the Smi conversion, if shift_value is 1.
1388 if (shift_value > 1) { 1375 if (shift_value > 1) {
(...skipping 12 matching lines...) Expand all
1401 } 1388 }
1402 } 1389 }
1403 break; 1390 break;
1404 } 1391 }
1405 1392
1406 case Token::BIT_OR: 1393 case Token::BIT_OR:
1407 case Token::BIT_XOR: 1394 case Token::BIT_XOR:
1408 case Token::BIT_AND: { 1395 case Token::BIT_AND: {
1409 DeferredCode* deferred = NULL; 1396 DeferredCode* deferred = NULL;
1410 if (reversed) { 1397 if (reversed) {
1411 deferred = new DeferredInlineSmiOperationReversed(this, op, smi_value, 1398 deferred = new DeferredInlineSmiOperationReversed(op, smi_value,
1412 overwrite_mode); 1399 overwrite_mode);
1413 } else { 1400 } else {
1414 deferred = new DeferredInlineSmiOperation(this, op, smi_value, 1401 deferred = new DeferredInlineSmiOperation(op, smi_value,
1415 overwrite_mode); 1402 overwrite_mode);
1416 } 1403 }
1417 operand->ToRegister(); 1404 operand->ToRegister();
1418 __ test(operand->reg(), Immediate(kSmiTagMask)); 1405 __ test(operand->reg(), Immediate(kSmiTagMask));
1419 deferred->enter()->Branch(not_zero, operand, not_taken); 1406 deferred->enter()->Branch(not_zero, operand, not_taken);
1420 frame_->Spill(operand->reg()); 1407 frame_->Spill(operand->reg());
1421 if (op == Token::BIT_AND) { 1408 if (op == Token::BIT_AND) {
1422 __ and_(Operand(operand->reg()), Immediate(value)); 1409 __ and_(Operand(operand->reg()), Immediate(value));
1423 } else if (op == Token::BIT_XOR) { 1410 } else if (op == Token::BIT_XOR) {
1424 if (int_value != 0) { 1411 if (int_value != 0) {
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
1690 Result answer = frame_->CallStub(&call_function, arg_count + 1); 1677 Result answer = frame_->CallStub(&call_function, arg_count + 1);
1691 // Restore context and replace function on the stack with the 1678 // Restore context and replace function on the stack with the
1692 // result of the stub invocation. 1679 // result of the stub invocation.
1693 frame_->RestoreContextRegister(); 1680 frame_->RestoreContextRegister();
1694 frame_->SetElementAt(0, &answer); 1681 frame_->SetElementAt(0, &answer);
1695 } 1682 }
1696 1683
1697 1684
1698 class DeferredStackCheck: public DeferredCode { 1685 class DeferredStackCheck: public DeferredCode {
1699 public: 1686 public:
1700 explicit DeferredStackCheck(CodeGenerator* generator) 1687 explicit DeferredStackCheck() {
1701 : DeferredCode(generator) {
1702 set_comment("[ DeferredStackCheck"); 1688 set_comment("[ DeferredStackCheck");
1703 } 1689 }
1704 1690
1705 virtual void Generate(); 1691 virtual void Generate();
1706 }; 1692 };
1707 1693
1708 1694
1709 void DeferredStackCheck::Generate() { 1695 void DeferredStackCheck::Generate() {
1710 enter()->Bind(); 1696 enter()->Bind();
1711 StackCheckStub stub; 1697 StackCheckStub stub;
1712 Result ignored = generator()->frame()->CallStub(&stub, 0); 1698 Result ignored = cgen()->frame()->CallStub(&stub, 0);
1713 ignored.Unuse(); 1699 ignored.Unuse();
1714 exit_.Jump(); 1700 exit_.Jump();
1715 } 1701 }
1716 1702
1717 1703
1718 void CodeGenerator::CheckStack() { 1704 void CodeGenerator::CheckStack() {
1719 if (FLAG_check_stack) { 1705 if (FLAG_check_stack) {
1720 DeferredStackCheck* deferred = new DeferredStackCheck(this); 1706 DeferredStackCheck* deferred = new DeferredStackCheck;
1721 ExternalReference stack_guard_limit = 1707 ExternalReference stack_guard_limit =
1722 ExternalReference::address_of_stack_guard_limit(); 1708 ExternalReference::address_of_stack_guard_limit();
1723 __ cmp(esp, Operand::StaticVariable(stack_guard_limit)); 1709 __ cmp(esp, Operand::StaticVariable(stack_guard_limit));
1724 deferred->enter()->Branch(below, not_taken); 1710 deferred->enter()->Branch(below, not_taken);
1725 deferred->BindExit(); 1711 deferred->BindExit();
1726 } 1712 }
1727 } 1713 }
1728 1714
1729 1715
1730 void CodeGenerator::VisitAndSpill(Statement* statement) { 1716 void CodeGenerator::VisitAndSpill(Statement* statement) {
(...skipping 1837 matching lines...) Expand 10 before | Expand all | Expand 10 after
3568 3554
3569 bool CodeGenerator::IsUnsafeSmi(Handle<Object> value) { 3555 bool CodeGenerator::IsUnsafeSmi(Handle<Object> value) {
3570 if (!value->IsSmi()) return false; 3556 if (!value->IsSmi()) return false;
3571 int int_value = Smi::cast(*value)->value(); 3557 int int_value = Smi::cast(*value)->value();
3572 return !is_intn(int_value, kMaxSmiInlinedBits); 3558 return !is_intn(int_value, kMaxSmiInlinedBits);
3573 } 3559 }
3574 3560
3575 3561
3576 class DeferredRegExpLiteral: public DeferredCode { 3562 class DeferredRegExpLiteral: public DeferredCode {
3577 public: 3563 public:
3578 DeferredRegExpLiteral(CodeGenerator* generator, RegExpLiteral* node) 3564 DeferredRegExpLiteral(RegExpLiteral* node) : node_(node) {
3579 : DeferredCode(generator), node_(node) {
3580 set_comment("[ DeferredRegExpLiteral"); 3565 set_comment("[ DeferredRegExpLiteral");
3581 } 3566 }
3582 3567
3583 virtual void Generate(); 3568 virtual void Generate();
3584 3569
3585 private: 3570 private:
3586 RegExpLiteral* node_; 3571 RegExpLiteral* node_;
3587 }; 3572 };
3588 3573
3589 3574
3590 void DeferredRegExpLiteral::Generate() { 3575 void DeferredRegExpLiteral::Generate() {
3591 Result literals; 3576 Result literals;
3592 enter()->Bind(&literals); 3577 enter()->Bind(&literals);
3593 // Since the entry is undefined we call the runtime system to 3578 // Since the entry is undefined we call the runtime system to
3594 // compute the literal. 3579 // compute the literal.
3595 3580
3596 VirtualFrame* frame = generator()->frame(); 3581 VirtualFrame* frame = cgen()->frame();
3597 // Literal array (0). 3582 // Literal array (0).
3598 frame->Push(&literals); 3583 frame->Push(&literals);
3599 // Literal index (1). 3584 // Literal index (1).
3600 frame->Push(Smi::FromInt(node_->literal_index())); 3585 frame->Push(Smi::FromInt(node_->literal_index()));
3601 // RegExp pattern (2). 3586 // RegExp pattern (2).
3602 frame->Push(node_->pattern()); 3587 frame->Push(node_->pattern());
3603 // RegExp flags (3). 3588 // RegExp flags (3).
3604 frame->Push(node_->flags()); 3589 frame->Push(node_->flags());
3605 Result boilerplate = 3590 Result boilerplate =
3606 frame->CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); 3591 frame->CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
3607 exit_.Jump(&boilerplate); 3592 exit_.Jump(&boilerplate);
3608 } 3593 }
3609 3594
3610 3595
3611 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) { 3596 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) {
3612 Comment cmnt(masm_, "[ RegExp Literal"); 3597 Comment cmnt(masm_, "[ RegExp Literal");
3613 DeferredRegExpLiteral* deferred = new DeferredRegExpLiteral(this, node); 3598 DeferredRegExpLiteral* deferred = new DeferredRegExpLiteral(node);
3614 3599
3615 // Retrieve the literals array and check the allocated entry. Begin 3600 // Retrieve the literals array and check the allocated entry. Begin
3616 // with a writable copy of the function of this activation in a 3601 // with a writable copy of the function of this activation in a
3617 // register. 3602 // register.
3618 frame_->PushFunction(); 3603 frame_->PushFunction();
3619 Result literals = frame_->Pop(); 3604 Result literals = frame_->Pop();
3620 literals.ToRegister(); 3605 literals.ToRegister();
3621 frame_->Spill(literals.reg()); 3606 frame_->Spill(literals.reg());
3622 3607
3623 // Load the literals array of the function. 3608 // Load the literals array of the function.
(...skipping 20 matching lines...) Expand all
3644 frame_->Push(&boilerplate); 3629 frame_->Push(&boilerplate);
3645 } 3630 }
3646 3631
3647 3632
3648 // This deferred code stub will be used for creating the boilerplate 3633 // This deferred code stub will be used for creating the boilerplate
3649 // by calling Runtime_CreateObjectLiteral. 3634 // by calling Runtime_CreateObjectLiteral.
3650 // Each created boilerplate is stored in the JSFunction and they are 3635 // Each created boilerplate is stored in the JSFunction and they are
3651 // therefore context dependent. 3636 // therefore context dependent.
3652 class DeferredObjectLiteral: public DeferredCode { 3637 class DeferredObjectLiteral: public DeferredCode {
3653 public: 3638 public:
3654 DeferredObjectLiteral(CodeGenerator* generator, 3639 DeferredObjectLiteral(ObjectLiteral* node) : node_(node) {
3655 ObjectLiteral* node)
3656 : DeferredCode(generator), node_(node) {
3657 set_comment("[ DeferredObjectLiteral"); 3640 set_comment("[ DeferredObjectLiteral");
3658 } 3641 }
3659 3642
3660 virtual void Generate(); 3643 virtual void Generate();
3661 3644
3662 private: 3645 private:
3663 ObjectLiteral* node_; 3646 ObjectLiteral* node_;
3664 }; 3647 };
3665 3648
3666 3649
3667 void DeferredObjectLiteral::Generate() { 3650 void DeferredObjectLiteral::Generate() {
3668 Result literals; 3651 Result literals;
3669 enter()->Bind(&literals); 3652 enter()->Bind(&literals);
3670 // Since the entry is undefined we call the runtime system to 3653 // Since the entry is undefined we call the runtime system to
3671 // compute the literal. 3654 // compute the literal.
3672 3655
3673 VirtualFrame* frame = generator()->frame(); 3656 VirtualFrame* frame = cgen()->frame();
3674 // Literal array (0). 3657 // Literal array (0).
3675 frame->Push(&literals); 3658 frame->Push(&literals);
3676 // Literal index (1). 3659 // Literal index (1).
3677 frame->Push(Smi::FromInt(node_->literal_index())); 3660 frame->Push(Smi::FromInt(node_->literal_index()));
3678 // Constant properties (2). 3661 // Constant properties (2).
3679 frame->Push(node_->constant_properties()); 3662 frame->Push(node_->constant_properties());
3680 Result boilerplate = 3663 Result boilerplate =
3681 frame->CallRuntime(Runtime::kCreateObjectLiteralBoilerplate, 3); 3664 frame->CallRuntime(Runtime::kCreateObjectLiteralBoilerplate, 3);
3682 exit_.Jump(&boilerplate); 3665 exit_.Jump(&boilerplate);
3683 } 3666 }
3684 3667
3685 3668
3686 void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { 3669 void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
3687 Comment cmnt(masm_, "[ ObjectLiteral"); 3670 Comment cmnt(masm_, "[ ObjectLiteral");
3688 DeferredObjectLiteral* deferred = new DeferredObjectLiteral(this, node); 3671 DeferredObjectLiteral* deferred = new DeferredObjectLiteral(node);
3689 3672
3690 // Retrieve the literals array and check the allocated entry. Begin 3673 // Retrieve the literals array and check the allocated entry. Begin
3691 // with a writable copy of the function of this activation in a 3674 // with a writable copy of the function of this activation in a
3692 // register. 3675 // register.
3693 frame_->PushFunction(); 3676 frame_->PushFunction();
3694 Result literals = frame_->Pop(); 3677 Result literals = frame_->Pop();
3695 literals.ToRegister(); 3678 literals.ToRegister();
3696 frame_->Spill(literals.reg()); 3679 frame_->Spill(literals.reg());
3697 3680
3698 // Load the literals array of the function. 3681 // Load the literals array of the function.
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
3782 } 3765 }
3783 } 3766 }
3784 3767
3785 3768
3786 // This deferred code stub will be used for creating the boilerplate 3769 // This deferred code stub will be used for creating the boilerplate
3787 // by calling Runtime_CreateArrayLiteralBoilerplate. 3770 // by calling Runtime_CreateArrayLiteralBoilerplate.
3788 // Each created boilerplate is stored in the JSFunction and they are 3771 // Each created boilerplate is stored in the JSFunction and they are
3789 // therefore context dependent. 3772 // therefore context dependent.
3790 class DeferredArrayLiteral: public DeferredCode { 3773 class DeferredArrayLiteral: public DeferredCode {
3791 public: 3774 public:
3792 DeferredArrayLiteral(CodeGenerator* generator, 3775 DeferredArrayLiteral(ArrayLiteral* node) : node_(node) {
3793 ArrayLiteral* node)
3794 : DeferredCode(generator), node_(node) {
3795 set_comment("[ DeferredArrayLiteral"); 3776 set_comment("[ DeferredArrayLiteral");
3796 } 3777 }
3797 3778
3798 virtual void Generate(); 3779 virtual void Generate();
3799 3780
3800 private: 3781 private:
3801 ArrayLiteral* node_; 3782 ArrayLiteral* node_;
3802 }; 3783 };
3803 3784
3804 3785
3805 void DeferredArrayLiteral::Generate() { 3786 void DeferredArrayLiteral::Generate() {
3806 Result literals; 3787 Result literals;
3807 enter()->Bind(&literals); 3788 enter()->Bind(&literals);
3808 // Since the entry is undefined we call the runtime system to 3789 // Since the entry is undefined we call the runtime system to
3809 // compute the literal. 3790 // compute the literal.
3810 3791
3811 VirtualFrame* frame = generator()->frame(); 3792 VirtualFrame* frame = cgen()->frame();
3812 // Literal array (0). 3793 // Literal array (0).
3813 frame->Push(&literals); 3794 frame->Push(&literals);
3814 // Literal index (1). 3795 // Literal index (1).
3815 frame->Push(Smi::FromInt(node_->literal_index())); 3796 frame->Push(Smi::FromInt(node_->literal_index()));
3816 // Constant properties (2). 3797 // Constant properties (2).
3817 frame->Push(node_->literals()); 3798 frame->Push(node_->literals());
3818 Result boilerplate = 3799 Result boilerplate =
3819 frame->CallRuntime(Runtime::kCreateArrayLiteralBoilerplate, 3); 3800 frame->CallRuntime(Runtime::kCreateArrayLiteralBoilerplate, 3);
3820 exit_.Jump(&boilerplate); 3801 exit_.Jump(&boilerplate);
3821 } 3802 }
3822 3803
3823 3804
3824 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { 3805 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) {
3825 Comment cmnt(masm_, "[ ArrayLiteral"); 3806 Comment cmnt(masm_, "[ ArrayLiteral");
3826 DeferredArrayLiteral* deferred = new DeferredArrayLiteral(this, node); 3807 DeferredArrayLiteral* deferred = new DeferredArrayLiteral(node);
3827 3808
3828 // Retrieve the literals array and check the allocated entry. Begin 3809 // Retrieve the literals array and check the allocated entry. Begin
3829 // with a writable copy of the function of this activation in a 3810 // with a writable copy of the function of this activation in a
3830 // register. 3811 // register.
3831 frame_->PushFunction(); 3812 frame_->PushFunction();
3832 Result literals = frame_->Pop(); 3813 Result literals = frame_->Pop();
3833 literals.ToRegister(); 3814 literals.ToRegister();
3834 frame_->Spill(literals.reg()); 3815 frame_->Spill(literals.reg());
3835 3816
3836 // Load the literals array of the function. 3817 // Load the literals array of the function.
(...skipping 934 matching lines...) Expand 10 before | Expand all | Expand 10 after
4771 4752
4772 default: 4753 default:
4773 UNREACHABLE(); 4754 UNREACHABLE();
4774 } 4755 }
4775 } 4756 }
4776 } 4757 }
4777 4758
4778 4759
4779 class DeferredCountOperation: public DeferredCode { 4760 class DeferredCountOperation: public DeferredCode {
4780 public: 4761 public:
4781 DeferredCountOperation(CodeGenerator* generator, 4762 DeferredCountOperation(bool is_postfix,
4782 bool is_postfix,
4783 bool is_increment, 4763 bool is_increment,
4784 int target_size) 4764 int target_size)
4785 : DeferredCode(generator), 4765 : is_postfix_(is_postfix),
4786 is_postfix_(is_postfix),
4787 is_increment_(is_increment), 4766 is_increment_(is_increment),
4788 target_size_(target_size) { 4767 target_size_(target_size) {
4789 set_comment("[ DeferredCountOperation"); 4768 set_comment("[ DeferredCountOperation");
4790 } 4769 }
4791 4770
4792 virtual void Generate(); 4771 virtual void Generate();
4793 4772
4794 private: 4773 private:
4795 bool is_postfix_; 4774 bool is_postfix_;
4796 bool is_increment_; 4775 bool is_increment_;
4797 int target_size_; 4776 int target_size_;
4798 }; 4777 };
4799 4778
4800 4779
4780 #undef __
4781 #define __ ACCESS_MASM(cgen()->masm())
4782
4783
4801 void DeferredCountOperation::Generate() { 4784 void DeferredCountOperation::Generate() {
4802 CodeGenerator* cgen = generator();
4803 Result value; 4785 Result value;
4804 enter()->Bind(&value); 4786 enter()->Bind(&value);
4805 VirtualFrame* frame = cgen->frame(); 4787 VirtualFrame* frame = cgen()->frame();
4806 // Undo the optimistic smi operation. 4788 // Undo the optimistic smi operation.
4807 value.ToRegister(); 4789 value.ToRegister();
4808 frame->Spill(value.reg()); 4790 frame->Spill(value.reg());
4809 if (is_increment_) { 4791 if (is_increment_) {
4810 __ sub(Operand(value.reg()), Immediate(Smi::FromInt(1))); 4792 __ sub(Operand(value.reg()), Immediate(Smi::FromInt(1)));
4811 } else { 4793 } else {
4812 __ add(Operand(value.reg()), Immediate(Smi::FromInt(1))); 4794 __ add(Operand(value.reg()), Immediate(Smi::FromInt(1)));
4813 } 4795 }
4814 frame->Push(&value); 4796 frame->Push(&value);
4815 value = frame->InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION, 1); 4797 value = frame->InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION, 1);
4816 frame->Push(&value); 4798 frame->Push(&value);
4817 if (is_postfix_) { // Fix up copy of old value with ToNumber(value). 4799 if (is_postfix_) { // Fix up copy of old value with ToNumber(value).
4818 // This is only safe because VisitCountOperation makes this frame slot 4800 // This is only safe because VisitCountOperation makes this frame slot
4819 // beneath the reference a register, which is spilled at the above call. 4801 // beneath the reference a register, which is spilled at the above call.
4820 // We cannot safely write to constants or copies below the water line. 4802 // We cannot safely write to constants or copies below the water line.
4821 frame->StoreToElementAt(target_size_ + 1); 4803 frame->StoreToElementAt(target_size_ + 1);
4822 } 4804 }
4823 frame->Push(Smi::FromInt(1)); 4805 frame->Push(Smi::FromInt(1));
4824 if (is_increment_) { 4806 if (is_increment_) {
4825 value = frame->CallRuntime(Runtime::kNumberAdd, 2); 4807 value = frame->CallRuntime(Runtime::kNumberAdd, 2);
4826 } else { 4808 } else {
4827 value = frame->CallRuntime(Runtime::kNumberSub, 2); 4809 value = frame->CallRuntime(Runtime::kNumberSub, 2);
4828 } 4810 }
4829 exit_.Jump(&value); 4811 exit_.Jump(&value);
4830 } 4812 }
4831 4813
4832 4814
4815 #undef __
4816 #define __ ACCESS_MASM(masm_)
4817
4818
4833 void CodeGenerator::VisitCountOperation(CountOperation* node) { 4819 void CodeGenerator::VisitCountOperation(CountOperation* node) {
4834 Comment cmnt(masm_, "[ CountOperation"); 4820 Comment cmnt(masm_, "[ CountOperation");
4835 4821
4836 bool is_postfix = node->is_postfix(); 4822 bool is_postfix = node->is_postfix();
4837 bool is_increment = node->op() == Token::INC; 4823 bool is_increment = node->op() == Token::INC;
4838 4824
4839 Variable* var = node->expression()->AsVariableProxy()->AsVariable(); 4825 Variable* var = node->expression()->AsVariableProxy()->AsVariable();
4840 bool is_const = (var != NULL && var->mode() == Variable::CONST); 4826 bool is_const = (var != NULL && var->mode() == Variable::CONST);
4841 4827
4842 // Postfix operators need a stack slot under the reference to hold 4828 // Postfix operators need a stack slot under the reference to hold
4843 // the old value while the new one is being stored. 4829 // the old value while the new one is being stored.
4844 if (is_postfix) { 4830 if (is_postfix) {
4845 frame_->Push(Smi::FromInt(0)); 4831 frame_->Push(Smi::FromInt(0));
4846 } 4832 }
4847 4833
4848 { Reference target(this, node->expression()); 4834 { Reference target(this, node->expression());
4849 if (target.is_illegal()) { 4835 if (target.is_illegal()) {
4850 // Spoof the virtual frame to have the expected height (one higher 4836 // Spoof the virtual frame to have the expected height (one higher
4851 // than on entry). 4837 // than on entry).
4852 if (!is_postfix) { 4838 if (!is_postfix) {
4853 frame_->Push(Smi::FromInt(0)); 4839 frame_->Push(Smi::FromInt(0));
4854 } 4840 }
4855 return; 4841 return;
4856 } 4842 }
4857 target.TakeValue(NOT_INSIDE_TYPEOF); 4843 target.TakeValue(NOT_INSIDE_TYPEOF);
4858 4844
4859 DeferredCountOperation* deferred = 4845 DeferredCountOperation* deferred =
4860 new DeferredCountOperation(this, is_postfix, 4846 new DeferredCountOperation(is_postfix, is_increment, target.size());
4861 is_increment, target.size());
4862 4847
4863 Result value = frame_->Pop(); 4848 Result value = frame_->Pop();
4864 value.ToRegister(); 4849 value.ToRegister();
4865 4850
4866 // Postfix: Store the old value as the result. 4851 // Postfix: Store the old value as the result.
4867 if (is_postfix) { 4852 if (is_postfix) {
4868 // Explicitly back the slot for the old value with a new register. 4853 // Explicitly back the slot for the old value with a new register.
4869 // This improves performance in some cases. 4854 // This improves performance in some cases.
4870 Result old_value = allocator_->Allocate(); 4855 Result old_value = allocator_->Allocate();
4871 ASSERT(old_value.is_valid()); 4856 ASSERT(old_value.is_valid());
(...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after
5275 && (allocator()->count(ebx) == (frame()->is_used(ebx) ? 1 : 0)) 5260 && (allocator()->count(ebx) == (frame()->is_used(ebx) ? 1 : 0))
5276 && (allocator()->count(ecx) == (frame()->is_used(ecx) ? 1 : 0)) 5261 && (allocator()->count(ecx) == (frame()->is_used(ecx) ? 1 : 0))
5277 && (allocator()->count(edx) == (frame()->is_used(edx) ? 1 : 0)) 5262 && (allocator()->count(edx) == (frame()->is_used(edx) ? 1 : 0))
5278 && (allocator()->count(edi) == (frame()->is_used(edi) ? 1 : 0)); 5263 && (allocator()->count(edi) == (frame()->is_used(edi) ? 1 : 0));
5279 } 5264 }
5280 #endif 5265 #endif
5281 5266
5282 5267
5283 class DeferredReferenceGetNamedValue: public DeferredCode { 5268 class DeferredReferenceGetNamedValue: public DeferredCode {
5284 public: 5269 public:
5285 DeferredReferenceGetNamedValue(CodeGenerator* cgen, Handle<String> name) 5270 DeferredReferenceGetNamedValue(Handle<String> name) : name_(name) {
5286 : DeferredCode(cgen), name_(name) {
5287 set_comment("[ DeferredReferenceGetNamedValue"); 5271 set_comment("[ DeferredReferenceGetNamedValue");
5288 } 5272 }
5289 5273
5290 virtual void Generate(); 5274 virtual void Generate();
5291 5275
5292 Label* patch_site() { return &patch_site_; } 5276 Label* patch_site() { return &patch_site_; }
5293 5277
5294 private: 5278 private:
5295 Label patch_site_; 5279 Label patch_site_;
5296 Handle<String> name_; 5280 Handle<String> name_;
5297 }; 5281 };
5298 5282
5299 5283
5300 void DeferredReferenceGetNamedValue::Generate() {
5301 CodeGenerator* cgen = generator();
5302 Result receiver;
5303 enter()->Bind(&receiver);
5304
5305 cgen->frame()->Push(&receiver);
5306 cgen->frame()->Push(name_);
5307 Result answer = cgen->frame()->CallLoadIC(RelocInfo::CODE_TARGET);
5308 // The call must be followed by a test eax instruction to indicate
5309 // that the inobject property case was inlined.
5310 ASSERT(answer.is_register() && answer.reg().is(eax));
5311 // Store the delta to the map check instruction here in the test instruction.
5312 // Use masm_-> instead of the double underscore macro since the latter can't
5313 // return a value.
5314 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site());
5315 // Here we use masm_-> instead of the double underscore macro because
5316 // this is the instruction that gets patched and coverage code gets in
5317 // the way.
5318 masm_->test(answer.reg(), Immediate(-delta_to_patch_site));
5319 __ IncrementCounter(&Counters::named_load_inline_miss, 1);
5320 receiver = cgen->frame()->Pop();
5321 exit_.Jump(&receiver, &answer);
5322 }
5323
5324
5325 class DeferredReferenceGetKeyedValue: public DeferredCode { 5284 class DeferredReferenceGetKeyedValue: public DeferredCode {
5326 public: 5285 public:
5327 DeferredReferenceGetKeyedValue(CodeGenerator* generator, bool is_global) 5286 DeferredReferenceGetKeyedValue(bool is_global) : is_global_(is_global) {
5328 : DeferredCode(generator), is_global_(is_global) {
5329 set_comment("[ DeferredReferenceGetKeyedValue"); 5287 set_comment("[ DeferredReferenceGetKeyedValue");
5330 } 5288 }
5331 5289
5332 virtual void Generate(); 5290 virtual void Generate();
5333 5291
5334 Label* patch_site() { return &patch_site_; } 5292 Label* patch_site() { return &patch_site_; }
5335 5293
5336 private: 5294 private:
5337 Label patch_site_; 5295 Label patch_site_;
5338 bool is_global_; 5296 bool is_global_;
5339 }; 5297 };
5340 5298
5341 5299
5300 #undef __
5301 #define __ ACCESS_MASM(cgen()->masm())
5302
5303
5304 void DeferredReferenceGetNamedValue::Generate() {
5305 Result receiver;
5306 enter()->Bind(&receiver);
5307
5308 cgen()->frame()->Push(&receiver);
5309 cgen()->frame()->Push(name_);
5310 Result answer = cgen()->frame()->CallLoadIC(RelocInfo::CODE_TARGET);
5311 // The call must be followed by a test eax instruction to indicate
5312 // that the inobject property case was inlined.
5313 ASSERT(answer.is_register() && answer.reg().is(eax));
5314 // Store the delta to the map check instruction here in the test
5315 // instruction. Use cgen()->masm()-> instead of the __ macro since
5316 // the latter can't return a value.
5317 int delta_to_patch_site =
5318 cgen()->masm()->SizeOfCodeGeneratedSince(patch_site());
5319 // Here we use cgen()->masm()-> instead of the __ macro because this
5320 // is the instruction that gets patched and coverage code gets in the
5321 // way.
5322 cgen()->masm()->test(answer.reg(), Immediate(-delta_to_patch_site));
5323 __ IncrementCounter(&Counters::named_load_inline_miss, 1);
5324 receiver = cgen()->frame()->Pop();
5325 exit_.Jump(&receiver, &answer);
5326 }
5327
5328
5342 void DeferredReferenceGetKeyedValue::Generate() { 5329 void DeferredReferenceGetKeyedValue::Generate() {
5343 CodeGenerator* cgen = generator();
5344 Result receiver; 5330 Result receiver;
5345 Result key; 5331 Result key;
5346 enter()->Bind(&receiver, &key); 5332 enter()->Bind(&receiver, &key);
5347 cgen->frame()->Push(&receiver); // First IC argument. 5333 cgen()->frame()->Push(&receiver); // First IC argument.
5348 cgen->frame()->Push(&key); // Second IC argument. 5334 cgen()->frame()->Push(&key); // Second IC argument.
5349 5335
5350 // Calculate the delta from the IC call instruction to the map check 5336 // Calculate the delta from the IC call instruction to the map check
5351 // cmp instruction in the inlined version. This delta is stored in 5337 // cmp instruction in the inlined version. This delta is stored in
5352 // a test(eax, delta) instruction after the call so that we can find 5338 // a test(eax, delta) instruction after the call so that we can find
5353 // it in the IC initialization code and patch the cmp instruction. 5339 // it in the IC initialization code and patch the cmp instruction.
5354 // This means that we cannot allow test instructions after calls to 5340 // This means that we cannot allow test instructions after calls to
5355 // KeyedLoadIC stubs in other places. 5341 // KeyedLoadIC stubs in other places.
5356 RelocInfo::Mode mode = is_global_ 5342 RelocInfo::Mode mode = is_global_
5357 ? RelocInfo::CODE_TARGET_CONTEXT 5343 ? RelocInfo::CODE_TARGET_CONTEXT
5358 : RelocInfo::CODE_TARGET; 5344 : RelocInfo::CODE_TARGET;
5359 Result value = cgen->frame()->CallKeyedLoadIC(mode); 5345 Result value = cgen()->frame()->CallKeyedLoadIC(mode);
5360 // The result needs to be specifically the eax register because the 5346 // The result needs to be specifically the eax register because the
5361 // offset to the patch site will be expected in a test eax 5347 // offset to the patch site will be expected in a test eax
5362 // instruction. 5348 // instruction.
5363 ASSERT(value.is_register() && value.reg().is(eax)); 5349 ASSERT(value.is_register() && value.reg().is(eax));
5364 // The delta from the start of the map-compare instruction to the 5350 // The delta from the start of the map-compare instruction to the test
5365 // test instruction. We use masm_ directly here instead of the 5351 // instruction. We use cgen()->masm() directly here instead of the __
5366 // double underscore macro because the macro sometimes uses macro 5352 // macro because the macro sometimes uses macro expansion to turn into
5367 // expansion to turn into something that can't return a value. This 5353 // something that can't return a value. This is encountered when
5368 // is encountered when doing generated code coverage tests. 5354 // doing generated code coverage tests.
5369 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site()); 5355 int delta_to_patch_site =
5370 // Here we use masm_-> instead of the double underscore macro because this 5356 cgen()->masm()->SizeOfCodeGeneratedSince(patch_site());
5371 // is the instruction that gets patched and coverage code gets in the way. 5357 // Here we use cgen()->masm()-> instead of the __ macro because this
5372 masm_->test(value.reg(), Immediate(-delta_to_patch_site)); 5358 // is the instruction that gets patched and coverage code gets in the
5359 // way.
5360 cgen()->masm()->test(value.reg(), Immediate(-delta_to_patch_site));
5373 __ IncrementCounter(&Counters::keyed_load_inline_miss, 1); 5361 __ IncrementCounter(&Counters::keyed_load_inline_miss, 1);
5374 5362
5375 // The receiver and key were spilled by the call, so their state as 5363 // The receiver and key were spilled by the call, so their state as
5376 // constants or copies has been changed. Thus, they need to be 5364 // constants or copies has been changed. Thus, they need to be
5377 // "mergable" in the block at the exit label and are therefore 5365 // "mergable" in the block at the exit label and are therefore
5378 // passed as return results here. 5366 // passed as return results here.
5379 key = cgen->frame()->Pop(); 5367 key = cgen()->frame()->Pop();
5380 receiver = cgen->frame()->Pop(); 5368 receiver = cgen()->frame()->Pop();
5381 exit_.Jump(&receiver, &key, &value); 5369 exit_.Jump(&receiver, &key, &value);
5382 } 5370 }
5383 5371
5384 5372
5385 #undef __ 5373 #undef __
5386 #define __ ACCESS_MASM(masm) 5374 #define __ ACCESS_MASM(masm)
5387 5375
5388 Handle<String> Reference::GetName() { 5376 Handle<String> Reference::GetName() {
5389 ASSERT(type_ == NAMED); 5377 ASSERT(type_ == NAMED);
5390 Property* property = expression_->AsProperty(); 5378 Property* property = expression_->AsProperty();
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
5443 Result answer = cgen_->frame()->CallLoadIC(mode); 5431 Result answer = cgen_->frame()->CallLoadIC(mode);
5444 // A test eax instruction following the call signals that the 5432 // A test eax instruction following the call signals that the
5445 // inobject property case was inlined. Ensure that there is not 5433 // inobject property case was inlined. Ensure that there is not
5446 // a test eax instruction here. 5434 // a test eax instruction here.
5447 __ nop(); 5435 __ nop();
5448 cgen_->frame()->Push(&answer); 5436 cgen_->frame()->Push(&answer);
5449 } else { 5437 } else {
5450 // Inline the inobject property case. 5438 // Inline the inobject property case.
5451 Comment cmnt(masm, "[ Inlined named property load"); 5439 Comment cmnt(masm, "[ Inlined named property load");
5452 DeferredReferenceGetNamedValue* deferred = 5440 DeferredReferenceGetNamedValue* deferred =
5453 new DeferredReferenceGetNamedValue(cgen_, GetName()); 5441 new DeferredReferenceGetNamedValue(GetName());
5454 Result receiver = cgen_->frame()->Pop(); 5442 Result receiver = cgen_->frame()->Pop();
5455 receiver.ToRegister(); 5443 receiver.ToRegister();
5456 5444
5457 // Try to preallocate the value register so that all frames 5445 // Try to preallocate the value register so that all frames
5458 // reaching the deferred code are identical. 5446 // reaching the deferred code are identical.
5459 Result value = cgen_->allocator()->AllocateWithoutSpilling(); 5447 Result value = cgen_->allocator()->AllocateWithoutSpilling();
5460 if (value.is_valid()) { 5448 if (value.is_valid()) {
5461 deferred->SetEntryFrame(&receiver); 5449 deferred->SetEntryFrame(&receiver);
5462 } 5450 }
5463 5451
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
5508 Variable* var = expression_->AsVariableProxy()->AsVariable(); 5496 Variable* var = expression_->AsVariableProxy()->AsVariable();
5509 bool is_global = var != NULL; 5497 bool is_global = var != NULL;
5510 ASSERT(!is_global || var->is_global()); 5498 ASSERT(!is_global || var->is_global());
5511 // Inline array load code if inside of a loop. We do not know 5499 // Inline array load code if inside of a loop. We do not know
5512 // the receiver map yet, so we initially generate the code with 5500 // the receiver map yet, so we initially generate the code with
5513 // a check against an invalid map. In the inline cache code, we 5501 // a check against an invalid map. In the inline cache code, we
5514 // patch the map check if appropriate. 5502 // patch the map check if appropriate.
5515 if (cgen_->loop_nesting() > 0) { 5503 if (cgen_->loop_nesting() > 0) {
5516 Comment cmnt(masm, "[ Inlined array index load"); 5504 Comment cmnt(masm, "[ Inlined array index load");
5517 DeferredReferenceGetKeyedValue* deferred = 5505 DeferredReferenceGetKeyedValue* deferred =
5518 new DeferredReferenceGetKeyedValue(cgen_, is_global); 5506 new DeferredReferenceGetKeyedValue(is_global);
5519 5507
5520 Result key = cgen_->frame()->Pop(); 5508 Result key = cgen_->frame()->Pop();
5521 Result receiver = cgen_->frame()->Pop(); 5509 Result receiver = cgen_->frame()->Pop();
5522 key.ToRegister(); 5510 key.ToRegister();
5523 receiver.ToRegister(); 5511 receiver.ToRegister();
5524 5512
5525 // Try to preallocate the elements and index scratch registers 5513 // Try to preallocate the elements and index scratch registers
5526 // so that all frames reaching the deferred code are identical. 5514 // so that all frames reaching the deferred code are identical.
5527 Result elements = cgen_->allocator()->AllocateWithoutSpilling(); 5515 Result elements = cgen_->allocator()->AllocateWithoutSpilling();
5528 Result index = cgen_->allocator()->AllocateWithoutSpilling(); 5516 Result index = cgen_->allocator()->AllocateWithoutSpilling();
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
5736 // Return 1/0 for true/false in eax. 5724 // Return 1/0 for true/false in eax.
5737 __ bind(&true_result); 5725 __ bind(&true_result);
5738 __ mov(eax, 1); 5726 __ mov(eax, 1);
5739 __ ret(1 * kPointerSize); 5727 __ ret(1 * kPointerSize);
5740 __ bind(&false_result); 5728 __ bind(&false_result);
5741 __ mov(eax, 0); 5729 __ mov(eax, 0);
5742 __ ret(1 * kPointerSize); 5730 __ ret(1 * kPointerSize);
5743 } 5731 }
5744 5732
5745 5733
5746 #undef __
5747 #define __ ACCESS_MASM(masm_)
5748
5749 Result DeferredInlineBinaryOperation::GenerateInlineCode(Result* left, 5734 Result DeferredInlineBinaryOperation::GenerateInlineCode(Result* left,
5750 Result* right) { 5735 Result* right) {
5736 MacroAssembler* masm = cgen()->masm();
5751 // Perform fast-case smi code for the operation (left <op> right) and 5737 // Perform fast-case smi code for the operation (left <op> right) and
5752 // returns the result in a Result. 5738 // returns the result in a Result.
5753 // If any fast-case tests fail, it jumps to the slow-case deferred code, 5739 // If any fast-case tests fail, it jumps to the slow-case deferred code,
5754 // which calls the binary operation stub, with the arguments (in registers) 5740 // which calls the binary operation stub, with the arguments (in registers)
5755 // on top of the frame. 5741 // on top of the frame.
5756 // Consumes its arguments (sets left and right to invalid and frees their 5742 // Consumes its arguments (sets left and right to invalid and frees their
5757 // registers). 5743 // registers).
5758 5744
5759 left->ToRegister(); 5745 left->ToRegister();
5760 right->ToRegister(); 5746 right->ToRegister();
5761 // A newly allocated register answer is used to hold the answer. 5747 // A newly allocated register answer is used to hold the answer.
5762 // The registers containing left and right are not modified in 5748 // The registers containing left and right are not modified in
5763 // most cases, so they usually don't need to be spilled in the fast case. 5749 // most cases, so they usually don't need to be spilled in the fast case.
5764 Result answer = generator()->allocator()->Allocate(); 5750 Result answer = cgen()->allocator()->Allocate();
5765 5751
5766 ASSERT(answer.is_valid()); 5752 ASSERT(answer.is_valid());
5767 // Perform the smi check. 5753 // Perform the smi check.
5768 if (left->reg().is(right->reg())) { 5754 if (left->reg().is(right->reg())) {
5769 __ test(left->reg(), Immediate(kSmiTagMask)); 5755 __ test(left->reg(), Immediate(kSmiTagMask));
5770 } else { 5756 } else {
5771 __ mov(answer.reg(), left->reg()); 5757 __ mov(answer.reg(), left->reg());
5772 __ or_(answer.reg(), Operand(right->reg())); 5758 __ or_(answer.reg(), Operand(right->reg()));
5773 ASSERT(kSmiTag == 0); // adjust zero check if not the case 5759 ASSERT(kSmiTag == 0); // adjust zero check if not the case
5774 __ test(answer.reg(), Immediate(kSmiTagMask)); 5760 __ test(answer.reg(), Immediate(kSmiTagMask));
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
5825 // Div and mod use the registers eax and edx. Left and right must 5811 // Div and mod use the registers eax and edx. Left and right must
5826 // be preserved, because the original operands are needed if we switch 5812 // be preserved, because the original operands are needed if we switch
5827 // to the slow case. Move them if either is in eax or edx. 5813 // to the slow case. Move them if either is in eax or edx.
5828 // The Result answer should be changed into an alias for eax. 5814 // The Result answer should be changed into an alias for eax.
5829 // Precondition: 5815 // Precondition:
5830 // The Results left and right are valid. They may be the same register, 5816 // The Results left and right are valid. They may be the same register,
5831 // and may be unspilled. The Result answer is valid and is distinct 5817 // and may be unspilled. The Result answer is valid and is distinct
5832 // from left and right, and is spilled. 5818 // from left and right, and is spilled.
5833 // The value in left is copied to answer. 5819 // The value in left is copied to answer.
5834 5820
5835 Result reg_eax = generator()->allocator()->Allocate(eax); 5821 Result reg_eax = cgen()->allocator()->Allocate(eax);
5836 Result reg_edx = generator()->allocator()->Allocate(edx); 5822 Result reg_edx = cgen()->allocator()->Allocate(edx);
5837 // These allocations may have failed, if one of left, right, or answer 5823 // These allocations may have failed, if one of left, right, or answer
5838 // is in register eax or edx. 5824 // is in register eax or edx.
5839 bool left_copied_to_eax = false; // We will make sure this becomes true. 5825 bool left_copied_to_eax = false; // We will make sure this becomes true.
5840 5826
5841 // Part 1: Get eax 5827 // Part 1: Get eax
5842 if (answer.reg().is(eax)) { 5828 if (answer.reg().is(eax)) {
5843 reg_eax = answer; 5829 reg_eax = answer;
5844 left_copied_to_eax = true; 5830 left_copied_to_eax = true;
5845 } else if (right->reg().is(eax) || left->reg().is(eax)) { 5831 } else if (right->reg().is(eax) || left->reg().is(eax)) {
5846 // We need a non-edx register to move one or both of left and right to. 5832 // We need a non-edx register to move one or both of left and right to.
5847 // We use answer if it is not edx, otherwise we allocate one. 5833 // We use answer if it is not edx, otherwise we allocate one.
5848 if (answer.reg().is(edx)) { 5834 if (answer.reg().is(edx)) {
5849 reg_edx = answer; 5835 reg_edx = answer;
5850 answer = generator()->allocator()->Allocate(); 5836 answer = cgen()->allocator()->Allocate();
5851 ASSERT(answer.is_valid()); 5837 ASSERT(answer.is_valid());
5852 } 5838 }
5853 5839
5854 if (left->reg().is(eax)) { 5840 if (left->reg().is(eax)) {
5855 reg_eax = *left; 5841 reg_eax = *left;
5856 left_copied_to_eax = true; 5842 left_copied_to_eax = true;
5857 *left = answer; 5843 *left = answer;
5858 } 5844 }
5859 if (right->reg().is(eax)) { 5845 if (right->reg().is(eax)) {
5860 reg_eax = *right; 5846 reg_eax = *right;
(...skipping 10 matching lines...) Expand all
5871 // Part 2: Get edx 5857 // Part 2: Get edx
5872 // reg_edx is invalid if and only if either left, right, 5858 // reg_edx is invalid if and only if either left, right,
5873 // or answer is in edx. If edx is valid, then either edx 5859 // or answer is in edx. If edx is valid, then either edx
5874 // was free, or it was answer, but answer was reallocated. 5860 // was free, or it was answer, but answer was reallocated.
5875 if (answer.reg().is(edx)) { 5861 if (answer.reg().is(edx)) {
5876 reg_edx = answer; 5862 reg_edx = answer;
5877 } else if (right->reg().is(edx) || left->reg().is(edx)) { 5863 } else if (right->reg().is(edx) || left->reg().is(edx)) {
5878 // Is answer used? 5864 // Is answer used?
5879 if (answer.reg().is(eax) || answer.reg().is(left->reg()) || 5865 if (answer.reg().is(eax) || answer.reg().is(left->reg()) ||
5880 answer.reg().is(right->reg())) { 5866 answer.reg().is(right->reg())) {
5881 answer = generator()->allocator()->Allocate(); 5867 answer = cgen()->allocator()->Allocate();
5882 ASSERT(answer.is_valid()); // We cannot hit both Allocate() calls. 5868 ASSERT(answer.is_valid()); // We cannot hit both Allocate() calls.
5883 } 5869 }
5884 if (left->reg().is(edx)) { 5870 if (left->reg().is(edx)) {
5885 reg_edx = *left; 5871 reg_edx = *left;
5886 *left = answer; 5872 *left = answer;
5887 } 5873 }
5888 if (right->reg().is(edx)) { 5874 if (right->reg().is(edx)) {
5889 reg_edx = *right; 5875 reg_edx = *right;
5890 *right = answer; 5876 *right = answer;
5891 } 5877 }
5892 __ mov(answer.reg(), edx); 5878 __ mov(answer.reg(), edx);
5893 } 5879 }
5894 // End of Part 2 5880 // End of Part 2
5895 ASSERT(reg_edx.is_valid()); 5881 ASSERT(reg_edx.is_valid());
5896 ASSERT(!left->reg().is(eax)); 5882 ASSERT(!left->reg().is(eax));
5897 ASSERT(!right->reg().is(eax)); 5883 ASSERT(!right->reg().is(eax));
5898 5884
5899 answer = reg_eax; // May free answer, if it was never used. 5885 answer = reg_eax; // May free answer, if it was never used.
5900 generator()->frame()->Spill(eax); 5886 cgen()->frame()->Spill(eax);
5901 if (!left_copied_to_eax) { 5887 if (!left_copied_to_eax) {
5902 __ mov(eax, left->reg()); 5888 __ mov(eax, left->reg());
5903 left_copied_to_eax = true; 5889 left_copied_to_eax = true;
5904 } 5890 }
5905 generator()->frame()->Spill(edx); 5891 cgen()->frame()->Spill(edx);
5906 5892
5907 // Postcondition: 5893 // Postcondition:
5908 // reg_eax, reg_edx are valid, correct, and spilled. 5894 // reg_eax, reg_edx are valid, correct, and spilled.
5909 // reg_eax contains the value originally in left 5895 // reg_eax contains the value originally in left
5910 // left and right are not eax or edx. They may or may not be 5896 // left and right are not eax or edx. They may or may not be
5911 // spilled or distinct. 5897 // spilled or distinct.
5912 // answer is an alias for reg_eax. 5898 // answer is an alias for reg_eax.
5913 5899
5914 // Sign extend eax into edx:eax. 5900 // Sign extend eax into edx:eax.
5915 __ cdq(); 5901 __ cdq();
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
5985 // Left is in two registers already, so even if left or answer is ecx, 5971 // Left is in two registers already, so even if left or answer is ecx,
5986 // we can move right to it, and use the other one. 5972 // we can move right to it, and use the other one.
5987 // Right operand must be in register cl because x86 likes it that way. 5973 // Right operand must be in register cl because x86 likes it that way.
5988 if (right->reg().is(ecx)) { 5974 if (right->reg().is(ecx)) {
5989 // Right is already in the right place. Left may be in the 5975 // Right is already in the right place. Left may be in the
5990 // same register, which causes problems. Always use answer 5976 // same register, which causes problems. Always use answer
5991 // instead of left, even if left is not ecx, since this avoids 5977 // instead of left, even if left is not ecx, since this avoids
5992 // spilling left. 5978 // spilling left.
5993 *left = answer; 5979 *left = answer;
5994 } else if (left->reg().is(ecx)) { 5980 } else if (left->reg().is(ecx)) {
5995 generator()->frame()->Spill(left->reg()); 5981 cgen()->frame()->Spill(left->reg());
5996 __ mov(left->reg(), right->reg()); 5982 __ mov(left->reg(), right->reg());
5997 *right = *left; 5983 *right = *left;
5998 *left = answer; // Use copy of left in answer as left. 5984 *left = answer; // Use copy of left in answer as left.
5999 } else if (answer.reg().is(ecx)) { 5985 } else if (answer.reg().is(ecx)) {
6000 __ mov(answer.reg(), right->reg()); 5986 __ mov(answer.reg(), right->reg());
6001 *right = answer; 5987 *right = answer;
6002 } else { 5988 } else {
6003 Result reg_ecx = generator()->allocator()->Allocate(ecx); 5989 Result reg_ecx = cgen()->allocator()->Allocate(ecx);
6004 ASSERT(reg_ecx.is_valid()); 5990 ASSERT(reg_ecx.is_valid());
6005 __ mov(ecx, right->reg()); 5991 __ mov(ecx, right->reg());
6006 *right = reg_ecx; 5992 *right = reg_ecx;
6007 // Answer and left both contain the left operand. Use answer, so 5993 // Answer and left both contain the left operand. Use answer, so
6008 // left is not spilled. 5994 // left is not spilled.
6009 *left = answer; 5995 *left = answer;
6010 } 5996 }
6011 ASSERT(left->reg().is_valid()); 5997 ASSERT(left->reg().is_valid());
6012 ASSERT(!left->reg().is(ecx)); 5998 ASSERT(!left->reg().is(ecx));
6013 ASSERT(right->reg().is(ecx)); 5999 ASSERT(right->reg().is(ecx));
6014 answer.Unuse(); // Answer may now be being used for left or right. 6000 answer.Unuse(); // Answer may now be being used for left or right.
6015 // We will modify left and right, which we do not do in any other 6001 // We will modify left and right, which we do not do in any other
6016 // binary operation. The exits to slow code need to restore the 6002 // binary operation. The exits to slow code need to restore the
6017 // original values of left and right, or at least values that give 6003 // original values of left and right, or at least values that give
6018 // the same answer. 6004 // the same answer.
6019 6005
6020 // We are modifying left and right. They must be spilled! 6006 // We are modifying left and right. They must be spilled!
6021 generator()->frame()->Spill(left->reg()); 6007 cgen()->frame()->Spill(left->reg());
6022 generator()->frame()->Spill(right->reg()); 6008 cgen()->frame()->Spill(right->reg());
6023 6009
6024 // Remove tags from operands (but keep sign). 6010 // Remove tags from operands (but keep sign).
6025 __ sar(left->reg(), kSmiTagSize); 6011 __ sar(left->reg(), kSmiTagSize);
6026 __ sar(ecx, kSmiTagSize); 6012 __ sar(ecx, kSmiTagSize);
6027 // Perform the operation. 6013 // Perform the operation.
6028 switch (op_) { 6014 switch (op_) {
6029 case Token::SAR: 6015 case Token::SAR:
6030 __ sar(left->reg()); 6016 __ sar(left->reg());
6031 // No checks of result necessary 6017 // No checks of result necessary
6032 break; 6018 break;
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
6082 default: 6068 default:
6083 UNREACHABLE(); 6069 UNREACHABLE();
6084 break; 6070 break;
6085 } 6071 }
6086 left->Unuse(); 6072 left->Unuse();
6087 right->Unuse(); 6073 right->Unuse();
6088 return answer; 6074 return answer;
6089 } 6075 }
6090 6076
6091 6077
6092 #undef __
6093 #define __ ACCESS_MASM(masm)
6094
6095 void GenericBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, Label* slow) { 6078 void GenericBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, Label* slow) {
6096 // Perform fast-case smi code for the operation (eax <op> ebx) and 6079 // Perform fast-case smi code for the operation (eax <op> ebx) and
6097 // leave result in register eax. 6080 // leave result in register eax.
6098 6081
6099 // Prepare the smi check of both operands by or'ing them together 6082 // Prepare the smi check of both operands by or'ing them together
6100 // before checking against the smi mask. 6083 // before checking against the smi mask.
6101 __ mov(ecx, Operand(ebx)); 6084 __ mov(ecx, Operand(ebx));
6102 __ or_(ecx, Operand(eax)); 6085 __ or_(ecx, Operand(eax));
6103 6086
6104 switch (op_) { 6087 switch (op_) {
(...skipping 1200 matching lines...) Expand 10 before | Expand all | Expand 10 after
7305 7288
7306 // Slow-case: Go through the JavaScript implementation. 7289 // Slow-case: Go through the JavaScript implementation.
7307 __ bind(&slow); 7290 __ bind(&slow);
7308 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 7291 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
7309 } 7292 }
7310 7293
7311 7294
7312 #undef __ 7295 #undef __
7313 7296
7314 } } // namespace v8::internal 7297 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ia32/codegen-ia32.h ('k') | src/x64/codegen-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698