| 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/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
| (...skipping 1229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1240 __ test(scratch, Immediate(kIsNotStringMask | kIsNotInternalizedMask)); | 1240 __ test(scratch, Immediate(kIsNotStringMask | kIsNotInternalizedMask)); |
| 1241 __ j(not_zero, label); | 1241 __ j(not_zero, label); |
| 1242 } | 1242 } |
| 1243 | 1243 |
| 1244 | 1244 |
| 1245 void ICCompareStub::GenerateGeneric(MacroAssembler* masm) { | 1245 void ICCompareStub::GenerateGeneric(MacroAssembler* masm) { |
| 1246 Label check_unequal_objects; | 1246 Label check_unequal_objects; |
| 1247 Condition cc = GetCondition(); | 1247 Condition cc = GetCondition(); |
| 1248 | 1248 |
| 1249 Label miss; | 1249 Label miss; |
| 1250 CheckInputType(masm, edx, left_, &miss); | 1250 CheckInputType(masm, edx, left(), &miss); |
| 1251 CheckInputType(masm, eax, right_, &miss); | 1251 CheckInputType(masm, eax, right(), &miss); |
| 1252 | 1252 |
| 1253 // Compare two smis. | 1253 // Compare two smis. |
| 1254 Label non_smi, smi_done; | 1254 Label non_smi, smi_done; |
| 1255 __ mov(ecx, edx); | 1255 __ mov(ecx, edx); |
| 1256 __ or_(ecx, eax); | 1256 __ or_(ecx, eax); |
| 1257 __ JumpIfNotSmi(ecx, &non_smi, Label::kNear); | 1257 __ JumpIfNotSmi(ecx, &non_smi, Label::kNear); |
| 1258 __ sub(edx, eax); // Return on the result of the subtraction. | 1258 __ sub(edx, eax); // Return on the result of the subtraction. |
| 1259 __ j(no_overflow, &smi_done, Label::kNear); | 1259 __ j(no_overflow, &smi_done, Label::kNear); |
| 1260 __ not_(edx); // Correct sign in case of overflow. edx is never 0 here. | 1260 __ not_(edx); // Correct sign in case of overflow. edx is never 0 here. |
| 1261 __ bind(&smi_done); | 1261 __ bind(&smi_done); |
| (...skipping 1801 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3063 } | 3063 } |
| 3064 | 3064 |
| 3065 // Tail call into the stub that handles binary operations with allocation | 3065 // Tail call into the stub that handles binary operations with allocation |
| 3066 // sites. | 3066 // sites. |
| 3067 BinaryOpWithAllocationSiteStub stub(isolate(), state()); | 3067 BinaryOpWithAllocationSiteStub stub(isolate(), state()); |
| 3068 __ TailCallStub(&stub); | 3068 __ TailCallStub(&stub); |
| 3069 } | 3069 } |
| 3070 | 3070 |
| 3071 | 3071 |
| 3072 void ICCompareStub::GenerateSmis(MacroAssembler* masm) { | 3072 void ICCompareStub::GenerateSmis(MacroAssembler* masm) { |
| 3073 DCHECK(state_ == CompareIC::SMI); | 3073 DCHECK(state() == CompareIC::SMI); |
| 3074 Label miss; | 3074 Label miss; |
| 3075 __ mov(ecx, edx); | 3075 __ mov(ecx, edx); |
| 3076 __ or_(ecx, eax); | 3076 __ or_(ecx, eax); |
| 3077 __ JumpIfNotSmi(ecx, &miss, Label::kNear); | 3077 __ JumpIfNotSmi(ecx, &miss, Label::kNear); |
| 3078 | 3078 |
| 3079 if (GetCondition() == equal) { | 3079 if (GetCondition() == equal) { |
| 3080 // For equality we do not care about the sign of the result. | 3080 // For equality we do not care about the sign of the result. |
| 3081 __ sub(eax, edx); | 3081 __ sub(eax, edx); |
| 3082 } else { | 3082 } else { |
| 3083 Label done; | 3083 Label done; |
| 3084 __ sub(edx, eax); | 3084 __ sub(edx, eax); |
| 3085 __ j(no_overflow, &done, Label::kNear); | 3085 __ j(no_overflow, &done, Label::kNear); |
| 3086 // Correct sign of result in case of overflow. | 3086 // Correct sign of result in case of overflow. |
| 3087 __ not_(edx); | 3087 __ not_(edx); |
| 3088 __ bind(&done); | 3088 __ bind(&done); |
| 3089 __ mov(eax, edx); | 3089 __ mov(eax, edx); |
| 3090 } | 3090 } |
| 3091 __ ret(0); | 3091 __ ret(0); |
| 3092 | 3092 |
| 3093 __ bind(&miss); | 3093 __ bind(&miss); |
| 3094 GenerateMiss(masm); | 3094 GenerateMiss(masm); |
| 3095 } | 3095 } |
| 3096 | 3096 |
| 3097 | 3097 |
| 3098 void ICCompareStub::GenerateNumbers(MacroAssembler* masm) { | 3098 void ICCompareStub::GenerateNumbers(MacroAssembler* masm) { |
| 3099 DCHECK(state_ == CompareIC::NUMBER); | 3099 DCHECK(state() == CompareIC::NUMBER); |
| 3100 | 3100 |
| 3101 Label generic_stub; | 3101 Label generic_stub; |
| 3102 Label unordered, maybe_undefined1, maybe_undefined2; | 3102 Label unordered, maybe_undefined1, maybe_undefined2; |
| 3103 Label miss; | 3103 Label miss; |
| 3104 | 3104 |
| 3105 if (left_ == CompareIC::SMI) { | 3105 if (left() == CompareIC::SMI) { |
| 3106 __ JumpIfNotSmi(edx, &miss); | 3106 __ JumpIfNotSmi(edx, &miss); |
| 3107 } | 3107 } |
| 3108 if (right_ == CompareIC::SMI) { | 3108 if (right() == CompareIC::SMI) { |
| 3109 __ JumpIfNotSmi(eax, &miss); | 3109 __ JumpIfNotSmi(eax, &miss); |
| 3110 } | 3110 } |
| 3111 | 3111 |
| 3112 // Inlining the double comparison and falling back to the general compare | 3112 // Inlining the double comparison and falling back to the general compare |
| 3113 // stub if NaN is involved or SSE2 or CMOV is unsupported. | 3113 // stub if NaN is involved or SSE2 or CMOV is unsupported. |
| 3114 __ mov(ecx, edx); | 3114 __ mov(ecx, edx); |
| 3115 __ and_(ecx, eax); | 3115 __ and_(ecx, eax); |
| 3116 __ JumpIfSmi(ecx, &generic_stub, Label::kNear); | 3116 __ JumpIfSmi(ecx, &generic_stub, Label::kNear); |
| 3117 | 3117 |
| 3118 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), | 3118 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), |
| 3119 isolate()->factory()->heap_number_map()); | 3119 isolate()->factory()->heap_number_map()); |
| 3120 __ j(not_equal, &maybe_undefined1, Label::kNear); | 3120 __ j(not_equal, &maybe_undefined1, Label::kNear); |
| 3121 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 3121 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
| 3122 isolate()->factory()->heap_number_map()); | 3122 isolate()->factory()->heap_number_map()); |
| 3123 __ j(not_equal, &maybe_undefined2, Label::kNear); | 3123 __ j(not_equal, &maybe_undefined2, Label::kNear); |
| 3124 | 3124 |
| 3125 __ bind(&unordered); | 3125 __ bind(&unordered); |
| 3126 __ bind(&generic_stub); | 3126 __ bind(&generic_stub); |
| 3127 ICCompareStub stub(isolate(), op_, CompareIC::GENERIC, CompareIC::GENERIC, | 3127 ICCompareStub stub(isolate(), op(), CompareIC::GENERIC, CompareIC::GENERIC, |
| 3128 CompareIC::GENERIC); | 3128 CompareIC::GENERIC); |
| 3129 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); | 3129 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); |
| 3130 | 3130 |
| 3131 __ bind(&maybe_undefined1); | 3131 __ bind(&maybe_undefined1); |
| 3132 if (Token::IsOrderedRelationalCompareOp(op_)) { | 3132 if (Token::IsOrderedRelationalCompareOp(op())) { |
| 3133 __ cmp(eax, Immediate(isolate()->factory()->undefined_value())); | 3133 __ cmp(eax, Immediate(isolate()->factory()->undefined_value())); |
| 3134 __ j(not_equal, &miss); | 3134 __ j(not_equal, &miss); |
| 3135 __ JumpIfSmi(edx, &unordered); | 3135 __ JumpIfSmi(edx, &unordered); |
| 3136 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ecx); | 3136 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ecx); |
| 3137 __ j(not_equal, &maybe_undefined2, Label::kNear); | 3137 __ j(not_equal, &maybe_undefined2, Label::kNear); |
| 3138 __ jmp(&unordered); | 3138 __ jmp(&unordered); |
| 3139 } | 3139 } |
| 3140 | 3140 |
| 3141 __ bind(&maybe_undefined2); | 3141 __ bind(&maybe_undefined2); |
| 3142 if (Token::IsOrderedRelationalCompareOp(op_)) { | 3142 if (Token::IsOrderedRelationalCompareOp(op())) { |
| 3143 __ cmp(edx, Immediate(isolate()->factory()->undefined_value())); | 3143 __ cmp(edx, Immediate(isolate()->factory()->undefined_value())); |
| 3144 __ j(equal, &unordered); | 3144 __ j(equal, &unordered); |
| 3145 } | 3145 } |
| 3146 | 3146 |
| 3147 __ bind(&miss); | 3147 __ bind(&miss); |
| 3148 GenerateMiss(masm); | 3148 GenerateMiss(masm); |
| 3149 } | 3149 } |
| 3150 | 3150 |
| 3151 | 3151 |
| 3152 void ICCompareStub::GenerateInternalizedStrings(MacroAssembler* masm) { | 3152 void ICCompareStub::GenerateInternalizedStrings(MacroAssembler* masm) { |
| 3153 DCHECK(state_ == CompareIC::INTERNALIZED_STRING); | 3153 DCHECK(state() == CompareIC::INTERNALIZED_STRING); |
| 3154 DCHECK(GetCondition() == equal); | 3154 DCHECK(GetCondition() == equal); |
| 3155 | 3155 |
| 3156 // Registers containing left and right operands respectively. | 3156 // Registers containing left and right operands respectively. |
| 3157 Register left = edx; | 3157 Register left = edx; |
| 3158 Register right = eax; | 3158 Register right = eax; |
| 3159 Register tmp1 = ecx; | 3159 Register tmp1 = ecx; |
| 3160 Register tmp2 = ebx; | 3160 Register tmp2 = ebx; |
| 3161 | 3161 |
| 3162 // Check that both operands are heap objects. | 3162 // Check that both operands are heap objects. |
| 3163 Label miss; | 3163 Label miss; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 3188 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); | 3188 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); |
| 3189 __ bind(&done); | 3189 __ bind(&done); |
| 3190 __ ret(0); | 3190 __ ret(0); |
| 3191 | 3191 |
| 3192 __ bind(&miss); | 3192 __ bind(&miss); |
| 3193 GenerateMiss(masm); | 3193 GenerateMiss(masm); |
| 3194 } | 3194 } |
| 3195 | 3195 |
| 3196 | 3196 |
| 3197 void ICCompareStub::GenerateUniqueNames(MacroAssembler* masm) { | 3197 void ICCompareStub::GenerateUniqueNames(MacroAssembler* masm) { |
| 3198 DCHECK(state_ == CompareIC::UNIQUE_NAME); | 3198 DCHECK(state() == CompareIC::UNIQUE_NAME); |
| 3199 DCHECK(GetCondition() == equal); | 3199 DCHECK(GetCondition() == equal); |
| 3200 | 3200 |
| 3201 // Registers containing left and right operands respectively. | 3201 // Registers containing left and right operands respectively. |
| 3202 Register left = edx; | 3202 Register left = edx; |
| 3203 Register right = eax; | 3203 Register right = eax; |
| 3204 Register tmp1 = ecx; | 3204 Register tmp1 = ecx; |
| 3205 Register tmp2 = ebx; | 3205 Register tmp2 = ebx; |
| 3206 | 3206 |
| 3207 // Check that both operands are heap objects. | 3207 // Check that both operands are heap objects. |
| 3208 Label miss; | 3208 Label miss; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 3233 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); | 3233 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); |
| 3234 __ bind(&done); | 3234 __ bind(&done); |
| 3235 __ ret(0); | 3235 __ ret(0); |
| 3236 | 3236 |
| 3237 __ bind(&miss); | 3237 __ bind(&miss); |
| 3238 GenerateMiss(masm); | 3238 GenerateMiss(masm); |
| 3239 } | 3239 } |
| 3240 | 3240 |
| 3241 | 3241 |
| 3242 void ICCompareStub::GenerateStrings(MacroAssembler* masm) { | 3242 void ICCompareStub::GenerateStrings(MacroAssembler* masm) { |
| 3243 DCHECK(state_ == CompareIC::STRING); | 3243 DCHECK(state() == CompareIC::STRING); |
| 3244 Label miss; | 3244 Label miss; |
| 3245 | 3245 |
| 3246 bool equality = Token::IsEqualityOp(op_); | 3246 bool equality = Token::IsEqualityOp(op()); |
| 3247 | 3247 |
| 3248 // Registers containing left and right operands respectively. | 3248 // Registers containing left and right operands respectively. |
| 3249 Register left = edx; | 3249 Register left = edx; |
| 3250 Register right = eax; | 3250 Register right = eax; |
| 3251 Register tmp1 = ecx; | 3251 Register tmp1 = ecx; |
| 3252 Register tmp2 = ebx; | 3252 Register tmp2 = ebx; |
| 3253 Register tmp3 = edi; | 3253 Register tmp3 = edi; |
| 3254 | 3254 |
| 3255 // Check that both operands are heap objects. | 3255 // Check that both operands are heap objects. |
| 3256 __ mov(tmp1, left); | 3256 __ mov(tmp1, left); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3323 } else { | 3323 } else { |
| 3324 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 3324 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
| 3325 } | 3325 } |
| 3326 | 3326 |
| 3327 __ bind(&miss); | 3327 __ bind(&miss); |
| 3328 GenerateMiss(masm); | 3328 GenerateMiss(masm); |
| 3329 } | 3329 } |
| 3330 | 3330 |
| 3331 | 3331 |
| 3332 void ICCompareStub::GenerateObjects(MacroAssembler* masm) { | 3332 void ICCompareStub::GenerateObjects(MacroAssembler* masm) { |
| 3333 DCHECK(state_ == CompareIC::OBJECT); | 3333 DCHECK(state() == CompareIC::OBJECT); |
| 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 __ CmpObjectType(eax, JS_OBJECT_TYPE, ecx); | 3339 __ CmpObjectType(eax, JS_OBJECT_TYPE, ecx); |
| 3340 __ j(not_equal, &miss, Label::kNear); | 3340 __ j(not_equal, &miss, Label::kNear); |
| 3341 __ CmpObjectType(edx, JS_OBJECT_TYPE, ecx); | 3341 __ CmpObjectType(edx, JS_OBJECT_TYPE, ecx); |
| 3342 __ j(not_equal, &miss, Label::kNear); | 3342 __ j(not_equal, &miss, Label::kNear); |
| 3343 | 3343 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 3374 void ICCompareStub::GenerateMiss(MacroAssembler* masm) { | 3374 void ICCompareStub::GenerateMiss(MacroAssembler* masm) { |
| 3375 { | 3375 { |
| 3376 // Call the runtime system in a fresh internal frame. | 3376 // Call the runtime system in a fresh internal frame. |
| 3377 ExternalReference miss = ExternalReference(IC_Utility(IC::kCompareIC_Miss), | 3377 ExternalReference miss = ExternalReference(IC_Utility(IC::kCompareIC_Miss), |
| 3378 isolate()); | 3378 isolate()); |
| 3379 FrameScope scope(masm, StackFrame::INTERNAL); | 3379 FrameScope scope(masm, StackFrame::INTERNAL); |
| 3380 __ push(edx); // Preserve edx and eax. | 3380 __ push(edx); // Preserve edx and eax. |
| 3381 __ push(eax); | 3381 __ push(eax); |
| 3382 __ push(edx); // And also use them as the arguments. | 3382 __ push(edx); // And also use them as the arguments. |
| 3383 __ push(eax); | 3383 __ push(eax); |
| 3384 __ push(Immediate(Smi::FromInt(op_))); | 3384 __ push(Immediate(Smi::FromInt(op()))); |
| 3385 __ CallExternalReference(miss, 3); | 3385 __ CallExternalReference(miss, 3); |
| 3386 // Compute the entry point of the rewritten stub. | 3386 // Compute the entry point of the rewritten stub. |
| 3387 __ lea(edi, FieldOperand(eax, Code::kHeaderSize)); | 3387 __ lea(edi, FieldOperand(eax, Code::kHeaderSize)); |
| 3388 __ pop(eax); | 3388 __ pop(eax); |
| 3389 __ pop(edx); | 3389 __ pop(edx); |
| 3390 } | 3390 } |
| 3391 | 3391 |
| 3392 // Do a tail call to the rewritten stub. | 3392 // Do a tail call to the rewritten stub. |
| 3393 __ jmp(edi); | 3393 __ jmp(edi); |
| 3394 } | 3394 } |
| (...skipping 1026 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4421 Operand(ebp, 7 * kPointerSize), | 4421 Operand(ebp, 7 * kPointerSize), |
| 4422 NULL); | 4422 NULL); |
| 4423 } | 4423 } |
| 4424 | 4424 |
| 4425 | 4425 |
| 4426 #undef __ | 4426 #undef __ |
| 4427 | 4427 |
| 4428 } } // namespace v8::internal | 4428 } } // namespace v8::internal |
| 4429 | 4429 |
| 4430 #endif // V8_TARGET_ARCH_X87 | 4430 #endif // V8_TARGET_ARCH_X87 |
| OLD | NEW |