OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |