Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "src/interpreter/bytecode-pipeline.h" | |
| 6 | |
| 7 #include <iomanip> | |
| 8 #include "src/interpreter/source-position-table.h" | |
| 9 | |
| 10 namespace v8 { | |
| 11 namespace internal { | |
| 12 namespace interpreter { | |
| 13 | |
| 14 void BytecodeSourceInfo::Update(const BytecodeSourceInfo& entry) { | |
| 15 DCHECK(entry.is_valid()); | |
| 16 if (!is_valid() || (entry.is_statement() && !is_statement()) || | |
| 17 (entry.is_statement() && is_statement() && | |
| 18 entry.source_position() > source_position())) { | |
| 19 // Position is updated if there is no existing position. Or the | |
| 20 // incoming position is a statement and the current position is an | |
| 21 // expression. Or we already have a statement and incoming | |
| 22 // statement is later. This last piece is needed for the first | |
| 23 // statement in a function. | |
| 24 source_position_ = entry.source_position_; | |
| 25 is_statement_ = entry.is_statement_; | |
| 26 } | |
| 27 } | |
| 28 | |
| 29 BytecodeNode::BytecodeNode(BytecodeNodeAllocator* allocator) | |
| 30 : bytecode_(Bytecode::kIllegal), | |
| 31 operand_scale_(OperandScale::kSingle), | |
| 32 allocator_(allocator) {} | |
| 33 | |
| 34 void BytecodeNode::set_bytecode(Bytecode bytecode) { | |
| 35 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 0); | |
| 36 bytecode_ = bytecode; | |
| 37 operand_scale_ = OperandScale::kSingle; | |
| 38 } | |
| 39 | |
| 40 void BytecodeNode::set_bytecode(Bytecode bytecode, uint32_t operand0, | |
| 41 OperandScale operand_scale) { | |
| 42 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 1); | |
| 43 bytecode_ = bytecode; | |
| 44 operands_[0] = operand0; | |
| 45 operand_scale_ = operand_scale; | |
| 46 } | |
| 47 | |
| 48 void BytecodeNode::set_bytecode(Bytecode bytecode, uint32_t operand0, | |
| 49 uint32_t operand1, OperandScale operand_scale) { | |
| 50 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 2); | |
| 51 bytecode_ = bytecode; | |
| 52 operands_[0] = operand0; | |
| 53 operands_[1] = operand1; | |
| 54 operand_scale_ = operand_scale; | |
| 55 } | |
| 56 | |
| 57 void BytecodeNode::set_bytecode(Bytecode bytecode, uint32_t operand0, | |
| 58 uint32_t operand1, uint32_t operand2, | |
| 59 OperandScale operand_scale) { | |
| 60 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 3); | |
| 61 bytecode_ = bytecode; | |
| 62 operands_[0] = operand0; | |
| 63 operands_[1] = operand1; | |
| 64 operands_[2] = operand2; | |
| 65 operand_scale_ = operand_scale; | |
| 66 } | |
| 67 | |
| 68 void BytecodeNode::set_bytecode(Bytecode bytecode, uint32_t operand0, | |
| 69 uint32_t operand1, uint32_t operand2, | |
| 70 uint32_t operand3, OperandScale operand_scale) { | |
| 71 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 4); | |
| 72 bytecode_ = bytecode; | |
| 73 operands_[0] = operand0; | |
| 74 operands_[1] = operand1; | |
| 75 operands_[2] = operand2; | |
| 76 operands_[3] = operand3; | |
| 77 operand_scale_ = operand_scale; | |
| 78 } | |
| 79 | |
| 80 void BytecodeNode::replace_bytecode(Bytecode bytecode) { | |
| 81 if (bytecode == Bytecode::kNop) { | |
| 82 bytecode_ = bytecode; | |
| 83 operand_scale_ = OperandScale::kSingle; | |
| 84 return; | |
| 85 } | |
| 86 | |
| 87 if (Bytecodes::IsJump(bytecode) && Bytecodes::IsJump(bytecode_) && | |
| 88 Bytecodes::GetOperandType(bytecode, 0) == | |
| 89 Bytecodes::GetOperandType(bytecode_, 0)) { | |
|
rmcilroy
2016/05/10 11:14:10
I think we should only do these checks as DCHECKS
oth
2016/05/11 13:17:31
The semantics of CanReplace will be too cryptic aw
rmcilroy
2016/05/12 12:15:13
Works for me.
| |
| 90 bytecode_ = bytecode; | |
| 91 return; | |
| 92 } | |
| 93 | |
| 94 UNREACHABLE(); | |
| 95 } | |
| 96 | |
| 97 size_t BytecodeNode::Size() const { | |
| 98 size_t size = Bytecodes::Size(bytecode_, operand_scale_); | |
| 99 if (Bytecodes::OperandScaleRequiresPrefixBytecode(operand_scale_)) { | |
| 100 size += 1; | |
| 101 } | |
| 102 return size; | |
| 103 } | |
| 104 | |
| 105 void BytecodeNode::Release() { | |
| 106 bytecode_ = Bytecode::kIllegal; | |
| 107 source_info_.set_invalid(); | |
| 108 allocator_->Release(this); | |
| 109 } | |
| 110 | |
| 111 void BytecodeNode::Print(std::ostream& os) { | |
| 112 #ifdef DEBUG | |
| 113 std::ios saved_state(nullptr); | |
| 114 saved_state.copyfmt(os); | |
| 115 | |
| 116 os << Bytecodes::ToString(bytecode_); | |
| 117 if (Bytecodes::OperandScaleRequiresPrefixBytecode(operand_scale_)) { | |
| 118 Bytecode scale_prefix = | |
| 119 Bytecodes::OperandScaleToPrefixBytecode(operand_scale_); | |
| 120 os << '.' << Bytecodes::ToString(scale_prefix); | |
| 121 } | |
| 122 | |
| 123 for (int i = 0; i < operand_count(); ++i) { | |
| 124 os << ' ' << std::setw(8) << std::setfill('0') << std::hex << operands_[i]; | |
| 125 } | |
| 126 os.copyfmt(saved_state); | |
| 127 | |
| 128 if (source_info_.is_valid()) { | |
| 129 char type = source_info_.is_statement() ? 'S' : 'E'; | |
| 130 os << ' ' << type << '@' << source_info_.source_position(); | |
| 131 } | |
| 132 os << '\n'; | |
| 133 #endif // DEBUG | |
| 134 } | |
| 135 | |
| 136 BytecodeNode* BytecodeNodeAllocator::Allocate() { | |
| 137 if (free_list_ != nullptr) { | |
| 138 BytecodeNode* node = free_list_; | |
| 139 free_list_ = free_list_->next_; | |
| 140 return node; | |
| 141 } else { | |
| 142 DCHECK_LT(allocation_count_, kMaxDebugAllocations); | |
| 143 allocation_count_++; | |
| 144 return new (zone()) BytecodeNode(this); | |
| 145 } | |
| 146 } | |
| 147 | |
| 148 void BytecodeNodeAllocator::Release(BytecodeNode* node) { | |
| 149 node->next_ = free_list_; | |
| 150 free_list_ = node; | |
| 151 } | |
| 152 | |
| 153 } // namespace interpreter | |
| 154 } // namespace internal | |
| 155 } // namespace v8 | |
| OLD | NEW |