OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 3820 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3831 | 3831 |
3832 context()->Plug(rax); | 3832 context()->Plug(rax); |
3833 } else { | 3833 } else { |
3834 // This expression cannot throw a reference error at the top level. | 3834 // This expression cannot throw a reference error at the top level. |
3835 VisitInCurrentContext(expr); | 3835 VisitInCurrentContext(expr); |
3836 } | 3836 } |
3837 } | 3837 } |
3838 | 3838 |
3839 | 3839 |
3840 void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, | 3840 void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, |
3841 Handle<String> check, | 3841 Handle<String> check) { |
3842 Label* if_true, | 3842 Label materialize_true, materialize_false; |
3843 Label* if_false, | 3843 Label* if_true = NULL; |
3844 Label* fall_through) { | 3844 Label* if_false = NULL; |
| 3845 Label* fall_through = NULL; |
| 3846 context()->PrepareTest(&materialize_true, &materialize_false, |
| 3847 &if_true, &if_false, &fall_through); |
| 3848 |
3845 { AccumulatorValueContext context(this); | 3849 { AccumulatorValueContext context(this); |
3846 VisitForTypeofValue(expr); | 3850 VisitForTypeofValue(expr); |
3847 } | 3851 } |
3848 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 3852 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
3849 | 3853 |
3850 if (check->Equals(isolate()->heap()->number_symbol())) { | 3854 if (check->Equals(isolate()->heap()->number_symbol())) { |
3851 __ JumpIfSmi(rax, if_true); | 3855 __ JumpIfSmi(rax, if_true); |
3852 __ movq(rax, FieldOperand(rax, HeapObject::kMapOffset)); | 3856 __ movq(rax, FieldOperand(rax, HeapObject::kMapOffset)); |
3853 __ CompareRoot(rax, Heap::kHeapNumberMapRootIndex); | 3857 __ CompareRoot(rax, Heap::kHeapNumberMapRootIndex); |
3854 Split(equal, if_true, if_false, fall_through); | 3858 Split(equal, if_true, if_false, fall_through); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3893 __ j(below, if_false); | 3897 __ j(below, if_false); |
3894 __ CmpInstanceType(rdx, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); | 3898 __ CmpInstanceType(rdx, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); |
3895 __ j(above, if_false); | 3899 __ j(above, if_false); |
3896 // Check for undetectable objects => false. | 3900 // Check for undetectable objects => false. |
3897 __ testb(FieldOperand(rdx, Map::kBitFieldOffset), | 3901 __ testb(FieldOperand(rdx, Map::kBitFieldOffset), |
3898 Immediate(1 << Map::kIsUndetectable)); | 3902 Immediate(1 << Map::kIsUndetectable)); |
3899 Split(zero, if_true, if_false, fall_through); | 3903 Split(zero, if_true, if_false, fall_through); |
3900 } else { | 3904 } else { |
3901 if (if_false != fall_through) __ jmp(if_false); | 3905 if (if_false != fall_through) __ jmp(if_false); |
3902 } | 3906 } |
3903 } | 3907 context()->Plug(if_true, if_false); |
3904 | |
3905 | |
3906 void FullCodeGenerator::EmitLiteralCompareUndefined(Expression* expr, | |
3907 Label* if_true, | |
3908 Label* if_false, | |
3909 Label* fall_through) { | |
3910 VisitForAccumulatorValue(expr); | |
3911 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | |
3912 | |
3913 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); | |
3914 Split(equal, if_true, if_false, fall_through); | |
3915 } | 3908 } |
3916 | 3909 |
3917 | 3910 |
3918 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { | 3911 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { |
3919 Comment cmnt(masm_, "[ CompareOperation"); | 3912 Comment cmnt(masm_, "[ CompareOperation"); |
3920 SetSourcePosition(expr->position()); | 3913 SetSourcePosition(expr->position()); |
3921 | 3914 |
| 3915 // First we try a fast inlined version of the compare when one of |
| 3916 // the operands is a literal. |
| 3917 if (TryLiteralCompare(expr)) return; |
| 3918 |
3922 // Always perform the comparison for its control flow. Pack the result | 3919 // Always perform the comparison for its control flow. Pack the result |
3923 // into the expression's context after the comparison is performed. | 3920 // into the expression's context after the comparison is performed. |
3924 Label materialize_true, materialize_false; | 3921 Label materialize_true, materialize_false; |
3925 Label* if_true = NULL; | 3922 Label* if_true = NULL; |
3926 Label* if_false = NULL; | 3923 Label* if_false = NULL; |
3927 Label* fall_through = NULL; | 3924 Label* fall_through = NULL; |
3928 context()->PrepareTest(&materialize_true, &materialize_false, | 3925 context()->PrepareTest(&materialize_true, &materialize_false, |
3929 &if_true, &if_false, &fall_through); | 3926 &if_true, &if_false, &fall_through); |
3930 | 3927 |
3931 // First we try a fast inlined version of the compare when one of | |
3932 // the operands is a literal. | |
3933 if (TryLiteralCompare(expr, if_true, if_false, fall_through)) { | |
3934 context()->Plug(if_true, if_false); | |
3935 return; | |
3936 } | |
3937 | |
3938 Token::Value op = expr->op(); | 3928 Token::Value op = expr->op(); |
3939 VisitForStackValue(expr->left()); | 3929 VisitForStackValue(expr->left()); |
3940 switch (op) { | 3930 switch (op) { |
3941 case Token::IN: | 3931 case Token::IN: |
3942 VisitForStackValue(expr->right()); | 3932 VisitForStackValue(expr->right()); |
3943 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); | 3933 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); |
3944 PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); | 3934 PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); |
3945 __ CompareRoot(rax, Heap::kTrueValueRootIndex); | 3935 __ CompareRoot(rax, Heap::kTrueValueRootIndex); |
3946 Split(equal, if_true, if_false, fall_through); | 3936 Split(equal, if_true, if_false, fall_through); |
3947 break; | 3937 break; |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4016 Split(cc, if_true, if_false, fall_through); | 4006 Split(cc, if_true, if_false, fall_through); |
4017 } | 4007 } |
4018 } | 4008 } |
4019 | 4009 |
4020 // Convert the result of the comparison into one expected for this | 4010 // Convert the result of the comparison into one expected for this |
4021 // expression's context. | 4011 // expression's context. |
4022 context()->Plug(if_true, if_false); | 4012 context()->Plug(if_true, if_false); |
4023 } | 4013 } |
4024 | 4014 |
4025 | 4015 |
4026 void FullCodeGenerator::EmitLiteralCompareNull(Expression* expr, | 4016 void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr, |
4027 bool is_strict, | 4017 Expression* sub_expr, |
4028 Label* if_true, | 4018 NilValue nil) { |
4029 Label* if_false, | 4019 Label materialize_true, materialize_false; |
4030 Label* fall_through) { | 4020 Label* if_true = NULL; |
4031 VisitForAccumulatorValue(expr); | 4021 Label* if_false = NULL; |
| 4022 Label* fall_through = NULL; |
| 4023 context()->PrepareTest(&materialize_true, &materialize_false, |
| 4024 &if_true, &if_false, &fall_through); |
| 4025 |
| 4026 VisitForAccumulatorValue(sub_expr); |
4032 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 4027 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
4033 __ CompareRoot(rax, Heap::kNullValueRootIndex); | 4028 Heap::RootListIndex nil_value = nil == kNullValue ? |
4034 if (is_strict) { | 4029 Heap::kNullValueRootIndex : |
| 4030 Heap::kUndefinedValueRootIndex; |
| 4031 __ CompareRoot(rax, nil_value); |
| 4032 if (expr->op() == Token::EQ_STRICT) { |
4035 Split(equal, if_true, if_false, fall_through); | 4033 Split(equal, if_true, if_false, fall_through); |
4036 } else { | 4034 } else { |
| 4035 Heap::RootListIndex other_nil_value = nil == kNullValue ? |
| 4036 Heap::kUndefinedValueRootIndex : |
| 4037 Heap::kNullValueRootIndex; |
4037 __ j(equal, if_true); | 4038 __ j(equal, if_true); |
4038 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); | 4039 __ CompareRoot(rax, other_nil_value); |
4039 __ j(equal, if_true); | 4040 __ j(equal, if_true); |
4040 __ JumpIfSmi(rax, if_false); | 4041 __ JumpIfSmi(rax, if_false); |
4041 // It can be an undetectable object. | 4042 // It can be an undetectable object. |
4042 __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset)); | 4043 __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset)); |
4043 __ testb(FieldOperand(rdx, Map::kBitFieldOffset), | 4044 __ testb(FieldOperand(rdx, Map::kBitFieldOffset), |
4044 Immediate(1 << Map::kIsUndetectable)); | 4045 Immediate(1 << Map::kIsUndetectable)); |
4045 Split(not_zero, if_true, if_false, fall_through); | 4046 Split(not_zero, if_true, if_false, fall_through); |
4046 } | 4047 } |
| 4048 context()->Plug(if_true, if_false); |
4047 } | 4049 } |
4048 | 4050 |
4049 | 4051 |
4050 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { | 4052 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { |
4051 __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 4053 __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
4052 context()->Plug(rax); | 4054 context()->Plug(rax); |
4053 } | 4055 } |
4054 | 4056 |
4055 | 4057 |
4056 Register FullCodeGenerator::result_register() { | 4058 Register FullCodeGenerator::result_register() { |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4151 *context_length = 0; | 4153 *context_length = 0; |
4152 return previous_; | 4154 return previous_; |
4153 } | 4155 } |
4154 | 4156 |
4155 | 4157 |
4156 #undef __ | 4158 #undef __ |
4157 | 4159 |
4158 } } // namespace v8::internal | 4160 } } // namespace v8::internal |
4159 | 4161 |
4160 #endif // V8_TARGET_ARCH_X64 | 4162 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |