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 |