OLD | NEW |
---|---|
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 1203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1214 | 1214 |
1215 // Duplicate the switch value. | 1215 // Duplicate the switch value. |
1216 frame_->Dup(); | 1216 frame_->Dup(); |
1217 | 1217 |
1218 // Compile the label expression. | 1218 // Compile the label expression. |
1219 Load(clause->label()); | 1219 Load(clause->label()); |
1220 | 1220 |
1221 // Compare and branch to the body if true or the next test if | 1221 // Compare and branch to the body if true or the next test if |
1222 // false. Prefer the next test as a fall through. | 1222 // false. Prefer the next test as a fall through. |
1223 ControlDestination dest(clause->body_target(), &next_test, false); | 1223 ControlDestination dest(clause->body_target(), &next_test, false); |
1224 Comparison(equal, true, &dest); | 1224 Comparison(node, equal, true, &dest); |
1225 | 1225 |
1226 // If the comparison fell through to the true target, jump to the | 1226 // If the comparison fell through to the true target, jump to the |
1227 // actual body. | 1227 // actual body. |
1228 if (dest.true_was_fall_through()) { | 1228 if (dest.true_was_fall_through()) { |
1229 clause->body_target()->Unuse(); | 1229 clause->body_target()->Unuse(); |
1230 clause->body_target()->Jump(); | 1230 clause->body_target()->Jump(); |
1231 } | 1231 } |
1232 } | 1232 } |
1233 | 1233 |
1234 // If there was control flow to a next test from the last one | 1234 // If there was control flow to a next test from the last one |
(...skipping 2343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3578 __ testq(answer.reg(), answer.reg()); | 3578 __ testq(answer.reg(), answer.reg()); |
3579 answer.Unuse(); | 3579 answer.Unuse(); |
3580 destination()->Split(zero); | 3580 destination()->Split(zero); |
3581 return; | 3581 return; |
3582 } | 3582 } |
3583 default: | 3583 default: |
3584 UNREACHABLE(); | 3584 UNREACHABLE(); |
3585 } | 3585 } |
3586 Load(left); | 3586 Load(left); |
3587 Load(right); | 3587 Load(right); |
3588 Comparison(cc, strict, destination()); | 3588 Comparison(node, cc, strict, destination()); |
3589 } | 3589 } |
3590 | 3590 |
3591 | 3591 |
3592 void CodeGenerator::VisitThisFunction(ThisFunction* node) { | 3592 void CodeGenerator::VisitThisFunction(ThisFunction* node) { |
3593 frame_->PushFunction(); | 3593 frame_->PushFunction(); |
3594 } | 3594 } |
3595 | 3595 |
3596 | 3596 |
3597 void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) { | 3597 void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) { |
3598 ASSERT(args->length() == 1); | 3598 ASSERT(args->length() == 1); |
(...skipping 1261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4860 // For a variable that rewrites to a slot, we signal it is the immediate | 4860 // For a variable that rewrites to a slot, we signal it is the immediate |
4861 // subexpression of a typeof. | 4861 // subexpression of a typeof. |
4862 LoadFromSlotCheckForArguments(variable->slot(), INSIDE_TYPEOF); | 4862 LoadFromSlotCheckForArguments(variable->slot(), INSIDE_TYPEOF); |
4863 } else { | 4863 } else { |
4864 // Anything else can be handled normally. | 4864 // Anything else can be handled normally. |
4865 Load(expr); | 4865 Load(expr); |
4866 } | 4866 } |
4867 } | 4867 } |
4868 | 4868 |
4869 | 4869 |
4870 void CodeGenerator::Comparison(Condition cc, | 4870 void CodeGenerator::Comparison(AstNode* node, |
4871 Condition cc, | |
4871 bool strict, | 4872 bool strict, |
4872 ControlDestination* dest) { | 4873 ControlDestination* dest) { |
4873 // Strict only makes sense for equality comparisons. | 4874 // Strict only makes sense for equality comparisons. |
4874 ASSERT(!strict || cc == equal); | 4875 ASSERT(!strict || cc == equal); |
4875 | 4876 |
4876 Result left_side; | 4877 Result left_side; |
4877 Result right_side; | 4878 Result right_side; |
4878 // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order. | 4879 // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order. |
4879 if (cc == greater || cc == less_equal) { | 4880 if (cc == greater || cc == less_equal) { |
4880 cc = ReverseCondition(cc); | 4881 cc = ReverseCondition(cc); |
(...skipping 26 matching lines...) Expand all Loading... | |
4907 break; | 4908 break; |
4908 case equal: | 4909 case equal: |
4909 dest->Goto(left_value == right_value); | 4910 dest->Goto(left_value == right_value); |
4910 break; | 4911 break; |
4911 case greater_equal: | 4912 case greater_equal: |
4912 dest->Goto(left_value >= right_value); | 4913 dest->Goto(left_value >= right_value); |
4913 break; | 4914 break; |
4914 default: | 4915 default: |
4915 UNREACHABLE(); | 4916 UNREACHABLE(); |
4916 } | 4917 } |
4917 } else { // Only one side is a constant Smi. | 4918 } else { |
4919 // Only one side is a constant Smi. | |
4918 // If left side is a constant Smi, reverse the operands. | 4920 // If left side is a constant Smi, reverse the operands. |
4919 // Since one side is a constant Smi, conversion order does not matter. | 4921 // Since one side is a constant Smi, conversion order does not matter. |
4920 if (left_side_constant_smi) { | 4922 if (left_side_constant_smi) { |
4921 Result temp = left_side; | 4923 Result temp = left_side; |
4922 left_side = right_side; | 4924 left_side = right_side; |
4923 right_side = temp; | 4925 right_side = temp; |
4924 cc = ReverseCondition(cc); | 4926 cc = ReverseCondition(cc); |
4925 // This may reintroduce greater or less_equal as the value of cc. | 4927 // This may reintroduce greater or less_equal as the value of cc. |
4926 // CompareStub and the inline code both support all values of cc. | 4928 // CompareStub and the inline code both support all values of cc. |
4927 } | 4929 } |
4928 // Implement comparison against a constant Smi, inlining the case | 4930 // Implement comparison against a constant Smi, inlining the case |
4929 // where both sides are Smis. | 4931 // where both sides are Smis. |
4930 left_side.ToRegister(); | 4932 left_side.ToRegister(); |
4933 Register left_reg = left_side.reg(); | |
4934 Handle<Object> right_val = right_side.handle(); | |
4931 | 4935 |
4932 // Here we split control flow to the stub call and inlined cases | 4936 // Here we split control flow to the stub call and inlined cases |
4933 // before finally splitting it to the control destination. We use | 4937 // before finally splitting it to the control destination. We use |
4934 // a jump target and branching to duplicate the virtual frame at | 4938 // a jump target and branching to duplicate the virtual frame at |
4935 // the first split. We manually handle the off-frame references | 4939 // the first split. We manually handle the off-frame references |
4936 // by reconstituting them on the non-fall-through path. | 4940 // by reconstituting them on the non-fall-through path. |
4937 JumpTarget is_smi; | 4941 JumpTarget is_smi; |
4938 Register left_reg = left_side.reg(); | |
4939 Handle<Object> right_val = right_side.handle(); | |
4940 | 4942 |
4941 Condition left_is_smi = masm_->CheckSmi(left_side.reg()); | 4943 Condition left_is_smi = masm_->CheckSmi(left_side.reg()); |
4942 is_smi.Branch(left_is_smi); | 4944 is_smi.Branch(left_is_smi); |
4943 | 4945 |
4946 bool is_for_loop_compare = (node->AsCompareOperation() != NULL) | |
4947 && node->AsCompareOperation()->is_for_loop_condition(); | |
4948 if (&& right_val->IsSmi()) { | |
Søren Thygesen Gjesse
2010/02/09 12:24:01
is_for_loop_compare missing before &&?
| |
4949 // Right side is a constant smi and left side has been checked | |
4950 // not to be a smi. | |
4951 JumpTarget not_number; | |
4952 __ Cmp(FieldOperand(left_reg, HeapObject::kMapOffset), | |
4953 Factory::heap_number_map()); | |
4954 not_number.Branch(not_equal, &left_side); | |
4955 __ movsd(xmm1, | |
4956 FieldOperand(left_reg, HeapNumber::kValueOffset)); | |
4957 int value = Smi::cast(*right_val)->value(); | |
4958 if (value == 0) { | |
4959 __ xorpd(xmm0, xmm0); | |
4960 } else { | |
4961 Result temp = allocator()->Allocate(); | |
4962 __ movl(temp.reg(), Immediate(value)); | |
4963 __ cvtlsi2sd(xmm0, temp.reg()); | |
4964 temp.Unuse(); | |
4965 } | |
4966 __ ucomisd(xmm1, xmm0); | |
4967 // Jump to builtin for NaN. | |
4968 not_number.Branch(parity_even, &left_side); | |
4969 left_side.Unuse(); | |
4970 Condition double_cc = cc; | |
4971 switch (cc) { | |
4972 case less: double_cc = below; break; | |
4973 case equal: double_cc = equal; break; | |
4974 case less_equal: double_cc = below_equal; break; | |
4975 case greater: double_cc = above; break; | |
4976 case greater_equal: double_cc = above_equal; break; | |
4977 default: UNREACHABLE(); | |
4978 } | |
4979 dest->true_target()->Branch(double_cc); | |
4980 dest->false_target()->Jump(); | |
4981 not_number.Bind(&left_side); | |
4982 } | |
4983 | |
4944 // Setup and call the compare stub. | 4984 // Setup and call the compare stub. |
4945 CompareStub stub(cc, strict); | 4985 CompareStub stub(cc, strict); |
4946 Result result = frame_->CallStub(&stub, &left_side, &right_side); | 4986 Result result = frame_->CallStub(&stub, &left_side, &right_side); |
4947 result.ToRegister(); | 4987 result.ToRegister(); |
4948 __ testq(result.reg(), result.reg()); | 4988 __ testq(result.reg(), result.reg()); |
4949 result.Unuse(); | 4989 result.Unuse(); |
4950 dest->true_target()->Branch(cc); | 4990 dest->true_target()->Branch(cc); |
4951 dest->false_target()->Jump(); | 4991 dest->false_target()->Jump(); |
4952 | 4992 |
4953 is_smi.Bind(); | 4993 is_smi.Bind(); |
(...skipping 4236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
9190 // Call the function from C++. | 9230 // Call the function from C++. |
9191 return FUNCTION_CAST<ModuloFunction>(buffer); | 9231 return FUNCTION_CAST<ModuloFunction>(buffer); |
9192 } | 9232 } |
9193 | 9233 |
9194 #endif | 9234 #endif |
9195 | 9235 |
9196 | 9236 |
9197 #undef __ | 9237 #undef __ |
9198 | 9238 |
9199 } } // namespace v8::internal | 9239 } } // namespace v8::internal |
OLD | NEW |