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_ARM64 | 7 #if V8_TARGET_ARCH_ARM64 |
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 495 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
506 } | 506 } |
507 | 507 |
508 | 508 |
509 void ICCompareStub::GenerateGeneric(MacroAssembler* masm) { | 509 void ICCompareStub::GenerateGeneric(MacroAssembler* masm) { |
510 Register lhs = x1; | 510 Register lhs = x1; |
511 Register rhs = x0; | 511 Register rhs = x0; |
512 Register result = x0; | 512 Register result = x0; |
513 Condition cond = GetCondition(); | 513 Condition cond = GetCondition(); |
514 | 514 |
515 Label miss; | 515 Label miss; |
516 ICCompareStub_CheckInputType(masm, lhs, x2, left_, &miss); | 516 ICCompareStub_CheckInputType(masm, lhs, x2, left(), &miss); |
517 ICCompareStub_CheckInputType(masm, rhs, x3, right_, &miss); | 517 ICCompareStub_CheckInputType(masm, rhs, x3, right(), &miss); |
518 | 518 |
519 Label slow; // Call builtin. | 519 Label slow; // Call builtin. |
520 Label not_smis, both_loaded_as_doubles; | 520 Label not_smis, both_loaded_as_doubles; |
521 Label not_two_smis, smi_done; | 521 Label not_two_smis, smi_done; |
522 __ JumpIfEitherNotSmi(lhs, rhs, ¬_two_smis); | 522 __ JumpIfEitherNotSmi(lhs, rhs, ¬_two_smis); |
523 __ SmiUntag(lhs); | 523 __ SmiUntag(lhs); |
524 __ Sub(result, lhs, Operand::UntagSmi(rhs)); | 524 __ Sub(result, lhs, Operand::UntagSmi(rhs)); |
525 __ Ret(); | 525 __ Ret(); |
526 | 526 |
527 __ Bind(¬_two_smis); | 527 __ Bind(¬_two_smis); |
(...skipping 2669 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3197 __ Mov(result_, x0); | 3197 __ Mov(result_, x0); |
3198 call_helper.AfterCall(masm); | 3198 call_helper.AfterCall(masm); |
3199 __ B(&exit_); | 3199 __ B(&exit_); |
3200 | 3200 |
3201 __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase); | 3201 __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase); |
3202 } | 3202 } |
3203 | 3203 |
3204 | 3204 |
3205 void ICCompareStub::GenerateSmis(MacroAssembler* masm) { | 3205 void ICCompareStub::GenerateSmis(MacroAssembler* masm) { |
3206 // Inputs are in x0 (lhs) and x1 (rhs). | 3206 // Inputs are in x0 (lhs) and x1 (rhs). |
3207 DCHECK(state_ == CompareIC::SMI); | 3207 DCHECK(state() == CompareIC::SMI); |
3208 ASM_LOCATION("ICCompareStub[Smis]"); | 3208 ASM_LOCATION("ICCompareStub[Smis]"); |
3209 Label miss; | 3209 Label miss; |
3210 // Bail out (to 'miss') unless both x0 and x1 are smis. | 3210 // Bail out (to 'miss') unless both x0 and x1 are smis. |
3211 __ JumpIfEitherNotSmi(x0, x1, &miss); | 3211 __ JumpIfEitherNotSmi(x0, x1, &miss); |
3212 | 3212 |
3213 if (GetCondition() == eq) { | 3213 if (GetCondition() == eq) { |
3214 // For equality we do not care about the sign of the result. | 3214 // For equality we do not care about the sign of the result. |
3215 __ Sub(x0, x0, x1); | 3215 __ Sub(x0, x0, x1); |
3216 } else { | 3216 } else { |
3217 // Untag before subtracting to avoid handling overflow. | 3217 // Untag before subtracting to avoid handling overflow. |
3218 __ SmiUntag(x1); | 3218 __ SmiUntag(x1); |
3219 __ Sub(x0, x1, Operand::UntagSmi(x0)); | 3219 __ Sub(x0, x1, Operand::UntagSmi(x0)); |
3220 } | 3220 } |
3221 __ Ret(); | 3221 __ Ret(); |
3222 | 3222 |
3223 __ Bind(&miss); | 3223 __ Bind(&miss); |
3224 GenerateMiss(masm); | 3224 GenerateMiss(masm); |
3225 } | 3225 } |
3226 | 3226 |
3227 | 3227 |
3228 void ICCompareStub::GenerateNumbers(MacroAssembler* masm) { | 3228 void ICCompareStub::GenerateNumbers(MacroAssembler* masm) { |
3229 DCHECK(state_ == CompareIC::NUMBER); | 3229 DCHECK(state() == CompareIC::NUMBER); |
3230 ASM_LOCATION("ICCompareStub[HeapNumbers]"); | 3230 ASM_LOCATION("ICCompareStub[HeapNumbers]"); |
3231 | 3231 |
3232 Label unordered, maybe_undefined1, maybe_undefined2; | 3232 Label unordered, maybe_undefined1, maybe_undefined2; |
3233 Label miss, handle_lhs, values_in_d_regs; | 3233 Label miss, handle_lhs, values_in_d_regs; |
3234 Label untag_rhs, untag_lhs; | 3234 Label untag_rhs, untag_lhs; |
3235 | 3235 |
3236 Register result = x0; | 3236 Register result = x0; |
3237 Register rhs = x0; | 3237 Register rhs = x0; |
3238 Register lhs = x1; | 3238 Register lhs = x1; |
3239 FPRegister rhs_d = d0; | 3239 FPRegister rhs_d = d0; |
3240 FPRegister lhs_d = d1; | 3240 FPRegister lhs_d = d1; |
3241 | 3241 |
3242 if (left_ == CompareIC::SMI) { | 3242 if (left() == CompareIC::SMI) { |
3243 __ JumpIfNotSmi(lhs, &miss); | 3243 __ JumpIfNotSmi(lhs, &miss); |
3244 } | 3244 } |
3245 if (right_ == CompareIC::SMI) { | 3245 if (right() == CompareIC::SMI) { |
3246 __ JumpIfNotSmi(rhs, &miss); | 3246 __ JumpIfNotSmi(rhs, &miss); |
3247 } | 3247 } |
3248 | 3248 |
3249 __ SmiUntagToDouble(rhs_d, rhs, kSpeculativeUntag); | 3249 __ SmiUntagToDouble(rhs_d, rhs, kSpeculativeUntag); |
3250 __ SmiUntagToDouble(lhs_d, lhs, kSpeculativeUntag); | 3250 __ SmiUntagToDouble(lhs_d, lhs, kSpeculativeUntag); |
3251 | 3251 |
3252 // Load rhs if it's a heap number. | 3252 // Load rhs if it's a heap number. |
3253 __ JumpIfSmi(rhs, &handle_lhs); | 3253 __ JumpIfSmi(rhs, &handle_lhs); |
3254 __ CheckMap(rhs, x10, Heap::kHeapNumberMapRootIndex, &maybe_undefined1, | 3254 __ CheckMap(rhs, x10, Heap::kHeapNumberMapRootIndex, &maybe_undefined1, |
3255 DONT_DO_SMI_CHECK); | 3255 DONT_DO_SMI_CHECK); |
3256 __ Ldr(rhs_d, FieldMemOperand(rhs, HeapNumber::kValueOffset)); | 3256 __ Ldr(rhs_d, FieldMemOperand(rhs, HeapNumber::kValueOffset)); |
3257 | 3257 |
3258 // Load lhs if it's a heap number. | 3258 // Load lhs if it's a heap number. |
3259 __ Bind(&handle_lhs); | 3259 __ Bind(&handle_lhs); |
3260 __ JumpIfSmi(lhs, &values_in_d_regs); | 3260 __ JumpIfSmi(lhs, &values_in_d_regs); |
3261 __ CheckMap(lhs, x10, Heap::kHeapNumberMapRootIndex, &maybe_undefined2, | 3261 __ CheckMap(lhs, x10, Heap::kHeapNumberMapRootIndex, &maybe_undefined2, |
3262 DONT_DO_SMI_CHECK); | 3262 DONT_DO_SMI_CHECK); |
3263 __ Ldr(lhs_d, FieldMemOperand(lhs, HeapNumber::kValueOffset)); | 3263 __ Ldr(lhs_d, FieldMemOperand(lhs, HeapNumber::kValueOffset)); |
3264 | 3264 |
3265 __ Bind(&values_in_d_regs); | 3265 __ Bind(&values_in_d_regs); |
3266 __ Fcmp(lhs_d, rhs_d); | 3266 __ Fcmp(lhs_d, rhs_d); |
3267 __ B(vs, &unordered); // Overflow flag set if either is NaN. | 3267 __ B(vs, &unordered); // Overflow flag set if either is NaN. |
3268 STATIC_ASSERT((LESS == -1) && (EQUAL == 0) && (GREATER == 1)); | 3268 STATIC_ASSERT((LESS == -1) && (EQUAL == 0) && (GREATER == 1)); |
3269 __ Cset(result, gt); // gt => 1, otherwise (lt, eq) => 0 (EQUAL). | 3269 __ Cset(result, gt); // gt => 1, otherwise (lt, eq) => 0 (EQUAL). |
3270 __ Csinv(result, result, xzr, ge); // lt => -1, gt => 1, eq => 0. | 3270 __ Csinv(result, result, xzr, ge); // lt => -1, gt => 1, eq => 0. |
3271 __ Ret(); | 3271 __ Ret(); |
3272 | 3272 |
3273 __ Bind(&unordered); | 3273 __ Bind(&unordered); |
3274 ICCompareStub stub(isolate(), op_, CompareIC::GENERIC, CompareIC::GENERIC, | 3274 ICCompareStub stub(isolate(), op(), CompareIC::GENERIC, CompareIC::GENERIC, |
3275 CompareIC::GENERIC); | 3275 CompareIC::GENERIC); |
3276 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); | 3276 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); |
3277 | 3277 |
3278 __ Bind(&maybe_undefined1); | 3278 __ Bind(&maybe_undefined1); |
3279 if (Token::IsOrderedRelationalCompareOp(op_)) { | 3279 if (Token::IsOrderedRelationalCompareOp(op())) { |
3280 __ JumpIfNotRoot(rhs, Heap::kUndefinedValueRootIndex, &miss); | 3280 __ JumpIfNotRoot(rhs, Heap::kUndefinedValueRootIndex, &miss); |
3281 __ JumpIfSmi(lhs, &unordered); | 3281 __ JumpIfSmi(lhs, &unordered); |
3282 __ JumpIfNotObjectType(lhs, x10, x10, HEAP_NUMBER_TYPE, &maybe_undefined2); | 3282 __ JumpIfNotObjectType(lhs, x10, x10, HEAP_NUMBER_TYPE, &maybe_undefined2); |
3283 __ B(&unordered); | 3283 __ B(&unordered); |
3284 } | 3284 } |
3285 | 3285 |
3286 __ Bind(&maybe_undefined2); | 3286 __ Bind(&maybe_undefined2); |
3287 if (Token::IsOrderedRelationalCompareOp(op_)) { | 3287 if (Token::IsOrderedRelationalCompareOp(op())) { |
3288 __ JumpIfRoot(lhs, Heap::kUndefinedValueRootIndex, &unordered); | 3288 __ JumpIfRoot(lhs, Heap::kUndefinedValueRootIndex, &unordered); |
3289 } | 3289 } |
3290 | 3290 |
3291 __ Bind(&miss); | 3291 __ Bind(&miss); |
3292 GenerateMiss(masm); | 3292 GenerateMiss(masm); |
3293 } | 3293 } |
3294 | 3294 |
3295 | 3295 |
3296 void ICCompareStub::GenerateInternalizedStrings(MacroAssembler* masm) { | 3296 void ICCompareStub::GenerateInternalizedStrings(MacroAssembler* masm) { |
3297 DCHECK(state_ == CompareIC::INTERNALIZED_STRING); | 3297 DCHECK(state() == CompareIC::INTERNALIZED_STRING); |
3298 ASM_LOCATION("ICCompareStub[InternalizedStrings]"); | 3298 ASM_LOCATION("ICCompareStub[InternalizedStrings]"); |
3299 Label miss; | 3299 Label miss; |
3300 | 3300 |
3301 Register result = x0; | 3301 Register result = x0; |
3302 Register rhs = x0; | 3302 Register rhs = x0; |
3303 Register lhs = x1; | 3303 Register lhs = x1; |
3304 | 3304 |
3305 // Check that both operands are heap objects. | 3305 // Check that both operands are heap objects. |
3306 __ JumpIfEitherSmi(lhs, rhs, &miss); | 3306 __ JumpIfEitherSmi(lhs, rhs, &miss); |
3307 | 3307 |
(...skipping 17 matching lines...) Expand all Loading... |
3325 __ Cmp(lhs, rhs); | 3325 __ Cmp(lhs, rhs); |
3326 __ Cset(result, ne); | 3326 __ Cset(result, ne); |
3327 __ Ret(); | 3327 __ Ret(); |
3328 | 3328 |
3329 __ Bind(&miss); | 3329 __ Bind(&miss); |
3330 GenerateMiss(masm); | 3330 GenerateMiss(masm); |
3331 } | 3331 } |
3332 | 3332 |
3333 | 3333 |
3334 void ICCompareStub::GenerateUniqueNames(MacroAssembler* masm) { | 3334 void ICCompareStub::GenerateUniqueNames(MacroAssembler* masm) { |
3335 DCHECK(state_ == CompareIC::UNIQUE_NAME); | 3335 DCHECK(state() == CompareIC::UNIQUE_NAME); |
3336 ASM_LOCATION("ICCompareStub[UniqueNames]"); | 3336 ASM_LOCATION("ICCompareStub[UniqueNames]"); |
3337 DCHECK(GetCondition() == eq); | 3337 DCHECK(GetCondition() == eq); |
3338 Label miss; | 3338 Label miss; |
3339 | 3339 |
3340 Register result = x0; | 3340 Register result = x0; |
3341 Register rhs = x0; | 3341 Register rhs = x0; |
3342 Register lhs = x1; | 3342 Register lhs = x1; |
3343 | 3343 |
3344 Register lhs_instance_type = w2; | 3344 Register lhs_instance_type = w2; |
3345 Register rhs_instance_type = w3; | 3345 Register rhs_instance_type = w3; |
(...skipping 18 matching lines...) Expand all Loading... |
3364 __ Cmp(lhs, rhs); | 3364 __ Cmp(lhs, rhs); |
3365 __ Cset(result, ne); | 3365 __ Cset(result, ne); |
3366 __ Ret(); | 3366 __ Ret(); |
3367 | 3367 |
3368 __ Bind(&miss); | 3368 __ Bind(&miss); |
3369 GenerateMiss(masm); | 3369 GenerateMiss(masm); |
3370 } | 3370 } |
3371 | 3371 |
3372 | 3372 |
3373 void ICCompareStub::GenerateStrings(MacroAssembler* masm) { | 3373 void ICCompareStub::GenerateStrings(MacroAssembler* masm) { |
3374 DCHECK(state_ == CompareIC::STRING); | 3374 DCHECK(state() == CompareIC::STRING); |
3375 ASM_LOCATION("ICCompareStub[Strings]"); | 3375 ASM_LOCATION("ICCompareStub[Strings]"); |
3376 | 3376 |
3377 Label miss; | 3377 Label miss; |
3378 | 3378 |
3379 bool equality = Token::IsEqualityOp(op_); | 3379 bool equality = Token::IsEqualityOp(op()); |
3380 | 3380 |
3381 Register result = x0; | 3381 Register result = x0; |
3382 Register rhs = x0; | 3382 Register rhs = x0; |
3383 Register lhs = x1; | 3383 Register lhs = x1; |
3384 | 3384 |
3385 // Check that both operands are heap objects. | 3385 // Check that both operands are heap objects. |
3386 __ JumpIfEitherSmi(rhs, lhs, &miss); | 3386 __ JumpIfEitherSmi(rhs, lhs, &miss); |
3387 | 3387 |
3388 // Check that both operands are strings. | 3388 // Check that both operands are strings. |
3389 Register rhs_map = x10; | 3389 Register rhs_map = x10; |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3445 } else { | 3445 } else { |
3446 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 3446 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
3447 } | 3447 } |
3448 | 3448 |
3449 __ Bind(&miss); | 3449 __ Bind(&miss); |
3450 GenerateMiss(masm); | 3450 GenerateMiss(masm); |
3451 } | 3451 } |
3452 | 3452 |
3453 | 3453 |
3454 void ICCompareStub::GenerateObjects(MacroAssembler* masm) { | 3454 void ICCompareStub::GenerateObjects(MacroAssembler* masm) { |
3455 DCHECK(state_ == CompareIC::OBJECT); | 3455 DCHECK(state() == CompareIC::OBJECT); |
3456 ASM_LOCATION("ICCompareStub[Objects]"); | 3456 ASM_LOCATION("ICCompareStub[Objects]"); |
3457 | 3457 |
3458 Label miss; | 3458 Label miss; |
3459 | 3459 |
3460 Register result = x0; | 3460 Register result = x0; |
3461 Register rhs = x0; | 3461 Register rhs = x0; |
3462 Register lhs = x1; | 3462 Register lhs = x1; |
3463 | 3463 |
3464 __ JumpIfEitherSmi(rhs, lhs, &miss); | 3464 __ JumpIfEitherSmi(rhs, lhs, &miss); |
3465 | 3465 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3515 ExternalReference miss = | 3515 ExternalReference miss = |
3516 ExternalReference(IC_Utility(IC::kCompareIC_Miss), isolate()); | 3516 ExternalReference(IC_Utility(IC::kCompareIC_Miss), isolate()); |
3517 | 3517 |
3518 FrameScope scope(masm, StackFrame::INTERNAL); | 3518 FrameScope scope(masm, StackFrame::INTERNAL); |
3519 Register op = x10; | 3519 Register op = x10; |
3520 Register left = x1; | 3520 Register left = x1; |
3521 Register right = x0; | 3521 Register right = x0; |
3522 // Preserve some caller-saved registers. | 3522 // Preserve some caller-saved registers. |
3523 __ Push(x1, x0, lr); | 3523 __ Push(x1, x0, lr); |
3524 // Push the arguments. | 3524 // Push the arguments. |
3525 __ Mov(op, Smi::FromInt(op_)); | 3525 __ Mov(op, Smi::FromInt(this->op())); |
3526 __ Push(left, right, op); | 3526 __ Push(left, right, op); |
3527 | 3527 |
3528 // Call the miss handler. This also pops the arguments. | 3528 // Call the miss handler. This also pops the arguments. |
3529 __ CallExternalReference(miss, 3); | 3529 __ CallExternalReference(miss, 3); |
3530 | 3530 |
3531 // Compute the entry point of the rewritten stub. | 3531 // Compute the entry point of the rewritten stub. |
3532 __ Add(stub_entry, x0, Code::kHeaderSize - kHeapObjectTag); | 3532 __ Add(stub_entry, x0, Code::kHeaderSize - kHeapObjectTag); |
3533 // Restore caller-saved registers. | 3533 // Restore caller-saved registers. |
3534 __ Pop(lr, x0, x1); | 3534 __ Pop(lr, x0, x1); |
3535 } | 3535 } |
(...skipping 1605 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5141 MemOperand(fp, 6 * kPointerSize), | 5141 MemOperand(fp, 6 * kPointerSize), |
5142 NULL); | 5142 NULL); |
5143 } | 5143 } |
5144 | 5144 |
5145 | 5145 |
5146 #undef __ | 5146 #undef __ |
5147 | 5147 |
5148 } } // namespace v8::internal | 5148 } } // namespace v8::internal |
5149 | 5149 |
5150 #endif // V8_TARGET_ARCH_ARM64 | 5150 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |