Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(19)

Side by Side Diff: src/interpreter/bytecode-array-writer.cc

Issue 2351763002: [Interpreter] Optimize BytecodeArrayBuilder and BytecodeArrayWriter. (Closed)
Patch Set: Fix Chromium Windows bots. Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/interpreter/bytecode-array-writer.h ('k') | src/interpreter/bytecode-dead-code-optimizer.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/bytecode-array-writer.h" 5 #include "src/interpreter/bytecode-array-writer.h"
6 6
7 #include "src/api.h" 7 #include "src/api.h"
8 #include "src/interpreter/bytecode-label.h" 8 #include "src/interpreter/bytecode-label.h"
9 #include "src/interpreter/bytecode-register.h" 9 #include "src/interpreter/bytecode-register.h"
10 #include "src/interpreter/constant-array-builder.h" 10 #include "src/interpreter/constant-array-builder.h"
11 #include "src/log.h" 11 #include "src/log.h"
12 12
13 namespace v8 { 13 namespace v8 {
14 namespace internal { 14 namespace internal {
15 namespace interpreter { 15 namespace interpreter {
16 16
17 STATIC_CONST_MEMBER_DEFINITION const size_t 17 STATIC_CONST_MEMBER_DEFINITION const size_t
18 BytecodeArrayWriter::kMaxSizeOfPackedBytecode; 18 BytecodeArrayWriter::kMaxSizeOfPackedBytecode;
19 19
20 BytecodeArrayWriter::BytecodeArrayWriter( 20 BytecodeArrayWriter::BytecodeArrayWriter(
21 Zone* zone, ConstantArrayBuilder* constant_array_builder, 21 Zone* zone, ConstantArrayBuilder* constant_array_builder,
22 SourcePositionTableBuilder::RecordingMode source_position_mode) 22 SourcePositionTableBuilder::RecordingMode source_position_mode)
23 : bytecodes_(zone), 23 : bytecodes_(zone),
24 max_register_count_(0),
25 unbound_jumps_(0), 24 unbound_jumps_(0),
26 source_position_table_builder_(zone, source_position_mode), 25 source_position_table_builder_(zone, source_position_mode),
27 constant_array_builder_(constant_array_builder) {} 26 constant_array_builder_(constant_array_builder) {
27 bytecodes_.reserve(512); // Derived via experimentation.
28 }
28 29
29 // override 30 // override
30 BytecodeArrayWriter::~BytecodeArrayWriter() {} 31 BytecodeArrayWriter::~BytecodeArrayWriter() {}
31 32
32 // override 33 // override
33 Handle<BytecodeArray> BytecodeArrayWriter::ToBytecodeArray( 34 Handle<BytecodeArray> BytecodeArrayWriter::ToBytecodeArray(
34 Isolate* isolate, int fixed_register_count, int parameter_count, 35 Isolate* isolate, int register_count, int parameter_count,
35 Handle<FixedArray> handler_table) { 36 Handle<FixedArray> handler_table) {
36 DCHECK_EQ(0, unbound_jumps_); 37 DCHECK_EQ(0, unbound_jumps_);
37 38
38 int bytecode_size = static_cast<int>(bytecodes()->size()); 39 int bytecode_size = static_cast<int>(bytecodes()->size());
39 40 int frame_size = register_count * kPointerSize;
40 // All locals need a frame slot for the debugger, but may not be
41 // present in generated code.
42 int frame_size_for_locals = fixed_register_count * kPointerSize;
43 int frame_size_used = max_register_count() * kPointerSize;
44 int frame_size = std::max(frame_size_for_locals, frame_size_used);
45 Handle<FixedArray> constant_pool = 41 Handle<FixedArray> constant_pool =
46 constant_array_builder()->ToFixedArray(isolate); 42 constant_array_builder()->ToFixedArray(isolate);
47 Handle<BytecodeArray> bytecode_array = isolate->factory()->NewBytecodeArray( 43 Handle<BytecodeArray> bytecode_array = isolate->factory()->NewBytecodeArray(
48 bytecode_size, &bytecodes()->front(), frame_size, parameter_count, 44 bytecode_size, &bytecodes()->front(), frame_size, parameter_count,
49 constant_pool); 45 constant_pool);
50 bytecode_array->set_handler_table(*handler_table); 46 bytecode_array->set_handler_table(*handler_table);
51 Handle<ByteArray> source_position_table = 47 Handle<ByteArray> source_position_table =
52 source_position_table_builder()->ToSourcePositionTable( 48 source_position_table_builder()->ToSourcePositionTable(
53 isolate, Handle<AbstractCode>::cast(bytecode_array)); 49 isolate, Handle<AbstractCode>::cast(bytecode_array));
54 bytecode_array->set_source_position_table(*source_position_table); 50 bytecode_array->set_source_position_table(*source_position_table);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 const BytecodeNode* const node) { 93 const BytecodeNode* const node) {
98 int bytecode_offset = static_cast<int>(bytecodes()->size()); 94 int bytecode_offset = static_cast<int>(bytecodes()->size());
99 const BytecodeSourceInfo& source_info = node->source_info(); 95 const BytecodeSourceInfo& source_info = node->source_info();
100 if (source_info.is_valid()) { 96 if (source_info.is_valid()) {
101 source_position_table_builder()->AddPosition(bytecode_offset, 97 source_position_table_builder()->AddPosition(bytecode_offset,
102 source_info.source_position(), 98 source_info.source_position(),
103 source_info.is_statement()); 99 source_info.is_statement());
104 } 100 }
105 } 101 }
106 102
107 namespace {
108
109 OperandScale ScaleForScalableByteOperand(OperandSize operand_size) {
110 STATIC_ASSERT(static_cast<int>(OperandSize::kByte) ==
111 static_cast<int>(OperandScale::kSingle));
112 STATIC_ASSERT(static_cast<int>(OperandSize::kShort) ==
113 static_cast<int>(OperandScale::kDouble));
114 STATIC_ASSERT(static_cast<int>(OperandSize::kQuad) ==
115 static_cast<int>(OperandScale::kQuadruple));
116 return static_cast<OperandScale>(operand_size);
117 }
118
119 OperandScale OperandScaleForScalableSignedByte(uint32_t operand_value) {
120 int32_t signed_operand = static_cast<int32_t>(operand_value);
121 OperandSize bytes_required = Bytecodes::SizeForSignedOperand(signed_operand);
122 return ScaleForScalableByteOperand(bytes_required);
123 }
124
125 OperandScale OperandScaleForScalableUnsignedByte(uint32_t operand_value) {
126 OperandSize bytes_required = Bytecodes::SizeForUnsignedOperand(operand_value);
127 return ScaleForScalableByteOperand(bytes_required);
128 }
129
130 OperandScale GetOperandScale(const BytecodeNode* const node) {
131 const OperandTypeInfo* operand_type_infos =
132 Bytecodes::GetOperandTypeInfos(node->bytecode());
133 OperandScale operand_scale = OperandScale::kSingle;
134 int operand_count = node->operand_count();
135 for (int i = 0; i < operand_count; ++i) {
136 switch (operand_type_infos[i]) {
137 case OperandTypeInfo::kScalableSignedByte: {
138 uint32_t operand = node->operand(i);
139 operand_scale =
140 std::max(operand_scale, OperandScaleForScalableSignedByte(operand));
141 break;
142 }
143 case OperandTypeInfo::kScalableUnsignedByte: {
144 uint32_t operand = node->operand(i);
145 operand_scale = std::max(operand_scale,
146 OperandScaleForScalableUnsignedByte(operand));
147 break;
148 }
149 case OperandTypeInfo::kFixedUnsignedByte:
150 case OperandTypeInfo::kFixedUnsignedShort:
151 break;
152 case OperandTypeInfo::kNone:
153 UNREACHABLE();
154 break;
155 }
156 }
157 return operand_scale;
158 }
159
160 } // namespace
161
162 void BytecodeArrayWriter::EmitBytecode(const BytecodeNode* const node) { 103 void BytecodeArrayWriter::EmitBytecode(const BytecodeNode* const node) {
163 DCHECK_NE(node->bytecode(), Bytecode::kIllegal); 104 DCHECK_NE(node->bytecode(), Bytecode::kIllegal);
164 105
165 uint8_t buffer[kMaxSizeOfPackedBytecode]; 106 Bytecode bytecode = node->bytecode();
166 uint8_t* buffer_limit = buffer; 107 OperandScale operand_scale = node->operand_scale();
167 108
168 OperandScale operand_scale = GetOperandScale(node);
169 if (operand_scale != OperandScale::kSingle) { 109 if (operand_scale != OperandScale::kSingle) {
170 Bytecode prefix = Bytecodes::OperandScaleToPrefixBytecode(operand_scale); 110 Bytecode prefix = Bytecodes::OperandScaleToPrefixBytecode(operand_scale);
171 *buffer_limit++ = Bytecodes::ToByte(prefix); 111 bytecodes()->push_back(Bytecodes::ToByte(prefix));
172 } 112 }
173 113 bytecodes()->push_back(Bytecodes::ToByte(bytecode));
174 Bytecode bytecode = node->bytecode();
175 *buffer_limit++ = Bytecodes::ToByte(bytecode);
176 114
177 const uint32_t* const operands = node->operands(); 115 const uint32_t* const operands = node->operands();
178 const OperandType* operand_types = Bytecodes::GetOperandTypes(bytecode); 116 const int operand_count = node->operand_count();
179 const int operand_count = Bytecodes::NumberOfOperands(bytecode); 117 const OperandSize* operand_sizes =
118 Bytecodes::GetOperandSizes(bytecode, operand_scale);
180 for (int i = 0; i < operand_count; ++i) { 119 for (int i = 0; i < operand_count; ++i) {
181 OperandSize operand_size = 120 switch (operand_sizes[i]) {
182 Bytecodes::SizeOfOperand(operand_types[i], operand_scale);
183 switch (operand_size) {
184 case OperandSize::kNone: 121 case OperandSize::kNone:
185 UNREACHABLE(); 122 UNREACHABLE();
186 break; 123 break;
187 case OperandSize::kByte: 124 case OperandSize::kByte:
188 *buffer_limit++ = static_cast<uint8_t>(operands[i]); 125 bytecodes()->push_back(static_cast<uint8_t>(operands[i]));
189 break; 126 break;
190 case OperandSize::kShort: { 127 case OperandSize::kShort: {
191 WriteUnalignedUInt16(buffer_limit, operands[i]); 128 const uint8_t* raw_operand =
192 buffer_limit += 2; 129 reinterpret_cast<const uint8_t*>(&operands[i]);
130 bytecodes()->push_back(raw_operand[0]);
131 bytecodes()->push_back(raw_operand[1]);
193 break; 132 break;
194 } 133 }
195 case OperandSize::kQuad: { 134 case OperandSize::kQuad: {
196 WriteUnalignedUInt32(buffer_limit, operands[i]); 135 const uint8_t* raw_operand =
197 buffer_limit += 4; 136 reinterpret_cast<const uint8_t*>(&operands[i]);
137 bytecodes()->push_back(raw_operand[0]);
138 bytecodes()->push_back(raw_operand[1]);
139 bytecodes()->push_back(raw_operand[2]);
140 bytecodes()->push_back(raw_operand[3]);
198 break; 141 break;
199 } 142 }
200 } 143 }
201
202 int count = Bytecodes::GetNumberOfRegistersRepresentedBy(operand_types[i]);
203 if (count == 0) {
204 continue;
205 }
206 // NB operand_types is terminated by OperandType::kNone so
207 // operand_types[i + 1] is valid whilst i < operand_count.
208 if (operand_types[i + 1] == OperandType::kRegCount) {
209 count = static_cast<int>(operands[i]);
210 }
211 Register reg = Register::FromOperand(static_cast<int32_t>(operands[i]));
212 max_register_count_ = std::max(max_register_count_, reg.index() + count);
213 } 144 }
214
215 DCHECK_LE(buffer_limit, buffer + sizeof(buffer));
216 bytecodes()->insert(bytecodes()->end(), buffer, buffer_limit);
217 } 145 }
218 146
219 // static 147 // static
220 Bytecode GetJumpWithConstantOperand(Bytecode jump_bytecode) { 148 Bytecode GetJumpWithConstantOperand(Bytecode jump_bytecode) {
221 switch (jump_bytecode) { 149 switch (jump_bytecode) {
222 case Bytecode::kJump: 150 case Bytecode::kJump:
223 return Bytecode::kJumpConstant; 151 return Bytecode::kJumpConstant;
224 case Bytecode::kJumpIfTrue: 152 case Bytecode::kJumpIfTrue:
225 return Bytecode::kJumpIfTrueConstant; 153 return Bytecode::kJumpIfTrueConstant;
226 case Bytecode::kJumpIfFalse: 154 case Bytecode::kJumpIfFalse:
(...skipping 13 matching lines...) Expand all
240 return Bytecode::kIllegal; 168 return Bytecode::kIllegal;
241 } 169 }
242 } 170 }
243 171
244 void BytecodeArrayWriter::PatchJumpWith8BitOperand(size_t jump_location, 172 void BytecodeArrayWriter::PatchJumpWith8BitOperand(size_t jump_location,
245 int delta) { 173 int delta) {
246 Bytecode jump_bytecode = Bytecodes::FromByte(bytecodes()->at(jump_location)); 174 Bytecode jump_bytecode = Bytecodes::FromByte(bytecodes()->at(jump_location));
247 DCHECK(Bytecodes::IsJumpImmediate(jump_bytecode)); 175 DCHECK(Bytecodes::IsJumpImmediate(jump_bytecode));
248 size_t operand_location = jump_location + 1; 176 size_t operand_location = jump_location + 1;
249 DCHECK_EQ(bytecodes()->at(operand_location), k8BitJumpPlaceholder); 177 DCHECK_EQ(bytecodes()->at(operand_location), k8BitJumpPlaceholder);
250 if (Bytecodes::SizeForSignedOperand(delta) == OperandSize::kByte) { 178 if (Bytecodes::ScaleForSignedOperand(delta) == OperandScale::kSingle) {
251 // The jump fits within the range of an Imm operand, so cancel 179 // The jump fits within the range of an Imm8 operand, so cancel
252 // the reservation and jump directly. 180 // the reservation and jump directly.
253 constant_array_builder()->DiscardReservedEntry(OperandSize::kByte); 181 constant_array_builder()->DiscardReservedEntry(OperandSize::kByte);
254 bytecodes()->at(operand_location) = static_cast<uint8_t>(delta); 182 bytecodes()->at(operand_location) = static_cast<uint8_t>(delta);
255 } else { 183 } else {
256 // The jump does not fit within the range of an Imm operand, so 184 // The jump does not fit within the range of an Imm8 operand, so
257 // commit reservation putting the offset into the constant pool, 185 // commit reservation putting the offset into the constant pool,
258 // and update the jump instruction and operand. 186 // and update the jump instruction and operand.
259 size_t entry = constant_array_builder()->CommitReservedEntry( 187 size_t entry = constant_array_builder()->CommitReservedEntry(
260 OperandSize::kByte, Smi::FromInt(delta)); 188 OperandSize::kByte, Smi::FromInt(delta));
261 DCHECK_LE(entry, kMaxUInt32);
262 DCHECK_EQ(Bytecodes::SizeForUnsignedOperand(static_cast<uint32_t>(entry)), 189 DCHECK_EQ(Bytecodes::SizeForUnsignedOperand(static_cast<uint32_t>(entry)),
263 OperandSize::kByte); 190 OperandSize::kByte);
264 jump_bytecode = GetJumpWithConstantOperand(jump_bytecode); 191 jump_bytecode = GetJumpWithConstantOperand(jump_bytecode);
265 bytecodes()->at(jump_location) = Bytecodes::ToByte(jump_bytecode); 192 bytecodes()->at(jump_location) = Bytecodes::ToByte(jump_bytecode);
266 bytecodes()->at(operand_location) = static_cast<uint8_t>(entry); 193 bytecodes()->at(operand_location) = static_cast<uint8_t>(entry);
267 } 194 }
268 } 195 }
269 196
270 void BytecodeArrayWriter::PatchJumpWith16BitOperand(size_t jump_location, 197 void BytecodeArrayWriter::PatchJumpWith16BitOperand(size_t jump_location,
271 int delta) { 198 int delta) {
272 Bytecode jump_bytecode = Bytecodes::FromByte(bytecodes()->at(jump_location)); 199 Bytecode jump_bytecode = Bytecodes::FromByte(bytecodes()->at(jump_location));
273 DCHECK(Bytecodes::IsJumpImmediate(jump_bytecode)); 200 DCHECK(Bytecodes::IsJumpImmediate(jump_bytecode));
274 size_t operand_location = jump_location + 1; 201 size_t operand_location = jump_location + 1;
275 uint8_t operand_bytes[2]; 202 uint8_t operand_bytes[2];
276 if (Bytecodes::SizeForSignedOperand(delta) <= OperandSize::kShort) { 203 if (Bytecodes::ScaleForSignedOperand(delta) <= OperandScale::kDouble) {
204 // The jump fits within the range of an Imm16 operand, so cancel
205 // the reservation and jump directly.
277 constant_array_builder()->DiscardReservedEntry(OperandSize::kShort); 206 constant_array_builder()->DiscardReservedEntry(OperandSize::kShort);
278 WriteUnalignedUInt16(operand_bytes, static_cast<uint16_t>(delta)); 207 WriteUnalignedUInt16(operand_bytes, static_cast<uint16_t>(delta));
279 } else { 208 } else {
209 // The jump does not fit within the range of an Imm16 operand, so
210 // commit reservation putting the offset into the constant pool,
211 // and update the jump instruction and operand.
212 size_t entry = constant_array_builder()->CommitReservedEntry(
213 OperandSize::kShort, Smi::FromInt(delta));
214 DCHECK_EQ(Bytecodes::SizeForUnsignedOperand(static_cast<uint32_t>(entry)),
215 OperandSize::kShort);
280 jump_bytecode = GetJumpWithConstantOperand(jump_bytecode); 216 jump_bytecode = GetJumpWithConstantOperand(jump_bytecode);
281 bytecodes()->at(jump_location) = Bytecodes::ToByte(jump_bytecode); 217 bytecodes()->at(jump_location) = Bytecodes::ToByte(jump_bytecode);
282 size_t entry = constant_array_builder()->CommitReservedEntry(
283 OperandSize::kShort, Smi::FromInt(delta));
284 WriteUnalignedUInt16(operand_bytes, static_cast<uint16_t>(entry)); 218 WriteUnalignedUInt16(operand_bytes, static_cast<uint16_t>(entry));
285 } 219 }
286 DCHECK(bytecodes()->at(operand_location) == k8BitJumpPlaceholder && 220 DCHECK(bytecodes()->at(operand_location) == k8BitJumpPlaceholder &&
287 bytecodes()->at(operand_location + 1) == k8BitJumpPlaceholder); 221 bytecodes()->at(operand_location + 1) == k8BitJumpPlaceholder);
288 bytecodes()->at(operand_location++) = operand_bytes[0]; 222 bytecodes()->at(operand_location++) = operand_bytes[0];
289 bytecodes()->at(operand_location) = operand_bytes[1]; 223 bytecodes()->at(operand_location) = operand_bytes[1];
290 } 224 }
291 225
292 void BytecodeArrayWriter::PatchJumpWith32BitOperand(size_t jump_location, 226 void BytecodeArrayWriter::PatchJumpWith32BitOperand(size_t jump_location,
293 int delta) { 227 int delta) {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
344 DCHECK_EQ(0, node->operand(0)); 278 DCHECK_EQ(0, node->operand(0));
345 279
346 size_t current_offset = bytecodes()->size(); 280 size_t current_offset = bytecodes()->size();
347 281
348 if (label->is_bound()) { 282 if (label->is_bound()) {
349 CHECK_GE(current_offset, label->offset()); 283 CHECK_GE(current_offset, label->offset());
350 CHECK_LE(current_offset, static_cast<size_t>(kMaxInt)); 284 CHECK_LE(current_offset, static_cast<size_t>(kMaxInt));
351 // Label has been bound already so this is a backwards jump. 285 // Label has been bound already so this is a backwards jump.
352 size_t abs_delta = current_offset - label->offset(); 286 size_t abs_delta = current_offset - label->offset();
353 int delta = -static_cast<int>(abs_delta); 287 int delta = -static_cast<int>(abs_delta);
354 OperandSize operand_size = Bytecodes::SizeForSignedOperand(delta); 288 OperandScale operand_scale = Bytecodes::ScaleForSignedOperand(delta);
355 if (operand_size > OperandSize::kByte) { 289 if (operand_scale > OperandScale::kSingle) {
356 // Adjust for scaling byte prefix for wide jump offset. 290 // Adjust for scaling byte prefix for wide jump offset.
357 DCHECK_LE(delta, 0); 291 DCHECK_LE(delta, 0);
358 delta -= 1; 292 delta -= 1;
359 } 293 }
360 DCHECK_EQ(Bytecode::kJumpLoop, node->bytecode()); 294 DCHECK_EQ(Bytecode::kJumpLoop, node->bytecode());
361 node->set_bytecode(node->bytecode(), delta, node->operand(1)); 295 node->set_bytecode(node->bytecode(), delta, node->operand(1));
362 } else { 296 } else {
363 // The label has not yet been bound so this is a forward reference 297 // The label has not yet been bound so this is a forward reference
364 // that will be patched when the label is bound. We create a 298 // that will be patched when the label is bound. We create a
365 // reservation in the constant pool so the jump can be patched 299 // reservation in the constant pool so the jump can be patched
(...skipping 19 matching lines...) Expand all
385 node->set_bytecode(node->bytecode(), k32BitJumpPlaceholder); 319 node->set_bytecode(node->bytecode(), k32BitJumpPlaceholder);
386 break; 320 break;
387 } 321 }
388 } 322 }
389 EmitBytecode(node); 323 EmitBytecode(node);
390 } 324 }
391 325
392 } // namespace interpreter 326 } // namespace interpreter
393 } // namespace internal 327 } // namespace internal
394 } // namespace v8 328 } // namespace v8
OLDNEW
« no previous file with comments | « src/interpreter/bytecode-array-writer.h ('k') | src/interpreter/bytecode-dead-code-optimizer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698