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_IA32 | 7 #if V8_TARGET_ARCH_IA32 |
8 | 8 |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
11 #include "src/code-stubs.h" | 11 #include "src/code-stubs.h" |
12 #include "src/codegen.h" | 12 #include "src/codegen.h" |
13 #include "src/ic/handler-compiler.h" | 13 #include "src/ic/handler-compiler.h" |
| 14 #include "src/ic/ic.h" |
14 #include "src/isolate.h" | 15 #include "src/isolate.h" |
15 #include "src/jsregexp.h" | 16 #include "src/jsregexp.h" |
16 #include "src/regexp-macro-assembler.h" | 17 #include "src/regexp-macro-assembler.h" |
17 #include "src/runtime.h" | 18 #include "src/runtime.h" |
18 | 19 |
19 namespace v8 { | 20 namespace v8 { |
20 namespace internal { | 21 namespace internal { |
21 | 22 |
22 | 23 |
23 static void InitializeArrayConstructorDescriptor( | 24 static void InitializeArrayConstructorDescriptor( |
(...skipping 1494 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1518 | 1519 |
1519 | 1520 |
1520 static int NegativeComparisonResult(Condition cc) { | 1521 static int NegativeComparisonResult(Condition cc) { |
1521 DCHECK(cc != equal); | 1522 DCHECK(cc != equal); |
1522 DCHECK((cc == less) || (cc == less_equal) | 1523 DCHECK((cc == less) || (cc == less_equal) |
1523 || (cc == greater) || (cc == greater_equal)); | 1524 || (cc == greater) || (cc == greater_equal)); |
1524 return (cc == greater || cc == greater_equal) ? LESS : GREATER; | 1525 return (cc == greater || cc == greater_equal) ? LESS : GREATER; |
1525 } | 1526 } |
1526 | 1527 |
1527 | 1528 |
1528 static void CheckInputType(MacroAssembler* masm, | 1529 static void CheckInputType(MacroAssembler* masm, Register input, |
1529 Register input, | 1530 CompareICState::State expected, Label* fail) { |
1530 CompareIC::State expected, | |
1531 Label* fail) { | |
1532 Label ok; | 1531 Label ok; |
1533 if (expected == CompareIC::SMI) { | 1532 if (expected == CompareICState::SMI) { |
1534 __ JumpIfNotSmi(input, fail); | 1533 __ JumpIfNotSmi(input, fail); |
1535 } else if (expected == CompareIC::NUMBER) { | 1534 } else if (expected == CompareICState::NUMBER) { |
1536 __ JumpIfSmi(input, &ok); | 1535 __ JumpIfSmi(input, &ok); |
1537 __ cmp(FieldOperand(input, HeapObject::kMapOffset), | 1536 __ cmp(FieldOperand(input, HeapObject::kMapOffset), |
1538 Immediate(masm->isolate()->factory()->heap_number_map())); | 1537 Immediate(masm->isolate()->factory()->heap_number_map())); |
1539 __ j(not_equal, fail); | 1538 __ j(not_equal, fail); |
1540 } | 1539 } |
1541 // We could be strict about internalized/non-internalized here, but as long as | 1540 // We could be strict about internalized/non-internalized here, but as long as |
1542 // hydrogen doesn't care, the stub doesn't have to care either. | 1541 // hydrogen doesn't care, the stub doesn't have to care either. |
1543 __ bind(&ok); | 1542 __ bind(&ok); |
1544 } | 1543 } |
1545 | 1544 |
(...skipping 584 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2130 Factory* factory = masm->isolate()->factory(); | 2129 Factory* factory = masm->isolate()->factory(); |
2131 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), | 2130 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), |
2132 factory->allocation_site_map()); | 2131 factory->allocation_site_map()); |
2133 __ j(not_equal, &miss); | 2132 __ j(not_equal, &miss); |
2134 | 2133 |
2135 __ mov(ebx, ecx); | 2134 __ mov(ebx, ecx); |
2136 ArrayConstructorStub stub(masm->isolate(), arg_count()); | 2135 ArrayConstructorStub stub(masm->isolate(), arg_count()); |
2137 __ TailCallStub(&stub); | 2136 __ TailCallStub(&stub); |
2138 | 2137 |
2139 __ bind(&miss); | 2138 __ bind(&miss); |
2140 GenerateMiss(masm, IC::kCallIC_Customization_Miss); | 2139 GenerateMiss(masm); |
2141 | 2140 |
2142 // The slow case, we need this no matter what to complete a call after a miss. | 2141 // The slow case, we need this no matter what to complete a call after a miss. |
2143 CallFunctionNoFeedback(masm, | 2142 CallFunctionNoFeedback(masm, |
2144 arg_count(), | 2143 arg_count(), |
2145 true, | 2144 true, |
2146 CallAsMethod()); | 2145 CallAsMethod()); |
2147 | 2146 |
2148 // Unreachable. | 2147 // Unreachable. |
2149 __ int3(); | 2148 __ int3(); |
2150 } | 2149 } |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2209 __ CmpObjectType(ecx, JS_FUNCTION_TYPE, ecx); | 2208 __ CmpObjectType(ecx, JS_FUNCTION_TYPE, ecx); |
2210 __ j(not_equal, &miss); | 2209 __ j(not_equal, &miss); |
2211 __ mov(FieldOperand(ebx, edx, times_half_pointer_size, | 2210 __ mov(FieldOperand(ebx, edx, times_half_pointer_size, |
2212 FixedArray::kHeaderSize), | 2211 FixedArray::kHeaderSize), |
2213 Immediate(TypeFeedbackInfo::MegamorphicSentinel(isolate))); | 2212 Immediate(TypeFeedbackInfo::MegamorphicSentinel(isolate))); |
2214 __ jmp(&slow_start); | 2213 __ jmp(&slow_start); |
2215 } | 2214 } |
2216 | 2215 |
2217 // We are here because tracing is on or we are going monomorphic. | 2216 // We are here because tracing is on or we are going monomorphic. |
2218 __ bind(&miss); | 2217 __ bind(&miss); |
2219 GenerateMiss(masm, IC::kCallIC_Miss); | 2218 GenerateMiss(masm); |
2220 | 2219 |
2221 // the slow case | 2220 // the slow case |
2222 __ bind(&slow_start); | 2221 __ bind(&slow_start); |
2223 | 2222 |
2224 // Check that the function really is a JavaScript function. | 2223 // Check that the function really is a JavaScript function. |
2225 __ JumpIfSmi(edi, &non_function); | 2224 __ JumpIfSmi(edi, &non_function); |
2226 | 2225 |
2227 // Goto slow case if we do not have a function. | 2226 // Goto slow case if we do not have a function. |
2228 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); | 2227 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); |
2229 __ j(not_equal, &slow); | 2228 __ j(not_equal, &slow); |
2230 __ jmp(&have_js_function); | 2229 __ jmp(&have_js_function); |
2231 | 2230 |
2232 // Unreachable | 2231 // Unreachable |
2233 __ int3(); | 2232 __ int3(); |
2234 } | 2233 } |
2235 | 2234 |
2236 | 2235 |
2237 void CallICStub::GenerateMiss(MacroAssembler* masm, IC::UtilityId id) { | 2236 void CallICStub::GenerateMiss(MacroAssembler* masm) { |
2238 // Get the receiver of the function from the stack; 1 ~ return address. | 2237 // Get the receiver of the function from the stack; 1 ~ return address. |
2239 __ mov(ecx, Operand(esp, (arg_count() + 1) * kPointerSize)); | 2238 __ mov(ecx, Operand(esp, (arg_count() + 1) * kPointerSize)); |
2240 | 2239 |
2241 { | 2240 { |
2242 FrameScope scope(masm, StackFrame::INTERNAL); | 2241 FrameScope scope(masm, StackFrame::INTERNAL); |
2243 | 2242 |
2244 // Push the receiver and the function and feedback info. | 2243 // Push the receiver and the function and feedback info. |
2245 __ push(ecx); | 2244 __ push(ecx); |
2246 __ push(edi); | 2245 __ push(edi); |
2247 __ push(ebx); | 2246 __ push(ebx); |
2248 __ push(edx); | 2247 __ push(edx); |
2249 | 2248 |
2250 // Call the entry. | 2249 // Call the entry. |
| 2250 IC::UtilityId id = GetICState() == DEFAULT ? IC::kCallIC_Miss |
| 2251 : IC::kCallIC_Customization_Miss; |
| 2252 |
2251 ExternalReference miss = ExternalReference(IC_Utility(id), | 2253 ExternalReference miss = ExternalReference(IC_Utility(id), |
2252 masm->isolate()); | 2254 masm->isolate()); |
2253 __ CallExternalReference(miss, 4); | 2255 __ CallExternalReference(miss, 4); |
2254 | 2256 |
2255 // Move result to edi and exit the internal frame. | 2257 // Move result to edi and exit the internal frame. |
2256 __ mov(edi, eax); | 2258 __ mov(edi, eax); |
2257 } | 2259 } |
2258 } | 2260 } |
2259 | 2261 |
2260 | 2262 |
(...skipping 1026 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3287 } | 3289 } |
3288 | 3290 |
3289 // Tail call into the stub that handles binary operations with allocation | 3291 // Tail call into the stub that handles binary operations with allocation |
3290 // sites. | 3292 // sites. |
3291 BinaryOpWithAllocationSiteStub stub(isolate(), state()); | 3293 BinaryOpWithAllocationSiteStub stub(isolate(), state()); |
3292 __ TailCallStub(&stub); | 3294 __ TailCallStub(&stub); |
3293 } | 3295 } |
3294 | 3296 |
3295 | 3297 |
3296 void CompareICStub::GenerateSmis(MacroAssembler* masm) { | 3298 void CompareICStub::GenerateSmis(MacroAssembler* masm) { |
3297 DCHECK(state() == CompareIC::SMI); | 3299 DCHECK(state() == CompareICState::SMI); |
3298 Label miss; | 3300 Label miss; |
3299 __ mov(ecx, edx); | 3301 __ mov(ecx, edx); |
3300 __ or_(ecx, eax); | 3302 __ or_(ecx, eax); |
3301 __ JumpIfNotSmi(ecx, &miss, Label::kNear); | 3303 __ JumpIfNotSmi(ecx, &miss, Label::kNear); |
3302 | 3304 |
3303 if (GetCondition() == equal) { | 3305 if (GetCondition() == equal) { |
3304 // For equality we do not care about the sign of the result. | 3306 // For equality we do not care about the sign of the result. |
3305 __ sub(eax, edx); | 3307 __ sub(eax, edx); |
3306 } else { | 3308 } else { |
3307 Label done; | 3309 Label done; |
3308 __ sub(edx, eax); | 3310 __ sub(edx, eax); |
3309 __ j(no_overflow, &done, Label::kNear); | 3311 __ j(no_overflow, &done, Label::kNear); |
3310 // Correct sign of result in case of overflow. | 3312 // Correct sign of result in case of overflow. |
3311 __ not_(edx); | 3313 __ not_(edx); |
3312 __ bind(&done); | 3314 __ bind(&done); |
3313 __ mov(eax, edx); | 3315 __ mov(eax, edx); |
3314 } | 3316 } |
3315 __ ret(0); | 3317 __ ret(0); |
3316 | 3318 |
3317 __ bind(&miss); | 3319 __ bind(&miss); |
3318 GenerateMiss(masm); | 3320 GenerateMiss(masm); |
3319 } | 3321 } |
3320 | 3322 |
3321 | 3323 |
3322 void CompareICStub::GenerateNumbers(MacroAssembler* masm) { | 3324 void CompareICStub::GenerateNumbers(MacroAssembler* masm) { |
3323 DCHECK(state() == CompareIC::NUMBER); | 3325 DCHECK(state() == CompareICState::NUMBER); |
3324 | 3326 |
3325 Label generic_stub; | 3327 Label generic_stub; |
3326 Label unordered, maybe_undefined1, maybe_undefined2; | 3328 Label unordered, maybe_undefined1, maybe_undefined2; |
3327 Label miss; | 3329 Label miss; |
3328 | 3330 |
3329 if (left() == CompareIC::SMI) { | 3331 if (left() == CompareICState::SMI) { |
3330 __ JumpIfNotSmi(edx, &miss); | 3332 __ JumpIfNotSmi(edx, &miss); |
3331 } | 3333 } |
3332 if (right() == CompareIC::SMI) { | 3334 if (right() == CompareICState::SMI) { |
3333 __ JumpIfNotSmi(eax, &miss); | 3335 __ JumpIfNotSmi(eax, &miss); |
3334 } | 3336 } |
3335 | 3337 |
3336 // Load left and right operand. | 3338 // Load left and right operand. |
3337 Label done, left, left_smi, right_smi; | 3339 Label done, left, left_smi, right_smi; |
3338 __ JumpIfSmi(eax, &right_smi, Label::kNear); | 3340 __ JumpIfSmi(eax, &right_smi, Label::kNear); |
3339 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), | 3341 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), |
3340 isolate()->factory()->heap_number_map()); | 3342 isolate()->factory()->heap_number_map()); |
3341 __ j(not_equal, &maybe_undefined1, Label::kNear); | 3343 __ j(not_equal, &maybe_undefined1, Label::kNear); |
3342 __ movsd(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); | 3344 __ movsd(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); |
(...skipping 26 matching lines...) Expand all Loading... |
3369 // Performing mov, because xor would destroy the flag register. | 3371 // Performing mov, because xor would destroy the flag register. |
3370 __ mov(eax, 0); // equal | 3372 __ mov(eax, 0); // equal |
3371 __ mov(ecx, Immediate(Smi::FromInt(1))); | 3373 __ mov(ecx, Immediate(Smi::FromInt(1))); |
3372 __ cmov(above, eax, ecx); | 3374 __ cmov(above, eax, ecx); |
3373 __ mov(ecx, Immediate(Smi::FromInt(-1))); | 3375 __ mov(ecx, Immediate(Smi::FromInt(-1))); |
3374 __ cmov(below, eax, ecx); | 3376 __ cmov(below, eax, ecx); |
3375 __ ret(0); | 3377 __ ret(0); |
3376 | 3378 |
3377 __ bind(&unordered); | 3379 __ bind(&unordered); |
3378 __ bind(&generic_stub); | 3380 __ bind(&generic_stub); |
3379 CompareICStub stub(isolate(), op(), CompareIC::GENERIC, CompareIC::GENERIC, | 3381 CompareICStub stub(isolate(), op(), CompareICState::GENERIC, |
3380 CompareIC::GENERIC); | 3382 CompareICState::GENERIC, CompareICState::GENERIC); |
3381 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); | 3383 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); |
3382 | 3384 |
3383 __ bind(&maybe_undefined1); | 3385 __ bind(&maybe_undefined1); |
3384 if (Token::IsOrderedRelationalCompareOp(op())) { | 3386 if (Token::IsOrderedRelationalCompareOp(op())) { |
3385 __ cmp(eax, Immediate(isolate()->factory()->undefined_value())); | 3387 __ cmp(eax, Immediate(isolate()->factory()->undefined_value())); |
3386 __ j(not_equal, &miss); | 3388 __ j(not_equal, &miss); |
3387 __ JumpIfSmi(edx, &unordered); | 3389 __ JumpIfSmi(edx, &unordered); |
3388 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ecx); | 3390 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ecx); |
3389 __ j(not_equal, &maybe_undefined2, Label::kNear); | 3391 __ j(not_equal, &maybe_undefined2, Label::kNear); |
3390 __ jmp(&unordered); | 3392 __ jmp(&unordered); |
3391 } | 3393 } |
3392 | 3394 |
3393 __ bind(&maybe_undefined2); | 3395 __ bind(&maybe_undefined2); |
3394 if (Token::IsOrderedRelationalCompareOp(op())) { | 3396 if (Token::IsOrderedRelationalCompareOp(op())) { |
3395 __ cmp(edx, Immediate(isolate()->factory()->undefined_value())); | 3397 __ cmp(edx, Immediate(isolate()->factory()->undefined_value())); |
3396 __ j(equal, &unordered); | 3398 __ j(equal, &unordered); |
3397 } | 3399 } |
3398 | 3400 |
3399 __ bind(&miss); | 3401 __ bind(&miss); |
3400 GenerateMiss(masm); | 3402 GenerateMiss(masm); |
3401 } | 3403 } |
3402 | 3404 |
3403 | 3405 |
3404 void CompareICStub::GenerateInternalizedStrings(MacroAssembler* masm) { | 3406 void CompareICStub::GenerateInternalizedStrings(MacroAssembler* masm) { |
3405 DCHECK(state() == CompareIC::INTERNALIZED_STRING); | 3407 DCHECK(state() == CompareICState::INTERNALIZED_STRING); |
3406 DCHECK(GetCondition() == equal); | 3408 DCHECK(GetCondition() == equal); |
3407 | 3409 |
3408 // Registers containing left and right operands respectively. | 3410 // Registers containing left and right operands respectively. |
3409 Register left = edx; | 3411 Register left = edx; |
3410 Register right = eax; | 3412 Register right = eax; |
3411 Register tmp1 = ecx; | 3413 Register tmp1 = ecx; |
3412 Register tmp2 = ebx; | 3414 Register tmp2 = ebx; |
3413 | 3415 |
3414 // Check that both operands are heap objects. | 3416 // Check that both operands are heap objects. |
3415 Label miss; | 3417 Label miss; |
(...skipping 24 matching lines...) Expand all Loading... |
3440 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); | 3442 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); |
3441 __ bind(&done); | 3443 __ bind(&done); |
3442 __ ret(0); | 3444 __ ret(0); |
3443 | 3445 |
3444 __ bind(&miss); | 3446 __ bind(&miss); |
3445 GenerateMiss(masm); | 3447 GenerateMiss(masm); |
3446 } | 3448 } |
3447 | 3449 |
3448 | 3450 |
3449 void CompareICStub::GenerateUniqueNames(MacroAssembler* masm) { | 3451 void CompareICStub::GenerateUniqueNames(MacroAssembler* masm) { |
3450 DCHECK(state() == CompareIC::UNIQUE_NAME); | 3452 DCHECK(state() == CompareICState::UNIQUE_NAME); |
3451 DCHECK(GetCondition() == equal); | 3453 DCHECK(GetCondition() == equal); |
3452 | 3454 |
3453 // Registers containing left and right operands respectively. | 3455 // Registers containing left and right operands respectively. |
3454 Register left = edx; | 3456 Register left = edx; |
3455 Register right = eax; | 3457 Register right = eax; |
3456 Register tmp1 = ecx; | 3458 Register tmp1 = ecx; |
3457 Register tmp2 = ebx; | 3459 Register tmp2 = ebx; |
3458 | 3460 |
3459 // Check that both operands are heap objects. | 3461 // Check that both operands are heap objects. |
3460 Label miss; | 3462 Label miss; |
(...skipping 24 matching lines...) Expand all Loading... |
3485 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); | 3487 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); |
3486 __ bind(&done); | 3488 __ bind(&done); |
3487 __ ret(0); | 3489 __ ret(0); |
3488 | 3490 |
3489 __ bind(&miss); | 3491 __ bind(&miss); |
3490 GenerateMiss(masm); | 3492 GenerateMiss(masm); |
3491 } | 3493 } |
3492 | 3494 |
3493 | 3495 |
3494 void CompareICStub::GenerateStrings(MacroAssembler* masm) { | 3496 void CompareICStub::GenerateStrings(MacroAssembler* masm) { |
3495 DCHECK(state() == CompareIC::STRING); | 3497 DCHECK(state() == CompareICState::STRING); |
3496 Label miss; | 3498 Label miss; |
3497 | 3499 |
3498 bool equality = Token::IsEqualityOp(op()); | 3500 bool equality = Token::IsEqualityOp(op()); |
3499 | 3501 |
3500 // Registers containing left and right operands respectively. | 3502 // Registers containing left and right operands respectively. |
3501 Register left = edx; | 3503 Register left = edx; |
3502 Register right = eax; | 3504 Register right = eax; |
3503 Register tmp1 = ecx; | 3505 Register tmp1 = ecx; |
3504 Register tmp2 = ebx; | 3506 Register tmp2 = ebx; |
3505 Register tmp3 = edi; | 3507 Register tmp3 = edi; |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3575 } else { | 3577 } else { |
3576 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 3578 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
3577 } | 3579 } |
3578 | 3580 |
3579 __ bind(&miss); | 3581 __ bind(&miss); |
3580 GenerateMiss(masm); | 3582 GenerateMiss(masm); |
3581 } | 3583 } |
3582 | 3584 |
3583 | 3585 |
3584 void CompareICStub::GenerateObjects(MacroAssembler* masm) { | 3586 void CompareICStub::GenerateObjects(MacroAssembler* masm) { |
3585 DCHECK(state() == CompareIC::OBJECT); | 3587 DCHECK(state() == CompareICState::OBJECT); |
3586 Label miss; | 3588 Label miss; |
3587 __ mov(ecx, edx); | 3589 __ mov(ecx, edx); |
3588 __ and_(ecx, eax); | 3590 __ and_(ecx, eax); |
3589 __ JumpIfSmi(ecx, &miss, Label::kNear); | 3591 __ JumpIfSmi(ecx, &miss, Label::kNear); |
3590 | 3592 |
3591 __ CmpObjectType(eax, JS_OBJECT_TYPE, ecx); | 3593 __ CmpObjectType(eax, JS_OBJECT_TYPE, ecx); |
3592 __ j(not_equal, &miss, Label::kNear); | 3594 __ j(not_equal, &miss, Label::kNear); |
3593 __ CmpObjectType(edx, JS_OBJECT_TYPE, ecx); | 3595 __ CmpObjectType(edx, JS_OBJECT_TYPE, ecx); |
3594 __ j(not_equal, &miss, Label::kNear); | 3596 __ j(not_equal, &miss, Label::kNear); |
3595 | 3597 |
(...skipping 1071 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4667 Operand(ebp, 7 * kPointerSize), | 4669 Operand(ebp, 7 * kPointerSize), |
4668 NULL); | 4670 NULL); |
4669 } | 4671 } |
4670 | 4672 |
4671 | 4673 |
4672 #undef __ | 4674 #undef __ |
4673 | 4675 |
4674 } } // namespace v8::internal | 4676 } } // namespace v8::internal |
4675 | 4677 |
4676 #endif // V8_TARGET_ARCH_IA32 | 4678 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |