| 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 #if V8_TARGET_ARCH_ARM64 | 5 #if V8_TARGET_ARCH_ARM64 |
| 6 | 6 |
| 7 #include "src/arm64/macro-assembler-arm64-inl.h" | 7 #include "src/arm64/macro-assembler-arm64-inl.h" |
| 8 #include "src/ast/compile-time-value.h" | 8 #include "src/ast/compile-time-value.h" |
| 9 #include "src/ast/scopes.h" | 9 #include "src/ast/scopes.h" |
| 10 #include "src/builtins/builtins-constructor.h" | 10 #include "src/builtins/builtins-constructor.h" |
| (...skipping 879 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 890 Comment cmnt(masm_, "[ Case comparison"); | 890 Comment cmnt(masm_, "[ Case comparison"); |
| 891 __ Bind(&next_test); | 891 __ Bind(&next_test); |
| 892 next_test.Unuse(); | 892 next_test.Unuse(); |
| 893 | 893 |
| 894 // Compile the label expression. | 894 // Compile the label expression. |
| 895 VisitForAccumulatorValue(clause->label()); | 895 VisitForAccumulatorValue(clause->label()); |
| 896 | 896 |
| 897 // Perform the comparison as if via '==='. | 897 // Perform the comparison as if via '==='. |
| 898 __ Peek(x1, 0); // Switch value. | 898 __ Peek(x1, 0); // Switch value. |
| 899 | 899 |
| 900 JumpPatchSite patch_site(masm_); | 900 { |
| 901 if (ShouldInlineSmiCase(Token::EQ_STRICT)) { | 901 Assembler::BlockPoolsScope scope(masm_); |
| 902 Label slow_case; | 902 JumpPatchSite patch_site(masm_); |
| 903 patch_site.EmitJumpIfEitherNotSmi(x0, x1, &slow_case); | 903 if (ShouldInlineSmiCase(Token::EQ_STRICT)) { |
| 904 __ Cmp(x1, x0); | 904 Label slow_case; |
| 905 __ B(ne, &next_test); | 905 patch_site.EmitJumpIfEitherNotSmi(x0, x1, &slow_case); |
| 906 __ Drop(1); // Switch value is no longer needed. | 906 __ Cmp(x1, x0); |
| 907 __ B(clause->body_target()); | 907 __ B(ne, &next_test); |
| 908 __ Bind(&slow_case); | 908 __ Drop(1); // Switch value is no longer needed. |
| 909 __ B(clause->body_target()); |
| 910 __ Bind(&slow_case); |
| 911 } |
| 912 |
| 913 // Record position before stub call for type feedback. |
| 914 SetExpressionPosition(clause); |
| 915 Handle<Code> ic = |
| 916 CodeFactory::CompareIC(isolate(), Token::EQ_STRICT).code(); |
| 917 CallIC(ic, clause->CompareId()); |
| 918 patch_site.EmitPatchInfo(); |
| 909 } | 919 } |
| 910 | 920 |
| 911 // Record position before stub call for type feedback. | |
| 912 SetExpressionPosition(clause); | |
| 913 Handle<Code> ic = | |
| 914 CodeFactory::CompareIC(isolate(), Token::EQ_STRICT).code(); | |
| 915 CallIC(ic, clause->CompareId()); | |
| 916 patch_site.EmitPatchInfo(); | |
| 917 | |
| 918 Label skip; | 921 Label skip; |
| 919 __ B(&skip); | 922 __ B(&skip); |
| 920 PrepareForBailout(clause, BailoutState::TOS_REGISTER); | 923 PrepareForBailout(clause, BailoutState::TOS_REGISTER); |
| 921 __ JumpIfNotRoot(x0, Heap::kTrueValueRootIndex, &next_test); | 924 __ JumpIfNotRoot(x0, Heap::kTrueValueRootIndex, &next_test); |
| 922 __ Drop(1); | 925 __ Drop(1); |
| 923 __ B(clause->body_target()); | 926 __ B(clause->body_target()); |
| 924 __ Bind(&skip); | 927 __ Bind(&skip); |
| 925 | 928 |
| 926 __ Cbnz(x0, &next_test); | 929 __ Cbnz(x0, &next_test); |
| 927 __ Drop(1); // Switch value is no longer needed. | 930 __ Drop(1); // Switch value is no longer needed. |
| (...skipping 573 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1501 Expression* right_expr) { | 1504 Expression* right_expr) { |
| 1502 Label done, both_smis, stub_call; | 1505 Label done, both_smis, stub_call; |
| 1503 | 1506 |
| 1504 // Get the arguments. | 1507 // Get the arguments. |
| 1505 Register left = x1; | 1508 Register left = x1; |
| 1506 Register right = x0; | 1509 Register right = x0; |
| 1507 Register result = x0; | 1510 Register result = x0; |
| 1508 PopOperand(left); | 1511 PopOperand(left); |
| 1509 | 1512 |
| 1510 // Perform combined smi check on both operands. | 1513 // Perform combined smi check on both operands. |
| 1511 __ Orr(x10, left, right); | |
| 1512 JumpPatchSite patch_site(masm_); | |
| 1513 patch_site.EmitJumpIfSmi(x10, &both_smis); | |
| 1514 | |
| 1515 __ Bind(&stub_call); | |
| 1516 | |
| 1517 Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code(); | |
| 1518 { | 1514 { |
| 1519 Assembler::BlockPoolsScope scope(masm_); | 1515 Assembler::BlockPoolsScope scope(masm_); |
| 1516 __ Orr(x10, left, right); |
| 1517 JumpPatchSite patch_site(masm_); |
| 1518 patch_site.EmitJumpIfSmi(x10, &both_smis); |
| 1519 |
| 1520 __ Bind(&stub_call); |
| 1521 |
| 1522 Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code(); |
| 1520 CallIC(code, expr->BinaryOperationFeedbackId()); | 1523 CallIC(code, expr->BinaryOperationFeedbackId()); |
| 1521 patch_site.EmitPatchInfo(); | 1524 patch_site.EmitPatchInfo(); |
| 1525 |
| 1526 __ B(&done); |
| 1527 __ Bind(&both_smis); |
| 1522 } | 1528 } |
| 1523 __ B(&done); | |
| 1524 | 1529 |
| 1525 __ Bind(&both_smis); | |
| 1526 // Smi case. This code works in the same way as the smi-smi case in the type | 1530 // Smi case. This code works in the same way as the smi-smi case in the type |
| 1527 // recording binary operation stub, see | 1531 // recording binary operation stub, see |
| 1528 // BinaryOpStub::GenerateSmiSmiOperation for comments. | 1532 // BinaryOpStub::GenerateSmiSmiOperation for comments. |
| 1529 // TODO(all): That doesn't exist any more. Where are the comments? | 1533 // TODO(all): That doesn't exist any more. Where are the comments? |
| 1530 // | 1534 // |
| 1531 // The set of operations that needs to be supported here is controlled by | 1535 // The set of operations that needs to be supported here is controlled by |
| 1532 // FullCodeGenerator::ShouldInlineSmiCase(). | 1536 // FullCodeGenerator::ShouldInlineSmiCase(). |
| 1533 switch (op) { | 1537 switch (op) { |
| 1534 case Token::SAR: | 1538 case Token::SAR: |
| 1535 __ Ubfx(right, right, kSmiShift, 5); | 1539 __ Ubfx(right, right, kSmiShift, 5); |
| (...skipping 808 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2344 | 2348 |
| 2345 // We need a second deoptimization point after loading the value | 2349 // We need a second deoptimization point after loading the value |
| 2346 // in case evaluating the property load my have a side effect. | 2350 // in case evaluating the property load my have a side effect. |
| 2347 if (assign_type == VARIABLE) { | 2351 if (assign_type == VARIABLE) { |
| 2348 PrepareForBailout(expr->expression(), BailoutState::TOS_REGISTER); | 2352 PrepareForBailout(expr->expression(), BailoutState::TOS_REGISTER); |
| 2349 } else { | 2353 } else { |
| 2350 PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER); | 2354 PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER); |
| 2351 } | 2355 } |
| 2352 | 2356 |
| 2353 // Inline smi case if we are in a loop. | 2357 // Inline smi case if we are in a loop. |
| 2354 Label stub_call, done; | 2358 { |
| 2355 JumpPatchSite patch_site(masm_); | 2359 Assembler::BlockPoolsScope scope(masm_); |
| 2360 Label stub_call, done; |
| 2361 JumpPatchSite patch_site(masm_); |
| 2356 | 2362 |
| 2357 int count_value = expr->op() == Token::INC ? 1 : -1; | 2363 int count_value = expr->op() == Token::INC ? 1 : -1; |
| 2358 if (ShouldInlineSmiCase(expr->op())) { | 2364 if (ShouldInlineSmiCase(expr->op())) { |
| 2359 Label slow; | 2365 Label slow; |
| 2360 patch_site.EmitJumpIfNotSmi(x0, &slow); | 2366 patch_site.EmitJumpIfNotSmi(x0, &slow); |
| 2367 |
| 2368 // Save result for postfix expressions. |
| 2369 if (expr->is_postfix()) { |
| 2370 if (!context()->IsEffect()) { |
| 2371 // Save the result on the stack. If we have a named or keyed property |
| 2372 // we store the result under the receiver that is currently on top of |
| 2373 // the stack. |
| 2374 switch (assign_type) { |
| 2375 case VARIABLE: |
| 2376 __ Push(x0); |
| 2377 break; |
| 2378 case NAMED_PROPERTY: |
| 2379 __ Poke(x0, kPointerSize); |
| 2380 break; |
| 2381 case KEYED_PROPERTY: |
| 2382 __ Poke(x0, kPointerSize * 2); |
| 2383 break; |
| 2384 case NAMED_SUPER_PROPERTY: |
| 2385 case KEYED_SUPER_PROPERTY: |
| 2386 UNREACHABLE(); |
| 2387 break; |
| 2388 } |
| 2389 } |
| 2390 } |
| 2391 |
| 2392 __ Adds(x0, x0, Smi::FromInt(count_value)); |
| 2393 __ B(vc, &done); |
| 2394 // Call stub. Undo operation first. |
| 2395 __ Sub(x0, x0, Smi::FromInt(count_value)); |
| 2396 __ B(&stub_call); |
| 2397 __ Bind(&slow); |
| 2398 } |
| 2399 |
| 2400 // Convert old value into a number. |
| 2401 __ Call(isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET); |
| 2402 RestoreContext(); |
| 2403 PrepareForBailoutForId(expr->ToNumberId(), BailoutState::TOS_REGISTER); |
| 2361 | 2404 |
| 2362 // Save result for postfix expressions. | 2405 // Save result for postfix expressions. |
| 2363 if (expr->is_postfix()) { | 2406 if (expr->is_postfix()) { |
| 2364 if (!context()->IsEffect()) { | 2407 if (!context()->IsEffect()) { |
| 2365 // Save the result on the stack. If we have a named or keyed property we | 2408 // Save the result on the stack. If we have a named or keyed property |
| 2366 // store the result under the receiver that is currently on top of the | 2409 // we store the result under the receiver that is currently on top |
| 2367 // stack. | 2410 // of the stack. |
| 2368 switch (assign_type) { | 2411 switch (assign_type) { |
| 2369 case VARIABLE: | 2412 case VARIABLE: |
| 2370 __ Push(x0); | 2413 PushOperand(x0); |
| 2371 break; | 2414 break; |
| 2372 case NAMED_PROPERTY: | 2415 case NAMED_PROPERTY: |
| 2373 __ Poke(x0, kPointerSize); | 2416 __ Poke(x0, kXRegSize); |
| 2374 break; | 2417 break; |
| 2375 case KEYED_PROPERTY: | 2418 case KEYED_PROPERTY: |
| 2376 __ Poke(x0, kPointerSize * 2); | 2419 __ Poke(x0, 2 * kXRegSize); |
| 2377 break; | 2420 break; |
| 2378 case NAMED_SUPER_PROPERTY: | 2421 case NAMED_SUPER_PROPERTY: |
| 2379 case KEYED_SUPER_PROPERTY: | 2422 case KEYED_SUPER_PROPERTY: |
| 2380 UNREACHABLE(); | 2423 UNREACHABLE(); |
| 2381 break; | 2424 break; |
| 2382 } | 2425 } |
| 2383 } | 2426 } |
| 2384 } | 2427 } |
| 2385 | 2428 |
| 2386 __ Adds(x0, x0, Smi::FromInt(count_value)); | 2429 __ Bind(&stub_call); |
| 2387 __ B(vc, &done); | 2430 __ Mov(x1, x0); |
| 2388 // Call stub. Undo operation first. | 2431 __ Mov(x0, Smi::FromInt(count_value)); |
| 2389 __ Sub(x0, x0, Smi::FromInt(count_value)); | |
| 2390 __ B(&stub_call); | |
| 2391 __ Bind(&slow); | |
| 2392 } | |
| 2393 | 2432 |
| 2394 // Convert old value into a number. | 2433 SetExpressionPosition(expr); |
| 2395 __ Call(isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET); | |
| 2396 RestoreContext(); | |
| 2397 PrepareForBailoutForId(expr->ToNumberId(), BailoutState::TOS_REGISTER); | |
| 2398 | 2434 |
| 2399 // Save result for postfix expressions. | |
| 2400 if (expr->is_postfix()) { | |
| 2401 if (!context()->IsEffect()) { | |
| 2402 // Save the result on the stack. If we have a named or keyed property | |
| 2403 // we store the result under the receiver that is currently on top | |
| 2404 // of the stack. | |
| 2405 switch (assign_type) { | |
| 2406 case VARIABLE: | |
| 2407 PushOperand(x0); | |
| 2408 break; | |
| 2409 case NAMED_PROPERTY: | |
| 2410 __ Poke(x0, kXRegSize); | |
| 2411 break; | |
| 2412 case KEYED_PROPERTY: | |
| 2413 __ Poke(x0, 2 * kXRegSize); | |
| 2414 break; | |
| 2415 case NAMED_SUPER_PROPERTY: | |
| 2416 case KEYED_SUPER_PROPERTY: | |
| 2417 UNREACHABLE(); | |
| 2418 break; | |
| 2419 } | |
| 2420 } | |
| 2421 } | |
| 2422 | |
| 2423 __ Bind(&stub_call); | |
| 2424 __ Mov(x1, x0); | |
| 2425 __ Mov(x0, Smi::FromInt(count_value)); | |
| 2426 | |
| 2427 SetExpressionPosition(expr); | |
| 2428 | |
| 2429 { | |
| 2430 Assembler::BlockPoolsScope scope(masm_); | |
| 2431 Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), Token::ADD).code(); | 2435 Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), Token::ADD).code(); |
| 2432 CallIC(code, expr->CountBinOpFeedbackId()); | 2436 CallIC(code, expr->CountBinOpFeedbackId()); |
| 2433 patch_site.EmitPatchInfo(); | 2437 patch_site.EmitPatchInfo(); |
| 2438 |
| 2439 __ Bind(&done); |
| 2434 } | 2440 } |
| 2435 __ Bind(&done); | |
| 2436 | 2441 |
| 2437 // Store the value returned in x0. | 2442 // Store the value returned in x0. |
| 2438 switch (assign_type) { | 2443 switch (assign_type) { |
| 2439 case VARIABLE: { | 2444 case VARIABLE: { |
| 2440 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 2445 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 2441 if (expr->is_postfix()) { | 2446 if (expr->is_postfix()) { |
| 2442 { EffectContext context(this); | 2447 { EffectContext context(this); |
| 2443 EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(), | 2448 EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(), |
| 2444 proxy->hole_check_mode()); | 2449 proxy->hole_check_mode()); |
| 2445 PrepareForBailoutForId(expr->AssignmentId(), | 2450 PrepareForBailoutForId(expr->AssignmentId(), |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2614 } | 2619 } |
| 2615 | 2620 |
| 2616 default: { | 2621 default: { |
| 2617 VisitForAccumulatorValue(expr->right()); | 2622 VisitForAccumulatorValue(expr->right()); |
| 2618 SetExpressionPosition(expr); | 2623 SetExpressionPosition(expr); |
| 2619 Condition cond = CompareIC::ComputeCondition(op); | 2624 Condition cond = CompareIC::ComputeCondition(op); |
| 2620 | 2625 |
| 2621 // Pop the stack value. | 2626 // Pop the stack value. |
| 2622 PopOperand(x1); | 2627 PopOperand(x1); |
| 2623 | 2628 |
| 2624 JumpPatchSite patch_site(masm_); | 2629 { |
| 2625 if (ShouldInlineSmiCase(op)) { | 2630 Assembler::BlockPoolsScope scope(masm_); |
| 2626 Label slow_case; | 2631 JumpPatchSite patch_site(masm_); |
| 2627 patch_site.EmitJumpIfEitherNotSmi(x0, x1, &slow_case); | 2632 if (ShouldInlineSmiCase(op)) { |
| 2628 __ Cmp(x1, x0); | 2633 Label slow_case; |
| 2629 Split(cond, if_true, if_false, NULL); | 2634 patch_site.EmitJumpIfEitherNotSmi(x0, x1, &slow_case); |
| 2630 __ Bind(&slow_case); | 2635 __ Cmp(x1, x0); |
| 2636 Split(cond, if_true, if_false, NULL); |
| 2637 __ Bind(&slow_case); |
| 2638 } |
| 2639 |
| 2640 Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code(); |
| 2641 CallIC(ic, expr->CompareOperationFeedbackId()); |
| 2642 patch_site.EmitPatchInfo(); |
| 2643 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
| 2644 __ CompareAndSplit(x0, 0, cond, if_true, if_false, fall_through); |
| 2631 } | 2645 } |
| 2632 | |
| 2633 Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code(); | |
| 2634 CallIC(ic, expr->CompareOperationFeedbackId()); | |
| 2635 patch_site.EmitPatchInfo(); | |
| 2636 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | |
| 2637 __ CompareAndSplit(x0, 0, cond, if_true, if_false, fall_through); | |
| 2638 } | 2646 } |
| 2639 } | 2647 } |
| 2640 | 2648 |
| 2641 // Convert the result of the comparison into one expected for this | 2649 // Convert the result of the comparison into one expected for this |
| 2642 // expression's context. | 2650 // expression's context. |
| 2643 context()->Plug(if_true, if_false); | 2651 context()->Plug(if_true, if_false); |
| 2644 } | 2652 } |
| 2645 | 2653 |
| 2646 | 2654 |
| 2647 void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr, | 2655 void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr, |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2882 } | 2890 } |
| 2883 | 2891 |
| 2884 return INTERRUPT; | 2892 return INTERRUPT; |
| 2885 } | 2893 } |
| 2886 | 2894 |
| 2887 | 2895 |
| 2888 } // namespace internal | 2896 } // namespace internal |
| 2889 } // namespace v8 | 2897 } // namespace v8 |
| 2890 | 2898 |
| 2891 #endif // V8_TARGET_ARCH_ARM64 | 2899 #endif // V8_TARGET_ARCH_ARM64 |
| OLD | NEW |