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/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/constant-array-builder.h" | 9 #include "src/interpreter/constant-array-builder.h" |
10 #include "src/log.h" | 10 #include "src/log.h" |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
98 const BytecodeNode* const node) { | 98 const BytecodeNode* const node) { |
99 int bytecode_offset = static_cast<int>(bytecodes()->size()); | 99 int bytecode_offset = static_cast<int>(bytecodes()->size()); |
100 const BytecodeSourceInfo& source_info = node->source_info(); | 100 const BytecodeSourceInfo& source_info = node->source_info(); |
101 if (source_info.is_valid()) { | 101 if (source_info.is_valid()) { |
102 source_position_table_builder()->AddPosition(bytecode_offset, | 102 source_position_table_builder()->AddPosition(bytecode_offset, |
103 source_info.source_position(), | 103 source_info.source_position(), |
104 source_info.is_statement()); | 104 source_info.is_statement()); |
105 } | 105 } |
106 } | 106 } |
107 | 107 |
| 108 namespace { |
| 109 |
| 110 OperandScale ScaleForScalableByteOperand(OperandSize operand_size) { |
| 111 STATIC_ASSERT(static_cast<int>(OperandSize::kByte) == |
| 112 static_cast<int>(OperandScale::kSingle)); |
| 113 STATIC_ASSERT(static_cast<int>(OperandSize::kShort) == |
| 114 static_cast<int>(OperandScale::kDouble)); |
| 115 STATIC_ASSERT(static_cast<int>(OperandSize::kQuad) == |
| 116 static_cast<int>(OperandScale::kQuadruple)); |
| 117 return static_cast<OperandScale>(operand_size); |
| 118 } |
| 119 |
| 120 OperandScale OperandScaleForScalableSignedByte(uint32_t operand_value) { |
| 121 int32_t signed_operand = static_cast<int32_t>(operand_value); |
| 122 OperandSize bytes_required = Bytecodes::SizeForSignedOperand(signed_operand); |
| 123 return ScaleForScalableByteOperand(bytes_required); |
| 124 } |
| 125 |
| 126 OperandScale OperandScaleForScalableUnsignedByte(uint32_t operand_value) { |
| 127 OperandSize bytes_required = Bytecodes::SizeForUnsignedOperand(operand_value); |
| 128 return ScaleForScalableByteOperand(bytes_required); |
| 129 } |
| 130 |
| 131 OperandScale GetOperandScale(const BytecodeNode* const node) { |
| 132 const OperandTypeInfo* operand_type_infos = |
| 133 Bytecodes::GetOperandTypeInfos(node->bytecode()); |
| 134 OperandScale operand_scale = OperandScale::kSingle; |
| 135 for (int i = 0; i < node->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 |
108 void BytecodeArrayWriter::EmitBytecode(const BytecodeNode* const node) { | 162 void BytecodeArrayWriter::EmitBytecode(const BytecodeNode* const node) { |
109 DCHECK_NE(node->bytecode(), Bytecode::kIllegal); | 163 DCHECK_NE(node->bytecode(), Bytecode::kIllegal); |
110 | 164 |
111 OperandScale operand_scale = node->operand_scale(); | 165 OperandScale operand_scale = GetOperandScale(node); |
112 if (operand_scale != OperandScale::kSingle) { | 166 if (operand_scale != OperandScale::kSingle) { |
113 Bytecode prefix = Bytecodes::OperandScaleToPrefixBytecode(operand_scale); | 167 Bytecode prefix = Bytecodes::OperandScaleToPrefixBytecode(operand_scale); |
114 bytecodes()->push_back(Bytecodes::ToByte(prefix)); | 168 bytecodes()->push_back(Bytecodes::ToByte(prefix)); |
115 } | 169 } |
116 | 170 |
117 Bytecode bytecode = node->bytecode(); | 171 Bytecode bytecode = node->bytecode(); |
118 bytecodes()->push_back(Bytecodes::ToByte(bytecode)); | 172 bytecodes()->push_back(Bytecodes::ToByte(bytecode)); |
119 | 173 |
120 int register_operand_bitmap = Bytecodes::GetRegisterOperandBitmap(bytecode); | 174 int register_operand_bitmap = Bytecodes::GetRegisterOperandBitmap(bytecode); |
121 const uint32_t* const operands = node->operands(); | 175 const uint32_t* const operands = node->operands(); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
153 count = static_cast<int>(operands[i + 1]); | 207 count = static_cast<int>(operands[i + 1]); |
154 } else { | 208 } else { |
155 count = Bytecodes::GetNumberOfRegistersRepresentedBy(operand_type); | 209 count = Bytecodes::GetNumberOfRegistersRepresentedBy(operand_type); |
156 } | 210 } |
157 Register reg = Register::FromOperand(static_cast<int32_t>(operands[i])); | 211 Register reg = Register::FromOperand(static_cast<int32_t>(operands[i])); |
158 max_register_count_ = std::max(max_register_count_, reg.index() + count); | 212 max_register_count_ = std::max(max_register_count_, reg.index() + count); |
159 } | 213 } |
160 } | 214 } |
161 } | 215 } |
162 | 216 |
163 // TODO(rmcilroy): This is the same as SignedOperand in BytecodeArrayBuilder. | |
164 // Once we move the scalable operand processing here remove the SignedOperand | |
165 // in BytecodeArrayBuilder. | |
166 static uint32_t SignedOperand(int value, OperandSize size) { | |
167 switch (size) { | |
168 case OperandSize::kByte: | |
169 return static_cast<uint8_t>(value & 0xff); | |
170 case OperandSize::kShort: | |
171 return static_cast<uint16_t>(value & 0xffff); | |
172 case OperandSize::kQuad: | |
173 return static_cast<uint32_t>(value); | |
174 case OperandSize::kNone: | |
175 UNREACHABLE(); | |
176 } | |
177 return 0; | |
178 } | |
179 | |
180 // static | 217 // static |
181 Bytecode GetJumpWithConstantOperand(Bytecode jump_bytecode) { | 218 Bytecode GetJumpWithConstantOperand(Bytecode jump_bytecode) { |
182 switch (jump_bytecode) { | 219 switch (jump_bytecode) { |
183 case Bytecode::kJump: | 220 case Bytecode::kJump: |
184 return Bytecode::kJumpConstant; | 221 return Bytecode::kJumpConstant; |
185 case Bytecode::kJumpIfTrue: | 222 case Bytecode::kJumpIfTrue: |
186 return Bytecode::kJumpIfTrueConstant; | 223 return Bytecode::kJumpIfTrueConstant; |
187 case Bytecode::kJumpIfFalse: | 224 case Bytecode::kJumpIfFalse: |
188 return Bytecode::kJumpIfFalseConstant; | 225 return Bytecode::kJumpIfFalseConstant; |
189 case Bytecode::kJumpIfToBooleanTrue: | 226 case Bytecode::kJumpIfToBooleanTrue: |
(...skipping 10 matching lines...) Expand all Loading... |
200 UNREACHABLE(); | 237 UNREACHABLE(); |
201 return Bytecode::kIllegal; | 238 return Bytecode::kIllegal; |
202 } | 239 } |
203 } | 240 } |
204 | 241 |
205 void BytecodeArrayWriter::PatchJumpWith8BitOperand(size_t jump_location, | 242 void BytecodeArrayWriter::PatchJumpWith8BitOperand(size_t jump_location, |
206 int delta) { | 243 int delta) { |
207 Bytecode jump_bytecode = Bytecodes::FromByte(bytecodes()->at(jump_location)); | 244 Bytecode jump_bytecode = Bytecodes::FromByte(bytecodes()->at(jump_location)); |
208 DCHECK(Bytecodes::IsJumpImmediate(jump_bytecode)); | 245 DCHECK(Bytecodes::IsJumpImmediate(jump_bytecode)); |
209 size_t operand_location = jump_location + 1; | 246 size_t operand_location = jump_location + 1; |
210 DCHECK_EQ(bytecodes()->at(operand_location), 0); | 247 DCHECK_EQ(bytecodes()->at(operand_location), k8BitJumpPlaceholder); |
211 if (Bytecodes::SizeForSignedOperand(delta) == OperandSize::kByte) { | 248 if (Bytecodes::SizeForSignedOperand(delta) == OperandSize::kByte) { |
212 // The jump fits within the range of an Imm operand, so cancel | 249 // The jump fits within the range of an Imm operand, so cancel |
213 // the reservation and jump directly. | 250 // the reservation and jump directly. |
214 constant_array_builder()->DiscardReservedEntry(OperandSize::kByte); | 251 constant_array_builder()->DiscardReservedEntry(OperandSize::kByte); |
215 bytecodes()->at(operand_location) = static_cast<uint8_t>(delta); | 252 bytecodes()->at(operand_location) = static_cast<uint8_t>(delta); |
216 } else { | 253 } else { |
217 // The jump does not fit within the range of an Imm operand, so | 254 // The jump does not fit within the range of an Imm operand, so |
218 // commit reservation putting the offset into the constant pool, | 255 // commit reservation putting the offset into the constant pool, |
219 // and update the jump instruction and operand. | 256 // and update the jump instruction and operand. |
220 size_t entry = constant_array_builder()->CommitReservedEntry( | 257 size_t entry = constant_array_builder()->CommitReservedEntry( |
221 OperandSize::kByte, handle(Smi::FromInt(delta), isolate())); | 258 OperandSize::kByte, handle(Smi::FromInt(delta), isolate())); |
222 DCHECK(Bytecodes::SizeForUnsignedOperand(entry) == OperandSize::kByte); | 259 DCHECK_LE(entry, kMaxUInt32); |
| 260 DCHECK_EQ(Bytecodes::SizeForUnsignedOperand(static_cast<uint32_t>(entry)), |
| 261 OperandSize::kByte); |
223 jump_bytecode = GetJumpWithConstantOperand(jump_bytecode); | 262 jump_bytecode = GetJumpWithConstantOperand(jump_bytecode); |
224 bytecodes()->at(jump_location) = Bytecodes::ToByte(jump_bytecode); | 263 bytecodes()->at(jump_location) = Bytecodes::ToByte(jump_bytecode); |
225 bytecodes()->at(operand_location) = static_cast<uint8_t>(entry); | 264 bytecodes()->at(operand_location) = static_cast<uint8_t>(entry); |
226 } | 265 } |
227 } | 266 } |
228 | 267 |
229 void BytecodeArrayWriter::PatchJumpWith16BitOperand(size_t jump_location, | 268 void BytecodeArrayWriter::PatchJumpWith16BitOperand(size_t jump_location, |
230 int delta) { | 269 int delta) { |
231 Bytecode jump_bytecode = Bytecodes::FromByte(bytecodes()->at(jump_location)); | 270 Bytecode jump_bytecode = Bytecodes::FromByte(bytecodes()->at(jump_location)); |
232 DCHECK(Bytecodes::IsJumpImmediate(jump_bytecode)); | 271 DCHECK(Bytecodes::IsJumpImmediate(jump_bytecode)); |
233 size_t operand_location = jump_location + 1; | 272 size_t operand_location = jump_location + 1; |
234 uint8_t operand_bytes[2]; | 273 uint8_t operand_bytes[2]; |
235 if (Bytecodes::SizeForSignedOperand(delta) <= OperandSize::kShort) { | 274 if (Bytecodes::SizeForSignedOperand(delta) <= OperandSize::kShort) { |
236 constant_array_builder()->DiscardReservedEntry(OperandSize::kShort); | 275 constant_array_builder()->DiscardReservedEntry(OperandSize::kShort); |
237 WriteUnalignedUInt16(operand_bytes, static_cast<uint16_t>(delta)); | 276 WriteUnalignedUInt16(operand_bytes, static_cast<uint16_t>(delta)); |
238 } else { | 277 } else { |
239 jump_bytecode = GetJumpWithConstantOperand(jump_bytecode); | 278 jump_bytecode = GetJumpWithConstantOperand(jump_bytecode); |
240 bytecodes()->at(jump_location) = Bytecodes::ToByte(jump_bytecode); | 279 bytecodes()->at(jump_location) = Bytecodes::ToByte(jump_bytecode); |
241 size_t entry = constant_array_builder()->CommitReservedEntry( | 280 size_t entry = constant_array_builder()->CommitReservedEntry( |
242 OperandSize::kShort, handle(Smi::FromInt(delta), isolate())); | 281 OperandSize::kShort, handle(Smi::FromInt(delta), isolate())); |
243 WriteUnalignedUInt16(operand_bytes, static_cast<uint16_t>(entry)); | 282 WriteUnalignedUInt16(operand_bytes, static_cast<uint16_t>(entry)); |
244 } | 283 } |
245 DCHECK(bytecodes()->at(operand_location) == 0 && | 284 DCHECK(bytecodes()->at(operand_location) == k8BitJumpPlaceholder && |
246 bytecodes()->at(operand_location + 1) == 0); | 285 bytecodes()->at(operand_location + 1) == k8BitJumpPlaceholder); |
247 bytecodes()->at(operand_location++) = operand_bytes[0]; | 286 bytecodes()->at(operand_location++) = operand_bytes[0]; |
248 bytecodes()->at(operand_location) = operand_bytes[1]; | 287 bytecodes()->at(operand_location) = operand_bytes[1]; |
249 } | 288 } |
250 | 289 |
251 void BytecodeArrayWriter::PatchJumpWith32BitOperand(size_t jump_location, | 290 void BytecodeArrayWriter::PatchJumpWith32BitOperand(size_t jump_location, |
252 int delta) { | 291 int delta) { |
253 DCHECK(Bytecodes::IsJumpImmediate( | 292 DCHECK(Bytecodes::IsJumpImmediate( |
254 Bytecodes::FromByte(bytecodes()->at(jump_location)))); | 293 Bytecodes::FromByte(bytecodes()->at(jump_location)))); |
255 constant_array_builder()->DiscardReservedEntry(OperandSize::kQuad); | 294 constant_array_builder()->DiscardReservedEntry(OperandSize::kQuad); |
256 uint8_t operand_bytes[4]; | 295 uint8_t operand_bytes[4]; |
257 WriteUnalignedUInt32(operand_bytes, static_cast<uint32_t>(delta)); | 296 WriteUnalignedUInt32(operand_bytes, static_cast<uint32_t>(delta)); |
258 size_t operand_location = jump_location + 1; | 297 size_t operand_location = jump_location + 1; |
259 DCHECK(bytecodes()->at(operand_location) == 0 && | 298 DCHECK(bytecodes()->at(operand_location) == k8BitJumpPlaceholder && |
260 bytecodes()->at(operand_location + 1) == 0 && | 299 bytecodes()->at(operand_location + 1) == k8BitJumpPlaceholder && |
261 bytecodes()->at(operand_location + 2) == 0 && | 300 bytecodes()->at(operand_location + 2) == k8BitJumpPlaceholder && |
262 bytecodes()->at(operand_location + 3) == 0); | 301 bytecodes()->at(operand_location + 3) == k8BitJumpPlaceholder); |
263 bytecodes()->at(operand_location++) = operand_bytes[0]; | 302 bytecodes()->at(operand_location++) = operand_bytes[0]; |
264 bytecodes()->at(operand_location++) = operand_bytes[1]; | 303 bytecodes()->at(operand_location++) = operand_bytes[1]; |
265 bytecodes()->at(operand_location++) = operand_bytes[2]; | 304 bytecodes()->at(operand_location++) = operand_bytes[2]; |
266 bytecodes()->at(operand_location) = operand_bytes[3]; | 305 bytecodes()->at(operand_location) = operand_bytes[3]; |
267 } | 306 } |
268 | 307 |
269 void BytecodeArrayWriter::PatchJump(size_t jump_target, size_t jump_location) { | 308 void BytecodeArrayWriter::PatchJump(size_t jump_target, size_t jump_location) { |
270 Bytecode jump_bytecode = Bytecodes::FromByte(bytecodes()->at(jump_location)); | 309 Bytecode jump_bytecode = Bytecodes::FromByte(bytecodes()->at(jump_location)); |
271 int delta = static_cast<int>(jump_target - jump_location); | 310 int delta = static_cast<int>(jump_target - jump_location); |
272 int prefix_offset = 0; | 311 int prefix_offset = 0; |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
309 CHECK_LE(current_offset, static_cast<size_t>(kMaxInt)); | 348 CHECK_LE(current_offset, static_cast<size_t>(kMaxInt)); |
310 // Label has been bound already so this is a backwards jump. | 349 // Label has been bound already so this is a backwards jump. |
311 size_t abs_delta = current_offset - label->offset(); | 350 size_t abs_delta = current_offset - label->offset(); |
312 int delta = -static_cast<int>(abs_delta); | 351 int delta = -static_cast<int>(abs_delta); |
313 OperandSize operand_size = Bytecodes::SizeForSignedOperand(delta); | 352 OperandSize operand_size = Bytecodes::SizeForSignedOperand(delta); |
314 if (operand_size > OperandSize::kByte) { | 353 if (operand_size > OperandSize::kByte) { |
315 // Adjust for scaling byte prefix for wide jump offset. | 354 // Adjust for scaling byte prefix for wide jump offset. |
316 DCHECK_LE(delta, 0); | 355 DCHECK_LE(delta, 0); |
317 delta -= 1; | 356 delta -= 1; |
318 } | 357 } |
319 node->set_bytecode(node->bytecode(), SignedOperand(delta, operand_size), | 358 node->set_bytecode(node->bytecode(), delta); |
320 Bytecodes::OperandSizesToScale(operand_size)); | |
321 } else { | 359 } else { |
322 // The label has not yet been bound so this is a forward reference | 360 // The label has not yet been bound so this is a forward reference |
323 // that will be patched when the label is bound. We create a | 361 // that will be patched when the label is bound. We create a |
324 // reservation in the constant pool so the jump can be patched | 362 // reservation in the constant pool so the jump can be patched |
325 // when the label is bound. The reservation means the maximum size | 363 // when the label is bound. The reservation means the maximum size |
326 // of the operand for the constant is known and the jump can | 364 // of the operand for the constant is known and the jump can |
327 // be emitted into the bytecode stream with space for the operand. | 365 // be emitted into the bytecode stream with space for the operand. |
328 unbound_jumps_++; | 366 unbound_jumps_++; |
329 label->set_referrer(current_offset); | 367 label->set_referrer(current_offset); |
330 OperandSize reserved_operand_size = | 368 OperandSize reserved_operand_size = |
331 constant_array_builder()->CreateReservedEntry(); | 369 constant_array_builder()->CreateReservedEntry(); |
332 OperandScale operand_scale = | 370 switch (reserved_operand_size) { |
333 Bytecodes::OperandSizesToScale(reserved_operand_size); | 371 case OperandSize::kNone: |
334 node->set_bytecode(node->bytecode(), 0, operand_scale); | 372 UNREACHABLE(); |
| 373 break; |
| 374 case OperandSize::kByte: |
| 375 node->set_bytecode(node->bytecode(), k8BitJumpPlaceholder); |
| 376 break; |
| 377 case OperandSize::kShort: |
| 378 node->set_bytecode(node->bytecode(), k16BitJumpPlaceholder); |
| 379 break; |
| 380 case OperandSize::kQuad: |
| 381 node->set_bytecode(node->bytecode(), k32BitJumpPlaceholder); |
| 382 break; |
| 383 } |
335 } | 384 } |
336 EmitBytecode(node); | 385 EmitBytecode(node); |
337 } | 386 } |
338 | 387 |
339 } // namespace interpreter | 388 } // namespace interpreter |
340 } // namespace internal | 389 } // namespace internal |
341 } // namespace v8 | 390 } // namespace v8 |
OLD | NEW |