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-writer.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())) { | |
rmcilroy
2016/05/06 15:25:48
Could we get rid of the whole candidate_ source po
oth
2016/05/09 11:02:17
Done.
| |
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 size_t BytecodeNode::Size() const { | |
81 size_t size = Bytecodes::Size(bytecode_, operand_scale_); | |
82 if (Bytecodes::OperandScaleRequiresPrefixBytecode(operand_scale_)) { | |
83 size += 1; | |
84 } | |
85 return size; | |
86 } | |
87 | |
88 void BytecodeNode::Release() { | |
89 bytecode_ = Bytecode::kIllegal; | |
90 source_info_.set_invalid(); | |
91 allocator_->Release(this); | |
92 } | |
93 | |
94 void BytecodeNode::Print(std::ostream& os) { | |
rmcilroy
2016/05/06 15:25:48
Unused - is this useful for debugging?
oth
2016/05/09 11:02:17
Yes, I'd opt to keep this around for a while.
| |
95 #ifdef DEBUG | |
96 std::ios saved_state(nullptr); | |
97 saved_state.copyfmt(os); | |
98 | |
99 os << Bytecodes::ToString(bytecode_); | |
100 if (Bytecodes::OperandScaleRequiresPrefixBytecode(operand_scale_)) { | |
101 Bytecode scale_prefix = | |
102 Bytecodes::OperandScaleToPrefixBytecode(operand_scale_); | |
103 os << '.' << Bytecodes::ToString(scale_prefix); | |
104 } | |
105 | |
106 for (int i = 0; i < operand_count(); ++i) { | |
107 os << ' ' << std::setw(8) << std::setfill('0') << std::hex << operands_[i]; | |
108 } | |
109 os.copyfmt(saved_state); | |
110 | |
111 if (source_info_.is_valid()) { | |
112 char type = source_info_.is_statement() ? 'S' : 'E'; | |
113 os << ' ' << type << '@' << source_info_.source_position(); | |
114 } | |
115 os << '\n'; | |
116 #endif // DEBUG | |
117 } | |
118 | |
119 BytecodeNode* BytecodeNodeAllocator::Allocate() { | |
120 if (free_list_ != nullptr) { | |
121 BytecodeNode* node = free_list_; | |
122 free_list_ = free_list_->next_; | |
123 return node; | |
124 } else { | |
125 DCHECK_LT(allocation_count_, kMaxDebugAllocations); | |
126 allocation_count_++; | |
127 return new (zone()) BytecodeNode(this); | |
128 } | |
129 } | |
130 | |
131 void BytecodeNodeAllocator::Release(BytecodeNode* node) { | |
132 node->next_ = free_list_; | |
133 free_list_ = node; | |
134 } | |
135 | |
136 FinalStageBytecodeWriter::FinalStageBytecodeWriter( | |
137 Zone* zone, SourcePositionTableBuilder* source_position_table_builder) | |
138 : bytecodes_(zone), | |
139 frame_register_count_(0), | |
140 source_position_table_builder_(source_position_table_builder) { | |
141 bytecodes_.reserve(256); | |
142 } | |
143 | |
144 // override | |
145 FinalStageBytecodeWriter::~FinalStageBytecodeWriter() {} | |
146 | |
147 // override | |
148 size_t FinalStageBytecodeWriter::FlushForOffset() { | |
149 return bytecodes()->size(); | |
150 } | |
151 | |
152 // override | |
153 void FinalStageBytecodeWriter::Write(BytecodeNode* node) { | |
154 UpdateSourcePositionTable(node); | |
155 EmitBytecode(node); | |
156 node->Release(); | |
157 } | |
158 | |
159 void FinalStageBytecodeWriter::UpdateSourcePositionTable( | |
160 const BytecodeNode* const node) { | |
161 int bytecode_offset = static_cast<int>(bytecodes()->size()); | |
162 const BytecodeSourceInfo& source_info = node->source_info(); | |
163 if (source_info.is_valid()) { | |
164 if (source_info.is_statement()) { | |
165 source_position_table_builder_->AddStatementPosition( | |
166 bytecode_offset, source_info.source_position()); | |
167 } else { | |
168 source_position_table_builder_->AddExpressionPosition( | |
169 bytecode_offset, source_info.source_position()); | |
170 } | |
171 } | |
172 } | |
173 | |
174 void FinalStageBytecodeWriter::EmitBytecode(const BytecodeNode* const node) { | |
175 OperandScale operand_scale = node->operand_scale(); | |
176 if (operand_scale != OperandScale::kSingle) { | |
177 Bytecode prefix = Bytecodes::OperandScaleToPrefixBytecode(operand_scale); | |
178 bytecodes()->push_back(Bytecodes::ToByte(prefix)); | |
179 } | |
180 | |
181 Bytecode bytecode = node->bytecode(); | |
182 bytecodes()->push_back(Bytecodes::ToByte(bytecode)); | |
183 | |
184 int register_operand_bitmap = Bytecodes::GetRegisterOperandBitmap(bytecode); | |
185 const uint32_t* const operands = node->operands(); | |
186 const OperandType* operand_types = Bytecodes::GetOperandTypes(bytecode); | |
187 for (int i = 0; operand_types[i] != OperandType::kNone; ++i) { | |
188 OperandType operand_type = operand_types[i]; | |
189 switch (Bytecodes::SizeOfOperand(operand_type, operand_scale)) { | |
190 case OperandSize::kNone: | |
191 UNREACHABLE(); | |
192 break; | |
193 case OperandSize::kByte: | |
194 bytecodes()->push_back(static_cast<uint8_t>(operands[i])); | |
195 break; | |
196 case OperandSize::kShort: { | |
197 uint8_t operand_bytes[2]; | |
198 WriteUnalignedUInt16(operand_bytes, operands[i]); | |
199 bytecodes()->insert(bytecodes()->end(), operand_bytes, | |
200 operand_bytes + 2); | |
201 break; | |
202 } | |
203 case OperandSize::kQuad: { | |
204 uint8_t operand_bytes[4]; | |
205 WriteUnalignedUInt32(operand_bytes, operands[i]); | |
206 bytecodes()->insert(bytecodes()->end(), operand_bytes, | |
207 operand_bytes + 4); | |
208 break; | |
209 } | |
210 } | |
211 | |
212 if ((register_operand_bitmap >> i) & 1) { | |
213 int count; | |
214 if (operand_types[i + 1] == OperandType::kRegCount) { | |
215 count = static_cast<int>(operands[i + 1]); | |
216 } else { | |
217 count = Bytecodes::GetNumberOfRegistersRepresentedBy(operand_type); | |
218 } | |
219 Register reg = Register::FromOperand(static_cast<int32_t>(operands[i])); | |
220 frame_register_count_ = | |
221 std::max(frame_register_count_, reg.index() + count); | |
222 } | |
223 } | |
224 } | |
225 | |
226 // override | |
227 void FinalStageBytecodeWriter::LeaveBasicBlock() {} | |
228 | |
229 int FinalStageBytecodeWriter::GetMeasuredFrameSize() { | |
230 return frame_register_count_ * kPointerSize; | |
231 } | |
232 | |
233 } // namespace interpreter | |
234 } // namespace internal | |
235 } // namespace v8 | |
OLD | NEW |