| 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/compiler/interpreter-assembler.h" | 5 #include "src/compiler/interpreter-assembler.h" |
| 6 | 6 |
| 7 #include <ostream> | 7 #include <ostream> |
| 8 | 8 |
| 9 #include "src/code-factory.h" | 9 #include "src/code-factory.h" |
| 10 #include "src/compiler/graph.h" | 10 #include "src/compiler/graph.h" |
| 11 #include "src/compiler/instruction-selector.h" | 11 #include "src/compiler/instruction-selector.h" |
| 12 #include "src/compiler/linkage.h" | 12 #include "src/compiler/linkage.h" |
| 13 #include "src/compiler/pipeline.h" | 13 #include "src/compiler/pipeline.h" |
| 14 #include "src/compiler/raw-machine-assembler.h" | 14 #include "src/compiler/raw-machine-assembler.h" |
| 15 #include "src/compiler/schedule.h" | 15 #include "src/compiler/schedule.h" |
| 16 #include "src/frames.h" | 16 #include "src/frames.h" |
| 17 #include "src/interface-descriptors.h" | 17 #include "src/interface-descriptors.h" |
| 18 #include "src/interpreter/bytecodes.h" | 18 #include "src/interpreter/bytecodes.h" |
| 19 #include "src/machine-type.h" | 19 #include "src/machine-type.h" |
| 20 #include "src/macro-assembler.h" | 20 #include "src/macro-assembler.h" |
| 21 #include "src/zone.h" | 21 #include "src/zone.h" |
| 22 | 22 |
| 23 namespace v8 { | 23 namespace v8 { |
| 24 namespace internal { | 24 namespace internal { |
| 25 namespace compiler { | 25 namespace compiler { |
| 26 | 26 |
| 27 | |
| 28 InterpreterAssembler::InterpreterAssembler(Isolate* isolate, Zone* zone, | 27 InterpreterAssembler::InterpreterAssembler(Isolate* isolate, Zone* zone, |
| 29 interpreter::Bytecode bytecode) | 28 interpreter::Bytecode bytecode) |
| 30 : bytecode_(bytecode), | 29 : bytecode_(bytecode), |
| 31 raw_assembler_(new RawMachineAssembler( | 30 raw_assembler_(new RawMachineAssembler( |
| 32 isolate, new (zone) Graph(zone), | 31 isolate, new (zone) Graph(zone), |
| 33 Linkage::GetInterpreterDispatchDescriptor(zone), | 32 Linkage::GetInterpreterDispatchDescriptor(zone), |
| 34 MachineType::PointerRepresentation(), | 33 MachineType::PointerRepresentation(), |
| 35 InstructionSelector::SupportedMachineOperatorFlags())), | 34 InstructionSelector::SupportedMachineOperatorFlags())), |
| 36 accumulator_( | 35 accumulator_( |
| 37 raw_assembler_->Parameter(Linkage::kInterpreterAccumulatorParameter)), | 36 raw_assembler_->Parameter(Linkage::kInterpreterAccumulatorParameter)), |
| 38 bytecode_offset_(raw_assembler_->Parameter( | |
| 39 Linkage::kInterpreterBytecodeOffsetParameter)), | |
| 40 context_( | 37 context_( |
| 41 raw_assembler_->Parameter(Linkage::kInterpreterContextParameter)), | 38 raw_assembler_->Parameter(Linkage::kInterpreterContextParameter)), |
| 42 code_generated_(false) {} | 39 code_generated_(false) { |
| 43 | 40 if (FLAG_trace_ignition) { |
| 41 TraceBytecode(Runtime::kInterpreterTraceBytecodeEntry); |
| 42 } |
| 43 } |
| 44 | 44 |
| 45 InterpreterAssembler::~InterpreterAssembler() {} | 45 InterpreterAssembler::~InterpreterAssembler() {} |
| 46 | 46 |
| 47 | 47 |
| 48 Handle<Code> InterpreterAssembler::GenerateCode() { | 48 Handle<Code> InterpreterAssembler::GenerateCode() { |
| 49 DCHECK(!code_generated_); | 49 DCHECK(!code_generated_); |
| 50 | 50 |
| 51 // Disallow empty handlers that never return. | 51 // Disallow empty handlers that never return. |
| 52 DCHECK_NE(0, graph()->end()->InputCount()); | 52 DCHECK_NE(0, graph()->end()->InputCount()); |
| 53 | 53 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 78 | 78 |
| 79 | 79 |
| 80 Node* InterpreterAssembler::GetContext() { return context_; } | 80 Node* InterpreterAssembler::GetContext() { return context_; } |
| 81 | 81 |
| 82 | 82 |
| 83 void InterpreterAssembler::SetContext(Node* value) { | 83 void InterpreterAssembler::SetContext(Node* value) { |
| 84 StoreRegister(value, interpreter::Register::current_context()); | 84 StoreRegister(value, interpreter::Register::current_context()); |
| 85 context_ = value; | 85 context_ = value; |
| 86 } | 86 } |
| 87 | 87 |
| 88 | 88 Node* InterpreterAssembler::BytecodeOffset() { |
| 89 Node* InterpreterAssembler::BytecodeOffset() { return bytecode_offset_; } | 89 return raw_assembler_->Parameter( |
| 90 | 90 Linkage::kInterpreterBytecodeOffsetParameter); |
| 91 } |
| 91 | 92 |
| 92 Node* InterpreterAssembler::RegisterFileRawPointer() { | 93 Node* InterpreterAssembler::RegisterFileRawPointer() { |
| 93 return raw_assembler_->Parameter(Linkage::kInterpreterRegisterFileParameter); | 94 return raw_assembler_->Parameter(Linkage::kInterpreterRegisterFileParameter); |
| 94 } | 95 } |
| 95 | 96 |
| 96 | 97 |
| 97 Node* InterpreterAssembler::BytecodeArrayTaggedPointer() { | 98 Node* InterpreterAssembler::BytecodeArrayTaggedPointer() { |
| 98 return raw_assembler_->Parameter(Linkage::kInterpreterBytecodeArrayParameter); | 99 return raw_assembler_->Parameter(Linkage::kInterpreterBytecodeArrayParameter); |
| 99 } | 100 } |
| 100 | 101 |
| (...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 457 args[1] = new_target; | 458 args[1] = new_target; |
| 458 args[2] = constructor; | 459 args[2] = constructor; |
| 459 args[3] = first_arg; | 460 args[3] = first_arg; |
| 460 args[4] = GetContext(); | 461 args[4] = GetContext(); |
| 461 | 462 |
| 462 return CallN(descriptor, code_target, args); | 463 return CallN(descriptor, code_target, args); |
| 463 } | 464 } |
| 464 | 465 |
| 465 | 466 |
| 466 void InterpreterAssembler::CallPrologue() { | 467 void InterpreterAssembler::CallPrologue() { |
| 467 StoreRegister(SmiTag(bytecode_offset_), | 468 StoreRegister(SmiTag(BytecodeOffset()), |
| 468 InterpreterFrameConstants::kBytecodeOffsetFromRegisterPointer); | 469 InterpreterFrameConstants::kBytecodeOffsetFromRegisterPointer); |
| 469 } | 470 } |
| 470 | 471 |
| 471 | 472 |
| 472 void InterpreterAssembler::CallEpilogue() { | |
| 473 // Restore the bytecode offset from the stack frame. | |
| 474 bytecode_offset_ = SmiUntag(LoadRegister( | |
| 475 InterpreterFrameConstants::kBytecodeOffsetFromRegisterPointer)); | |
| 476 } | |
| 477 | |
| 478 | |
| 479 Node* InterpreterAssembler::CallN(CallDescriptor* descriptor, Node* code_target, | 473 Node* InterpreterAssembler::CallN(CallDescriptor* descriptor, Node* code_target, |
| 480 Node** args) { | 474 Node** args) { |
| 481 CallPrologue(); | 475 CallPrologue(); |
| 482 | 476 |
| 483 Node* stack_pointer_before_call = nullptr; | 477 Node* stack_pointer_before_call = nullptr; |
| 484 if (FLAG_debug_code) { | 478 if (FLAG_debug_code) { |
| 485 stack_pointer_before_call = raw_assembler_->LoadStackPointer(); | 479 stack_pointer_before_call = raw_assembler_->LoadStackPointer(); |
| 486 } | 480 } |
| 487 Node* return_val = raw_assembler_->CallN(descriptor, code_target, args); | 481 Node* return_val = raw_assembler_->CallN(descriptor, code_target, args); |
| 488 if (FLAG_debug_code) { | 482 if (FLAG_debug_code) { |
| 489 Node* stack_pointer_after_call = raw_assembler_->LoadStackPointer(); | 483 Node* stack_pointer_after_call = raw_assembler_->LoadStackPointer(); |
| 490 AbortIfWordNotEqual(stack_pointer_before_call, stack_pointer_after_call, | 484 AbortIfWordNotEqual(stack_pointer_before_call, stack_pointer_after_call, |
| 491 kUnexpectedStackPointer); | 485 kUnexpectedStackPointer); |
| 492 } | 486 } |
| 493 | 487 |
| 494 CallEpilogue(); | |
| 495 return return_val; | 488 return return_val; |
| 496 } | 489 } |
| 497 | 490 |
| 498 | 491 |
| 499 Node* InterpreterAssembler::CallJS(Node* function, Node* first_arg, | 492 Node* InterpreterAssembler::CallJS(Node* function, Node* first_arg, |
| 500 Node* arg_count) { | 493 Node* arg_count) { |
| 501 Callable callable = CodeFactory::InterpreterPushArgsAndCall(isolate()); | 494 Callable callable = CodeFactory::InterpreterPushArgsAndCall(isolate()); |
| 502 CallDescriptor* descriptor = Linkage::GetStubCallDescriptor( | 495 CallDescriptor* descriptor = Linkage::GetStubCallDescriptor( |
| 503 isolate(), zone(), callable.descriptor(), 0, CallDescriptor::kNoFlags); | 496 isolate(), zone(), callable.descriptor(), 0, CallDescriptor::kNoFlags); |
| 504 | 497 |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 587 | 580 |
| 588 return CallN(descriptor, code_target, args); | 581 return CallN(descriptor, code_target, args); |
| 589 } | 582 } |
| 590 | 583 |
| 591 | 584 |
| 592 Node* InterpreterAssembler::CallRuntime(Runtime::FunctionId function_id, | 585 Node* InterpreterAssembler::CallRuntime(Runtime::FunctionId function_id, |
| 593 Node* arg1) { | 586 Node* arg1) { |
| 594 CallPrologue(); | 587 CallPrologue(); |
| 595 Node* return_val = | 588 Node* return_val = |
| 596 raw_assembler_->CallRuntime1(function_id, arg1, GetContext()); | 589 raw_assembler_->CallRuntime1(function_id, arg1, GetContext()); |
| 597 CallEpilogue(); | |
| 598 return return_val; | 590 return return_val; |
| 599 } | 591 } |
| 600 | 592 |
| 601 | 593 |
| 602 Node* InterpreterAssembler::CallRuntime(Runtime::FunctionId function_id, | 594 Node* InterpreterAssembler::CallRuntime(Runtime::FunctionId function_id, |
| 603 Node* arg1, Node* arg2) { | 595 Node* arg1, Node* arg2) { |
| 604 CallPrologue(); | 596 CallPrologue(); |
| 605 Node* return_val = | 597 Node* return_val = |
| 606 raw_assembler_->CallRuntime2(function_id, arg1, arg2, GetContext()); | 598 raw_assembler_->CallRuntime2(function_id, arg1, arg2, GetContext()); |
| 607 CallEpilogue(); | |
| 608 return return_val; | 599 return return_val; |
| 609 } | 600 } |
| 610 | 601 |
| 602 Node* InterpreterAssembler::CallRuntime(Runtime::FunctionId function_id, |
| 603 Node* arg1, Node* arg2, Node* arg3) { |
| 604 CallPrologue(); |
| 605 Node* return_val = |
| 606 raw_assembler_->CallRuntime3(function_id, arg1, arg2, arg3, GetContext()); |
| 607 return return_val; |
| 608 } |
| 611 | 609 |
| 612 Node* InterpreterAssembler::CallRuntime(Runtime::FunctionId function_id, | 610 Node* InterpreterAssembler::CallRuntime(Runtime::FunctionId function_id, |
| 613 Node* arg1, Node* arg2, Node* arg3, | 611 Node* arg1, Node* arg2, Node* arg3, |
| 614 Node* arg4) { | 612 Node* arg4) { |
| 615 CallPrologue(); | 613 CallPrologue(); |
| 616 Node* return_val = raw_assembler_->CallRuntime4(function_id, arg1, arg2, arg3, | 614 Node* return_val = raw_assembler_->CallRuntime4(function_id, arg1, arg2, arg3, |
| 617 arg4, GetContext()); | 615 arg4, GetContext()); |
| 618 CallEpilogue(); | |
| 619 return return_val; | 616 return return_val; |
| 620 } | 617 } |
| 621 | 618 |
| 622 | 619 |
| 623 void InterpreterAssembler::Return() { | 620 void InterpreterAssembler::Return() { |
| 621 if (FLAG_trace_ignition) { |
| 622 TraceBytecode(Runtime::kInterpreterTraceBytecodeExit); |
| 623 } |
| 624 |
| 624 Node* exit_trampoline_code_object = | 625 Node* exit_trampoline_code_object = |
| 625 HeapConstant(isolate()->builtins()->InterpreterExitTrampoline()); | 626 HeapConstant(isolate()->builtins()->InterpreterExitTrampoline()); |
| 626 // If the order of the parameters you need to change the call signature below. | 627 // If the order of the parameters you need to change the call signature below. |
| 627 STATIC_ASSERT(0 == Linkage::kInterpreterAccumulatorParameter); | 628 STATIC_ASSERT(0 == Linkage::kInterpreterAccumulatorParameter); |
| 628 STATIC_ASSERT(1 == Linkage::kInterpreterRegisterFileParameter); | 629 STATIC_ASSERT(1 == Linkage::kInterpreterRegisterFileParameter); |
| 629 STATIC_ASSERT(2 == Linkage::kInterpreterBytecodeOffsetParameter); | 630 STATIC_ASSERT(2 == Linkage::kInterpreterBytecodeOffsetParameter); |
| 630 STATIC_ASSERT(3 == Linkage::kInterpreterBytecodeArrayParameter); | 631 STATIC_ASSERT(3 == Linkage::kInterpreterBytecodeArrayParameter); |
| 631 STATIC_ASSERT(4 == Linkage::kInterpreterDispatchTableParameter); | 632 STATIC_ASSERT(4 == Linkage::kInterpreterDispatchTableParameter); |
| 632 STATIC_ASSERT(5 == Linkage::kInterpreterContextParameter); | 633 STATIC_ASSERT(5 == Linkage::kInterpreterContextParameter); |
| 633 Node* args[] = { GetAccumulator(), | 634 Node* args[] = { GetAccumulator(), |
| 634 RegisterFileRawPointer(), | 635 RegisterFileRawPointer(), |
| 635 BytecodeOffset(), | 636 BytecodeOffset(), |
| 636 BytecodeArrayTaggedPointer(), | 637 BytecodeArrayTaggedPointer(), |
| 637 DispatchTableRawPointer(), | 638 DispatchTableRawPointer(), |
| 638 GetContext() }; | 639 GetContext() }; |
| 639 raw_assembler_->TailCallN(call_descriptor(), exit_trampoline_code_object, | 640 raw_assembler_->TailCallN(call_descriptor(), exit_trampoline_code_object, |
| 640 args); | 641 args); |
| 641 } | 642 } |
| 642 | 643 |
| 643 | 644 |
| 644 Node* InterpreterAssembler::Advance(int delta) { | 645 Node* InterpreterAssembler::Advance(int delta) { |
| 645 return IntPtrAdd(BytecodeOffset(), Int32Constant(delta)); | 646 return IntPtrAdd(BytecodeOffset(), Int32Constant(delta)); |
| 646 } | 647 } |
| 647 | 648 |
| 648 | 649 |
| 649 Node* InterpreterAssembler::Advance(Node* delta) { | 650 Node* InterpreterAssembler::Advance(Node* delta) { |
| 650 return raw_assembler_->IntPtrAdd(BytecodeOffset(), delta); | 651 return raw_assembler_->IntPtrAdd(BytecodeOffset(), delta); |
| 651 } | 652 } |
| 652 | 653 |
| 653 | |
| 654 void InterpreterAssembler::Jump(Node* delta) { DispatchTo(Advance(delta)); } | 654 void InterpreterAssembler::Jump(Node* delta) { DispatchTo(Advance(delta)); } |
| 655 | 655 |
| 656 | |
| 657 void InterpreterAssembler::JumpIfWordEqual(Node* lhs, Node* rhs, Node* delta) { | 656 void InterpreterAssembler::JumpIfWordEqual(Node* lhs, Node* rhs, Node* delta) { |
| 658 RawMachineLabel match, no_match; | 657 RawMachineLabel match, no_match; |
| 659 Node* condition = raw_assembler_->WordEqual(lhs, rhs); | 658 Node* condition = raw_assembler_->WordEqual(lhs, rhs); |
| 660 raw_assembler_->Branch(condition, &match, &no_match); | 659 raw_assembler_->Branch(condition, &match, &no_match); |
| 661 raw_assembler_->Bind(&match); | 660 raw_assembler_->Bind(&match); |
| 662 DispatchTo(Advance(delta)); | 661 DispatchTo(Advance(delta)); |
| 663 raw_assembler_->Bind(&no_match); | 662 raw_assembler_->Bind(&no_match); |
| 664 Dispatch(); | 663 Dispatch(); |
| 665 } | 664 } |
| 666 | 665 |
| 667 | 666 |
| 668 void InterpreterAssembler::Dispatch() { | 667 void InterpreterAssembler::Dispatch() { |
| 669 DispatchTo(Advance(interpreter::Bytecodes::Size(bytecode_))); | 668 DispatchTo(Advance(interpreter::Bytecodes::Size(bytecode_))); |
| 670 } | 669 } |
| 671 | 670 |
| 672 | 671 |
| 673 void InterpreterAssembler::DispatchTo(Node* new_bytecode_offset) { | 672 void InterpreterAssembler::DispatchTo(Node* new_bytecode_offset) { |
| 673 if (FLAG_trace_ignition) { |
| 674 TraceBytecode(Runtime::kInterpreterTraceBytecodeExit); |
| 675 } |
| 674 Node* target_bytecode = raw_assembler_->Load( | 676 Node* target_bytecode = raw_assembler_->Load( |
| 675 MachineType::Uint8(), BytecodeArrayTaggedPointer(), new_bytecode_offset); | 677 MachineType::Uint8(), BytecodeArrayTaggedPointer(), new_bytecode_offset); |
| 676 | 678 |
| 677 // TODO(rmcilroy): Create a code target dispatch table to avoid conversion | 679 // TODO(rmcilroy): Create a code target dispatch table to avoid conversion |
| 678 // from code object on every dispatch. | 680 // from code object on every dispatch. |
| 679 Node* target_code_object = raw_assembler_->Load( | 681 Node* target_code_object = raw_assembler_->Load( |
| 680 MachineType::Pointer(), DispatchTableRawPointer(), | 682 MachineType::Pointer(), DispatchTableRawPointer(), |
| 681 raw_assembler_->Word32Shl(target_bytecode, | 683 raw_assembler_->Word32Shl(target_bytecode, |
| 682 Int32Constant(kPointerSizeLog2))); | 684 Int32Constant(kPointerSizeLog2))); |
| 683 | 685 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 709 void InterpreterAssembler::AbortIfWordNotEqual(Node* lhs, Node* rhs, | 711 void InterpreterAssembler::AbortIfWordNotEqual(Node* lhs, Node* rhs, |
| 710 BailoutReason bailout_reason) { | 712 BailoutReason bailout_reason) { |
| 711 RawMachineLabel match, no_match; | 713 RawMachineLabel match, no_match; |
| 712 Node* condition = raw_assembler_->WordEqual(lhs, rhs); | 714 Node* condition = raw_assembler_->WordEqual(lhs, rhs); |
| 713 raw_assembler_->Branch(condition, &match, &no_match); | 715 raw_assembler_->Branch(condition, &match, &no_match); |
| 714 raw_assembler_->Bind(&no_match); | 716 raw_assembler_->Bind(&no_match); |
| 715 Abort(bailout_reason); | 717 Abort(bailout_reason); |
| 716 raw_assembler_->Bind(&match); | 718 raw_assembler_->Bind(&match); |
| 717 } | 719 } |
| 718 | 720 |
| 721 void InterpreterAssembler::TraceBytecode(Runtime::FunctionId function_id) { |
| 722 CallRuntime(function_id, BytecodeArrayTaggedPointer(), |
| 723 SmiTag(BytecodeOffset()), GetAccumulator()); |
| 724 } |
| 719 | 725 |
| 720 // static | 726 // static |
| 721 bool InterpreterAssembler::TargetSupportsUnalignedAccess() { | 727 bool InterpreterAssembler::TargetSupportsUnalignedAccess() { |
| 722 #if V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 | 728 #if V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 |
| 723 return false; | 729 return false; |
| 724 #elif V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_PPC | 730 #elif V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_PPC |
| 725 return CpuFeatures::IsSupported(UNALIGNED_ACCESSES); | 731 return CpuFeatures::IsSupported(UNALIGNED_ACCESSES); |
| 726 #elif V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_X87 | 732 #elif V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_X87 |
| 727 return true; | 733 return true; |
| 728 #else | 734 #else |
| (...skipping 13 matching lines...) Expand all Loading... |
| 742 return raw_assembler_->call_descriptor(); | 748 return raw_assembler_->call_descriptor(); |
| 743 } | 749 } |
| 744 | 750 |
| 745 | 751 |
| 746 Zone* InterpreterAssembler::zone() { return raw_assembler_->zone(); } | 752 Zone* InterpreterAssembler::zone() { return raw_assembler_->zone(); } |
| 747 | 753 |
| 748 | 754 |
| 749 } // namespace compiler | 755 } // namespace compiler |
| 750 } // namespace internal | 756 } // namespace internal |
| 751 } // namespace v8 | 757 } // namespace v8 |
| OLD | NEW |