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 2967 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2978 | 2978 |
2979 | 2979 |
2980 void CodeGenerator::VisitCompareOperation(CompareOperation* node) { | 2980 void CodeGenerator::VisitCompareOperation(CompareOperation* node) { |
2981 Comment cmnt(masm_, "[ CompareOperation"); | 2981 Comment cmnt(masm_, "[ CompareOperation"); |
2982 | 2982 |
2983 // Get the expressions from the node. | 2983 // Get the expressions from the node. |
2984 Expression* left = node->left(); | 2984 Expression* left = node->left(); |
2985 Expression* right = node->right(); | 2985 Expression* right = node->right(); |
2986 Token::Value op = node->op(); | 2986 Token::Value op = node->op(); |
2987 | 2987 |
2988 // NOTE: To make null checks efficient, we check if either left or | 2988 // To make null checks efficient, we check if either left or right is the |
2989 // right is the literal 'null'. If so, we optimize the code by | 2989 // literal 'null'. If so, we optimize the code by inlining a null check |
2990 // inlining a null check instead of calling the (very) general | 2990 // instead of calling the (very) general runtime routine for checking |
2991 // runtime routine for checking equality. | 2991 // equality. |
2992 | |
2993 if (op == Token::EQ || op == Token::EQ_STRICT) { | 2992 if (op == Token::EQ || op == Token::EQ_STRICT) { |
2994 bool left_is_null = | 2993 bool left_is_null = |
2995 left->AsLiteral() != NULL && left->AsLiteral()->IsNull(); | 2994 left->AsLiteral() != NULL && left->AsLiteral()->IsNull(); |
2996 bool right_is_null = | 2995 bool right_is_null = |
2997 right->AsLiteral() != NULL && right->AsLiteral()->IsNull(); | 2996 right->AsLiteral() != NULL && right->AsLiteral()->IsNull(); |
2998 // The 'null' value is only equal to 'null' or 'undefined'. | 2997 // The 'null' value can only be equal to 'null' or 'undefined'. |
2999 if (left_is_null || right_is_null) { | 2998 if (left_is_null || right_is_null) { |
3000 Load(left_is_null ? right : left); | 2999 Load(left_is_null ? right : left); |
3001 Label exit, undetectable; | |
3002 frame_->Pop(r0); | 3000 frame_->Pop(r0); |
3003 __ cmp(r0, Operand(Factory::null_value())); | 3001 __ cmp(r0, Operand(Factory::null_value())); |
3004 | 3002 |
3005 // The 'null' value is only equal to 'undefined' if using | 3003 // The 'null' value is only equal to 'undefined' if using non-strict |
3006 // non-strict comparisons. | 3004 // comparisons. |
3007 if (op != Token::EQ_STRICT) { | 3005 if (op != Token::EQ_STRICT) { |
3008 __ b(eq, &exit); | 3006 __ b(eq, true_target()); |
| 3007 |
3009 __ cmp(r0, Operand(Factory::undefined_value())); | 3008 __ cmp(r0, Operand(Factory::undefined_value())); |
| 3009 __ b(eq, true_target()); |
3010 | 3010 |
3011 // NOTE: it can be undetectable object. | |
3012 __ b(eq, &exit); | |
3013 __ tst(r0, Operand(kSmiTagMask)); | 3011 __ tst(r0, Operand(kSmiTagMask)); |
| 3012 __ b(eq, false_target()); |
3014 | 3013 |
3015 __ b(ne, &undetectable); | 3014 // It can be an undetectable object. |
3016 __ b(false_target()); | 3015 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); |
3017 | 3016 __ ldrb(r0, FieldMemOperand(r0, Map::kBitFieldOffset)); |
3018 __ bind(&undetectable); | 3017 __ and_(r0, r0, Operand(1 << Map::kIsUndetectable)); |
3019 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); | 3018 __ cmp(r0, Operand(1 << Map::kIsUndetectable)); |
3020 __ ldrb(r2, FieldMemOperand(r1, Map::kBitFieldOffset)); | |
3021 __ and_(r2, r2, Operand(1 << Map::kIsUndetectable)); | |
3022 __ cmp(r2, Operand(1 << Map::kIsUndetectable)); | |
3023 } | 3019 } |
3024 | 3020 |
3025 __ bind(&exit); | |
3026 | |
3027 cc_reg_ = eq; | 3021 cc_reg_ = eq; |
3028 return; | 3022 return; |
3029 } | 3023 } |
3030 } | 3024 } |
3031 | 3025 |
3032 | 3026 // To make typeof testing for natives implemented in JavaScript really |
3033 // NOTE: To make typeof testing for natives implemented in | 3027 // efficient, we generate special code for expressions of the form: |
3034 // JavaScript really efficient, we generate special code for | 3028 // 'typeof <expression> == <string>'. |
3035 // expressions of the form: 'typeof <expression> == <string>'. | |
3036 | |
3037 UnaryOperation* operation = left->AsUnaryOperation(); | 3029 UnaryOperation* operation = left->AsUnaryOperation(); |
3038 if ((op == Token::EQ || op == Token::EQ_STRICT) && | 3030 if ((op == Token::EQ || op == Token::EQ_STRICT) && |
3039 (operation != NULL && operation->op() == Token::TYPEOF) && | 3031 (operation != NULL && operation->op() == Token::TYPEOF) && |
3040 (right->AsLiteral() != NULL && | 3032 (right->AsLiteral() != NULL && |
3041 right->AsLiteral()->handle()->IsString())) { | 3033 right->AsLiteral()->handle()->IsString())) { |
3042 Handle<String> check(String::cast(*right->AsLiteral()->handle())); | 3034 Handle<String> check(String::cast(*right->AsLiteral()->handle())); |
3043 | 3035 |
3044 // Load the operand, move it to register r1. | 3036 // Load the operand, move it to register r1. |
3045 LoadTypeofExpression(operation->expression()); | 3037 LoadTypeofExpression(operation->expression()); |
3046 frame_->Pop(r1); | 3038 frame_->Pop(r1); |
3047 | 3039 |
3048 if (check->Equals(Heap::number_symbol())) { | 3040 if (check->Equals(Heap::number_symbol())) { |
3049 __ tst(r1, Operand(kSmiTagMask)); | 3041 __ tst(r1, Operand(kSmiTagMask)); |
3050 __ b(eq, true_target()); | 3042 __ b(eq, true_target()); |
3051 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset)); | 3043 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset)); |
3052 __ cmp(r1, Operand(Factory::heap_number_map())); | 3044 __ cmp(r1, Operand(Factory::heap_number_map())); |
3053 cc_reg_ = eq; | 3045 cc_reg_ = eq; |
3054 | 3046 |
3055 } else if (check->Equals(Heap::string_symbol())) { | 3047 } else if (check->Equals(Heap::string_symbol())) { |
3056 __ tst(r1, Operand(kSmiTagMask)); | 3048 __ tst(r1, Operand(kSmiTagMask)); |
3057 __ b(eq, false_target()); | 3049 __ b(eq, false_target()); |
3058 | 3050 |
3059 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset)); | 3051 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset)); |
3060 | 3052 |
3061 // NOTE: it might be an undetectable string object | 3053 // It can be an undetectable string object. |
3062 __ ldrb(r2, FieldMemOperand(r1, Map::kBitFieldOffset)); | 3054 __ ldrb(r2, FieldMemOperand(r1, Map::kBitFieldOffset)); |
3063 __ and_(r2, r2, Operand(1 << Map::kIsUndetectable)); | 3055 __ and_(r2, r2, Operand(1 << Map::kIsUndetectable)); |
3064 __ cmp(r2, Operand(1 << Map::kIsUndetectable)); | 3056 __ cmp(r2, Operand(1 << Map::kIsUndetectable)); |
3065 __ b(eq, false_target()); | 3057 __ b(eq, false_target()); |
3066 | 3058 |
3067 __ ldrb(r2, FieldMemOperand(r1, Map::kInstanceTypeOffset)); | 3059 __ ldrb(r2, FieldMemOperand(r1, Map::kInstanceTypeOffset)); |
3068 __ cmp(r2, Operand(FIRST_NONSTRING_TYPE)); | 3060 __ cmp(r2, Operand(FIRST_NONSTRING_TYPE)); |
3069 cc_reg_ = lt; | 3061 cc_reg_ = lt; |
3070 | 3062 |
3071 } else if (check->Equals(Heap::boolean_symbol())) { | 3063 } else if (check->Equals(Heap::boolean_symbol())) { |
3072 __ cmp(r1, Operand(Factory::true_value())); | 3064 __ cmp(r1, Operand(Factory::true_value())); |
3073 __ b(eq, true_target()); | 3065 __ b(eq, true_target()); |
3074 __ cmp(r1, Operand(Factory::false_value())); | 3066 __ cmp(r1, Operand(Factory::false_value())); |
3075 cc_reg_ = eq; | 3067 cc_reg_ = eq; |
3076 | 3068 |
3077 } else if (check->Equals(Heap::undefined_symbol())) { | 3069 } else if (check->Equals(Heap::undefined_symbol())) { |
3078 __ cmp(r1, Operand(Factory::undefined_value())); | 3070 __ cmp(r1, Operand(Factory::undefined_value())); |
3079 __ b(eq, true_target()); | 3071 __ b(eq, true_target()); |
3080 | 3072 |
3081 __ tst(r1, Operand(kSmiTagMask)); | 3073 __ tst(r1, Operand(kSmiTagMask)); |
3082 __ b(eq, false_target()); | 3074 __ b(eq, false_target()); |
3083 | 3075 |
3084 // NOTE: it can be undetectable object. | 3076 // It can be an undetectable object. |
3085 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset)); | 3077 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset)); |
3086 __ ldrb(r2, FieldMemOperand(r1, Map::kBitFieldOffset)); | 3078 __ ldrb(r2, FieldMemOperand(r1, Map::kBitFieldOffset)); |
3087 __ and_(r2, r2, Operand(1 << Map::kIsUndetectable)); | 3079 __ and_(r2, r2, Operand(1 << Map::kIsUndetectable)); |
3088 __ cmp(r2, Operand(1 << Map::kIsUndetectable)); | 3080 __ cmp(r2, Operand(1 << Map::kIsUndetectable)); |
3089 | 3081 |
3090 cc_reg_ = eq; | 3082 cc_reg_ = eq; |
3091 | 3083 |
3092 } else if (check->Equals(Heap::function_symbol())) { | 3084 } else if (check->Equals(Heap::function_symbol())) { |
3093 __ tst(r1, Operand(kSmiTagMask)); | 3085 __ tst(r1, Operand(kSmiTagMask)); |
3094 __ b(eq, false_target()); | 3086 __ b(eq, false_target()); |
3095 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset)); | 3087 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset)); |
3096 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset)); | 3088 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset)); |
3097 __ cmp(r1, Operand(JS_FUNCTION_TYPE)); | 3089 __ cmp(r1, Operand(JS_FUNCTION_TYPE)); |
3098 cc_reg_ = eq; | 3090 cc_reg_ = eq; |
3099 | 3091 |
3100 } else if (check->Equals(Heap::object_symbol())) { | 3092 } else if (check->Equals(Heap::object_symbol())) { |
3101 __ tst(r1, Operand(kSmiTagMask)); | 3093 __ tst(r1, Operand(kSmiTagMask)); |
3102 __ b(eq, false_target()); | 3094 __ b(eq, false_target()); |
3103 | 3095 |
3104 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); | 3096 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); |
3105 __ cmp(r1, Operand(Factory::null_value())); | 3097 __ cmp(r1, Operand(Factory::null_value())); |
3106 __ b(eq, true_target()); | 3098 __ b(eq, true_target()); |
3107 | 3099 |
3108 // NOTE: it might be an undetectable object. | 3100 // It can be an undetectable object. |
3109 __ ldrb(r1, FieldMemOperand(r2, Map::kBitFieldOffset)); | 3101 __ ldrb(r1, FieldMemOperand(r2, Map::kBitFieldOffset)); |
3110 __ and_(r1, r1, Operand(1 << Map::kIsUndetectable)); | 3102 __ and_(r1, r1, Operand(1 << Map::kIsUndetectable)); |
3111 __ cmp(r1, Operand(1 << Map::kIsUndetectable)); | 3103 __ cmp(r1, Operand(1 << Map::kIsUndetectable)); |
3112 __ b(eq, false_target()); | 3104 __ b(eq, false_target()); |
3113 | 3105 |
3114 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset)); | 3106 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset)); |
3115 __ cmp(r2, Operand(FIRST_JS_OBJECT_TYPE)); | 3107 __ cmp(r2, Operand(FIRST_JS_OBJECT_TYPE)); |
3116 __ b(lt, false_target()); | 3108 __ b(lt, false_target()); |
3117 __ cmp(r2, Operand(LAST_JS_OBJECT_TYPE)); | 3109 __ cmp(r2, Operand(LAST_JS_OBJECT_TYPE)); |
3118 cc_reg_ = le; | 3110 cc_reg_ = le; |
3119 | 3111 |
3120 } else { | 3112 } else { |
3121 // Uncommon case: Typeof testing against a string literal that | 3113 // Uncommon case: typeof testing against a string literal that is |
3122 // is never returned from the typeof operator. | 3114 // never returned from the typeof operator. |
3123 __ b(false_target()); | 3115 __ b(false_target()); |
3124 } | 3116 } |
3125 return; | 3117 return; |
3126 } | 3118 } |
3127 | 3119 |
3128 Load(left); | 3120 Load(left); |
3129 Load(right); | 3121 Load(right); |
3130 switch (op) { | 3122 switch (op) { |
3131 case Token::EQ: | 3123 case Token::EQ: |
3132 Comparison(eq, false); | 3124 Comparison(eq, false); |
(...skipping 1153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4286 __ mov(r2, Operand(0)); | 4278 __ mov(r2, Operand(0)); |
4287 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); | 4279 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); |
4288 __ Jump(Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)), | 4280 __ Jump(Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)), |
4289 RelocInfo::CODE_TARGET); | 4281 RelocInfo::CODE_TARGET); |
4290 } | 4282 } |
4291 | 4283 |
4292 | 4284 |
4293 #undef __ | 4285 #undef __ |
4294 | 4286 |
4295 } } // namespace v8::internal | 4287 } } // namespace v8::internal |
OLD | NEW |