| OLD | NEW |
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 396 } | 396 } |
| 397 | 397 |
| 398 | 398 |
| 399 void CodeGenerator::Load(Expression* x, TypeofState typeof_state) { | 399 void CodeGenerator::Load(Expression* x, TypeofState typeof_state) { |
| 400 JumpTarget true_target(this); | 400 JumpTarget true_target(this); |
| 401 JumpTarget false_target(this); | 401 JumpTarget false_target(this); |
| 402 LoadCondition(x, typeof_state, &true_target, &false_target, false); | 402 LoadCondition(x, typeof_state, &true_target, &false_target, false); |
| 403 | 403 |
| 404 if (has_cc()) { | 404 if (has_cc()) { |
| 405 ASSERT(frame_ != NULL); | 405 ASSERT(frame_ != NULL); |
| 406 frame_->SpillAll(); |
| 406 // Convert cc_reg_ into a boolean value. | 407 // Convert cc_reg_ into a boolean value. |
| 407 JumpTarget loaded(this); | 408 JumpTarget loaded(this); |
| 408 JumpTarget materialize_true(this); | 409 JumpTarget materialize_true(this); |
| 409 materialize_true.Branch(cc_reg_); | 410 materialize_true.Branch(cc_reg_); |
| 410 frame_->EmitPush(Immediate(Factory::false_value())); | 411 frame_->EmitPush(Immediate(Factory::false_value())); |
| 411 loaded.Jump(); | 412 loaded.Jump(); |
| 412 materialize_true.Bind(); | 413 materialize_true.Bind(); |
| 413 frame_->EmitPush(Immediate(Factory::true_value())); | 414 frame_->EmitPush(Immediate(Factory::true_value())); |
| 414 loaded.Bind(); | 415 loaded.Bind(); |
| 415 cc_reg_ = no_condition; | 416 cc_reg_ = no_condition; |
| 416 } | 417 } |
| 417 | 418 |
| 418 if (true_target.is_linked() || false_target.is_linked()) { | 419 if (true_target.is_linked() || false_target.is_linked()) { |
| 419 // We have at least one condition value that has been "translated" into | 420 // We have at least one condition value that has been "translated" into |
| 420 // a branch, thus it needs to be loaded explicitly. | 421 // a branch, thus it needs to be loaded explicitly. |
| 421 JumpTarget loaded(this); | 422 JumpTarget loaded(this); |
| 422 if (frame_ != NULL) { | 423 if (frame_ != NULL) { |
| 423 loaded.Jump(); // Don't lose the current TOS. | 424 loaded.Jump(); // Don't lose the current TOS. |
| 424 } | 425 } |
| 425 bool both = true_target.is_linked() && false_target.is_linked(); | 426 bool both = true_target.is_linked() && false_target.is_linked(); |
| 426 // Load "true" if necessary. | 427 // Load "true" if necessary. |
| 427 if (true_target.is_linked()) { | 428 if (true_target.is_linked()) { |
| 428 true_target.Bind(); | 429 true_target.Bind(); |
| 430 frame_->SpillAll(); |
| 429 frame_->EmitPush(Immediate(Factory::true_value())); | 431 frame_->EmitPush(Immediate(Factory::true_value())); |
| 430 } | 432 } |
| 431 // If both "true" and "false" need to be reincarnated jump across the | 433 // If both "true" and "false" need to be reincarnated jump across the |
| 432 // code for "false". | 434 // code for "false". |
| 433 if (both) { | 435 if (both) { |
| 434 loaded.Jump(); | 436 loaded.Jump(); |
| 435 } | 437 } |
| 436 // Load "false" if necessary. | 438 // Load "false" if necessary. |
| 437 if (false_target.is_linked()) { | 439 if (false_target.is_linked()) { |
| 438 false_target.Bind(); | 440 false_target.Bind(); |
| 441 frame_->SpillAll(); |
| 439 frame_->EmitPush(Immediate(Factory::false_value())); | 442 frame_->EmitPush(Immediate(Factory::false_value())); |
| 440 } | 443 } |
| 441 // A value is loaded on all paths reaching this point. | 444 // A value is loaded on all paths reaching this point. |
| 442 loaded.Bind(); | 445 loaded.Bind(); |
| 443 } | 446 } |
| 444 ASSERT(frame_ != NULL); | 447 ASSERT(frame_ != NULL); |
| 445 ASSERT(!has_cc()); | 448 ASSERT(!has_cc()); |
| 446 } | 449 } |
| 447 | 450 |
| 448 | 451 |
| (...skipping 729 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1178 done.Bind(); | 1181 done.Bind(); |
| 1179 cc_reg_ = cc; | 1182 cc_reg_ = cc; |
| 1180 } | 1183 } |
| 1181 | 1184 |
| 1182 | 1185 |
| 1183 class SmiComparisonDeferred: public DeferredCode { | 1186 class SmiComparisonDeferred: public DeferredCode { |
| 1184 public: | 1187 public: |
| 1185 SmiComparisonDeferred(CodeGenerator* generator, | 1188 SmiComparisonDeferred(CodeGenerator* generator, |
| 1186 Condition cc, | 1189 Condition cc, |
| 1187 bool strict, | 1190 bool strict, |
| 1188 int value) | 1191 Register left_side, |
| 1189 : DeferredCode(generator), cc_(cc), strict_(strict), value_(value) { | 1192 int right_side) : |
| 1193 DeferredCode(generator), |
| 1194 cc_(cc), |
| 1195 strict_(strict), |
| 1196 left_side_(left_side), |
| 1197 right_side_(right_side) { |
| 1190 set_comment("[ ComparisonDeferred"); | 1198 set_comment("[ ComparisonDeferred"); |
| 1191 } | 1199 } |
| 1192 virtual void Generate(); | 1200 virtual void Generate(); |
| 1193 | 1201 |
| 1194 private: | 1202 private: |
| 1195 Condition cc_; | 1203 Condition cc_; |
| 1196 bool strict_; | 1204 bool strict_; |
| 1197 int value_; | 1205 Register left_side_; |
| 1206 int right_side_; |
| 1198 }; | 1207 }; |
| 1199 | 1208 |
| 1200 | 1209 |
| 1201 void SmiComparisonDeferred::Generate() { | 1210 void SmiComparisonDeferred::Generate() { |
| 1202 CompareStub stub(cc_, strict_); | 1211 CompareStub stub(cc_, strict_); |
| 1203 // Setup parameters and call stub. | 1212 // Setup parameters and call stub. |
| 1204 __ mov(edx, Operand(eax)); | 1213 if (!left_side_.is(edx)) { |
| 1205 __ Set(eax, Immediate(Smi::FromInt(value_))); | 1214 __ mov(edx, Operand(left_side_)); |
| 1215 } |
| 1216 __ Set(eax, Immediate(Smi::FromInt(right_side_))); |
| 1206 __ CallStub(&stub); | 1217 __ CallStub(&stub); |
| 1207 __ cmp(eax, 0); | 1218 __ cmp(eax, 0); |
| 1208 // "result" is returned in the flags | 1219 // "result" is returned in the flags. |
| 1209 } | 1220 } |
| 1210 | 1221 |
| 1211 | 1222 |
| 1212 void CodeGenerator::SmiComparison(Condition cc, | 1223 void CodeGenerator::SmiComparison(Condition cc, |
| 1213 Handle<Object> value, | 1224 Handle<Object> value, |
| 1214 bool strict) { | 1225 bool strict) { |
| 1215 // Strict only makes sense for equality comparisons. | 1226 // Strict only makes sense for equality comparisons. |
| 1216 ASSERT(!strict || cc == equal); | 1227 ASSERT(!strict || cc == equal); |
| 1217 | 1228 |
| 1218 int int_value = Smi::cast(*value)->value(); | 1229 int int_value = Smi::cast(*value)->value(); |
| 1219 ASSERT(is_intn(int_value, kMaxSmiInlinedBits)); | 1230 ASSERT(is_intn(int_value, kMaxSmiInlinedBits)); |
| 1220 | 1231 |
| 1232 Result comparee = frame_->Pop(); |
| 1233 comparee.ToRegister(); |
| 1234 Register reg = comparee.reg(); |
| 1235 __ test(reg, Immediate(kSmiTagMask)); |
| 1221 SmiComparisonDeferred* deferred = | 1236 SmiComparisonDeferred* deferred = |
| 1222 new SmiComparisonDeferred(this, cc, strict, int_value); | 1237 new SmiComparisonDeferred(this, cc, strict, reg, int_value); |
| 1223 frame_->EmitPop(eax); | |
| 1224 __ test(eax, Immediate(kSmiTagMask)); | |
| 1225 deferred->enter()->Branch(not_zero, not_taken); | 1238 deferred->enter()->Branch(not_zero, not_taken); |
| 1226 // Test smi equality by pointer comparison. | 1239 // Test smi equality and comparison by signed int comparison. |
| 1227 __ cmp(Operand(eax), Immediate(value)); | 1240 __ cmp(Operand(reg), Immediate(value)); |
| 1241 comparee.Unuse(); |
| 1228 deferred->exit()->Bind(); | 1242 deferred->exit()->Bind(); |
| 1229 cc_reg_ = cc; | 1243 cc_reg_ = cc; |
| 1230 } | 1244 } |
| 1231 | 1245 |
| 1232 | 1246 |
| 1233 class CallFunctionStub: public CodeStub { | 1247 class CallFunctionStub: public CodeStub { |
| 1234 public: | 1248 public: |
| 1235 explicit CallFunctionStub(int argc) : argc_(argc) { } | 1249 explicit CallFunctionStub(int argc) : argc_(argc) { } |
| 1236 | 1250 |
| 1237 void Generate(MacroAssembler* masm); | 1251 void Generate(MacroAssembler* masm); |
| (...skipping 2741 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3979 // literal 'null'. If so, we optimize the code by inlining a null check | 3993 // literal 'null'. If so, we optimize the code by inlining a null check |
| 3980 // instead of calling the (very) general runtime routine for checking | 3994 // instead of calling the (very) general runtime routine for checking |
| 3981 // equality. | 3995 // equality. |
| 3982 if (op == Token::EQ || op == Token::EQ_STRICT) { | 3996 if (op == Token::EQ || op == Token::EQ_STRICT) { |
| 3983 bool left_is_null = | 3997 bool left_is_null = |
| 3984 left->AsLiteral() != NULL && left->AsLiteral()->IsNull(); | 3998 left->AsLiteral() != NULL && left->AsLiteral()->IsNull(); |
| 3985 bool right_is_null = | 3999 bool right_is_null = |
| 3986 right->AsLiteral() != NULL && right->AsLiteral()->IsNull(); | 4000 right->AsLiteral() != NULL && right->AsLiteral()->IsNull(); |
| 3987 // The 'null' value can only be equal to 'null' or 'undefined'. | 4001 // The 'null' value can only be equal to 'null' or 'undefined'. |
| 3988 if (left_is_null || right_is_null) { | 4002 if (left_is_null || right_is_null) { |
| 4003 frame_->SpillAll(); |
| 3989 Load(left_is_null ? right : left); | 4004 Load(left_is_null ? right : left); |
| 3990 frame_->SpillAll(); | 4005 frame_->SpillAll(); |
| 3991 frame_->EmitPop(eax); | 4006 frame_->EmitPop(eax); |
| 3992 __ cmp(eax, Factory::null_value()); | 4007 __ cmp(eax, Factory::null_value()); |
| 3993 | 4008 |
| 3994 // The 'null' value is only equal to 'undefined' if using non-strict | 4009 // The 'null' value is only equal to 'undefined' if using non-strict |
| 3995 // comparisons. | 4010 // comparisons. |
| 3996 if (op != Token::EQ_STRICT) { | 4011 if (op != Token::EQ_STRICT) { |
| 3997 true_target()->Branch(equal); | 4012 true_target()->Branch(equal); |
| 3998 | 4013 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 4017 // To make typeof testing for natives implemented in JavaScript really | 4032 // To make typeof testing for natives implemented in JavaScript really |
| 4018 // efficient, we generate special code for expressions of the form: | 4033 // efficient, we generate special code for expressions of the form: |
| 4019 // 'typeof <expression> == <string>'. | 4034 // 'typeof <expression> == <string>'. |
| 4020 UnaryOperation* operation = left->AsUnaryOperation(); | 4035 UnaryOperation* operation = left->AsUnaryOperation(); |
| 4021 if ((op == Token::EQ || op == Token::EQ_STRICT) && | 4036 if ((op == Token::EQ || op == Token::EQ_STRICT) && |
| 4022 (operation != NULL && operation->op() == Token::TYPEOF) && | 4037 (operation != NULL && operation->op() == Token::TYPEOF) && |
| 4023 (right->AsLiteral() != NULL && | 4038 (right->AsLiteral() != NULL && |
| 4024 right->AsLiteral()->handle()->IsString())) { | 4039 right->AsLiteral()->handle()->IsString())) { |
| 4025 Handle<String> check(String::cast(*right->AsLiteral()->handle())); | 4040 Handle<String> check(String::cast(*right->AsLiteral()->handle())); |
| 4026 | 4041 |
| 4042 frame_->SpillAll(); |
| 4027 // Load the operand and move it to register edx. | 4043 // Load the operand and move it to register edx. |
| 4028 LoadTypeofExpression(operation->expression()); | 4044 LoadTypeofExpression(operation->expression()); |
| 4029 frame_->SpillAll(); | 4045 frame_->SpillAll(); |
| 4030 frame_->EmitPop(edx); | 4046 frame_->EmitPop(edx); |
| 4031 | 4047 |
| 4032 if (check->Equals(Heap::number_symbol())) { | 4048 if (check->Equals(Heap::number_symbol())) { |
| 4033 __ test(edx, Immediate(kSmiTagMask)); | 4049 __ test(edx, Immediate(kSmiTagMask)); |
| 4034 true_target()->Branch(zero); | 4050 true_target()->Branch(zero); |
| 4035 __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset)); | 4051 __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset)); |
| 4036 __ cmp(edx, Factory::heap_number_map()); | 4052 __ cmp(edx, Factory::heap_number_map()); |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4126 case Token::GT: | 4142 case Token::GT: |
| 4127 cc = greater; | 4143 cc = greater; |
| 4128 break; | 4144 break; |
| 4129 case Token::LTE: | 4145 case Token::LTE: |
| 4130 cc = less_equal; | 4146 cc = less_equal; |
| 4131 break; | 4147 break; |
| 4132 case Token::GTE: | 4148 case Token::GTE: |
| 4133 cc = greater_equal; | 4149 cc = greater_equal; |
| 4134 break; | 4150 break; |
| 4135 case Token::IN: { | 4151 case Token::IN: { |
| 4152 frame_->SpillAll(); |
| 4136 Load(left); | 4153 Load(left); |
| 4137 frame_->SpillAll(); | 4154 frame_->SpillAll(); |
| 4138 Load(right); | 4155 Load(right); |
| 4139 frame_->SpillAll(); | 4156 frame_->SpillAll(); |
| 4140 frame_->InvokeBuiltin(Builtins::IN, CALL_FUNCTION, 2); | 4157 frame_->InvokeBuiltin(Builtins::IN, CALL_FUNCTION, 2); |
| 4141 frame_->EmitPush(eax); // push the result | 4158 frame_->EmitPush(eax); // push the result |
| 4142 return; | 4159 return; |
| 4143 } | 4160 } |
| 4144 case Token::INSTANCEOF: { | 4161 case Token::INSTANCEOF: { |
| 4162 frame_->SpillAll(); |
| 4145 Load(left); | 4163 Load(left); |
| 4146 frame_->SpillAll(); | 4164 frame_->SpillAll(); |
| 4147 Load(right); | 4165 Load(right); |
| 4148 frame_->SpillAll(); | 4166 frame_->SpillAll(); |
| 4149 InstanceofStub stub; | 4167 InstanceofStub stub; |
| 4150 frame_->CallStub(&stub, 2); | 4168 frame_->CallStub(&stub, 2); |
| 4151 __ test(eax, Operand(eax)); | 4169 __ test(eax, Operand(eax)); |
| 4152 cc_reg_ = zero; | 4170 cc_reg_ = zero; |
| 4153 return; | 4171 return; |
| 4154 } | 4172 } |
| 4155 default: | 4173 default: |
| 4156 UNREACHABLE(); | 4174 UNREACHABLE(); |
| 4157 } | 4175 } |
| 4158 | 4176 |
| 4159 // Optimize for the case where (at least) one of the expressions | 4177 // Optimize for the case where (at least) one of the expressions |
| 4160 // is a literal small integer. | 4178 // is a literal small integer. |
| 4161 if (IsInlineSmi(left->AsLiteral())) { | 4179 if (IsInlineSmi(left->AsLiteral())) { |
| 4180 frame_->SpillAll(); |
| 4162 Load(right); | 4181 Load(right); |
| 4163 frame_->SpillAll(); | 4182 frame_->SpillAll(); |
| 4164 SmiComparison(ReverseCondition(cc), left->AsLiteral()->handle(), strict); | 4183 SmiComparison(ReverseCondition(cc), left->AsLiteral()->handle(), strict); |
| 4165 return; | 4184 return; |
| 4166 } | 4185 } |
| 4167 if (IsInlineSmi(right->AsLiteral())) { | 4186 if (IsInlineSmi(right->AsLiteral())) { |
| 4168 Load(left); | 4187 Load(left); |
| 4169 frame_->SpillAll(); | |
| 4170 SmiComparison(cc, right->AsLiteral()->handle(), strict); | 4188 SmiComparison(cc, right->AsLiteral()->handle(), strict); |
| 4171 return; | 4189 return; |
| 4172 } | 4190 } |
| 4173 | 4191 |
| 4192 frame_->SpillAll(); |
| 4174 Load(left); | 4193 Load(left); |
| 4175 frame_->SpillAll(); | 4194 frame_->SpillAll(); |
| 4176 Load(right); | 4195 Load(right); |
| 4177 frame_->SpillAll(); | 4196 frame_->SpillAll(); |
| 4178 Comparison(cc, strict); | 4197 Comparison(cc, strict); |
| 4179 } | 4198 } |
| 4180 | 4199 |
| 4181 | 4200 |
| 4182 void CodeGenerator::RecordStatementPosition(Node* node) { | 4201 void CodeGenerator::RecordStatementPosition(Node* node) { |
| 4183 if (FLAG_debug_info) { | 4202 if (FLAG_debug_info) { |
| (...skipping 1521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5705 | 5724 |
| 5706 // Slow-case: Go through the JavaScript implementation. | 5725 // Slow-case: Go through the JavaScript implementation. |
| 5707 __ bind(&slow); | 5726 __ bind(&slow); |
| 5708 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 5727 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
| 5709 } | 5728 } |
| 5710 | 5729 |
| 5711 | 5730 |
| 5712 #undef __ | 5731 #undef __ |
| 5713 | 5732 |
| 5714 } } // namespace v8::internal | 5733 } } // namespace v8::internal |
| OLD | NEW |