Chromium Code Reviews| 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 12 matching lines...) Expand all Loading... | |
| 23 using compiler::Node; | 23 using compiler::Node; |
| 24 | 24 |
| 25 InterpreterAssembler::InterpreterAssembler(Isolate* isolate, Zone* zone, | 25 InterpreterAssembler::InterpreterAssembler(Isolate* isolate, Zone* zone, |
| 26 Bytecode bytecode, | 26 Bytecode bytecode, |
| 27 OperandScale operand_scale) | 27 OperandScale operand_scale) |
| 28 : CodeStubAssembler(isolate, zone, InterpreterDispatchDescriptor(isolate), | 28 : CodeStubAssembler(isolate, zone, InterpreterDispatchDescriptor(isolate), |
| 29 Code::ComputeFlags(Code::BYTECODE_HANDLER), | 29 Code::ComputeFlags(Code::BYTECODE_HANDLER), |
| 30 Bytecodes::ToString(bytecode), | 30 Bytecodes::ToString(bytecode), |
| 31 Bytecodes::ReturnCount(bytecode)), | 31 Bytecodes::ReturnCount(bytecode)), |
| 32 bytecode_(bytecode), | 32 bytecode_(bytecode), |
| 33 bytecode_offset_(this, MachineRepresentation::kTagged), | |
| 33 operand_scale_(operand_scale), | 34 operand_scale_(operand_scale), |
| 34 interpreted_frame_pointer_(this, MachineType::PointerRepresentation()), | 35 interpreted_frame_pointer_(this, MachineType::PointerRepresentation()), |
| 35 accumulator_(this, MachineRepresentation::kTagged), | 36 accumulator_(this, MachineRepresentation::kTagged), |
| 36 accumulator_use_(AccumulatorUse::kNone), | 37 accumulator_use_(AccumulatorUse::kNone), |
| 37 made_call_(false), | 38 made_call_(false), |
| 38 disable_stack_check_across_call_(false), | 39 disable_stack_check_across_call_(false), |
| 39 stack_pointer_before_call_(nullptr) { | 40 stack_pointer_before_call_(nullptr) { |
| 40 accumulator_.Bind( | 41 accumulator_.Bind( |
| 41 Parameter(InterpreterDispatchDescriptor::kAccumulatorParameter)); | 42 Parameter(InterpreterDispatchDescriptor::kAccumulatorParameter)); |
| 43 bytecode_offset_.Bind( | |
| 44 Parameter(InterpreterDispatchDescriptor::kBytecodeOffsetParameter)); | |
| 42 if (FLAG_trace_ignition) { | 45 if (FLAG_trace_ignition) { |
| 43 TraceBytecode(Runtime::kInterpreterTraceBytecodeEntry); | 46 TraceBytecode(Runtime::kInterpreterTraceBytecodeEntry); |
| 44 } | 47 } |
| 45 } | 48 } |
| 46 | 49 |
| 47 InterpreterAssembler::~InterpreterAssembler() { | 50 InterpreterAssembler::~InterpreterAssembler() { |
| 48 // If the following check fails the handler does not use the | 51 // If the following check fails the handler does not use the |
| 49 // accumulator in the way described in the bytecode definitions in | 52 // accumulator in the way described in the bytecode definitions in |
| 50 // bytecodes.h. | 53 // bytecodes.h. |
| 51 DCHECK_EQ(accumulator_use_, Bytecodes::GetAccumulatorUse(bytecode_)); | 54 DCHECK_EQ(accumulator_use_, Bytecodes::GetAccumulatorUse(bytecode_)); |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 76 | 79 |
| 77 Node* InterpreterAssembler::GetContext() { | 80 Node* InterpreterAssembler::GetContext() { |
| 78 return LoadRegister(Register::current_context()); | 81 return LoadRegister(Register::current_context()); |
| 79 } | 82 } |
| 80 | 83 |
| 81 void InterpreterAssembler::SetContext(Node* value) { | 84 void InterpreterAssembler::SetContext(Node* value) { |
| 82 StoreRegister(value, Register::current_context()); | 85 StoreRegister(value, Register::current_context()); |
| 83 } | 86 } |
| 84 | 87 |
| 85 Node* InterpreterAssembler::BytecodeOffset() { | 88 Node* InterpreterAssembler::BytecodeOffset() { |
| 86 return Parameter(InterpreterDispatchDescriptor::kBytecodeOffsetParameter); | 89 return bytecode_offset_.value(); |
| 87 } | 90 } |
| 88 | 91 |
| 89 Node* InterpreterAssembler::BytecodeArrayTaggedPointer() { | 92 Node* InterpreterAssembler::BytecodeArrayTaggedPointer() { |
| 90 if (made_call_) { | 93 if (made_call_) { |
| 91 // If we have made a call, restore bytecode array from stack frame in case | 94 // If we have made a call, restore bytecode array from stack frame in case |
| 92 // the debugger has swapped us to the patched debugger bytecode array. | 95 // the debugger has swapped us to the patched debugger bytecode array. |
| 93 return LoadRegister(Register::bytecode_array()); | 96 return LoadRegister(Register::bytecode_array()); |
| 94 } else { | 97 } else { |
| 95 return Parameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter); | 98 return Parameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter); |
| 96 } | 99 } |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 124 MachineRepresentation::kTagged, GetInterpretedFramePointer(), | 127 MachineRepresentation::kTagged, GetInterpretedFramePointer(), |
| 125 IntPtrConstant(reg.ToOperand() << kPointerSizeLog2), value); | 128 IntPtrConstant(reg.ToOperand() << kPointerSizeLog2), value); |
| 126 } | 129 } |
| 127 | 130 |
| 128 Node* InterpreterAssembler::StoreRegister(Node* value, Node* reg_index) { | 131 Node* InterpreterAssembler::StoreRegister(Node* value, Node* reg_index) { |
| 129 return StoreNoWriteBarrier(MachineRepresentation::kTagged, | 132 return StoreNoWriteBarrier(MachineRepresentation::kTagged, |
| 130 GetInterpretedFramePointer(), | 133 GetInterpretedFramePointer(), |
| 131 RegisterFrameOffset(reg_index), value); | 134 RegisterFrameOffset(reg_index), value); |
| 132 } | 135 } |
| 133 | 136 |
| 137 Node* InterpreterAssembler::StoreAccumulatorToRegister() { | |
| 138 DCHECK_EQ(bytecode_, Bytecode::kStar); | |
| 139 Node* reg_index = BytecodeOperandReg(0); | |
| 140 Node* accumulator = GetAccumulator(); | |
| 141 return StoreRegister(accumulator, reg_index); | |
| 142 } | |
| 143 | |
| 134 Node* InterpreterAssembler::NextRegister(Node* reg_index) { | 144 Node* InterpreterAssembler::NextRegister(Node* reg_index) { |
| 135 // Register indexes are negative, so the next index is minus one. | 145 // Register indexes are negative, so the next index is minus one. |
| 136 return IntPtrAdd(reg_index, IntPtrConstant(-1)); | 146 return IntPtrAdd(reg_index, IntPtrConstant(-1)); |
| 137 } | 147 } |
| 138 | 148 |
| 139 Node* InterpreterAssembler::OperandOffset(int operand_index) { | 149 Node* InterpreterAssembler::OperandOffset(int operand_index) { |
| 140 return IntPtrConstant( | 150 return IntPtrConstant( |
| 141 Bytecodes::GetOperandOffset(bytecode_, operand_index, operand_scale())); | 151 Bytecodes::GetOperandOffset(bytecode_, operand_index, operand_scale())); |
| 142 } | 152 } |
| 143 | 153 |
| (...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 499 Goto(&ok); | 509 Goto(&ok); |
| 500 } | 510 } |
| 501 | 511 |
| 502 // Update budget. | 512 // Update budget. |
| 503 Bind(&ok); | 513 Bind(&ok); |
| 504 StoreNoWriteBarrier(MachineRepresentation::kWord32, | 514 StoreNoWriteBarrier(MachineRepresentation::kWord32, |
| 505 BytecodeArrayTaggedPointer(), budget_offset, | 515 BytecodeArrayTaggedPointer(), budget_offset, |
| 506 new_budget.value()); | 516 new_budget.value()); |
| 507 } | 517 } |
| 508 | 518 |
| 519 Node* InterpreterAssembler::Advance() { | |
| 520 return Advance(Bytecodes::Size(bytecode_, operand_scale_)); | |
| 521 } | |
| 522 | |
| 509 Node* InterpreterAssembler::Advance(int delta) { | 523 Node* InterpreterAssembler::Advance(int delta) { |
| 510 return IntPtrAdd(BytecodeOffset(), IntPtrConstant(delta)); | 524 return Advance(IntPtrConstant(delta)); |
| 511 } | 525 } |
| 512 | 526 |
| 513 Node* InterpreterAssembler::Advance(Node* delta) { | 527 Node* InterpreterAssembler::Advance(Node* delta) { |
| 514 return IntPtrAdd(BytecodeOffset(), delta); | 528 return IntPtrAdd(BytecodeOffset(), delta); |
| 515 } | 529 } |
| 516 | 530 |
| 517 Node* InterpreterAssembler::Jump(Node* delta) { | 531 Node* InterpreterAssembler::Jump(Node* delta) { |
| 518 UpdateInterruptBudget(delta); | 532 UpdateInterruptBudget(delta); |
| 519 return DispatchTo(Advance(delta)); | 533 return DispatchTo(Advance(delta)); |
| 520 } | 534 } |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 531 | 545 |
| 532 void InterpreterAssembler::JumpIfWordEqual(Node* lhs, Node* rhs, Node* delta) { | 546 void InterpreterAssembler::JumpIfWordEqual(Node* lhs, Node* rhs, Node* delta) { |
| 533 JumpConditional(WordEqual(lhs, rhs), delta); | 547 JumpConditional(WordEqual(lhs, rhs), delta); |
| 534 } | 548 } |
| 535 | 549 |
| 536 void InterpreterAssembler::JumpIfWordNotEqual(Node* lhs, Node* rhs, | 550 void InterpreterAssembler::JumpIfWordNotEqual(Node* lhs, Node* rhs, |
| 537 Node* delta) { | 551 Node* delta) { |
| 538 JumpConditional(WordNotEqual(lhs, rhs), delta); | 552 JumpConditional(WordNotEqual(lhs, rhs), delta); |
| 539 } | 553 } |
| 540 | 554 |
| 555 Node* InterpreterAssembler::LoadBytecode(compiler::Node* bytecode_offset) { | |
| 556 return Load(MachineType::Uint8(), BytecodeArrayTaggedPointer(), | |
| 557 bytecode_offset); | |
| 558 } | |
| 559 | |
| 541 Node* InterpreterAssembler::Dispatch() { | 560 Node* InterpreterAssembler::Dispatch() { |
| 542 return DispatchTo(Advance(Bytecodes::Size(bytecode_, operand_scale_))); | 561 Node* target_offset = Advance(); |
| 562 Node* target_bytecode = LoadBytecode(target_offset); | |
| 563 Variable var_offset(this, MachineRepresentation::kTagged); | |
| 564 Variable var_bytecode(this, MachineRepresentation::kWord32); | |
| 565 var_offset.Bind(target_offset); | |
| 566 var_bytecode.Bind(target_bytecode); | |
| 567 | |
| 568 if (Bytecodes::IsStarLookahead(bytecode_, operand_scale_)) { | |
| 569 InlineDispatchToStar(var_bytecode, var_offset); | |
| 570 } | |
| 571 return DispatchToLoaded(var_bytecode.value(), var_offset.value()); | |
| 572 } | |
| 573 | |
| 574 void InterpreterAssembler::InlineDispatchToStar(Variable& target_bytecode, | |
| 575 Variable& target_offset) { | |
| 576 if (FLAG_trace_ignition) { | |
| 577 TraceBytecode(Runtime::kInterpreterTraceBytecodeExit); | |
| 578 } | |
| 579 DCHECK_EQ(accumulator_use_, Bytecodes::GetAccumulatorUse(bytecode_)); | |
| 580 bytecode_ = Bytecode::kStar; | |
| 581 bytecode_offset_.Bind(target_offset.value()); | |
| 582 accumulator_use_ = AccumulatorUse::kNone; | |
| 583 if (FLAG_trace_ignition) { | |
| 584 TraceBytecode(Runtime::kInterpreterTraceBytecodeEntry); | |
| 585 } | |
| 586 | |
| 587 Variable* merged_vars[2] = {&target_offset, &target_bytecode}; | |
| 588 Label store_register(this), dispatch(this, 2, merged_vars); | |
|
oth
2016/07/15 15:30:51
Naming here might be better as store and store_don
klaasb
2016/07/15 18:01:24
Done.
| |
| 589 | |
| 590 Node* star_bytecode = Int32Constant(static_cast<int>(Bytecode::kStar)); | |
| 591 Node* is_star = WordEqual(target_bytecode.value(), star_bytecode); | |
| 592 BranchIf(is_star, &store_register, &dispatch); | |
| 593 Bind(&store_register); | |
| 594 { | |
| 595 StoreAccumulatorToRegister(); | |
| 596 Node* next_bytecode_offset = Advance(); | |
| 597 target_offset.Bind(next_bytecode_offset); | |
| 598 target_bytecode.Bind(LoadBytecode(next_bytecode_offset)); | |
| 599 Goto(&dispatch); | |
| 600 } | |
| 601 Bind(&dispatch); | |
| 543 } | 602 } |
| 544 | 603 |
| 545 Node* InterpreterAssembler::DispatchTo(Node* new_bytecode_offset) { | 604 Node* InterpreterAssembler::DispatchTo(Node* new_bytecode_offset) { |
| 546 Node* target_bytecode = Load( | 605 Node* target_bytecode = LoadBytecode(new_bytecode_offset); |
| 547 MachineType::Uint8(), BytecodeArrayTaggedPointer(), new_bytecode_offset); | 606 return DispatchToLoaded(target_bytecode, new_bytecode_offset); |
| 607 } | |
| 608 | |
| 609 Node* InterpreterAssembler::DispatchToLoaded(Node* target_bytecode, | |
| 610 Node* new_bytecode_offset) { | |
| 548 if (kPointerSize == 8) { | 611 if (kPointerSize == 8) { |
| 549 target_bytecode = ChangeUint32ToUint64(target_bytecode); | 612 target_bytecode = ChangeUint32ToUint64(target_bytecode); |
| 550 } | 613 } |
| 551 | |
| 552 if (FLAG_trace_ignition_dispatches) { | 614 if (FLAG_trace_ignition_dispatches) { |
| 553 TraceBytecodeDispatch(target_bytecode); | 615 TraceBytecodeDispatch(target_bytecode); |
| 554 } | 616 } |
| 555 | 617 |
| 556 Node* target_code_entry = | 618 Node* target_code_entry = |
| 557 Load(MachineType::Pointer(), DispatchTableRawPointer(), | 619 Load(MachineType::Pointer(), DispatchTableRawPointer(), |
| 558 WordShl(target_bytecode, IntPtrConstant(kPointerSizeLog2))); | 620 WordShl(target_bytecode, IntPtrConstant(kPointerSizeLog2))); |
| 559 | 621 |
| 560 return DispatchToBytecodeHandlerEntry(target_code_entry, new_bytecode_offset); | 622 return DispatchToBytecodeHandlerEntry(target_code_entry, new_bytecode_offset); |
| 561 } | 623 } |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 581 | 643 |
| 582 void InterpreterAssembler::DispatchWide(OperandScale operand_scale) { | 644 void InterpreterAssembler::DispatchWide(OperandScale operand_scale) { |
| 583 // Dispatching a wide bytecode requires treating the prefix | 645 // Dispatching a wide bytecode requires treating the prefix |
| 584 // bytecode a base pointer into the dispatch table and dispatching | 646 // bytecode a base pointer into the dispatch table and dispatching |
| 585 // the bytecode that follows relative to this base. | 647 // the bytecode that follows relative to this base. |
| 586 // | 648 // |
| 587 // Indices 0-255 correspond to bytecodes with operand_scale == 0 | 649 // Indices 0-255 correspond to bytecodes with operand_scale == 0 |
| 588 // Indices 256-511 correspond to bytecodes with operand_scale == 1 | 650 // Indices 256-511 correspond to bytecodes with operand_scale == 1 |
| 589 // Indices 512-767 correspond to bytecodes with operand_scale == 2 | 651 // Indices 512-767 correspond to bytecodes with operand_scale == 2 |
| 590 Node* next_bytecode_offset = Advance(1); | 652 Node* next_bytecode_offset = Advance(1); |
| 591 Node* next_bytecode = Load(MachineType::Uint8(), BytecodeArrayTaggedPointer(), | 653 Node* next_bytecode = LoadBytecode(next_bytecode_offset); |
| 592 next_bytecode_offset); | |
| 593 if (kPointerSize == 8) { | 654 if (kPointerSize == 8) { |
| 594 next_bytecode = ChangeUint32ToUint64(next_bytecode); | 655 next_bytecode = ChangeUint32ToUint64(next_bytecode); |
| 595 } | 656 } |
| 596 | 657 |
| 597 if (FLAG_trace_ignition_dispatches) { | 658 if (FLAG_trace_ignition_dispatches) { |
| 598 TraceBytecodeDispatch(next_bytecode); | 659 TraceBytecodeDispatch(next_bytecode); |
| 599 } | 660 } |
| 600 | 661 |
| 601 Node* base_index; | 662 Node* base_index; |
| 602 switch (operand_scale) { | 663 switch (operand_scale) { |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 779 Goto(&loop); | 840 Goto(&loop); |
| 780 } | 841 } |
| 781 Bind(&done_loop); | 842 Bind(&done_loop); |
| 782 | 843 |
| 783 return array; | 844 return array; |
| 784 } | 845 } |
| 785 | 846 |
| 786 } // namespace interpreter | 847 } // namespace interpreter |
| 787 } // namespace internal | 848 } // namespace internal |
| 788 } // namespace v8 | 849 } // namespace v8 |
| OLD | NEW |