| 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/base/bits.h" | 7 #include "src/base/bits.h" |
| 8 #include "src/base/division-by-constant.h" | 8 #include "src/base/division-by-constant.h" |
| 9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
| 10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
| (...skipping 2521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2532 // adaptor. | 2532 // adaptor. |
| 2533 if (!definitely_matches) { | 2533 if (!definitely_matches) { |
| 2534 Handle<Code> adaptor = | 2534 Handle<Code> adaptor = |
| 2535 isolate()->builtins()->ArgumentsAdaptorTrampoline(); | 2535 isolate()->builtins()->ArgumentsAdaptorTrampoline(); |
| 2536 if (flag == CALL_FUNCTION) { | 2536 if (flag == CALL_FUNCTION) { |
| 2537 call_wrapper.BeforeCall(CallSize(adaptor)); | 2537 call_wrapper.BeforeCall(CallSize(adaptor)); |
| 2538 Call(adaptor); | 2538 Call(adaptor); |
| 2539 call_wrapper.AfterCall(); | 2539 call_wrapper.AfterCall(); |
| 2540 if (!*definitely_mismatches) { | 2540 if (!*definitely_mismatches) { |
| 2541 // If the arg counts don't match, no extra code is emitted by | 2541 // If the arg counts don't match, no extra code is emitted by |
| 2542 // MAsm::InvokeFunctionCode and we can just fall through. | 2542 // MAsm::InvokeCode and we can just fall through. |
| 2543 B(done); | 2543 B(done); |
| 2544 } | 2544 } |
| 2545 } else { | 2545 } else { |
| 2546 Jump(adaptor, RelocInfo::CODE_TARGET); | 2546 Jump(adaptor, RelocInfo::CODE_TARGET); |
| 2547 } | 2547 } |
| 2548 } | 2548 } |
| 2549 Bind(®ular_invoke); | 2549 Bind(®ular_invoke); |
| 2550 } | 2550 } |
| 2551 | 2551 |
| 2552 | 2552 |
| 2553 void MacroAssembler::FloodFunctionIfStepping(Register fun, Register new_target, | 2553 void MacroAssembler::InvokeCode(Register code, |
| 2554 const ParameterCount& expected, | 2554 Register new_target, |
| 2555 const ParameterCount& actual) { | 2555 const ParameterCount& expected, |
| 2556 Label skip_flooding; | 2556 const ParameterCount& actual, |
| 2557 ExternalReference debug_step_action = | 2557 InvokeFlag flag, |
| 2558 ExternalReference::debug_last_step_action_address(isolate()); | 2558 const CallWrapper& call_wrapper) { |
| 2559 Mov(x4, Operand(debug_step_action)); | |
| 2560 ldrb(x4, MemOperand(x4)); | |
| 2561 CompareAndBranch(x4, Operand(StepIn), ne, &skip_flooding); | |
| 2562 { | |
| 2563 FrameScope frame(this, | |
| 2564 has_frame() ? StackFrame::NONE : StackFrame::INTERNAL); | |
| 2565 if (expected.is_reg()) { | |
| 2566 SmiTag(expected.reg()); | |
| 2567 Push(expected.reg()); | |
| 2568 } | |
| 2569 if (actual.is_reg()) { | |
| 2570 SmiTag(actual.reg()); | |
| 2571 Push(actual.reg()); | |
| 2572 } | |
| 2573 if (new_target.is_valid()) { | |
| 2574 Push(new_target); | |
| 2575 } | |
| 2576 Push(fun); | |
| 2577 Push(fun); | |
| 2578 CallRuntime(Runtime::kDebugPrepareStepInIfStepping, 1); | |
| 2579 Pop(fun); | |
| 2580 if (new_target.is_valid()) { | |
| 2581 Pop(new_target); | |
| 2582 } | |
| 2583 if (actual.is_reg()) { | |
| 2584 Pop(actual.reg()); | |
| 2585 SmiUntag(actual.reg()); | |
| 2586 } | |
| 2587 if (expected.is_reg()) { | |
| 2588 Pop(expected.reg()); | |
| 2589 SmiUntag(expected.reg()); | |
| 2590 } | |
| 2591 } | |
| 2592 bind(&skip_flooding); | |
| 2593 } | |
| 2594 | |
| 2595 | |
| 2596 void MacroAssembler::InvokeFunctionCode(Register function, Register new_target, | |
| 2597 const ParameterCount& expected, | |
| 2598 const ParameterCount& actual, | |
| 2599 InvokeFlag flag, | |
| 2600 const CallWrapper& call_wrapper) { | |
| 2601 // You can't call a function without a valid frame. | 2559 // You can't call a function without a valid frame. |
| 2602 DCHECK(flag == JUMP_FUNCTION || has_frame()); | 2560 DCHECK(flag == JUMP_FUNCTION || has_frame()); |
| 2603 DCHECK(function.is(x1)); | 2561 |
| 2562 // Ensure new target is passed in the correct register. Otherwise clear the |
| 2563 // appropriate register in case new target is not given. |
| 2604 DCHECK_IMPLIES(new_target.is_valid(), new_target.is(x3)); | 2564 DCHECK_IMPLIES(new_target.is_valid(), new_target.is(x3)); |
| 2605 | |
| 2606 FloodFunctionIfStepping(function, new_target, expected, actual); | |
| 2607 | |
| 2608 // Clear the new.target register if not given. | |
| 2609 if (!new_target.is_valid()) { | 2565 if (!new_target.is_valid()) { |
| 2610 LoadRoot(x3, Heap::kUndefinedValueRootIndex); | 2566 LoadRoot(x3, Heap::kUndefinedValueRootIndex); |
| 2611 } | 2567 } |
| 2612 | 2568 |
| 2613 Label done; | 2569 Label done; |
| 2614 bool definitely_mismatches = false; | 2570 bool definitely_mismatches = false; |
| 2615 InvokePrologue(expected, actual, &done, flag, &definitely_mismatches, | 2571 InvokePrologue(expected, actual, &done, flag, &definitely_mismatches, |
| 2616 call_wrapper); | 2572 call_wrapper); |
| 2617 | 2573 |
| 2618 // If we are certain that actual != expected, then we know InvokePrologue will | 2574 // If we are certain that actual != expected, then we know InvokePrologue will |
| 2619 // have handled the call through the argument adaptor mechanism. | 2575 // have handled the call through the argument adaptor mechanism. |
| 2620 // The called function expects the call kind in x5. | 2576 // The called function expects the call kind in x5. |
| 2621 if (!definitely_mismatches) { | 2577 if (!definitely_mismatches) { |
| 2622 // We call indirectly through the code field in the function to | |
| 2623 // allow recompilation to take effect without changing any of the | |
| 2624 // call sites. | |
| 2625 Register code = x4; | |
| 2626 Ldr(code, FieldMemOperand(function, JSFunction::kCodeEntryOffset)); | |
| 2627 if (flag == CALL_FUNCTION) { | 2578 if (flag == CALL_FUNCTION) { |
| 2628 call_wrapper.BeforeCall(CallSize(code)); | 2579 call_wrapper.BeforeCall(CallSize(code)); |
| 2629 Call(code); | 2580 Call(code); |
| 2630 call_wrapper.AfterCall(); | 2581 call_wrapper.AfterCall(); |
| 2631 } else { | 2582 } else { |
| 2632 DCHECK(flag == JUMP_FUNCTION); | 2583 DCHECK(flag == JUMP_FUNCTION); |
| 2633 Jump(code); | 2584 Jump(code); |
| 2634 } | 2585 } |
| 2635 } | 2586 } |
| 2636 | 2587 |
| 2637 // Continue here if InvokePrologue does handle the invocation due to | 2588 // Continue here if InvokePrologue does handle the invocation due to |
| 2638 // mismatched parameter counts. | 2589 // mismatched parameter counts. |
| 2639 Bind(&done); | 2590 Bind(&done); |
| 2640 } | 2591 } |
| 2641 | 2592 |
| 2642 | 2593 |
| 2643 void MacroAssembler::InvokeFunction(Register function, | 2594 void MacroAssembler::InvokeFunction(Register function, |
| 2644 Register new_target, | 2595 Register new_target, |
| 2645 const ParameterCount& actual, | 2596 const ParameterCount& actual, |
| 2646 InvokeFlag flag, | 2597 InvokeFlag flag, |
| 2647 const CallWrapper& call_wrapper) { | 2598 const CallWrapper& call_wrapper) { |
| 2648 // You can't call a function without a valid frame. | 2599 // You can't call a function without a valid frame. |
| 2649 DCHECK(flag == JUMP_FUNCTION || has_frame()); | 2600 DCHECK(flag == JUMP_FUNCTION || has_frame()); |
| 2650 | 2601 |
| 2651 // Contract with called JS functions requires that function is passed in x1. | 2602 // Contract with called JS functions requires that function is passed in x1. |
| 2652 // (See FullCodeGenerator::Generate().) | 2603 // (See FullCodeGenerator::Generate().) |
| 2653 DCHECK(function.is(x1)); | 2604 DCHECK(function.is(x1)); |
| 2654 | 2605 |
| 2655 Register expected_reg = x2; | 2606 Register expected_reg = x2; |
| 2607 Register code_reg = x4; |
| 2656 | 2608 |
| 2657 Ldr(cp, FieldMemOperand(function, JSFunction::kContextOffset)); | 2609 Ldr(cp, FieldMemOperand(function, JSFunction::kContextOffset)); |
| 2658 // The number of arguments is stored as an int32_t, and -1 is a marker | 2610 // The number of arguments is stored as an int32_t, and -1 is a marker |
| 2659 // (SharedFunctionInfo::kDontAdaptArgumentsSentinel), so we need sign | 2611 // (SharedFunctionInfo::kDontAdaptArgumentsSentinel), so we need sign |
| 2660 // extension to correctly handle it. | 2612 // extension to correctly handle it. |
| 2661 Ldr(expected_reg, FieldMemOperand(function, | 2613 Ldr(expected_reg, FieldMemOperand(function, |
| 2662 JSFunction::kSharedFunctionInfoOffset)); | 2614 JSFunction::kSharedFunctionInfoOffset)); |
| 2663 Ldrsw(expected_reg, | 2615 Ldrsw(expected_reg, |
| 2664 FieldMemOperand(expected_reg, | 2616 FieldMemOperand(expected_reg, |
| 2665 SharedFunctionInfo::kFormalParameterCountOffset)); | 2617 SharedFunctionInfo::kFormalParameterCountOffset)); |
| 2618 Ldr(code_reg, |
| 2619 FieldMemOperand(function, JSFunction::kCodeEntryOffset)); |
| 2666 | 2620 |
| 2667 ParameterCount expected(expected_reg); | 2621 ParameterCount expected(expected_reg); |
| 2668 InvokeFunctionCode(function, new_target, expected, actual, flag, | 2622 InvokeCode(code_reg, new_target, expected, actual, flag, call_wrapper); |
| 2669 call_wrapper); | |
| 2670 } | 2623 } |
| 2671 | 2624 |
| 2672 | 2625 |
| 2673 void MacroAssembler::InvokeFunction(Register function, | 2626 void MacroAssembler::InvokeFunction(Register function, |
| 2674 const ParameterCount& expected, | 2627 const ParameterCount& expected, |
| 2675 const ParameterCount& actual, | 2628 const ParameterCount& actual, |
| 2676 InvokeFlag flag, | 2629 InvokeFlag flag, |
| 2677 const CallWrapper& call_wrapper) { | 2630 const CallWrapper& call_wrapper) { |
| 2678 // You can't call a function without a valid frame. | 2631 // You can't call a function without a valid frame. |
| 2679 DCHECK(flag == JUMP_FUNCTION || has_frame()); | 2632 DCHECK(flag == JUMP_FUNCTION || has_frame()); |
| 2680 | 2633 |
| 2681 // Contract with called JS functions requires that function is passed in x1. | 2634 // Contract with called JS functions requires that function is passed in x1. |
| 2682 // (See FullCodeGenerator::Generate().) | 2635 // (See FullCodeGenerator::Generate().) |
| 2683 DCHECK(function.Is(x1)); | 2636 DCHECK(function.Is(x1)); |
| 2684 | 2637 |
| 2638 Register code_reg = x4; |
| 2639 |
| 2685 // Set up the context. | 2640 // Set up the context. |
| 2686 Ldr(cp, FieldMemOperand(function, JSFunction::kContextOffset)); | 2641 Ldr(cp, FieldMemOperand(function, JSFunction::kContextOffset)); |
| 2687 | 2642 |
| 2688 InvokeFunctionCode(function, no_reg, expected, actual, flag, call_wrapper); | 2643 // We call indirectly through the code field in the function to |
| 2644 // allow recompilation to take effect without changing any of the |
| 2645 // call sites. |
| 2646 Ldr(code_reg, FieldMemOperand(function, JSFunction::kCodeEntryOffset)); |
| 2647 InvokeCode(code_reg, no_reg, expected, actual, flag, call_wrapper); |
| 2689 } | 2648 } |
| 2690 | 2649 |
| 2691 | 2650 |
| 2692 void MacroAssembler::InvokeFunction(Handle<JSFunction> function, | 2651 void MacroAssembler::InvokeFunction(Handle<JSFunction> function, |
| 2693 const ParameterCount& expected, | 2652 const ParameterCount& expected, |
| 2694 const ParameterCount& actual, | 2653 const ParameterCount& actual, |
| 2695 InvokeFlag flag, | 2654 InvokeFlag flag, |
| 2696 const CallWrapper& call_wrapper) { | 2655 const CallWrapper& call_wrapper) { |
| 2697 // Contract with called JS functions requires that function is passed in x1. | 2656 // Contract with called JS functions requires that function is passed in x1. |
| 2698 // (See FullCodeGenerator::Generate().) | 2657 // (See FullCodeGenerator::Generate().) |
| (...skipping 2416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5115 } | 5074 } |
| 5116 | 5075 |
| 5117 | 5076 |
| 5118 #undef __ | 5077 #undef __ |
| 5119 | 5078 |
| 5120 | 5079 |
| 5121 } // namespace internal | 5080 } // namespace internal |
| 5122 } // namespace v8 | 5081 } // namespace v8 |
| 5123 | 5082 |
| 5124 #endif // V8_TARGET_ARCH_ARM64 | 5083 #endif // V8_TARGET_ARCH_ARM64 |
| OLD | NEW |