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

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

Issue 113455: Clean up the Result class. Reduce the size of Result from four words... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years, 7 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
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 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 #endif 274 #endif
275 VisitStatements(body); 275 VisitStatements(body);
276 276
277 // Handle the return from the function. 277 // Handle the return from the function.
278 if (has_valid_frame()) { 278 if (has_valid_frame()) {
279 // If there is a valid frame, control flow can fall off the end of 279 // If there is a valid frame, control flow can fall off the end of
280 // the body. In that case there is an implicit return statement. 280 // the body. In that case there is an implicit return statement.
281 ASSERT(!function_return_is_shadowed_); 281 ASSERT(!function_return_is_shadowed_);
282 CodeForReturnPosition(fun); 282 CodeForReturnPosition(fun);
283 frame_->PrepareForReturn(); 283 frame_->PrepareForReturn();
284 Result undefined(Factory::undefined_value(), this); 284 Result undefined(Factory::undefined_value());
285 if (function_return_.is_bound()) { 285 if (function_return_.is_bound()) {
286 function_return_.Jump(&undefined); 286 function_return_.Jump(&undefined);
287 } else { 287 } else {
288 // Though this is a (possibly) backward block, the frames 288 // Though this is a (possibly) backward block, the frames
289 // can only differ on their top element. 289 // can only differ on their top element.
290 function_return_.Bind(&undefined, 1); 290 function_return_.Bind(&undefined, 1);
291 GenerateReturnSequence(&undefined); 291 GenerateReturnSequence(&undefined);
292 } 292 }
293 } else if (function_return_.is_linked()) { 293 } else if (function_return_.is_linked()) {
294 // If the return target has dangling jumps to it, then we have not 294 // If the return target has dangling jumps to it, then we have not
295 // yet generated the return sequence. This can happen when (a) 295 // yet generated the return sequence. This can happen when (a)
296 // control does not flow off the end of the body so we did not 296 // control does not flow off the end of the body so we did not
297 // compile an artificial return statement just above, and (b) there 297 // compile an artificial return statement just above, and (b) there
298 // are return statements in the body but (c) they are all shadowed. 298 // are return statements in the body but (c) they are all shadowed.
299 Result return_value(this); 299 Result return_value;
300 // Though this is a (possibly) backward block, the frames can 300 // Though this is a (possibly) backward block, the frames can
301 // only differ on their top element. 301 // only differ on their top element.
302 function_return_.Bind(&return_value, 1); 302 function_return_.Bind(&return_value, 1);
303 GenerateReturnSequence(&return_value); 303 GenerateReturnSequence(&return_value);
304 } 304 }
305 } 305 }
306 } 306 }
307 307
308 // Adjust for function-level loop nesting. 308 // Adjust for function-level loop nesting.
309 loop_nesting_ -= fun->loop_nesting(); 309 loop_nesting_ -= fun->loop_nesting();
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
381 return Operand(eax); 381 return Operand(eax);
382 } 382 }
383 } 383 }
384 384
385 385
386 Operand CodeGenerator::ContextSlotOperandCheckExtensions(Slot* slot, 386 Operand CodeGenerator::ContextSlotOperandCheckExtensions(Slot* slot,
387 Result tmp, 387 Result tmp,
388 JumpTarget* slow) { 388 JumpTarget* slow) {
389 ASSERT(slot->type() == Slot::CONTEXT); 389 ASSERT(slot->type() == Slot::CONTEXT);
390 ASSERT(tmp.is_register()); 390 ASSERT(tmp.is_register());
391 Result context(esi, this); 391 Result context(esi);
392 392
393 for (Scope* s = scope(); s != slot->var()->scope(); s = s->outer_scope()) { 393 for (Scope* s = scope(); s != slot->var()->scope(); s = s->outer_scope()) {
394 if (s->num_heap_slots() > 0) { 394 if (s->num_heap_slots() > 0) {
395 if (s->calls_eval()) { 395 if (s->calls_eval()) {
396 // Check that extension is NULL. 396 // Check that extension is NULL.
397 __ cmp(ContextOperand(context.reg(), Context::EXTENSION_INDEX), 397 __ cmp(ContextOperand(context.reg(), Context::EXTENSION_INDEX),
398 Immediate(0)); 398 Immediate(0));
399 slow->Branch(not_equal, not_taken); 399 slow->Branch(not_equal, not_taken);
400 } 400 }
401 __ mov(tmp.reg(), ContextOperand(context.reg(), Context::CLOSURE_INDEX)); 401 __ mov(tmp.reg(), ContextOperand(context.reg(), Context::CLOSURE_INDEX));
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after
796 796
797 virtual void Generate(); 797 virtual void Generate();
798 798
799 private: 799 private:
800 GenericBinaryOpStub stub_; 800 GenericBinaryOpStub stub_;
801 Token::Value op_; 801 Token::Value op_;
802 }; 802 };
803 803
804 804
805 void DeferredInlineBinaryOperation::Generate() { 805 void DeferredInlineBinaryOperation::Generate() {
806 Result left(generator()); 806 Result left;
Kevin Millikin (Chromium) 2009/05/15 10:50:49 A separate cleanup, since we have it now, is to us
807 Result right(generator()); 807 Result right;
808 enter()->Bind(&left, &right); 808 enter()->Bind(&left, &right);
809 generator()->frame()->Push(&left); 809 generator()->frame()->Push(&left);
810 generator()->frame()->Push(&right); 810 generator()->frame()->Push(&right);
811 Result answer = generator()->frame()->CallStub(&stub_, 2); 811 Result answer = generator()->frame()->CallStub(&stub_, 2);
812 exit_.Jump(&answer); 812 exit_.Jump(&answer);
813 } 813 }
814 814
815 815
816 void CodeGenerator::GenericBinaryOperation(Token::Value op, 816 void CodeGenerator::GenericBinaryOperation(Token::Value op,
817 SmiAnalysis* type, 817 SmiAnalysis* type,
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
852 852
853 Result right = frame_->Pop(); 853 Result right = frame_->Pop();
854 Result left = frame_->Pop(); 854 Result left = frame_->Pop();
855 855
856 if (op == Token::ADD) { 856 if (op == Token::ADD) {
857 bool left_is_string = left.static_type().is_jsstring(); 857 bool left_is_string = left.static_type().is_jsstring();
858 bool right_is_string = right.static_type().is_jsstring(); 858 bool right_is_string = right.static_type().is_jsstring();
859 if (left_is_string || right_is_string) { 859 if (left_is_string || right_is_string) {
860 frame_->Push(&left); 860 frame_->Push(&left);
861 frame_->Push(&right); 861 frame_->Push(&right);
862 Result answer(this); 862 Result answer;
863 if (left_is_string) { 863 if (left_is_string) {
864 if (right_is_string) { 864 if (right_is_string) {
865 // TODO(lrn): if (left.is_constant() && right.is_constant()) 865 // TODO(lrn): if (left.is_constant() && right.is_constant())
866 // -- do a compile time cons, if allocation during codegen is allowed. 866 // -- do a compile time cons, if allocation during codegen is allowed.
867 answer = frame_->CallRuntime(Runtime::kStringAdd, 2); 867 answer = frame_->CallRuntime(Runtime::kStringAdd, 2);
868 } else { 868 } else {
869 answer = 869 answer =
870 frame_->InvokeBuiltin(Builtins::STRING_ADD_LEFT, CALL_FUNCTION, 2); 870 frame_->InvokeBuiltin(Builtins::STRING_ADD_LEFT, CALL_FUNCTION, 2);
871 } 871 }
872 } else if (right_is_string) { 872 } else if (right_is_string) {
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
1038 virtual void Generate(); 1038 virtual void Generate();
1039 1039
1040 private: 1040 private:
1041 Token::Value op_; 1041 Token::Value op_;
1042 Smi* value_; 1042 Smi* value_;
1043 OverwriteMode overwrite_mode_; 1043 OverwriteMode overwrite_mode_;
1044 }; 1044 };
1045 1045
1046 1046
1047 void DeferredInlineSmiOperation::Generate() { 1047 void DeferredInlineSmiOperation::Generate() {
1048 Result left(generator()); 1048 Result left;
1049 enter()->Bind(&left); 1049 enter()->Bind(&left);
1050 generator()->frame()->Push(&left); 1050 generator()->frame()->Push(&left);
1051 generator()->frame()->Push(value_); 1051 generator()->frame()->Push(value_);
1052 GenericBinaryOpStub igostub(op_, overwrite_mode_, SMI_CODE_INLINED); 1052 GenericBinaryOpStub igostub(op_, overwrite_mode_, SMI_CODE_INLINED);
1053 Result answer = generator()->frame()->CallStub(&igostub, 2); 1053 Result answer = generator()->frame()->CallStub(&igostub, 2);
1054 exit_.Jump(&answer); 1054 exit_.Jump(&answer);
1055 } 1055 }
1056 1056
1057 1057
1058 class DeferredInlineSmiOperationReversed: public DeferredCode { 1058 class DeferredInlineSmiOperationReversed: public DeferredCode {
(...skipping 12 matching lines...) Expand all
1071 virtual void Generate(); 1071 virtual void Generate();
1072 1072
1073 private: 1073 private:
1074 Token::Value op_; 1074 Token::Value op_;
1075 Smi* value_; 1075 Smi* value_;
1076 OverwriteMode overwrite_mode_; 1076 OverwriteMode overwrite_mode_;
1077 }; 1077 };
1078 1078
1079 1079
1080 void DeferredInlineSmiOperationReversed::Generate() { 1080 void DeferredInlineSmiOperationReversed::Generate() {
1081 Result right(generator()); 1081 Result right;
1082 enter()->Bind(&right); 1082 enter()->Bind(&right);
1083 generator()->frame()->Push(value_); 1083 generator()->frame()->Push(value_);
1084 generator()->frame()->Push(&right); 1084 generator()->frame()->Push(&right);
1085 GenericBinaryOpStub igostub(op_, overwrite_mode_, SMI_CODE_INLINED); 1085 GenericBinaryOpStub igostub(op_, overwrite_mode_, SMI_CODE_INLINED);
1086 Result answer = generator()->frame()->CallStub(&igostub, 2); 1086 Result answer = generator()->frame()->CallStub(&igostub, 2);
1087 exit_.Jump(&answer); 1087 exit_.Jump(&answer);
1088 } 1088 }
1089 1089
1090 1090
1091 class DeferredInlineSmiAdd: public DeferredCode { 1091 class DeferredInlineSmiAdd: public DeferredCode {
(...skipping 10 matching lines...) Expand all
1102 virtual void Generate(); 1102 virtual void Generate();
1103 1103
1104 private: 1104 private:
1105 Smi* value_; 1105 Smi* value_;
1106 OverwriteMode overwrite_mode_; 1106 OverwriteMode overwrite_mode_;
1107 }; 1107 };
1108 1108
1109 1109
1110 void DeferredInlineSmiAdd::Generate() { 1110 void DeferredInlineSmiAdd::Generate() {
1111 // Undo the optimistic add operation and call the shared stub. 1111 // Undo the optimistic add operation and call the shared stub.
1112 Result left(generator()); // Initially left + value_. 1112 Result left; // Initially left + value_.
1113 enter()->Bind(&left); 1113 enter()->Bind(&left);
1114 left.ToRegister(); 1114 left.ToRegister();
1115 generator()->frame()->Spill(left.reg()); 1115 generator()->frame()->Spill(left.reg());
1116 __ sub(Operand(left.reg()), Immediate(value_)); 1116 __ sub(Operand(left.reg()), Immediate(value_));
1117 generator()->frame()->Push(&left); 1117 generator()->frame()->Push(&left);
1118 generator()->frame()->Push(value_); 1118 generator()->frame()->Push(value_);
1119 GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED); 1119 GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED);
1120 Result answer = generator()->frame()->CallStub(&igostub, 2); 1120 Result answer = generator()->frame()->CallStub(&igostub, 2);
1121 exit_.Jump(&answer); 1121 exit_.Jump(&answer);
1122 } 1122 }
(...skipping 13 matching lines...) Expand all
1136 virtual void Generate(); 1136 virtual void Generate();
1137 1137
1138 private: 1138 private:
1139 Smi* value_; 1139 Smi* value_;
1140 OverwriteMode overwrite_mode_; 1140 OverwriteMode overwrite_mode_;
1141 }; 1141 };
1142 1142
1143 1143
1144 void DeferredInlineSmiAddReversed::Generate() { 1144 void DeferredInlineSmiAddReversed::Generate() {
1145 // Undo the optimistic add operation and call the shared stub. 1145 // Undo the optimistic add operation and call the shared stub.
1146 Result right(generator()); // Initially value_ + right. 1146 Result right; // Initially value_ + right.
1147 enter()->Bind(&right); 1147 enter()->Bind(&right);
1148 right.ToRegister(); 1148 right.ToRegister();
1149 generator()->frame()->Spill(right.reg()); 1149 generator()->frame()->Spill(right.reg());
1150 __ sub(Operand(right.reg()), Immediate(value_)); 1150 __ sub(Operand(right.reg()), Immediate(value_));
1151 generator()->frame()->Push(value_); 1151 generator()->frame()->Push(value_);
1152 generator()->frame()->Push(&right); 1152 generator()->frame()->Push(&right);
1153 GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED); 1153 GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED);
1154 Result answer = generator()->frame()->CallStub(&igostub, 2); 1154 Result answer = generator()->frame()->CallStub(&igostub, 2);
1155 exit_.Jump(&answer); 1155 exit_.Jump(&answer);
1156 } 1156 }
(...skipping 13 matching lines...) Expand all
1170 virtual void Generate(); 1170 virtual void Generate();
1171 1171
1172 private: 1172 private:
1173 Smi* value_; 1173 Smi* value_;
1174 OverwriteMode overwrite_mode_; 1174 OverwriteMode overwrite_mode_;
1175 }; 1175 };
1176 1176
1177 1177
1178 void DeferredInlineSmiSub::Generate() { 1178 void DeferredInlineSmiSub::Generate() {
1179 // Undo the optimistic sub operation and call the shared stub. 1179 // Undo the optimistic sub operation and call the shared stub.
1180 Result left(generator()); // Initially left - value_. 1180 Result left; // Initially left - value_.
1181 enter()->Bind(&left); 1181 enter()->Bind(&left);
1182 left.ToRegister(); 1182 left.ToRegister();
1183 generator()->frame()->Spill(left.reg()); 1183 generator()->frame()->Spill(left.reg());
1184 __ add(Operand(left.reg()), Immediate(value_)); 1184 __ add(Operand(left.reg()), Immediate(value_));
1185 generator()->frame()->Push(&left); 1185 generator()->frame()->Push(&left);
1186 generator()->frame()->Push(value_); 1186 generator()->frame()->Push(value_);
1187 GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, SMI_CODE_INLINED); 1187 GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, SMI_CODE_INLINED);
1188 Result answer = generator()->frame()->CallStub(&igostub, 2); 1188 Result answer = generator()->frame()->CallStub(&igostub, 2);
1189 exit_.Jump(&answer); 1189 exit_.Jump(&answer);
1190 } 1190 }
(...skipping 13 matching lines...) Expand all
1204 virtual void Generate(); 1204 virtual void Generate();
1205 1205
1206 private: 1206 private:
1207 Smi* value_; 1207 Smi* value_;
1208 OverwriteMode overwrite_mode_; 1208 OverwriteMode overwrite_mode_;
1209 }; 1209 };
1210 1210
1211 1211
1212 void DeferredInlineSmiSubReversed::Generate() { 1212 void DeferredInlineSmiSubReversed::Generate() {
1213 // Call the shared stub. 1213 // Call the shared stub.
1214 Result right(generator()); 1214 Result right;
1215 enter()->Bind(&right); 1215 enter()->Bind(&right);
1216 generator()->frame()->Push(value_); 1216 generator()->frame()->Push(value_);
1217 generator()->frame()->Push(&right); 1217 generator()->frame()->Push(&right);
1218 GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, SMI_CODE_INLINED); 1218 GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, SMI_CODE_INLINED);
1219 Result answer = generator()->frame()->CallStub(&igostub, 2); 1219 Result answer = generator()->frame()->CallStub(&igostub, 2);
1220 exit_.Jump(&answer); 1220 exit_.Jump(&answer);
1221 } 1221 }
1222 1222
1223 1223
1224 void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op, 1224 void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
1225 Result* operand, 1225 Result* operand,
1226 Handle<Object> value, 1226 Handle<Object> value,
1227 SmiAnalysis* type, 1227 SmiAnalysis* type,
1228 bool reversed, 1228 bool reversed,
1229 OverwriteMode overwrite_mode) { 1229 OverwriteMode overwrite_mode) {
1230 // NOTE: This is an attempt to inline (a bit) more of the code for 1230 // NOTE: This is an attempt to inline (a bit) more of the code for
1231 // some possible smi operations (like + and -) when (at least) one 1231 // some possible smi operations (like + and -) when (at least) one
1232 // of the operands is a constant smi. 1232 // of the operands is a constant smi.
1233 // Consumes the argument "operand". 1233 // Consumes the argument "operand".
1234 1234
1235 // TODO(199): Optimize some special cases of operations involving a 1235 // TODO(199): Optimize some special cases of operations involving a
1236 // smi literal (multiply by 2, shift by 0, etc.). 1236 // smi literal (multiply by 2, shift by 0, etc.).
1237 if (IsUnsafeSmi(value)) { 1237 if (IsUnsafeSmi(value)) {
1238 Result unsafe_operand(value, this); 1238 Result unsafe_operand(value);
1239 if (reversed) { 1239 if (reversed) {
1240 LikelySmiBinaryOperation(op, &unsafe_operand, operand, 1240 LikelySmiBinaryOperation(op, &unsafe_operand, operand,
1241 overwrite_mode); 1241 overwrite_mode);
1242 } else { 1242 } else {
1243 LikelySmiBinaryOperation(op, operand, &unsafe_operand, 1243 LikelySmiBinaryOperation(op, operand, &unsafe_operand,
1244 overwrite_mode); 1244 overwrite_mode);
1245 } 1245 }
1246 ASSERT(!operand->is_valid()); 1246 ASSERT(!operand->is_valid());
1247 return; 1247 return;
1248 } 1248 }
(...skipping 19 matching lines...) Expand all
1268 deferred->enter()->Branch(overflow, operand, not_taken); 1268 deferred->enter()->Branch(overflow, operand, not_taken);
1269 __ test(operand->reg(), Immediate(kSmiTagMask)); 1269 __ test(operand->reg(), Immediate(kSmiTagMask));
1270 deferred->enter()->Branch(not_zero, operand, not_taken); 1270 deferred->enter()->Branch(not_zero, operand, not_taken);
1271 deferred->BindExit(operand); 1271 deferred->BindExit(operand);
1272 frame_->Push(operand); 1272 frame_->Push(operand);
1273 break; 1273 break;
1274 } 1274 }
1275 1275
1276 case Token::SUB: { 1276 case Token::SUB: {
1277 DeferredCode* deferred = NULL; 1277 DeferredCode* deferred = NULL;
1278 Result answer(this); // Only allocate a new register if reversed. 1278 Result answer; // Only allocate a new register if reversed.
1279 if (reversed) { 1279 if (reversed) {
1280 answer = allocator()->Allocate(); 1280 answer = allocator()->Allocate();
1281 ASSERT(answer.is_valid()); 1281 ASSERT(answer.is_valid());
1282 deferred = new DeferredInlineSmiSubReversed(this, smi_value, 1282 deferred = new DeferredInlineSmiSubReversed(this, smi_value,
1283 overwrite_mode); 1283 overwrite_mode);
1284 __ Set(answer.reg(), Immediate(value)); 1284 __ Set(answer.reg(), Immediate(value));
1285 // We are in the reversed case so they can't both be Smi constants. 1285 // We are in the reversed case so they can't both be Smi constants.
1286 ASSERT(operand->is_register()); 1286 ASSERT(operand->is_register());
1287 __ sub(answer.reg(), Operand(operand->reg())); 1287 __ sub(answer.reg(), Operand(operand->reg()));
1288 } else { 1288 } else {
1289 operand->ToRegister(); 1289 operand->ToRegister();
1290 frame_->Spill(operand->reg()); 1290 frame_->Spill(operand->reg());
1291 deferred = new DeferredInlineSmiSub(this, smi_value, overwrite_mode); 1291 deferred = new DeferredInlineSmiSub(this, smi_value, overwrite_mode);
1292 __ sub(Operand(operand->reg()), Immediate(value)); 1292 __ sub(Operand(operand->reg()), Immediate(value));
1293 answer = *operand; 1293 answer = *operand;
1294 } 1294 }
1295 deferred->SetEntryFrame(operand); 1295 deferred->SetEntryFrame(operand);
1296 deferred->enter()->Branch(overflow, operand, not_taken); 1296 deferred->enter()->Branch(overflow, operand, not_taken);
1297 __ test(answer.reg(), Immediate(kSmiTagMask)); 1297 __ test(answer.reg(), Immediate(kSmiTagMask));
1298 deferred->enter()->Branch(not_zero, operand, not_taken); 1298 deferred->enter()->Branch(not_zero, operand, not_taken);
1299 operand->Unuse(); 1299 operand->Unuse();
1300 deferred->BindExit(&answer); 1300 deferred->BindExit(&answer);
1301 frame_->Push(&answer); 1301 frame_->Push(&answer);
1302 break; 1302 break;
1303 } 1303 }
1304 1304
1305 case Token::SAR: { 1305 case Token::SAR: {
1306 if (reversed) { 1306 if (reversed) {
1307 Result constant_operand(value, this); 1307 Result constant_operand(value);
1308 LikelySmiBinaryOperation(op, &constant_operand, operand, 1308 LikelySmiBinaryOperation(op, &constant_operand, operand,
1309 overwrite_mode); 1309 overwrite_mode);
1310 } else { 1310 } else {
1311 // Only the least significant 5 bits of the shift value are used. 1311 // Only the least significant 5 bits of the shift value are used.
1312 // In the slow case, this masking is done inside the runtime call. 1312 // In the slow case, this masking is done inside the runtime call.
1313 int shift_value = int_value & 0x1f; 1313 int shift_value = int_value & 0x1f;
1314 DeferredCode* deferred = 1314 DeferredCode* deferred =
1315 new DeferredInlineSmiOperation(this, Token::SAR, smi_value, 1315 new DeferredInlineSmiOperation(this, Token::SAR, smi_value,
1316 overwrite_mode); 1316 overwrite_mode);
1317 operand->ToRegister(); 1317 operand->ToRegister();
1318 __ test(operand->reg(), Immediate(kSmiTagMask)); 1318 __ test(operand->reg(), Immediate(kSmiTagMask));
1319 deferred->enter()->Branch(not_zero, operand, not_taken); 1319 deferred->enter()->Branch(not_zero, operand, not_taken);
1320 if (shift_value > 0) { 1320 if (shift_value > 0) {
1321 frame_->Spill(operand->reg()); 1321 frame_->Spill(operand->reg());
1322 __ sar(operand->reg(), shift_value); 1322 __ sar(operand->reg(), shift_value);
1323 __ and_(operand->reg(), ~kSmiTagMask); 1323 __ and_(operand->reg(), ~kSmiTagMask);
1324 } 1324 }
1325 deferred->BindExit(operand); 1325 deferred->BindExit(operand);
1326 frame_->Push(operand); 1326 frame_->Push(operand);
1327 } 1327 }
1328 break; 1328 break;
1329 } 1329 }
1330 1330
1331 case Token::SHR: { 1331 case Token::SHR: {
1332 if (reversed) { 1332 if (reversed) {
1333 Result constant_operand(value, this); 1333 Result constant_operand(value);
1334 LikelySmiBinaryOperation(op, &constant_operand, operand, 1334 LikelySmiBinaryOperation(op, &constant_operand, operand,
1335 overwrite_mode); 1335 overwrite_mode);
1336 } else { 1336 } else {
1337 // Only the least significant 5 bits of the shift value are used. 1337 // Only the least significant 5 bits of the shift value are used.
1338 // In the slow case, this masking is done inside the runtime call. 1338 // In the slow case, this masking is done inside the runtime call.
1339 int shift_value = int_value & 0x1f; 1339 int shift_value = int_value & 0x1f;
1340 DeferredCode* deferred = 1340 DeferredCode* deferred =
1341 new DeferredInlineSmiOperation(this, Token::SHR, smi_value, 1341 new DeferredInlineSmiOperation(this, Token::SHR, smi_value,
1342 overwrite_mode); 1342 overwrite_mode);
1343 operand->ToRegister(); 1343 operand->ToRegister();
(...skipping 14 matching lines...) Expand all
1358 __ lea(answer.reg(), 1358 __ lea(answer.reg(),
1359 Operand(answer.reg(), answer.reg(), times_1, kSmiTag)); 1359 Operand(answer.reg(), answer.reg(), times_1, kSmiTag));
1360 deferred->BindExit(&answer); 1360 deferred->BindExit(&answer);
1361 frame_->Push(&answer); 1361 frame_->Push(&answer);
1362 } 1362 }
1363 break; 1363 break;
1364 } 1364 }
1365 1365
1366 case Token::SHL: { 1366 case Token::SHL: {
1367 if (reversed) { 1367 if (reversed) {
1368 Result constant_operand(value, this); 1368 Result constant_operand(value);
1369 LikelySmiBinaryOperation(op, &constant_operand, operand, 1369 LikelySmiBinaryOperation(op, &constant_operand, operand,
1370 overwrite_mode); 1370 overwrite_mode);
1371 } else { 1371 } else {
1372 // Only the least significant 5 bits of the shift value are used. 1372 // Only the least significant 5 bits of the shift value are used.
1373 // In the slow case, this masking is done inside the runtime call. 1373 // In the slow case, this masking is done inside the runtime call.
1374 int shift_value = int_value & 0x1f; 1374 int shift_value = int_value & 0x1f;
1375 DeferredCode* deferred = 1375 DeferredCode* deferred =
1376 new DeferredInlineSmiOperation(this, Token::SHL, smi_value, 1376 new DeferredInlineSmiOperation(this, Token::SHL, smi_value,
1377 overwrite_mode); 1377 overwrite_mode);
1378 operand->ToRegister(); 1378 operand->ToRegister();
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1428 if (int_value != 0) { 1428 if (int_value != 0) {
1429 __ or_(Operand(operand->reg()), Immediate(value)); 1429 __ or_(Operand(operand->reg()), Immediate(value));
1430 } 1430 }
1431 } 1431 }
1432 deferred->BindExit(operand); 1432 deferred->BindExit(operand);
1433 frame_->Push(operand); 1433 frame_->Push(operand);
1434 break; 1434 break;
1435 } 1435 }
1436 1436
1437 default: { 1437 default: {
1438 Result constant_operand(value, this); 1438 Result constant_operand(value);
1439 if (reversed) { 1439 if (reversed) {
1440 LikelySmiBinaryOperation(op, &constant_operand, operand, 1440 LikelySmiBinaryOperation(op, &constant_operand, operand,
1441 overwrite_mode); 1441 overwrite_mode);
1442 } else { 1442 } else {
1443 LikelySmiBinaryOperation(op, operand, &constant_operand, 1443 LikelySmiBinaryOperation(op, operand, &constant_operand,
1444 overwrite_mode); 1444 overwrite_mode);
1445 } 1445 }
1446 break; 1446 break;
1447 } 1447 }
1448 } 1448 }
(...skipping 28 matching lines...) Expand all
1477 #endif 1477 #endif
1478 }; 1478 };
1479 1479
1480 1480
1481 void CodeGenerator::Comparison(Condition cc, 1481 void CodeGenerator::Comparison(Condition cc,
1482 bool strict, 1482 bool strict,
1483 ControlDestination* dest) { 1483 ControlDestination* dest) {
1484 // Strict only makes sense for equality comparisons. 1484 // Strict only makes sense for equality comparisons.
1485 ASSERT(!strict || cc == equal); 1485 ASSERT(!strict || cc == equal);
1486 1486
1487 Result left_side(this); 1487 Result left_side;
1488 Result right_side(this); 1488 Result right_side;
1489 // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order. 1489 // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order.
1490 if (cc == greater || cc == less_equal) { 1490 if (cc == greater || cc == less_equal) {
1491 cc = ReverseCondition(cc); 1491 cc = ReverseCondition(cc);
1492 left_side = frame_->Pop(); 1492 left_side = frame_->Pop();
1493 right_side = frame_->Pop(); 1493 right_side = frame_->Pop();
1494 } else { 1494 } else {
1495 right_side = frame_->Pop(); 1495 right_side = frame_->Pop();
1496 left_side = frame_->Pop(); 1496 left_side = frame_->Pop();
1497 } 1497 }
1498 ASSERT(cc == less || cc == equal || cc == greater_equal); 1498 ASSERT(cc == less || cc == equal || cc == greater_equal);
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
1762 node->break_target()->Bind(); 1762 node->break_target()->Bind();
1763 } 1763 }
1764 node->break_target()->Unuse(); 1764 node->break_target()->Unuse();
1765 } 1765 }
1766 1766
1767 1767
1768 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 1768 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
1769 frame_->Push(pairs); 1769 frame_->Push(pairs);
1770 1770
1771 // Duplicate the context register. 1771 // Duplicate the context register.
1772 Result context(esi, this); 1772 Result context(esi);
1773 frame_->Push(&context); 1773 frame_->Push(&context);
1774 1774
1775 frame_->Push(Smi::FromInt(is_eval() ? 1 : 0)); 1775 frame_->Push(Smi::FromInt(is_eval() ? 1 : 0));
1776 Result ignored = frame_->CallRuntime(Runtime::kDeclareGlobals, 3); 1776 Result ignored = frame_->CallRuntime(Runtime::kDeclareGlobals, 3);
1777 // Return value is ignored. 1777 // Return value is ignored.
1778 } 1778 }
1779 1779
1780 1780
1781 void CodeGenerator::VisitDeclaration(Declaration* node) { 1781 void CodeGenerator::VisitDeclaration(Declaration* node) {
1782 Comment cmnt(masm_, "[ Declaration"); 1782 Comment cmnt(masm_, "[ Declaration");
1783 CodeForStatementPosition(node); 1783 CodeForStatementPosition(node);
1784 Variable* var = node->proxy()->var(); 1784 Variable* var = node->proxy()->var();
1785 ASSERT(var != NULL); // must have been resolved 1785 ASSERT(var != NULL); // must have been resolved
1786 Slot* slot = var->slot(); 1786 Slot* slot = var->slot();
1787 1787
1788 // If it was not possible to allocate the variable at compile time, 1788 // If it was not possible to allocate the variable at compile time,
1789 // we need to "declare" it at runtime to make sure it actually 1789 // we need to "declare" it at runtime to make sure it actually
1790 // exists in the local context. 1790 // exists in the local context.
1791 if (slot != NULL && slot->type() == Slot::LOOKUP) { 1791 if (slot != NULL && slot->type() == Slot::LOOKUP) {
1792 // Variables with a "LOOKUP" slot were introduced as non-locals 1792 // Variables with a "LOOKUP" slot were introduced as non-locals
1793 // during variable resolution and must have mode DYNAMIC. 1793 // during variable resolution and must have mode DYNAMIC.
1794 ASSERT(var->is_dynamic()); 1794 ASSERT(var->is_dynamic());
1795 // For now, just do a runtime call. Duplicate the context register. 1795 // For now, just do a runtime call. Duplicate the context register.
1796 Result context(esi, this); 1796 Result context(esi);
1797 frame_->Push(&context); 1797 frame_->Push(&context);
1798 frame_->Push(var->name()); 1798 frame_->Push(var->name());
1799 // Declaration nodes are always introduced in one of two modes. 1799 // Declaration nodes are always introduced in one of two modes.
1800 ASSERT(node->mode() == Variable::VAR || node->mode() == Variable::CONST); 1800 ASSERT(node->mode() == Variable::VAR || node->mode() == Variable::CONST);
1801 PropertyAttributes attr = node->mode() == Variable::VAR ? NONE : READ_ONLY; 1801 PropertyAttributes attr = node->mode() == Variable::VAR ? NONE : READ_ONLY;
1802 frame_->Push(Smi::FromInt(attr)); 1802 frame_->Push(Smi::FromInt(attr));
1803 // Push initial value, if any. 1803 // Push initial value, if any.
1804 // Note: For variables we must not push an initial value (such as 1804 // Note: For variables we must not push an initial value (such as
1805 // 'undefined') because we may have a (legal) redeclaration and we 1805 // 'undefined') because we may have a (legal) redeclaration and we
1806 // must not destroy the current value. 1806 // must not destroy the current value.
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
2025 ASSERT_EQ(Debug::kIa32JSReturnSequenceLength, 2025 ASSERT_EQ(Debug::kIa32JSReturnSequenceLength,
2026 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); 2026 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize));
2027 } 2027 }
2028 2028
2029 2029
2030 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) { 2030 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) {
2031 ASSERT(!in_spilled_code()); 2031 ASSERT(!in_spilled_code());
2032 Comment cmnt(masm_, "[ WithEnterStatement"); 2032 Comment cmnt(masm_, "[ WithEnterStatement");
2033 CodeForStatementPosition(node); 2033 CodeForStatementPosition(node);
2034 Load(node->expression()); 2034 Load(node->expression());
2035 Result context(this); 2035 Result context;
2036 if (node->is_catch_block()) { 2036 if (node->is_catch_block()) {
2037 context = frame_->CallRuntime(Runtime::kPushCatchContext, 1); 2037 context = frame_->CallRuntime(Runtime::kPushCatchContext, 1);
2038 } else { 2038 } else {
2039 context = frame_->CallRuntime(Runtime::kPushContext, 1); 2039 context = frame_->CallRuntime(Runtime::kPushContext, 1);
2040 } 2040 }
2041 2041
2042 // Update context local. 2042 // Update context local.
2043 frame_->SaveContextRegister(); 2043 frame_->SaveContextRegister();
2044 2044
2045 // Verify that the runtime call result and esi agree. 2045 // Verify that the runtime call result and esi agree.
(...skipping 888 matching lines...) Expand 10 before | Expand all | Expand 10 after
2934 // frame. 2934 // frame.
2935 frame_->EmitPop(Operand::StaticVariable(handler_address)); 2935 frame_->EmitPop(Operand::StaticVariable(handler_address));
2936 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); 2936 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
2937 if (has_unlinks) { 2937 if (has_unlinks) {
2938 exit.Jump(); 2938 exit.Jump();
2939 } 2939 }
2940 } 2940 }
2941 2941
2942 // Generate unlink code for the (formerly) shadowing targets that 2942 // Generate unlink code for the (formerly) shadowing targets that
2943 // have been jumped to. Deallocate each shadow target. 2943 // have been jumped to. Deallocate each shadow target.
2944 Result return_value(this); 2944 Result return_value;
2945 for (int i = 0; i < shadows.length(); i++) { 2945 for (int i = 0; i < shadows.length(); i++) {
2946 if (shadows[i]->is_linked()) { 2946 if (shadows[i]->is_linked()) {
2947 // Unlink from try chain; be careful not to destroy the TOS if 2947 // Unlink from try chain; be careful not to destroy the TOS if
2948 // there is one. 2948 // there is one.
2949 if (i == kReturnShadowIndex) { 2949 if (i == kReturnShadowIndex) {
2950 shadows[i]->Bind(&return_value); 2950 shadows[i]->Bind(&return_value);
2951 return_value.ToRegister(eax); 2951 return_value.ToRegister(eax);
2952 } else { 2952 } else {
2953 shadows[i]->Bind(); 2953 shadows[i]->Bind();
2954 } 2954 }
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
3066 } 3066 }
3067 3067
3068 // Generate code to unlink and set the state for the (formerly) 3068 // Generate code to unlink and set the state for the (formerly)
3069 // shadowing targets that have been jumped to. 3069 // shadowing targets that have been jumped to.
3070 for (int i = 0; i < shadows.length(); i++) { 3070 for (int i = 0; i < shadows.length(); i++) {
3071 if (shadows[i]->is_linked()) { 3071 if (shadows[i]->is_linked()) {
3072 // If we have come from the shadowed return, the return value is 3072 // If we have come from the shadowed return, the return value is
3073 // on the virtual frame. We must preserve it until it is 3073 // on the virtual frame. We must preserve it until it is
3074 // pushed. 3074 // pushed.
3075 if (i == kReturnShadowIndex) { 3075 if (i == kReturnShadowIndex) {
3076 Result return_value(this); 3076 Result return_value;
3077 shadows[i]->Bind(&return_value); 3077 shadows[i]->Bind(&return_value);
3078 return_value.ToRegister(eax); 3078 return_value.ToRegister(eax);
3079 } else { 3079 } else {
3080 shadows[i]->Bind(); 3080 shadows[i]->Bind();
3081 } 3081 }
3082 // Because we can be jumping here (to spilled code) from 3082 // Because we can be jumping here (to spilled code) from
3083 // unspilled code, we need to reestablish a spilled frame at 3083 // unspilled code, we need to reestablish a spilled frame at
3084 // this block. 3084 // this block.
3085 frame_->SpillAll(); 3085 frame_->SpillAll();
3086 3086
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
3249 exit.Bind(); 3249 exit.Bind();
3250 } 3250 }
3251 3251
3252 3252
3253 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { 3253 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
3254 if (slot->type() == Slot::LOOKUP) { 3254 if (slot->type() == Slot::LOOKUP) {
3255 ASSERT(slot->var()->is_dynamic()); 3255 ASSERT(slot->var()->is_dynamic());
3256 3256
3257 JumpTarget slow(this); 3257 JumpTarget slow(this);
3258 JumpTarget done(this); 3258 JumpTarget done(this);
3259 Result value(this); 3259 Result value;
3260 3260
3261 // Generate fast-case code for variables that might be shadowed by 3261 // Generate fast-case code for variables that might be shadowed by
3262 // eval-introduced variables. Eval is used a lot without 3262 // eval-introduced variables. Eval is used a lot without
3263 // introducing variables. In those cases, we do not want to 3263 // introducing variables. In those cases, we do not want to
3264 // perform a runtime call for all variables in the scope 3264 // perform a runtime call for all variables in the scope
3265 // containing the eval. 3265 // containing the eval.
3266 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) { 3266 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) {
3267 value = LoadFromGlobalSlotCheckExtensions(slot, typeof_state, &slow); 3267 value = LoadFromGlobalSlotCheckExtensions(slot, typeof_state, &slow);
3268 // If there was no control flow to slow, we can exit early. 3268 // If there was no control flow to slow, we can exit early.
3269 if (!slow.is_linked()) { 3269 if (!slow.is_linked()) {
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
3349 } 3349 }
3350 } 3350 }
3351 3351
3352 3352
3353 Result CodeGenerator::LoadFromGlobalSlotCheckExtensions( 3353 Result CodeGenerator::LoadFromGlobalSlotCheckExtensions(
3354 Slot* slot, 3354 Slot* slot,
3355 TypeofState typeof_state, 3355 TypeofState typeof_state,
3356 JumpTarget* slow) { 3356 JumpTarget* slow) {
3357 // Check that no extension objects have been created by calls to 3357 // Check that no extension objects have been created by calls to
3358 // eval from the current scope to the global scope. 3358 // eval from the current scope to the global scope.
3359 Result context(esi, this); 3359 Result context(esi);
3360 Result tmp = allocator_->Allocate(); 3360 Result tmp = allocator_->Allocate();
3361 ASSERT(tmp.is_valid()); // All non-reserved registers were available. 3361 ASSERT(tmp.is_valid()); // All non-reserved registers were available.
3362 3362
3363 Scope* s = scope(); 3363 Scope* s = scope();
3364 while (s != NULL) { 3364 while (s != NULL) {
3365 if (s->num_heap_slots() > 0) { 3365 if (s->num_heap_slots() > 0) {
3366 if (s->calls_eval()) { 3366 if (s->calls_eval()) {
3367 // Check that extension is NULL. 3367 // Check that extension is NULL.
3368 __ cmp(ContextOperand(context.reg(), Context::EXTENSION_INDEX), 3368 __ cmp(ContextOperand(context.reg(), Context::EXTENSION_INDEX),
3369 Immediate(0)); 3369 Immediate(0));
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
3424 3424
3425 3425
3426 void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) { 3426 void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) {
3427 if (slot->type() == Slot::LOOKUP) { 3427 if (slot->type() == Slot::LOOKUP) {
3428 ASSERT(slot->var()->is_dynamic()); 3428 ASSERT(slot->var()->is_dynamic());
3429 3429
3430 // For now, just do a runtime call. 3430 // For now, just do a runtime call.
3431 frame_->Push(esi); 3431 frame_->Push(esi);
3432 frame_->Push(slot->var()->name()); 3432 frame_->Push(slot->var()->name());
3433 3433
3434 Result value(this); 3434 Result value;
3435 if (init_state == CONST_INIT) { 3435 if (init_state == CONST_INIT) {
3436 // Same as the case for a normal store, but ignores attribute 3436 // Same as the case for a normal store, but ignores attribute
3437 // (e.g. READ_ONLY) of context slot so that we can initialize const 3437 // (e.g. READ_ONLY) of context slot so that we can initialize const
3438 // properties (introduced via eval("const foo = (some expr);")). Also, 3438 // properties (introduced via eval("const foo = (some expr);")). Also,
3439 // uses the current function context instead of the top context. 3439 // uses the current function context instead of the top context.
3440 // 3440 //
3441 // Note that we must declare the foo upon entry of eval(), via a 3441 // Note that we must declare the foo upon entry of eval(), via a
3442 // context slot declaration, but we cannot initialize it at the same 3442 // context slot declaration, but we cannot initialize it at the same
3443 // time, because the const declaration may be at the end of the eval 3443 // time, because the const declaration may be at the end of the eval
3444 // code (sigh...) and the const variable may have been used before 3444 // code (sigh...) and the const variable may have been used before
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
3567 } 3567 }
3568 3568
3569 virtual void Generate(); 3569 virtual void Generate();
3570 3570
3571 private: 3571 private:
3572 RegExpLiteral* node_; 3572 RegExpLiteral* node_;
3573 }; 3573 };
3574 3574
3575 3575
3576 void DeferredRegExpLiteral::Generate() { 3576 void DeferredRegExpLiteral::Generate() {
3577 Result literals(generator()); 3577 Result literals;
3578 enter()->Bind(&literals); 3578 enter()->Bind(&literals);
3579 // Since the entry is undefined we call the runtime system to 3579 // Since the entry is undefined we call the runtime system to
3580 // compute the literal. 3580 // compute the literal.
3581 3581
3582 VirtualFrame* frame = generator()->frame(); 3582 VirtualFrame* frame = generator()->frame();
3583 // Literal array (0). 3583 // Literal array (0).
3584 frame->Push(&literals); 3584 frame->Push(&literals);
3585 // Literal index (1). 3585 // Literal index (1).
3586 frame->Push(Smi::FromInt(node_->literal_index())); 3586 frame->Push(Smi::FromInt(node_->literal_index()));
3587 // RegExp pattern (2). 3587 // RegExp pattern (2).
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
3644 } 3644 }
3645 3645
3646 virtual void Generate(); 3646 virtual void Generate();
3647 3647
3648 private: 3648 private:
3649 ObjectLiteral* node_; 3649 ObjectLiteral* node_;
3650 }; 3650 };
3651 3651
3652 3652
3653 void DeferredObjectLiteral::Generate() { 3653 void DeferredObjectLiteral::Generate() {
3654 Result literals(generator()); 3654 Result literals;
3655 enter()->Bind(&literals); 3655 enter()->Bind(&literals);
3656 // Since the entry is undefined we call the runtime system to 3656 // Since the entry is undefined we call the runtime system to
3657 // compute the literal. 3657 // compute the literal.
3658 3658
3659 VirtualFrame* frame = generator()->frame(); 3659 VirtualFrame* frame = generator()->frame();
3660 // Literal array (0). 3660 // Literal array (0).
3661 frame->Push(&literals); 3661 frame->Push(&literals);
3662 // Literal index (1). 3662 // Literal index (1).
3663 frame->Push(Smi::FromInt(node_->literal_index())); 3663 frame->Push(Smi::FromInt(node_->literal_index()));
3664 // Constant properties (2). 3664 // Constant properties (2).
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
3782 } 3782 }
3783 3783
3784 virtual void Generate(); 3784 virtual void Generate();
3785 3785
3786 private: 3786 private:
3787 ArrayLiteral* node_; 3787 ArrayLiteral* node_;
3788 }; 3788 };
3789 3789
3790 3790
3791 void DeferredArrayLiteral::Generate() { 3791 void DeferredArrayLiteral::Generate() {
3792 Result literals(generator()); 3792 Result literals;
3793 enter()->Bind(&literals); 3793 enter()->Bind(&literals);
3794 // Since the entry is undefined we call the runtime system to 3794 // Since the entry is undefined we call the runtime system to
3795 // compute the literal. 3795 // compute the literal.
3796 3796
3797 VirtualFrame* frame = generator()->frame(); 3797 VirtualFrame* frame = generator()->frame();
3798 // Literal array (0). 3798 // Literal array (0).
3799 frame->Push(&literals); 3799 frame->Push(&literals);
3800 // Literal index (1). 3800 // Literal index (1).
3801 frame->Push(Smi::FromInt(node_->literal_index())); 3801 frame->Push(Smi::FromInt(node_->literal_index()));
3802 // Constant properties (2). 3802 // Constant properties (2).
(...skipping 628 matching lines...) Expand 10 before | Expand all | Expand 10 after
4431 value.Unuse(); 4431 value.Unuse();
4432 temp.Unuse(); 4432 temp.Unuse();
4433 destination()->Split(equal); 4433 destination()->Split(equal);
4434 } 4434 }
4435 4435
4436 4436
4437 void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) { 4437 void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) {
4438 ASSERT(args->length() == 0); 4438 ASSERT(args->length() == 0);
4439 // ArgumentsAccessStub takes the parameter count as an input argument 4439 // ArgumentsAccessStub takes the parameter count as an input argument
4440 // in register eax. Create a constant result for it. 4440 // in register eax. Create a constant result for it.
4441 Result count(Handle<Smi>(Smi::FromInt(scope_->num_parameters())), this); 4441 Result count(Handle<Smi>(Smi::FromInt(scope_->num_parameters())));
4442 // Call the shared stub to get to the arguments.length. 4442 // Call the shared stub to get to the arguments.length.
4443 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH); 4443 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH);
4444 Result result = frame_->CallStub(&stub, &count); 4444 Result result = frame_->CallStub(&stub, &count);
4445 frame_->Push(&result); 4445 frame_->Push(&result);
4446 } 4446 }
4447 4447
4448 4448
4449 void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) { 4449 void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) {
4450 ASSERT(args->length() == 1); 4450 ASSERT(args->length() == 1);
4451 JumpTarget leave(this); 4451 JumpTarget leave(this);
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
4514 4514
4515 4515
4516 void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) { 4516 void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) {
4517 ASSERT(args->length() == 1); 4517 ASSERT(args->length() == 1);
4518 4518
4519 // ArgumentsAccessStub expects the key in edx and the formal 4519 // ArgumentsAccessStub expects the key in edx and the formal
4520 // parameter count in eax. 4520 // parameter count in eax.
4521 Load(args->at(0)); 4521 Load(args->at(0));
4522 Result key = frame_->Pop(); 4522 Result key = frame_->Pop();
4523 // Explicitly create a constant result. 4523 // Explicitly create a constant result.
4524 Result count(Handle<Smi>(Smi::FromInt(scope_->num_parameters())), this); 4524 Result count(Handle<Smi>(Smi::FromInt(scope_->num_parameters())));
4525 // Call the shared stub to get to arguments[key]. 4525 // Call the shared stub to get to arguments[key].
4526 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); 4526 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
4527 Result result = frame_->CallStub(&stub, &key, &count); 4527 Result result = frame_->CallStub(&stub, &key, &count);
4528 frame_->Push(&result); 4528 frame_->Push(&result);
4529 } 4529 }
4530 4530
4531 4531
4532 void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) { 4532 void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) {
4533 ASSERT(args->length() == 2); 4533 ASSERT(args->length() == 2);
4534 4534
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after
4764 4764
4765 private: 4765 private:
4766 bool is_postfix_; 4766 bool is_postfix_;
4767 bool is_increment_; 4767 bool is_increment_;
4768 int target_size_; 4768 int target_size_;
4769 }; 4769 };
4770 4770
4771 4771
4772 void DeferredCountOperation::Generate() { 4772 void DeferredCountOperation::Generate() {
4773 CodeGenerator* cgen = generator(); 4773 CodeGenerator* cgen = generator();
4774 Result value(cgen); 4774 Result value;
4775 enter()->Bind(&value); 4775 enter()->Bind(&value);
4776 VirtualFrame* frame = cgen->frame(); 4776 VirtualFrame* frame = cgen->frame();
4777 // Undo the optimistic smi operation. 4777 // Undo the optimistic smi operation.
4778 value.ToRegister(); 4778 value.ToRegister();
4779 frame->Spill(value.reg()); 4779 frame->Spill(value.reg());
4780 if (is_increment_) { 4780 if (is_increment_) {
4781 __ sub(Operand(value.reg()), Immediate(Smi::FromInt(1))); 4781 __ sub(Operand(value.reg()), Immediate(Smi::FromInt(1)));
4782 } else { 4782 } else {
4783 __ add(Operand(value.reg()), Immediate(Smi::FromInt(1))); 4783 __ add(Operand(value.reg()), Immediate(Smi::FromInt(1)));
4784 } 4784 }
(...skipping 477 matching lines...) Expand 10 before | Expand all | Expand 10 after
5262 Label* patch_site() { return &patch_site_; } 5262 Label* patch_site() { return &patch_site_; }
5263 5263
5264 private: 5264 private:
5265 Label patch_site_; 5265 Label patch_site_;
5266 Handle<String> name_; 5266 Handle<String> name_;
5267 }; 5267 };
5268 5268
5269 5269
5270 void DeferredReferenceGetNamedValue::Generate() { 5270 void DeferredReferenceGetNamedValue::Generate() {
5271 CodeGenerator* cgen = generator(); 5271 CodeGenerator* cgen = generator();
5272 Result receiver(cgen); 5272 Result receiver;
5273 enter()->Bind(&receiver); 5273 enter()->Bind(&receiver);
5274 5274
5275 cgen->frame()->Push(&receiver); 5275 cgen->frame()->Push(&receiver);
5276 cgen->frame()->Push(name_); 5276 cgen->frame()->Push(name_);
5277 Result answer = cgen->frame()->CallLoadIC(RelocInfo::CODE_TARGET); 5277 Result answer = cgen->frame()->CallLoadIC(RelocInfo::CODE_TARGET);
5278 // The call must be followed by a test eax instruction to indicate 5278 // The call must be followed by a test eax instruction to indicate
5279 // that the inobject property case was inlined. 5279 // that the inobject property case was inlined.
5280 ASSERT(answer.is_register() && answer.reg().is(eax)); 5280 ASSERT(answer.is_register() && answer.reg().is(eax));
5281 // Store the delta to the map check instruction here in the test instruction. 5281 // Store the delta to the map check instruction here in the test instruction.
5282 // Use masm_-> instead of the double underscore macro since the latter can't 5282 // Use masm_-> instead of the double underscore macro since the latter can't
(...skipping 21 matching lines...) Expand all
5304 Label* patch_site() { return &patch_site_; } 5304 Label* patch_site() { return &patch_site_; }
5305 5305
5306 private: 5306 private:
5307 Label patch_site_; 5307 Label patch_site_;
5308 bool is_global_; 5308 bool is_global_;
5309 }; 5309 };
5310 5310
5311 5311
5312 void DeferredReferenceGetKeyedValue::Generate() { 5312 void DeferredReferenceGetKeyedValue::Generate() {
5313 CodeGenerator* cgen = generator(); 5313 CodeGenerator* cgen = generator();
5314 Result receiver(cgen); 5314 Result receiver;
5315 Result key(cgen); 5315 Result key;
5316 enter()->Bind(&receiver, &key); 5316 enter()->Bind(&receiver, &key);
5317 cgen->frame()->Push(&receiver); // First IC argument. 5317 cgen->frame()->Push(&receiver); // First IC argument.
5318 cgen->frame()->Push(&key); // Second IC argument. 5318 cgen->frame()->Push(&key); // Second IC argument.
5319 5319
5320 // Calculate the delta from the IC call instruction to the map check 5320 // Calculate the delta from the IC call instruction to the map check
5321 // cmp instruction in the inlined version. This delta is stored in 5321 // cmp instruction in the inlined version. This delta is stored in
5322 // a test(eax, delta) instruction after the call so that we can find 5322 // a test(eax, delta) instruction after the call so that we can find
5323 // it in the IC initialization code and patch the cmp instruction. 5323 // it in the IC initialization code and patch the cmp instruction.
5324 // This means that we cannot allow test instructions after calls to 5324 // This means that we cannot allow test instructions after calls to
5325 // KeyedLoadIC stubs in other places. 5325 // KeyedLoadIC stubs in other places.
(...skipping 1912 matching lines...) Expand 10 before | Expand all | Expand 10 after
7238 7238
7239 // Slow-case: Go through the JavaScript implementation. 7239 // Slow-case: Go through the JavaScript implementation.
7240 __ bind(&slow); 7240 __ bind(&slow);
7241 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 7241 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
7242 } 7242 }
7243 7243
7244 7244
7245 #undef __ 7245 #undef __
7246 7246
7247 } } // namespace v8::internal 7247 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698