| 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 |