| 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 3108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3119 __ CallStub(&stub); | 3119 __ CallStub(&stub); |
| 3120 context()->Plug(r0); | 3120 context()->Plug(r0); |
| 3121 } | 3121 } |
| 3122 | 3122 |
| 3123 | 3123 |
| 3124 void FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) { | 3124 void FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) { |
| 3125 ASSERT(args->length() == 3); | 3125 ASSERT(args->length() == 3); |
| 3126 VisitForStackValue(args->at(0)); | 3126 VisitForStackValue(args->at(0)); |
| 3127 VisitForStackValue(args->at(1)); | 3127 VisitForStackValue(args->at(1)); |
| 3128 VisitForStackValue(args->at(2)); | 3128 VisitForStackValue(args->at(2)); |
| 3129 Label done; |
| 3130 Label slow_case; |
| 3131 Register object = r0; |
| 3132 Register index1 = r1; |
| 3133 Register index2 = r2; |
| 3134 Register elements = r3; |
| 3135 Register scratch1 = r4; |
| 3136 Register scratch2 = r5; |
| 3137 |
| 3138 __ ldr(object, MemOperand(sp, 2 * kPointerSize)); |
| 3139 // Fetch the map and check if array is in fast case. |
| 3140 // Check that object doesn't require security checks and |
| 3141 // has no indexed interceptor. |
| 3142 __ CompareObjectType(object, scratch1, scratch2, FIRST_JS_OBJECT_TYPE); |
| 3143 __ b(lt, &slow_case); |
| 3144 // Map is now in scratch1. |
| 3145 |
| 3146 __ ldrb(scratch2, FieldMemOperand(scratch1, Map::kBitFieldOffset)); |
| 3147 __ tst(scratch2, Operand(KeyedLoadIC::kSlowCaseBitFieldMask)); |
| 3148 __ b(ne, &slow_case); |
| 3149 |
| 3150 // Check the object's elements are in fast case and writable. |
| 3151 __ ldr(elements, FieldMemOperand(object, JSObject::kElementsOffset)); |
| 3152 __ ldr(scratch1, FieldMemOperand(elements, HeapObject::kMapOffset)); |
| 3153 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); |
| 3154 __ cmp(scratch1, ip); |
| 3155 __ b(ne, &slow_case); |
| 3156 |
| 3157 // Check that both indices are smis. |
| 3158 __ ldr(index1, MemOperand(sp, 1 * kPointerSize)); |
| 3159 __ ldr(index2, MemOperand(sp, 0)); |
| 3160 __ JumpIfNotBothSmi(index1, index2, &slow_case); |
| 3161 |
| 3162 // Check that both indices are valid. |
| 3163 __ ldr(scratch1, FieldMemOperand(object, JSArray::kLengthOffset)); |
| 3164 __ cmp(scratch1, index1); |
| 3165 __ cmp(scratch1, index2, hi); |
| 3166 __ b(ls, &slow_case); |
| 3167 |
| 3168 // Bring the address of the elements into index1 and index2. |
| 3169 __ add(scratch1, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
| 3170 __ add(index1, |
| 3171 scratch1, |
| 3172 Operand(index1, LSL, kPointerSizeLog2 - kSmiTagSize)); |
| 3173 __ add(index2, |
| 3174 scratch1, |
| 3175 Operand(index2, LSL, kPointerSizeLog2 - kSmiTagSize)); |
| 3176 |
| 3177 // Swap elements. |
| 3178 __ ldr(scratch1, MemOperand(index1, 0)); |
| 3179 __ ldr(scratch2, MemOperand(index2, 0)); |
| 3180 __ str(scratch1, MemOperand(index2, 0)); |
| 3181 __ str(scratch2, MemOperand(index1, 0)); |
| 3182 |
| 3183 Label new_space; |
| 3184 __ InNewSpace(elements, scratch1, eq, &new_space); |
| 3185 // Possible optimization: do a check that both values are Smis |
| 3186 // (or them and test against Smi mask.) |
| 3187 |
| 3188 __ mov(scratch1, elements); |
| 3189 __ RecordWriteHelper(elements, index1, scratch2); |
| 3190 __ RecordWriteHelper(scratch1, index2, scratch2); // scratch1 holds elements. |
| 3191 |
| 3192 __ bind(&new_space); |
| 3193 // We are done. Drop elements from the stack, and return undefined. |
| 3194 __ Drop(3); |
| 3195 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); |
| 3196 __ jmp(&done); |
| 3197 |
| 3198 __ bind(&slow_case); |
| 3129 __ CallRuntime(Runtime::kSwapElements, 3); | 3199 __ CallRuntime(Runtime::kSwapElements, 3); |
| 3200 |
| 3201 __ bind(&done); |
| 3130 context()->Plug(r0); | 3202 context()->Plug(r0); |
| 3131 } | 3203 } |
| 3132 | 3204 |
| 3133 | 3205 |
| 3134 void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) { | 3206 void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) { |
| 3135 ASSERT_EQ(2, args->length()); | 3207 ASSERT_EQ(2, args->length()); |
| 3136 | 3208 |
| 3137 ASSERT_NE(NULL, args->at(0)->AsLiteral()); | 3209 ASSERT_NE(NULL, args->at(0)->AsLiteral()); |
| 3138 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value(); | 3210 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value(); |
| 3139 | 3211 |
| (...skipping 773 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3913 UnaryOperation* left_unary = left->AsUnaryOperation(); | 3985 UnaryOperation* left_unary = left->AsUnaryOperation(); |
| 3914 if (left_unary == NULL || left_unary->op() != Token::TYPEOF) return false; | 3986 if (left_unary == NULL || left_unary->op() != Token::TYPEOF) return false; |
| 3915 Handle<String> check = Handle<String>::cast(right_literal_value); | 3987 Handle<String> check = Handle<String>::cast(right_literal_value); |
| 3916 | 3988 |
| 3917 { AccumulatorValueContext context(this); | 3989 { AccumulatorValueContext context(this); |
| 3918 VisitForTypeofValue(left_unary->expression()); | 3990 VisitForTypeofValue(left_unary->expression()); |
| 3919 } | 3991 } |
| 3920 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 3992 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
| 3921 | 3993 |
| 3922 if (check->Equals(isolate()->heap()->number_symbol())) { | 3994 if (check->Equals(isolate()->heap()->number_symbol())) { |
| 3923 __ tst(r0, Operand(kSmiTagMask)); | 3995 __ JumpIfSmi(r0, if_true); |
| 3924 __ b(eq, if_true); | |
| 3925 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); | 3996 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); |
| 3926 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); | 3997 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
| 3927 __ cmp(r0, ip); | 3998 __ cmp(r0, ip); |
| 3928 Split(eq, if_true, if_false, fall_through); | 3999 Split(eq, if_true, if_false, fall_through); |
| 3929 } else if (check->Equals(isolate()->heap()->string_symbol())) { | 4000 } else if (check->Equals(isolate()->heap()->string_symbol())) { |
| 3930 __ tst(r0, Operand(kSmiTagMask)); | 4001 __ JumpIfSmi(r0, if_false); |
| 3931 __ b(eq, if_false); | |
| 3932 // Check for undetectable objects => false. | 4002 // Check for undetectable objects => false. |
| 3933 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); | 4003 __ CompareObjectType(r0, r0, r1, FIRST_NONSTRING_TYPE); |
| 4004 __ b(ge, if_false); |
| 3934 __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset)); | 4005 __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset)); |
| 3935 __ and_(r1, r1, Operand(1 << Map::kIsUndetectable)); | 4006 __ tst(r1, Operand(1 << Map::kIsUndetectable)); |
| 3936 __ cmp(r1, Operand(1 << Map::kIsUndetectable)); | 4007 Split(eq, if_true, if_false, fall_through); |
| 3937 __ b(eq, if_false); | |
| 3938 __ ldrb(r1, FieldMemOperand(r0, Map::kInstanceTypeOffset)); | |
| 3939 __ cmp(r1, Operand(FIRST_NONSTRING_TYPE)); | |
| 3940 Split(lt, if_true, if_false, fall_through); | |
| 3941 } else if (check->Equals(isolate()->heap()->boolean_symbol())) { | 4008 } else if (check->Equals(isolate()->heap()->boolean_symbol())) { |
| 3942 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | 4009 __ CompareRoot(r0, Heap::kTrueValueRootIndex); |
| 3943 __ cmp(r0, ip); | |
| 3944 __ b(eq, if_true); | 4010 __ b(eq, if_true); |
| 3945 __ LoadRoot(ip, Heap::kFalseValueRootIndex); | 4011 __ CompareRoot(r0, Heap::kFalseValueRootIndex); |
| 3946 __ cmp(r0, ip); | |
| 3947 Split(eq, if_true, if_false, fall_through); | 4012 Split(eq, if_true, if_false, fall_through); |
| 3948 } else if (check->Equals(isolate()->heap()->undefined_symbol())) { | 4013 } else if (check->Equals(isolate()->heap()->undefined_symbol())) { |
| 3949 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 4014 __ CompareRoot(r0, Heap::kUndefinedValueRootIndex); |
| 3950 __ cmp(r0, ip); | |
| 3951 __ b(eq, if_true); | 4015 __ b(eq, if_true); |
| 3952 __ tst(r0, Operand(kSmiTagMask)); | 4016 __ JumpIfSmi(r0, if_false); |
| 3953 __ b(eq, if_false); | |
| 3954 // Check for undetectable objects => true. | 4017 // Check for undetectable objects => true. |
| 3955 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); | 4018 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); |
| 3956 __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset)); | 4019 __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset)); |
| 3957 __ and_(r1, r1, Operand(1 << Map::kIsUndetectable)); | 4020 __ tst(r1, Operand(1 << Map::kIsUndetectable)); |
| 3958 __ cmp(r1, Operand(1 << Map::kIsUndetectable)); | 4021 Split(ne, if_true, if_false, fall_through); |
| 4022 |
| 4023 } else if (check->Equals(isolate()->heap()->function_symbol())) { |
| 4024 __ JumpIfSmi(r0, if_false); |
| 4025 __ CompareObjectType(r0, r1, r0, FIRST_FUNCTION_CLASS_TYPE); |
| 4026 Split(ge, if_true, if_false, fall_through); |
| 4027 |
| 4028 } else if (check->Equals(isolate()->heap()->object_symbol())) { |
| 4029 __ JumpIfSmi(r0, if_false); |
| 4030 __ CompareRoot(r0, Heap::kNullValueRootIndex); |
| 4031 __ b(eq, if_true); |
| 4032 // Check for JS objects => true. |
| 4033 __ CompareObjectType(r0, r0, r1, FIRST_JS_OBJECT_TYPE); |
| 4034 __ b(lo, if_false); |
| 4035 __ CompareInstanceType(r0, r1, FIRST_FUNCTION_CLASS_TYPE); |
| 4036 __ b(hs, if_false); |
| 4037 // Check for undetectable objects => false. |
| 4038 __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset)); |
| 4039 __ tst(r1, Operand(1 << Map::kIsUndetectable)); |
| 3959 Split(eq, if_true, if_false, fall_through); | 4040 Split(eq, if_true, if_false, fall_through); |
| 3960 } else if (check->Equals(isolate()->heap()->function_symbol())) { | |
| 3961 __ tst(r0, Operand(kSmiTagMask)); | |
| 3962 __ b(eq, if_false); | |
| 3963 __ CompareObjectType(r0, r1, r0, JS_FUNCTION_TYPE); | |
| 3964 __ b(eq, if_true); | |
| 3965 // Regular expressions => 'function' (they are callable). | |
| 3966 __ CompareInstanceType(r1, r0, JS_REGEXP_TYPE); | |
| 3967 Split(eq, if_true, if_false, fall_through); | |
| 3968 } else if (check->Equals(isolate()->heap()->object_symbol())) { | |
| 3969 __ tst(r0, Operand(kSmiTagMask)); | |
| 3970 __ b(eq, if_false); | |
| 3971 __ LoadRoot(ip, Heap::kNullValueRootIndex); | |
| 3972 __ cmp(r0, ip); | |
| 3973 __ b(eq, if_true); | |
| 3974 // Regular expressions => 'function', not 'object'. | |
| 3975 __ CompareObjectType(r0, r1, r0, JS_REGEXP_TYPE); | |
| 3976 __ b(eq, if_false); | |
| 3977 // Check for undetectable objects => false. | |
| 3978 __ ldrb(r0, FieldMemOperand(r1, Map::kBitFieldOffset)); | |
| 3979 __ and_(r0, r0, Operand(1 << Map::kIsUndetectable)); | |
| 3980 __ cmp(r0, Operand(1 << Map::kIsUndetectable)); | |
| 3981 __ b(eq, if_false); | |
| 3982 // Check for JS objects => true. | |
| 3983 __ ldrb(r0, FieldMemOperand(r1, Map::kInstanceTypeOffset)); | |
| 3984 __ cmp(r0, Operand(FIRST_JS_OBJECT_TYPE)); | |
| 3985 __ b(lt, if_false); | |
| 3986 __ cmp(r0, Operand(LAST_JS_OBJECT_TYPE)); | |
| 3987 Split(le, if_true, if_false, fall_through); | |
| 3988 } else { | 4041 } else { |
| 3989 if (if_false != fall_through) __ jmp(if_false); | 4042 if (if_false != fall_through) __ jmp(if_false); |
| 3990 } | 4043 } |
| 3991 | 4044 |
| 3992 return true; | 4045 return true; |
| 3993 } | 4046 } |
| 3994 | 4047 |
| 3995 | 4048 |
| 3996 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { | 4049 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { |
| 3997 Comment cmnt(masm_, "[ CompareOperation"); | 4050 Comment cmnt(masm_, "[ CompareOperation"); |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4239 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. | 4292 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. |
| 4240 __ add(pc, r1, Operand(masm_->CodeObject())); | 4293 __ add(pc, r1, Operand(masm_->CodeObject())); |
| 4241 } | 4294 } |
| 4242 | 4295 |
| 4243 | 4296 |
| 4244 #undef __ | 4297 #undef __ |
| 4245 | 4298 |
| 4246 } } // namespace v8::internal | 4299 } } // namespace v8::internal |
| 4247 | 4300 |
| 4248 #endif // V8_TARGET_ARCH_ARM | 4301 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |