OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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_X64 | 7 #if V8_TARGET_ARCH_X64 |
8 | 8 |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
11 #include "src/codegen.h" | 11 #include "src/codegen.h" |
12 #include "src/ic/handler-compiler.h" | 12 #include "src/ic/handler-compiler.h" |
| 13 #include "src/ic/ic.h" |
13 #include "src/isolate.h" | 14 #include "src/isolate.h" |
14 #include "src/jsregexp.h" | 15 #include "src/jsregexp.h" |
15 #include "src/regexp-macro-assembler.h" | 16 #include "src/regexp-macro-assembler.h" |
16 #include "src/runtime.h" | 17 #include "src/runtime.h" |
17 | 18 |
18 namespace v8 { | 19 namespace v8 { |
19 namespace internal { | 20 namespace internal { |
20 | 21 |
21 | 22 |
22 static void InitializeArrayConstructorDescriptor( | 23 static void InitializeArrayConstructorDescriptor( |
(...skipping 1359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1382 | 1383 |
1383 | 1384 |
1384 static int NegativeComparisonResult(Condition cc) { | 1385 static int NegativeComparisonResult(Condition cc) { |
1385 DCHECK(cc != equal); | 1386 DCHECK(cc != equal); |
1386 DCHECK((cc == less) || (cc == less_equal) | 1387 DCHECK((cc == less) || (cc == less_equal) |
1387 || (cc == greater) || (cc == greater_equal)); | 1388 || (cc == greater) || (cc == greater_equal)); |
1388 return (cc == greater || cc == greater_equal) ? LESS : GREATER; | 1389 return (cc == greater || cc == greater_equal) ? LESS : GREATER; |
1389 } | 1390 } |
1390 | 1391 |
1391 | 1392 |
1392 static void CheckInputType(MacroAssembler* masm, | 1393 static void CheckInputType(MacroAssembler* masm, Register input, |
1393 Register input, | 1394 CompareICState::State expected, Label* fail) { |
1394 CompareIC::State expected, | |
1395 Label* fail) { | |
1396 Label ok; | 1395 Label ok; |
1397 if (expected == CompareIC::SMI) { | 1396 if (expected == CompareICState::SMI) { |
1398 __ JumpIfNotSmi(input, fail); | 1397 __ JumpIfNotSmi(input, fail); |
1399 } else if (expected == CompareIC::NUMBER) { | 1398 } else if (expected == CompareICState::NUMBER) { |
1400 __ JumpIfSmi(input, &ok); | 1399 __ JumpIfSmi(input, &ok); |
1401 __ CompareMap(input, masm->isolate()->factory()->heap_number_map()); | 1400 __ CompareMap(input, masm->isolate()->factory()->heap_number_map()); |
1402 __ j(not_equal, fail); | 1401 __ j(not_equal, fail); |
1403 } | 1402 } |
1404 // We could be strict about internalized/non-internalized here, but as long as | 1403 // We could be strict about internalized/non-internalized here, but as long as |
1405 // hydrogen doesn't care, the stub doesn't have to care either. | 1404 // hydrogen doesn't care, the stub doesn't have to care either. |
1406 __ bind(&ok); | 1405 __ bind(&ok); |
1407 } | 1406 } |
1408 | 1407 |
1409 | 1408 |
(...skipping 593 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2003 Factory* factory = masm->isolate()->factory(); | 2002 Factory* factory = masm->isolate()->factory(); |
2004 __ Cmp(FieldOperand(rcx, HeapObject::kMapOffset), | 2003 __ Cmp(FieldOperand(rcx, HeapObject::kMapOffset), |
2005 factory->allocation_site_map()); | 2004 factory->allocation_site_map()); |
2006 __ j(not_equal, &miss); | 2005 __ j(not_equal, &miss); |
2007 | 2006 |
2008 __ movp(rbx, rcx); | 2007 __ movp(rbx, rcx); |
2009 ArrayConstructorStub stub(masm->isolate(), arg_count()); | 2008 ArrayConstructorStub stub(masm->isolate(), arg_count()); |
2010 __ TailCallStub(&stub); | 2009 __ TailCallStub(&stub); |
2011 | 2010 |
2012 __ bind(&miss); | 2011 __ bind(&miss); |
2013 GenerateMiss(masm, IC::kCallIC_Customization_Miss); | 2012 GenerateMiss(masm); |
2014 | 2013 |
2015 // The slow case, we need this no matter what to complete a call after a miss. | 2014 // The slow case, we need this no matter what to complete a call after a miss. |
2016 CallFunctionNoFeedback(masm, | 2015 CallFunctionNoFeedback(masm, |
2017 arg_count(), | 2016 arg_count(), |
2018 true, | 2017 true, |
2019 CallAsMethod()); | 2018 CallAsMethod()); |
2020 | 2019 |
2021 // Unreachable. | 2020 // Unreachable. |
2022 __ int3(); | 2021 __ int3(); |
2023 } | 2022 } |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2084 __ CmpObjectType(rcx, JS_FUNCTION_TYPE, rcx); | 2083 __ CmpObjectType(rcx, JS_FUNCTION_TYPE, rcx); |
2085 __ j(not_equal, &miss); | 2084 __ j(not_equal, &miss); |
2086 __ Move(FieldOperand(rbx, rdx, times_pointer_size, | 2085 __ Move(FieldOperand(rbx, rdx, times_pointer_size, |
2087 FixedArray::kHeaderSize), | 2086 FixedArray::kHeaderSize), |
2088 TypeFeedbackInfo::MegamorphicSentinel(isolate)); | 2087 TypeFeedbackInfo::MegamorphicSentinel(isolate)); |
2089 __ jmp(&slow_start); | 2088 __ jmp(&slow_start); |
2090 } | 2089 } |
2091 | 2090 |
2092 // We are here because tracing is on or we are going monomorphic. | 2091 // We are here because tracing is on or we are going monomorphic. |
2093 __ bind(&miss); | 2092 __ bind(&miss); |
2094 GenerateMiss(masm, IC::kCallIC_Miss); | 2093 GenerateMiss(masm); |
2095 | 2094 |
2096 // the slow case | 2095 // the slow case |
2097 __ bind(&slow_start); | 2096 __ bind(&slow_start); |
2098 // Check that function is not a smi. | 2097 // Check that function is not a smi. |
2099 __ JumpIfSmi(rdi, &non_function); | 2098 __ JumpIfSmi(rdi, &non_function); |
2100 // Check that function is a JSFunction. | 2099 // Check that function is a JSFunction. |
2101 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); | 2100 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); |
2102 __ j(not_equal, &slow); | 2101 __ j(not_equal, &slow); |
2103 __ jmp(&have_js_function); | 2102 __ jmp(&have_js_function); |
2104 | 2103 |
2105 // Unreachable | 2104 // Unreachable |
2106 __ int3(); | 2105 __ int3(); |
2107 } | 2106 } |
2108 | 2107 |
2109 | 2108 |
2110 void CallICStub::GenerateMiss(MacroAssembler* masm, IC::UtilityId id) { | 2109 void CallICStub::GenerateMiss(MacroAssembler* masm) { |
2111 // Get the receiver of the function from the stack; 1 ~ return address. | 2110 // Get the receiver of the function from the stack; 1 ~ return address. |
2112 __ movp(rcx, Operand(rsp, (arg_count() + 1) * kPointerSize)); | 2111 __ movp(rcx, Operand(rsp, (arg_count() + 1) * kPointerSize)); |
2113 | 2112 |
2114 { | 2113 { |
2115 FrameScope scope(masm, StackFrame::INTERNAL); | 2114 FrameScope scope(masm, StackFrame::INTERNAL); |
2116 | 2115 |
2117 // Push the receiver and the function and feedback info. | 2116 // Push the receiver and the function and feedback info. |
2118 __ Push(rcx); | 2117 __ Push(rcx); |
2119 __ Push(rdi); | 2118 __ Push(rdi); |
2120 __ Push(rbx); | 2119 __ Push(rbx); |
2121 __ Integer32ToSmi(rdx, rdx); | 2120 __ Integer32ToSmi(rdx, rdx); |
2122 __ Push(rdx); | 2121 __ Push(rdx); |
2123 | 2122 |
2124 // Call the entry. | 2123 // Call the entry. |
| 2124 IC::UtilityId id = GetICState() == DEFAULT ? IC::kCallIC_Miss |
| 2125 : IC::kCallIC_Customization_Miss; |
| 2126 |
2125 ExternalReference miss = ExternalReference(IC_Utility(id), | 2127 ExternalReference miss = ExternalReference(IC_Utility(id), |
2126 masm->isolate()); | 2128 masm->isolate()); |
2127 __ CallExternalReference(miss, 4); | 2129 __ CallExternalReference(miss, 4); |
2128 | 2130 |
2129 // Move result to edi and exit the internal frame. | 2131 // Move result to edi and exit the internal frame. |
2130 __ movp(rdi, rax); | 2132 __ movp(rdi, rax); |
2131 } | 2133 } |
2132 } | 2134 } |
2133 | 2135 |
2134 | 2136 |
(...skipping 1115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3250 } | 3252 } |
3251 | 3253 |
3252 // Tail call into the stub that handles binary operations with allocation | 3254 // Tail call into the stub that handles binary operations with allocation |
3253 // sites. | 3255 // sites. |
3254 BinaryOpWithAllocationSiteStub stub(isolate(), state()); | 3256 BinaryOpWithAllocationSiteStub stub(isolate(), state()); |
3255 __ TailCallStub(&stub); | 3257 __ TailCallStub(&stub); |
3256 } | 3258 } |
3257 | 3259 |
3258 | 3260 |
3259 void CompareICStub::GenerateSmis(MacroAssembler* masm) { | 3261 void CompareICStub::GenerateSmis(MacroAssembler* masm) { |
3260 DCHECK(state() == CompareIC::SMI); | 3262 DCHECK(state() == CompareICState::SMI); |
3261 Label miss; | 3263 Label miss; |
3262 __ JumpIfNotBothSmi(rdx, rax, &miss, Label::kNear); | 3264 __ JumpIfNotBothSmi(rdx, rax, &miss, Label::kNear); |
3263 | 3265 |
3264 if (GetCondition() == equal) { | 3266 if (GetCondition() == equal) { |
3265 // For equality we do not care about the sign of the result. | 3267 // For equality we do not care about the sign of the result. |
3266 __ subp(rax, rdx); | 3268 __ subp(rax, rdx); |
3267 } else { | 3269 } else { |
3268 Label done; | 3270 Label done; |
3269 __ subp(rdx, rax); | 3271 __ subp(rdx, rax); |
3270 __ j(no_overflow, &done, Label::kNear); | 3272 __ j(no_overflow, &done, Label::kNear); |
3271 // Correct sign of result in case of overflow. | 3273 // Correct sign of result in case of overflow. |
3272 __ notp(rdx); | 3274 __ notp(rdx); |
3273 __ bind(&done); | 3275 __ bind(&done); |
3274 __ movp(rax, rdx); | 3276 __ movp(rax, rdx); |
3275 } | 3277 } |
3276 __ ret(0); | 3278 __ ret(0); |
3277 | 3279 |
3278 __ bind(&miss); | 3280 __ bind(&miss); |
3279 GenerateMiss(masm); | 3281 GenerateMiss(masm); |
3280 } | 3282 } |
3281 | 3283 |
3282 | 3284 |
3283 void CompareICStub::GenerateNumbers(MacroAssembler* masm) { | 3285 void CompareICStub::GenerateNumbers(MacroAssembler* masm) { |
3284 DCHECK(state() == CompareIC::NUMBER); | 3286 DCHECK(state() == CompareICState::NUMBER); |
3285 | 3287 |
3286 Label generic_stub; | 3288 Label generic_stub; |
3287 Label unordered, maybe_undefined1, maybe_undefined2; | 3289 Label unordered, maybe_undefined1, maybe_undefined2; |
3288 Label miss; | 3290 Label miss; |
3289 | 3291 |
3290 if (left() == CompareIC::SMI) { | 3292 if (left() == CompareICState::SMI) { |
3291 __ JumpIfNotSmi(rdx, &miss); | 3293 __ JumpIfNotSmi(rdx, &miss); |
3292 } | 3294 } |
3293 if (right() == CompareIC::SMI) { | 3295 if (right() == CompareICState::SMI) { |
3294 __ JumpIfNotSmi(rax, &miss); | 3296 __ JumpIfNotSmi(rax, &miss); |
3295 } | 3297 } |
3296 | 3298 |
3297 // Load left and right operand. | 3299 // Load left and right operand. |
3298 Label done, left, left_smi, right_smi; | 3300 Label done, left, left_smi, right_smi; |
3299 __ JumpIfSmi(rax, &right_smi, Label::kNear); | 3301 __ JumpIfSmi(rax, &right_smi, Label::kNear); |
3300 __ CompareMap(rax, isolate()->factory()->heap_number_map()); | 3302 __ CompareMap(rax, isolate()->factory()->heap_number_map()); |
3301 __ j(not_equal, &maybe_undefined1, Label::kNear); | 3303 __ j(not_equal, &maybe_undefined1, Label::kNear); |
3302 __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset)); | 3304 __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset)); |
3303 __ jmp(&left, Label::kNear); | 3305 __ jmp(&left, Label::kNear); |
(...skipping 21 matching lines...) Expand all Loading... |
3325 // Return a result of -1, 0, or 1, based on EFLAGS. | 3327 // Return a result of -1, 0, or 1, based on EFLAGS. |
3326 // Performing mov, because xor would destroy the flag register. | 3328 // Performing mov, because xor would destroy the flag register. |
3327 __ movl(rax, Immediate(0)); | 3329 __ movl(rax, Immediate(0)); |
3328 __ movl(rcx, Immediate(0)); | 3330 __ movl(rcx, Immediate(0)); |
3329 __ setcc(above, rax); // Add one to zero if carry clear and not equal. | 3331 __ setcc(above, rax); // Add one to zero if carry clear and not equal. |
3330 __ sbbp(rax, rcx); // Subtract one if below (aka. carry set). | 3332 __ sbbp(rax, rcx); // Subtract one if below (aka. carry set). |
3331 __ ret(0); | 3333 __ ret(0); |
3332 | 3334 |
3333 __ bind(&unordered); | 3335 __ bind(&unordered); |
3334 __ bind(&generic_stub); | 3336 __ bind(&generic_stub); |
3335 CompareICStub stub(isolate(), op(), CompareIC::GENERIC, CompareIC::GENERIC, | 3337 CompareICStub stub(isolate(), op(), CompareICState::GENERIC, |
3336 CompareIC::GENERIC); | 3338 CompareICState::GENERIC, CompareICState::GENERIC); |
3337 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); | 3339 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); |
3338 | 3340 |
3339 __ bind(&maybe_undefined1); | 3341 __ bind(&maybe_undefined1); |
3340 if (Token::IsOrderedRelationalCompareOp(op())) { | 3342 if (Token::IsOrderedRelationalCompareOp(op())) { |
3341 __ Cmp(rax, isolate()->factory()->undefined_value()); | 3343 __ Cmp(rax, isolate()->factory()->undefined_value()); |
3342 __ j(not_equal, &miss); | 3344 __ j(not_equal, &miss); |
3343 __ JumpIfSmi(rdx, &unordered); | 3345 __ JumpIfSmi(rdx, &unordered); |
3344 __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rcx); | 3346 __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rcx); |
3345 __ j(not_equal, &maybe_undefined2, Label::kNear); | 3347 __ j(not_equal, &maybe_undefined2, Label::kNear); |
3346 __ jmp(&unordered); | 3348 __ jmp(&unordered); |
3347 } | 3349 } |
3348 | 3350 |
3349 __ bind(&maybe_undefined2); | 3351 __ bind(&maybe_undefined2); |
3350 if (Token::IsOrderedRelationalCompareOp(op())) { | 3352 if (Token::IsOrderedRelationalCompareOp(op())) { |
3351 __ Cmp(rdx, isolate()->factory()->undefined_value()); | 3353 __ Cmp(rdx, isolate()->factory()->undefined_value()); |
3352 __ j(equal, &unordered); | 3354 __ j(equal, &unordered); |
3353 } | 3355 } |
3354 | 3356 |
3355 __ bind(&miss); | 3357 __ bind(&miss); |
3356 GenerateMiss(masm); | 3358 GenerateMiss(masm); |
3357 } | 3359 } |
3358 | 3360 |
3359 | 3361 |
3360 void CompareICStub::GenerateInternalizedStrings(MacroAssembler* masm) { | 3362 void CompareICStub::GenerateInternalizedStrings(MacroAssembler* masm) { |
3361 DCHECK(state() == CompareIC::INTERNALIZED_STRING); | 3363 DCHECK(state() == CompareICState::INTERNALIZED_STRING); |
3362 DCHECK(GetCondition() == equal); | 3364 DCHECK(GetCondition() == equal); |
3363 | 3365 |
3364 // Registers containing left and right operands respectively. | 3366 // Registers containing left and right operands respectively. |
3365 Register left = rdx; | 3367 Register left = rdx; |
3366 Register right = rax; | 3368 Register right = rax; |
3367 Register tmp1 = rcx; | 3369 Register tmp1 = rcx; |
3368 Register tmp2 = rbx; | 3370 Register tmp2 = rbx; |
3369 | 3371 |
3370 // Check that both operands are heap objects. | 3372 // Check that both operands are heap objects. |
3371 Label miss; | 3373 Label miss; |
(...skipping 22 matching lines...) Expand all Loading... |
3394 __ Move(rax, Smi::FromInt(EQUAL)); | 3396 __ Move(rax, Smi::FromInt(EQUAL)); |
3395 __ bind(&done); | 3397 __ bind(&done); |
3396 __ ret(0); | 3398 __ ret(0); |
3397 | 3399 |
3398 __ bind(&miss); | 3400 __ bind(&miss); |
3399 GenerateMiss(masm); | 3401 GenerateMiss(masm); |
3400 } | 3402 } |
3401 | 3403 |
3402 | 3404 |
3403 void CompareICStub::GenerateUniqueNames(MacroAssembler* masm) { | 3405 void CompareICStub::GenerateUniqueNames(MacroAssembler* masm) { |
3404 DCHECK(state() == CompareIC::UNIQUE_NAME); | 3406 DCHECK(state() == CompareICState::UNIQUE_NAME); |
3405 DCHECK(GetCondition() == equal); | 3407 DCHECK(GetCondition() == equal); |
3406 | 3408 |
3407 // Registers containing left and right operands respectively. | 3409 // Registers containing left and right operands respectively. |
3408 Register left = rdx; | 3410 Register left = rdx; |
3409 Register right = rax; | 3411 Register right = rax; |
3410 Register tmp1 = rcx; | 3412 Register tmp1 = rcx; |
3411 Register tmp2 = rbx; | 3413 Register tmp2 = rbx; |
3412 | 3414 |
3413 // Check that both operands are heap objects. | 3415 // Check that both operands are heap objects. |
3414 Label miss; | 3416 Label miss; |
(...skipping 22 matching lines...) Expand all Loading... |
3437 __ Move(rax, Smi::FromInt(EQUAL)); | 3439 __ Move(rax, Smi::FromInt(EQUAL)); |
3438 __ bind(&done); | 3440 __ bind(&done); |
3439 __ ret(0); | 3441 __ ret(0); |
3440 | 3442 |
3441 __ bind(&miss); | 3443 __ bind(&miss); |
3442 GenerateMiss(masm); | 3444 GenerateMiss(masm); |
3443 } | 3445 } |
3444 | 3446 |
3445 | 3447 |
3446 void CompareICStub::GenerateStrings(MacroAssembler* masm) { | 3448 void CompareICStub::GenerateStrings(MacroAssembler* masm) { |
3447 DCHECK(state() == CompareIC::STRING); | 3449 DCHECK(state() == CompareICState::STRING); |
3448 Label miss; | 3450 Label miss; |
3449 | 3451 |
3450 bool equality = Token::IsEqualityOp(op()); | 3452 bool equality = Token::IsEqualityOp(op()); |
3451 | 3453 |
3452 // Registers containing left and right operands respectively. | 3454 // Registers containing left and right operands respectively. |
3453 Register left = rdx; | 3455 Register left = rdx; |
3454 Register right = rax; | 3456 Register right = rax; |
3455 Register tmp1 = rcx; | 3457 Register tmp1 = rcx; |
3456 Register tmp2 = rbx; | 3458 Register tmp2 = rbx; |
3457 Register tmp3 = rdi; | 3459 Register tmp3 = rdi; |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3524 } else { | 3526 } else { |
3525 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 3527 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
3526 } | 3528 } |
3527 | 3529 |
3528 __ bind(&miss); | 3530 __ bind(&miss); |
3529 GenerateMiss(masm); | 3531 GenerateMiss(masm); |
3530 } | 3532 } |
3531 | 3533 |
3532 | 3534 |
3533 void CompareICStub::GenerateObjects(MacroAssembler* masm) { | 3535 void CompareICStub::GenerateObjects(MacroAssembler* masm) { |
3534 DCHECK(state() == CompareIC::OBJECT); | 3536 DCHECK(state() == CompareICState::OBJECT); |
3535 Label miss; | 3537 Label miss; |
3536 Condition either_smi = masm->CheckEitherSmi(rdx, rax); | 3538 Condition either_smi = masm->CheckEitherSmi(rdx, rax); |
3537 __ j(either_smi, &miss, Label::kNear); | 3539 __ j(either_smi, &miss, Label::kNear); |
3538 | 3540 |
3539 __ CmpObjectType(rax, JS_OBJECT_TYPE, rcx); | 3541 __ CmpObjectType(rax, JS_OBJECT_TYPE, rcx); |
3540 __ j(not_equal, &miss, Label::kNear); | 3542 __ j(not_equal, &miss, Label::kNear); |
3541 __ CmpObjectType(rdx, JS_OBJECT_TYPE, rcx); | 3543 __ CmpObjectType(rdx, JS_OBJECT_TYPE, rcx); |
3542 __ j(not_equal, &miss, Label::kNear); | 3544 __ j(not_equal, &miss, Label::kNear); |
3543 | 3545 |
3544 DCHECK(GetCondition() == equal); | 3546 DCHECK(GetCondition() == equal); |
(...skipping 1089 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4634 return_value_operand, | 4636 return_value_operand, |
4635 NULL); | 4637 NULL); |
4636 } | 4638 } |
4637 | 4639 |
4638 | 4640 |
4639 #undef __ | 4641 #undef __ |
4640 | 4642 |
4641 } } // namespace v8::internal | 4643 } } // namespace v8::internal |
4642 | 4644 |
4643 #endif // V8_TARGET_ARCH_X64 | 4645 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |