| 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 |