OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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/interpreter/interpreter-assembler.h" | 5 #include "src/interpreter/interpreter-assembler.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 #include <ostream> | 8 #include <ostream> |
9 | 9 |
10 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
(...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
453 Node* function = IntPtrAdd(function_table, function_offset); | 453 Node* function = IntPtrAdd(function_table, function_offset); |
454 Node* function_entry = | 454 Node* function_entry = |
455 Load(MachineType::Pointer(), function, | 455 Load(MachineType::Pointer(), function, |
456 IntPtrConstant(offsetof(Runtime::Function, entry))); | 456 IntPtrConstant(offsetof(Runtime::Function, entry))); |
457 | 457 |
458 return CallStub(callable.descriptor(), code_target, context, arg_count, | 458 return CallStub(callable.descriptor(), code_target, context, arg_count, |
459 first_arg, function_entry, result_size); | 459 first_arg, function_entry, result_size); |
460 } | 460 } |
461 | 461 |
462 void InterpreterAssembler::UpdateInterruptBudget(Node* weight) { | 462 void InterpreterAssembler::UpdateInterruptBudget(Node* weight) { |
463 CodeStubAssembler::Label ok(this); | 463 Label ok(this), interrupt_check(this, Label::kDeferred), end(this); |
464 CodeStubAssembler::Label interrupt_check(this); | |
465 CodeStubAssembler::Label end(this); | |
466 Node* budget_offset = | 464 Node* budget_offset = |
467 IntPtrConstant(BytecodeArray::kInterruptBudgetOffset - kHeapObjectTag); | 465 IntPtrConstant(BytecodeArray::kInterruptBudgetOffset - kHeapObjectTag); |
468 | 466 |
469 // Update budget by |weight| and check if it reaches zero. | 467 // Update budget by |weight| and check if it reaches zero. |
| 468 Variable new_budget(this, MachineRepresentation::kWord32); |
470 Node* old_budget = | 469 Node* old_budget = |
471 Load(MachineType::Int32(), BytecodeArrayTaggedPointer(), budget_offset); | 470 Load(MachineType::Int32(), BytecodeArrayTaggedPointer(), budget_offset); |
472 Node* new_budget = Int32Add(old_budget, weight); | 471 new_budget.Bind(Int32Add(old_budget, weight)); |
473 Node* condition = Int32GreaterThanOrEqual(new_budget, Int32Constant(0)); | 472 Node* condition = |
| 473 Int32GreaterThanOrEqual(new_budget.value(), Int32Constant(0)); |
474 Branch(condition, &ok, &interrupt_check); | 474 Branch(condition, &ok, &interrupt_check); |
475 | 475 |
476 // Perform interrupt and reset budget. | 476 // Perform interrupt and reset budget. |
477 Bind(&interrupt_check); | 477 Bind(&interrupt_check); |
478 CallRuntime(Runtime::kInterrupt, GetContext()); | 478 { |
479 StoreNoWriteBarrier(MachineRepresentation::kWord32, | 479 CallRuntime(Runtime::kInterrupt, GetContext()); |
480 BytecodeArrayTaggedPointer(), budget_offset, | 480 new_budget.Bind(Int32Constant(Interpreter::InterruptBudget())); |
481 Int32Constant(Interpreter::InterruptBudget())); | 481 Goto(&ok); |
482 Goto(&end); | 482 } |
483 | 483 |
484 // Update budget. | 484 // Update budget. |
485 Bind(&ok); | 485 Bind(&ok); |
486 StoreNoWriteBarrier(MachineRepresentation::kWord32, | 486 StoreNoWriteBarrier(MachineRepresentation::kWord32, |
487 BytecodeArrayTaggedPointer(), budget_offset, new_budget); | 487 BytecodeArrayTaggedPointer(), budget_offset, |
488 Goto(&end); | 488 new_budget.value()); |
489 Bind(&end); | |
490 } | 489 } |
491 | 490 |
492 Node* InterpreterAssembler::Advance(int delta) { | 491 Node* InterpreterAssembler::Advance(int delta) { |
493 return IntPtrAdd(BytecodeOffset(), IntPtrConstant(delta)); | 492 return IntPtrAdd(BytecodeOffset(), IntPtrConstant(delta)); |
494 } | 493 } |
495 | 494 |
496 Node* InterpreterAssembler::Advance(Node* delta) { | 495 Node* InterpreterAssembler::Advance(Node* delta) { |
497 return IntPtrAdd(BytecodeOffset(), delta); | 496 return IntPtrAdd(BytecodeOffset(), delta); |
498 } | 497 } |
499 | 498 |
500 Node* InterpreterAssembler::Jump(Node* delta) { | 499 Node* InterpreterAssembler::Jump(Node* delta) { |
501 UpdateInterruptBudget(delta); | 500 UpdateInterruptBudget(delta); |
502 return DispatchTo(Advance(delta)); | 501 return DispatchTo(Advance(delta)); |
503 } | 502 } |
504 | 503 |
505 void InterpreterAssembler::JumpConditional(Node* condition, Node* delta) { | 504 void InterpreterAssembler::JumpConditional(Node* condition, Node* delta) { |
506 CodeStubAssembler::Label match(this); | 505 Label match(this), no_match(this); |
507 CodeStubAssembler::Label no_match(this); | |
508 | 506 |
509 Branch(condition, &match, &no_match); | 507 BranchIf(condition, &match, &no_match); |
510 Bind(&match); | 508 Bind(&match); |
511 Jump(delta); | 509 Jump(delta); |
512 Bind(&no_match); | 510 Bind(&no_match); |
513 Dispatch(); | 511 Dispatch(); |
514 } | 512 } |
515 | 513 |
516 void InterpreterAssembler::JumpIfWordEqual(Node* lhs, Node* rhs, Node* delta) { | 514 void InterpreterAssembler::JumpIfWordEqual(Node* lhs, Node* rhs, Node* delta) { |
517 JumpConditional(WordEqual(lhs, rhs), delta); | 515 JumpConditional(WordEqual(lhs, rhs), delta); |
518 } | 516 } |
519 | 517 |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
611 Node* profiling_weight = | 609 Node* profiling_weight = |
612 Int32Sub(Int32Constant(kHeapObjectTag + BytecodeArray::kHeaderSize), | 610 Int32Sub(Int32Constant(kHeapObjectTag + BytecodeArray::kHeaderSize), |
613 BytecodeOffset()); | 611 BytecodeOffset()); |
614 UpdateInterruptBudget(profiling_weight); | 612 UpdateInterruptBudget(profiling_weight); |
615 | 613 |
616 Node* exit_trampoline_code_object = | 614 Node* exit_trampoline_code_object = |
617 HeapConstant(isolate()->builtins()->InterpreterExitTrampoline()); | 615 HeapConstant(isolate()->builtins()->InterpreterExitTrampoline()); |
618 return DispatchToBytecodeHandler(exit_trampoline_code_object); | 616 return DispatchToBytecodeHandler(exit_trampoline_code_object); |
619 } | 617 } |
620 | 618 |
621 void InterpreterAssembler::StackCheck() { | 619 Node* InterpreterAssembler::StackCheckTriggeredInterrupt() { |
622 CodeStubAssembler::Label end(this); | |
623 CodeStubAssembler::Label ok(this); | |
624 CodeStubAssembler::Label stack_guard(this); | |
625 | |
626 Node* sp = LoadStackPointer(); | 620 Node* sp = LoadStackPointer(); |
627 Node* stack_limit = Load( | 621 Node* stack_limit = Load( |
628 MachineType::Pointer(), | 622 MachineType::Pointer(), |
629 ExternalConstant(ExternalReference::address_of_stack_limit(isolate()))); | 623 ExternalConstant(ExternalReference::address_of_stack_limit(isolate()))); |
630 Node* condition = UintPtrGreaterThanOrEqual(sp, stack_limit); | 624 return UintPtrLessThan(sp, stack_limit); |
631 Branch(condition, &ok, &stack_guard); | |
632 Bind(&stack_guard); | |
633 CallRuntime(Runtime::kStackGuard, GetContext()); | |
634 Goto(&end); | |
635 Bind(&ok); | |
636 Goto(&end); | |
637 Bind(&end); | |
638 } | 625 } |
639 | 626 |
640 void InterpreterAssembler::Abort(BailoutReason bailout_reason) { | 627 void InterpreterAssembler::Abort(BailoutReason bailout_reason) { |
641 disable_stack_check_across_call_ = true; | 628 disable_stack_check_across_call_ = true; |
642 Node* abort_id = SmiTag(Int32Constant(bailout_reason)); | 629 Node* abort_id = SmiTag(Int32Constant(bailout_reason)); |
643 CallRuntime(Runtime::kAbort, GetContext(), abort_id); | 630 CallRuntime(Runtime::kAbort, GetContext(), abort_id); |
644 disable_stack_check_across_call_ = false; | 631 disable_stack_check_across_call_ = false; |
645 } | 632 } |
646 | 633 |
647 void InterpreterAssembler::AbortIfWordNotEqual(Node* lhs, Node* rhs, | 634 void InterpreterAssembler::AbortIfWordNotEqual(Node* lhs, Node* rhs, |
648 BailoutReason bailout_reason) { | 635 BailoutReason bailout_reason) { |
649 CodeStubAssembler::Label match(this); | 636 Label ok(this), abort(this, Label::kDeferred); |
650 CodeStubAssembler::Label no_match(this); | 637 BranchIfWordEqual(lhs, rhs, &ok, &abort); |
651 CodeStubAssembler::Label end(this); | |
652 | 638 |
653 Node* condition = WordEqual(lhs, rhs); | 639 Bind(&abort); |
654 Branch(condition, &match, &no_match); | |
655 Bind(&no_match); | |
656 Abort(bailout_reason); | 640 Abort(bailout_reason); |
657 Goto(&end); | 641 Goto(&ok); |
658 Bind(&match); | 642 |
659 Goto(&end); | 643 Bind(&ok); |
660 Bind(&end); | |
661 } | 644 } |
662 | 645 |
663 void InterpreterAssembler::TraceBytecode(Runtime::FunctionId function_id) { | 646 void InterpreterAssembler::TraceBytecode(Runtime::FunctionId function_id) { |
664 CallRuntime(function_id, GetContext(), BytecodeArrayTaggedPointer(), | 647 CallRuntime(function_id, GetContext(), BytecodeArrayTaggedPointer(), |
665 SmiTag(BytecodeOffset()), GetAccumulatorUnchecked()); | 648 SmiTag(BytecodeOffset()), GetAccumulatorUnchecked()); |
666 } | 649 } |
667 | 650 |
668 void InterpreterAssembler::TraceBytecodeDispatch(Node* target_bytecode) { | 651 void InterpreterAssembler::TraceBytecodeDispatch(Node* target_bytecode) { |
669 Node* counters_table = ExternalConstant( | 652 Node* counters_table = ExternalConstant( |
670 ExternalReference::interpreter_dispatch_counters(isolate())); | 653 ExternalReference::interpreter_dispatch_counters(isolate())); |
671 Node* source_bytecode_table_index = IntPtrConstant( | 654 Node* source_bytecode_table_index = IntPtrConstant( |
672 static_cast<int>(bytecode_) * (static_cast<int>(Bytecode::kLast) + 1)); | 655 static_cast<int>(bytecode_) * (static_cast<int>(Bytecode::kLast) + 1)); |
673 | 656 |
674 Node* counter_offset = | 657 Node* counter_offset = |
675 WordShl(IntPtrAdd(source_bytecode_table_index, target_bytecode), | 658 WordShl(IntPtrAdd(source_bytecode_table_index, target_bytecode), |
676 IntPtrConstant(kPointerSizeLog2)); | 659 IntPtrConstant(kPointerSizeLog2)); |
677 Node* old_counter = | 660 Node* old_counter = |
678 Load(MachineType::IntPtr(), counters_table, counter_offset); | 661 Load(MachineType::IntPtr(), counters_table, counter_offset); |
679 | 662 |
680 CodeStubAssembler::Label counter_ok(this); | 663 Label counter_ok(this), counter_saturated(this, Label::kDeferred); |
681 CodeStubAssembler::Label counter_saturated(this); | |
682 CodeStubAssembler::Label end(this); | |
683 | 664 |
684 Node* counter_reached_max = WordEqual( | 665 Node* counter_reached_max = WordEqual( |
685 old_counter, IntPtrConstant(std::numeric_limits<uintptr_t>::max())); | 666 old_counter, IntPtrConstant(std::numeric_limits<uintptr_t>::max())); |
686 Branch(counter_reached_max, &counter_saturated, &counter_ok); | 667 BranchIf(counter_reached_max, &counter_saturated, &counter_ok); |
| 668 |
687 Bind(&counter_ok); | 669 Bind(&counter_ok); |
688 Node* new_counter = IntPtrAdd(old_counter, IntPtrConstant(1)); | 670 { |
689 StoreNoWriteBarrier(MachineType::PointerRepresentation(), counters_table, | 671 Node* new_counter = IntPtrAdd(old_counter, IntPtrConstant(1)); |
690 counter_offset, new_counter); | 672 StoreNoWriteBarrier(MachineType::PointerRepresentation(), counters_table, |
691 Goto(&end); | 673 counter_offset, new_counter); |
| 674 Goto(&counter_saturated); |
| 675 } |
| 676 |
692 Bind(&counter_saturated); | 677 Bind(&counter_saturated); |
693 Goto(&end); | |
694 Bind(&end); | |
695 } | 678 } |
696 | 679 |
697 // static | 680 // static |
698 bool InterpreterAssembler::TargetSupportsUnalignedAccess() { | 681 bool InterpreterAssembler::TargetSupportsUnalignedAccess() { |
699 #if V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 | 682 #if V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 |
700 return false; | 683 return false; |
701 #elif V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_PPC | 684 #elif V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_PPC |
702 return CpuFeatures::IsSupported(UNALIGNED_ACCESSES); | 685 return CpuFeatures::IsSupported(UNALIGNED_ACCESSES); |
703 #elif V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_X87 || \ | 686 #elif V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_X87 || \ |
704 V8_TARGET_ARCH_S390 | 687 V8_TARGET_ARCH_S390 |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
782 Goto(&loop); | 765 Goto(&loop); |
783 } | 766 } |
784 Bind(&done_loop); | 767 Bind(&done_loop); |
785 | 768 |
786 return array; | 769 return array; |
787 } | 770 } |
788 | 771 |
789 } // namespace interpreter | 772 } // namespace interpreter |
790 } // namespace internal | 773 } // namespace internal |
791 } // namespace v8 | 774 } // namespace v8 |
OLD | NEW |