OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_X87 | 7 #if V8_TARGET_ARCH_X87 |
8 | 8 |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
(...skipping 1221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1232 Register scratch) { | 1232 Register scratch) { |
1233 __ JumpIfSmi(object, label); | 1233 __ JumpIfSmi(object, label); |
1234 __ mov(scratch, FieldOperand(object, HeapObject::kMapOffset)); | 1234 __ mov(scratch, FieldOperand(object, HeapObject::kMapOffset)); |
1235 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); | 1235 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); |
1236 STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); | 1236 STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); |
1237 __ test(scratch, Immediate(kIsNotStringMask | kIsNotInternalizedMask)); | 1237 __ test(scratch, Immediate(kIsNotStringMask | kIsNotInternalizedMask)); |
1238 __ j(not_zero, label); | 1238 __ j(not_zero, label); |
1239 } | 1239 } |
1240 | 1240 |
1241 | 1241 |
1242 void ICCompareStub::GenerateGeneric(MacroAssembler* masm) { | 1242 void CompareICStub::GenerateGeneric(MacroAssembler* masm) { |
1243 Label check_unequal_objects; | 1243 Label check_unequal_objects; |
1244 Condition cc = GetCondition(); | 1244 Condition cc = GetCondition(); |
1245 | 1245 |
1246 Label miss; | 1246 Label miss; |
1247 CheckInputType(masm, edx, left(), &miss); | 1247 CheckInputType(masm, edx, left(), &miss); |
1248 CheckInputType(masm, eax, right(), &miss); | 1248 CheckInputType(masm, eax, right(), &miss); |
1249 | 1249 |
1250 // Compare two smis. | 1250 // Compare two smis. |
1251 Label non_smi, smi_done; | 1251 Label non_smi, smi_done; |
1252 __ mov(ecx, edx); | 1252 __ mov(ecx, edx); |
(...skipping 1790 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3043 __ Assert(equal, kExpectedAllocationSite); | 3043 __ Assert(equal, kExpectedAllocationSite); |
3044 } | 3044 } |
3045 | 3045 |
3046 // Tail call into the stub that handles binary operations with allocation | 3046 // Tail call into the stub that handles binary operations with allocation |
3047 // sites. | 3047 // sites. |
3048 BinaryOpWithAllocationSiteStub stub(isolate(), state()); | 3048 BinaryOpWithAllocationSiteStub stub(isolate(), state()); |
3049 __ TailCallStub(&stub); | 3049 __ TailCallStub(&stub); |
3050 } | 3050 } |
3051 | 3051 |
3052 | 3052 |
3053 void ICCompareStub::GenerateSmis(MacroAssembler* masm) { | 3053 void CompareICStub::GenerateSmis(MacroAssembler* masm) { |
3054 DCHECK(state() == CompareIC::SMI); | 3054 DCHECK(state() == CompareIC::SMI); |
3055 Label miss; | 3055 Label miss; |
3056 __ mov(ecx, edx); | 3056 __ mov(ecx, edx); |
3057 __ or_(ecx, eax); | 3057 __ or_(ecx, eax); |
3058 __ JumpIfNotSmi(ecx, &miss, Label::kNear); | 3058 __ JumpIfNotSmi(ecx, &miss, Label::kNear); |
3059 | 3059 |
3060 if (GetCondition() == equal) { | 3060 if (GetCondition() == equal) { |
3061 // For equality we do not care about the sign of the result. | 3061 // For equality we do not care about the sign of the result. |
3062 __ sub(eax, edx); | 3062 __ sub(eax, edx); |
3063 } else { | 3063 } else { |
3064 Label done; | 3064 Label done; |
3065 __ sub(edx, eax); | 3065 __ sub(edx, eax); |
3066 __ j(no_overflow, &done, Label::kNear); | 3066 __ j(no_overflow, &done, Label::kNear); |
3067 // Correct sign of result in case of overflow. | 3067 // Correct sign of result in case of overflow. |
3068 __ not_(edx); | 3068 __ not_(edx); |
3069 __ bind(&done); | 3069 __ bind(&done); |
3070 __ mov(eax, edx); | 3070 __ mov(eax, edx); |
3071 } | 3071 } |
3072 __ ret(0); | 3072 __ ret(0); |
3073 | 3073 |
3074 __ bind(&miss); | 3074 __ bind(&miss); |
3075 GenerateMiss(masm); | 3075 GenerateMiss(masm); |
3076 } | 3076 } |
3077 | 3077 |
3078 | 3078 |
3079 void ICCompareStub::GenerateNumbers(MacroAssembler* masm) { | 3079 void CompareICStub::GenerateNumbers(MacroAssembler* masm) { |
3080 DCHECK(state() == CompareIC::NUMBER); | 3080 DCHECK(state() == CompareIC::NUMBER); |
3081 | 3081 |
3082 Label generic_stub; | 3082 Label generic_stub; |
3083 Label unordered, maybe_undefined1, maybe_undefined2; | 3083 Label unordered, maybe_undefined1, maybe_undefined2; |
3084 Label miss; | 3084 Label miss; |
3085 | 3085 |
3086 if (left() == CompareIC::SMI) { | 3086 if (left() == CompareIC::SMI) { |
3087 __ JumpIfNotSmi(edx, &miss); | 3087 __ JumpIfNotSmi(edx, &miss); |
3088 } | 3088 } |
3089 if (right() == CompareIC::SMI) { | 3089 if (right() == CompareIC::SMI) { |
3090 __ JumpIfNotSmi(eax, &miss); | 3090 __ JumpIfNotSmi(eax, &miss); |
3091 } | 3091 } |
3092 | 3092 |
3093 // Inlining the double comparison and falling back to the general compare | 3093 // Inlining the double comparison and falling back to the general compare |
3094 // stub if NaN is involved or SSE2 or CMOV is unsupported. | 3094 // stub if NaN is involved or SSE2 or CMOV is unsupported. |
3095 __ mov(ecx, edx); | 3095 __ mov(ecx, edx); |
3096 __ and_(ecx, eax); | 3096 __ and_(ecx, eax); |
3097 __ JumpIfSmi(ecx, &generic_stub, Label::kNear); | 3097 __ JumpIfSmi(ecx, &generic_stub, Label::kNear); |
3098 | 3098 |
3099 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), | 3099 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), |
3100 isolate()->factory()->heap_number_map()); | 3100 isolate()->factory()->heap_number_map()); |
3101 __ j(not_equal, &maybe_undefined1, Label::kNear); | 3101 __ j(not_equal, &maybe_undefined1, Label::kNear); |
3102 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 3102 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
3103 isolate()->factory()->heap_number_map()); | 3103 isolate()->factory()->heap_number_map()); |
3104 __ j(not_equal, &maybe_undefined2, Label::kNear); | 3104 __ j(not_equal, &maybe_undefined2, Label::kNear); |
3105 | 3105 |
3106 __ bind(&unordered); | 3106 __ bind(&unordered); |
3107 __ bind(&generic_stub); | 3107 __ bind(&generic_stub); |
3108 ICCompareStub stub(isolate(), op(), CompareIC::GENERIC, CompareIC::GENERIC, | 3108 CompareICStub stub(isolate(), op(), CompareIC::GENERIC, CompareIC::GENERIC, |
3109 CompareIC::GENERIC); | 3109 CompareIC::GENERIC); |
3110 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); | 3110 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); |
3111 | 3111 |
3112 __ bind(&maybe_undefined1); | 3112 __ bind(&maybe_undefined1); |
3113 if (Token::IsOrderedRelationalCompareOp(op())) { | 3113 if (Token::IsOrderedRelationalCompareOp(op())) { |
3114 __ cmp(eax, Immediate(isolate()->factory()->undefined_value())); | 3114 __ cmp(eax, Immediate(isolate()->factory()->undefined_value())); |
3115 __ j(not_equal, &miss); | 3115 __ j(not_equal, &miss); |
3116 __ JumpIfSmi(edx, &unordered); | 3116 __ JumpIfSmi(edx, &unordered); |
3117 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ecx); | 3117 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ecx); |
3118 __ j(not_equal, &maybe_undefined2, Label::kNear); | 3118 __ j(not_equal, &maybe_undefined2, Label::kNear); |
3119 __ jmp(&unordered); | 3119 __ jmp(&unordered); |
3120 } | 3120 } |
3121 | 3121 |
3122 __ bind(&maybe_undefined2); | 3122 __ bind(&maybe_undefined2); |
3123 if (Token::IsOrderedRelationalCompareOp(op())) { | 3123 if (Token::IsOrderedRelationalCompareOp(op())) { |
3124 __ cmp(edx, Immediate(isolate()->factory()->undefined_value())); | 3124 __ cmp(edx, Immediate(isolate()->factory()->undefined_value())); |
3125 __ j(equal, &unordered); | 3125 __ j(equal, &unordered); |
3126 } | 3126 } |
3127 | 3127 |
3128 __ bind(&miss); | 3128 __ bind(&miss); |
3129 GenerateMiss(masm); | 3129 GenerateMiss(masm); |
3130 } | 3130 } |
3131 | 3131 |
3132 | 3132 |
3133 void ICCompareStub::GenerateInternalizedStrings(MacroAssembler* masm) { | 3133 void CompareICStub::GenerateInternalizedStrings(MacroAssembler* masm) { |
3134 DCHECK(state() == CompareIC::INTERNALIZED_STRING); | 3134 DCHECK(state() == CompareIC::INTERNALIZED_STRING); |
3135 DCHECK(GetCondition() == equal); | 3135 DCHECK(GetCondition() == equal); |
3136 | 3136 |
3137 // Registers containing left and right operands respectively. | 3137 // Registers containing left and right operands respectively. |
3138 Register left = edx; | 3138 Register left = edx; |
3139 Register right = eax; | 3139 Register right = eax; |
3140 Register tmp1 = ecx; | 3140 Register tmp1 = ecx; |
3141 Register tmp2 = ebx; | 3141 Register tmp2 = ebx; |
3142 | 3142 |
3143 // Check that both operands are heap objects. | 3143 // Check that both operands are heap objects. |
(...skipping 24 matching lines...) Expand all Loading... |
3168 STATIC_ASSERT(kSmiTag == 0); | 3168 STATIC_ASSERT(kSmiTag == 0); |
3169 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); | 3169 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); |
3170 __ bind(&done); | 3170 __ bind(&done); |
3171 __ ret(0); | 3171 __ ret(0); |
3172 | 3172 |
3173 __ bind(&miss); | 3173 __ bind(&miss); |
3174 GenerateMiss(masm); | 3174 GenerateMiss(masm); |
3175 } | 3175 } |
3176 | 3176 |
3177 | 3177 |
3178 void ICCompareStub::GenerateUniqueNames(MacroAssembler* masm) { | 3178 void CompareICStub::GenerateUniqueNames(MacroAssembler* masm) { |
3179 DCHECK(state() == CompareIC::UNIQUE_NAME); | 3179 DCHECK(state() == CompareIC::UNIQUE_NAME); |
3180 DCHECK(GetCondition() == equal); | 3180 DCHECK(GetCondition() == equal); |
3181 | 3181 |
3182 // Registers containing left and right operands respectively. | 3182 // Registers containing left and right operands respectively. |
3183 Register left = edx; | 3183 Register left = edx; |
3184 Register right = eax; | 3184 Register right = eax; |
3185 Register tmp1 = ecx; | 3185 Register tmp1 = ecx; |
3186 Register tmp2 = ebx; | 3186 Register tmp2 = ebx; |
3187 | 3187 |
3188 // Check that both operands are heap objects. | 3188 // Check that both operands are heap objects. |
(...skipping 24 matching lines...) Expand all Loading... |
3213 STATIC_ASSERT(kSmiTag == 0); | 3213 STATIC_ASSERT(kSmiTag == 0); |
3214 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); | 3214 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); |
3215 __ bind(&done); | 3215 __ bind(&done); |
3216 __ ret(0); | 3216 __ ret(0); |
3217 | 3217 |
3218 __ bind(&miss); | 3218 __ bind(&miss); |
3219 GenerateMiss(masm); | 3219 GenerateMiss(masm); |
3220 } | 3220 } |
3221 | 3221 |
3222 | 3222 |
3223 void ICCompareStub::GenerateStrings(MacroAssembler* masm) { | 3223 void CompareICStub::GenerateStrings(MacroAssembler* masm) { |
3224 DCHECK(state() == CompareIC::STRING); | 3224 DCHECK(state() == CompareIC::STRING); |
3225 Label miss; | 3225 Label miss; |
3226 | 3226 |
3227 bool equality = Token::IsEqualityOp(op()); | 3227 bool equality = Token::IsEqualityOp(op()); |
3228 | 3228 |
3229 // Registers containing left and right operands respectively. | 3229 // Registers containing left and right operands respectively. |
3230 Register left = edx; | 3230 Register left = edx; |
3231 Register right = eax; | 3231 Register right = eax; |
3232 Register tmp1 = ecx; | 3232 Register tmp1 = ecx; |
3233 Register tmp2 = ebx; | 3233 Register tmp2 = ebx; |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3302 __ TailCallRuntime(Runtime::kStringEquals, 2, 1); | 3302 __ TailCallRuntime(Runtime::kStringEquals, 2, 1); |
3303 } else { | 3303 } else { |
3304 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 3304 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
3305 } | 3305 } |
3306 | 3306 |
3307 __ bind(&miss); | 3307 __ bind(&miss); |
3308 GenerateMiss(masm); | 3308 GenerateMiss(masm); |
3309 } | 3309 } |
3310 | 3310 |
3311 | 3311 |
3312 void ICCompareStub::GenerateObjects(MacroAssembler* masm) { | 3312 void CompareICStub::GenerateObjects(MacroAssembler* masm) { |
3313 DCHECK(state() == CompareIC::OBJECT); | 3313 DCHECK(state() == CompareIC::OBJECT); |
3314 Label miss; | 3314 Label miss; |
3315 __ mov(ecx, edx); | 3315 __ mov(ecx, edx); |
3316 __ and_(ecx, eax); | 3316 __ and_(ecx, eax); |
3317 __ JumpIfSmi(ecx, &miss, Label::kNear); | 3317 __ JumpIfSmi(ecx, &miss, Label::kNear); |
3318 | 3318 |
3319 __ CmpObjectType(eax, JS_OBJECT_TYPE, ecx); | 3319 __ CmpObjectType(eax, JS_OBJECT_TYPE, ecx); |
3320 __ j(not_equal, &miss, Label::kNear); | 3320 __ j(not_equal, &miss, Label::kNear); |
3321 __ CmpObjectType(edx, JS_OBJECT_TYPE, ecx); | 3321 __ CmpObjectType(edx, JS_OBJECT_TYPE, ecx); |
3322 __ j(not_equal, &miss, Label::kNear); | 3322 __ j(not_equal, &miss, Label::kNear); |
3323 | 3323 |
3324 DCHECK(GetCondition() == equal); | 3324 DCHECK(GetCondition() == equal); |
3325 __ sub(eax, edx); | 3325 __ sub(eax, edx); |
3326 __ ret(0); | 3326 __ ret(0); |
3327 | 3327 |
3328 __ bind(&miss); | 3328 __ bind(&miss); |
3329 GenerateMiss(masm); | 3329 GenerateMiss(masm); |
3330 } | 3330 } |
3331 | 3331 |
3332 | 3332 |
3333 void ICCompareStub::GenerateKnownObjects(MacroAssembler* masm) { | 3333 void CompareICStub::GenerateKnownObjects(MacroAssembler* masm) { |
3334 Label miss; | 3334 Label miss; |
3335 __ mov(ecx, edx); | 3335 __ mov(ecx, edx); |
3336 __ and_(ecx, eax); | 3336 __ and_(ecx, eax); |
3337 __ JumpIfSmi(ecx, &miss, Label::kNear); | 3337 __ JumpIfSmi(ecx, &miss, Label::kNear); |
3338 | 3338 |
3339 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); | 3339 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); |
3340 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); | 3340 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); |
3341 __ cmp(ecx, known_map_); | 3341 __ cmp(ecx, known_map_); |
3342 __ j(not_equal, &miss, Label::kNear); | 3342 __ j(not_equal, &miss, Label::kNear); |
3343 __ cmp(ebx, known_map_); | 3343 __ cmp(ebx, known_map_); |
3344 __ j(not_equal, &miss, Label::kNear); | 3344 __ j(not_equal, &miss, Label::kNear); |
3345 | 3345 |
3346 __ sub(eax, edx); | 3346 __ sub(eax, edx); |
3347 __ ret(0); | 3347 __ ret(0); |
3348 | 3348 |
3349 __ bind(&miss); | 3349 __ bind(&miss); |
3350 GenerateMiss(masm); | 3350 GenerateMiss(masm); |
3351 } | 3351 } |
3352 | 3352 |
3353 | 3353 |
3354 void ICCompareStub::GenerateMiss(MacroAssembler* masm) { | 3354 void CompareICStub::GenerateMiss(MacroAssembler* masm) { |
3355 { | 3355 { |
3356 // Call the runtime system in a fresh internal frame. | 3356 // Call the runtime system in a fresh internal frame. |
3357 ExternalReference miss = ExternalReference(IC_Utility(IC::kCompareIC_Miss), | 3357 ExternalReference miss = ExternalReference(IC_Utility(IC::kCompareIC_Miss), |
3358 isolate()); | 3358 isolate()); |
3359 FrameScope scope(masm, StackFrame::INTERNAL); | 3359 FrameScope scope(masm, StackFrame::INTERNAL); |
3360 __ push(edx); // Preserve edx and eax. | 3360 __ push(edx); // Preserve edx and eax. |
3361 __ push(eax); | 3361 __ push(eax); |
3362 __ push(edx); // And also use them as the arguments. | 3362 __ push(edx); // And also use them as the arguments. |
3363 __ push(eax); | 3363 __ push(eax); |
3364 __ push(Immediate(Smi::FromInt(op()))); | 3364 __ push(Immediate(Smi::FromInt(op()))); |
(...skipping 1026 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4391 Operand(ebp, 7 * kPointerSize), | 4391 Operand(ebp, 7 * kPointerSize), |
4392 NULL); | 4392 NULL); |
4393 } | 4393 } |
4394 | 4394 |
4395 | 4395 |
4396 #undef __ | 4396 #undef __ |
4397 | 4397 |
4398 } } // namespace v8::internal | 4398 } } // namespace v8::internal |
4399 | 4399 |
4400 #endif // V8_TARGET_ARCH_X87 | 4400 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |