blob: c757557a0d750e97fa3ef9439679e09d280e1766 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// Copyright 2014 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
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005#include "src/compiler/common-operator.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006#include "src/compiler/graph.h"
7#include "src/compiler/instruction.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008#include "src/compiler/schedule.h"
9#include "src/compiler/state-values-utils.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010
11namespace v8 {
12namespace internal {
13namespace compiler {
14
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015
16FlagsCondition CommuteFlagsCondition(FlagsCondition condition) {
17 switch (condition) {
18 case kSignedLessThan:
19 return kSignedGreaterThan;
20 case kSignedGreaterThanOrEqual:
21 return kSignedLessThanOrEqual;
22 case kSignedLessThanOrEqual:
23 return kSignedGreaterThanOrEqual;
24 case kSignedGreaterThan:
25 return kSignedLessThan;
26 case kUnsignedLessThan:
27 return kUnsignedGreaterThan;
28 case kUnsignedGreaterThanOrEqual:
29 return kUnsignedLessThanOrEqual;
30 case kUnsignedLessThanOrEqual:
31 return kUnsignedGreaterThanOrEqual;
32 case kUnsignedGreaterThan:
33 return kUnsignedLessThan;
34 case kFloatLessThanOrUnordered:
35 return kFloatGreaterThanOrUnordered;
36 case kFloatGreaterThanOrEqual:
37 return kFloatLessThanOrEqual;
38 case kFloatLessThanOrEqual:
39 return kFloatGreaterThanOrEqual;
40 case kFloatGreaterThanOrUnordered:
41 return kFloatLessThanOrUnordered;
42 case kFloatLessThan:
43 return kFloatGreaterThan;
44 case kFloatGreaterThanOrEqualOrUnordered:
45 return kFloatLessThanOrEqualOrUnordered;
46 case kFloatLessThanOrEqualOrUnordered:
47 return kFloatGreaterThanOrEqualOrUnordered;
48 case kFloatGreaterThan:
49 return kFloatLessThan;
50 case kEqual:
51 case kNotEqual:
52 case kOverflow:
53 case kNotOverflow:
54 case kUnorderedEqual:
55 case kUnorderedNotEqual:
56 return condition;
57 }
58 UNREACHABLE();
59 return condition;
60}
61
62
63void InstructionOperand::Print(const RegisterConfiguration* config) const {
64 OFStream os(stdout);
65 PrintableInstructionOperand wrapper;
66 wrapper.register_configuration_ = config;
67 wrapper.op_ = *this;
68 os << wrapper << std::endl;
69}
70
71
72void InstructionOperand::Print() const {
73 const RegisterConfiguration* config =
74 RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN);
75 Print(config);
76}
77
78
Emily Bernierd0a1eb72015-03-24 16:35:39 -040079std::ostream& operator<<(std::ostream& os,
80 const PrintableInstructionOperand& printable) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000081 const InstructionOperand& op = printable.op_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040082 const RegisterConfiguration* conf = printable.register_configuration_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000083 switch (op.kind()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000084 case InstructionOperand::UNALLOCATED: {
85 const UnallocatedOperand* unalloc = UnallocatedOperand::cast(&op);
86 os << "v" << unalloc->virtual_register();
87 if (unalloc->basic_policy() == UnallocatedOperand::FIXED_SLOT) {
88 return os << "(=" << unalloc->fixed_slot_index() << "S)";
89 }
90 switch (unalloc->extended_policy()) {
91 case UnallocatedOperand::NONE:
92 return os;
93 case UnallocatedOperand::FIXED_REGISTER:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000094 return os << "(="
95 << conf->GetGeneralRegisterName(
96 unalloc->fixed_register_index())
97 << ")";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000098 case UnallocatedOperand::FIXED_DOUBLE_REGISTER:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000099 return os << "(="
100 << conf->GetDoubleRegisterName(
101 unalloc->fixed_register_index())
102 << ")";
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000103 case UnallocatedOperand::MUST_HAVE_REGISTER:
104 return os << "(R)";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000105 case UnallocatedOperand::MUST_HAVE_SLOT:
106 return os << "(S)";
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000107 case UnallocatedOperand::SAME_AS_FIRST_INPUT:
108 return os << "(1)";
109 case UnallocatedOperand::ANY:
110 return os << "(-)";
111 }
112 }
113 case InstructionOperand::CONSTANT:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000114 return os << "[constant:" << ConstantOperand::cast(op).virtual_register()
115 << "]";
116 case InstructionOperand::IMMEDIATE: {
Ben Murdochda12d292016-06-02 14:46:10 +0100117 ImmediateOperand imm = ImmediateOperand::cast(op);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000118 switch (imm.type()) {
119 case ImmediateOperand::INLINE:
120 return os << "#" << imm.inline_value();
121 case ImmediateOperand::INDEXED:
122 return os << "[immediate:" << imm.indexed_value() << "]";
123 }
124 }
125 case InstructionOperand::EXPLICIT:
126 case InstructionOperand::ALLOCATED: {
Ben Murdochda12d292016-06-02 14:46:10 +0100127 LocationOperand allocated = LocationOperand::cast(op);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000128 if (op.IsStackSlot()) {
129 os << "[stack:" << LocationOperand::cast(op).index();
130 } else if (op.IsDoubleStackSlot()) {
131 os << "[double_stack:" << LocationOperand::cast(op).index();
132 } else if (op.IsRegister()) {
133 os << "[" << LocationOperand::cast(op).GetRegister().ToString() << "|R";
134 } else {
135 DCHECK(op.IsDoubleRegister());
136 os << "[" << LocationOperand::cast(op).GetDoubleRegister().ToString()
137 << "|R";
138 }
139 if (allocated.IsExplicit()) {
140 os << "|E";
141 }
142 switch (allocated.representation()) {
143 case MachineRepresentation::kNone:
144 os << "|-";
145 break;
146 case MachineRepresentation::kBit:
147 os << "|b";
148 break;
149 case MachineRepresentation::kWord8:
150 os << "|w8";
151 break;
152 case MachineRepresentation::kWord16:
153 os << "|w16";
154 break;
155 case MachineRepresentation::kWord32:
156 os << "|w32";
157 break;
158 case MachineRepresentation::kWord64:
159 os << "|w64";
160 break;
161 case MachineRepresentation::kFloat32:
162 os << "|f32";
163 break;
164 case MachineRepresentation::kFloat64:
165 os << "|f64";
166 break;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100167 case MachineRepresentation::kSimd128:
168 os << "|s128";
169 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000170 case MachineRepresentation::kTagged:
171 os << "|t";
172 break;
173 }
174 return os << "]";
175 }
176 case InstructionOperand::INVALID:
177 return os << "(x)";
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000178 }
179 UNREACHABLE();
180 return os;
181}
182
183
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000184void MoveOperands::Print(const RegisterConfiguration* config) const {
185 OFStream os(stdout);
186 PrintableInstructionOperand wrapper;
187 wrapper.register_configuration_ = config;
188 wrapper.op_ = destination();
189 os << wrapper << " = ";
190 wrapper.op_ = source();
191 os << wrapper << std::endl;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000192}
193
194
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000195void MoveOperands::Print() const {
196 const RegisterConfiguration* config =
197 RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN);
198 Print(config);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000199}
200
201
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400202std::ostream& operator<<(std::ostream& os,
203 const PrintableMoveOperands& printable) {
204 const MoveOperands& mo = *printable.move_operands_;
205 PrintableInstructionOperand printable_op = {printable.register_configuration_,
206 mo.destination()};
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400207 os << printable_op;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000208 if (!mo.source().Equals(mo.destination())) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400209 printable_op.op_ = mo.source();
210 os << " = " << printable_op;
211 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000212 return os << ";";
213}
214
215
216bool ParallelMove::IsRedundant() const {
Ben Murdochda12d292016-06-02 14:46:10 +0100217 for (MoveOperands* move : *this) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000218 if (!move->IsRedundant()) return false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000219 }
220 return true;
221}
222
223
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000224MoveOperands* ParallelMove::PrepareInsertAfter(MoveOperands* move) const {
225 MoveOperands* replacement = nullptr;
226 MoveOperands* to_eliminate = nullptr;
Ben Murdochda12d292016-06-02 14:46:10 +0100227 for (MoveOperands* curr : *this) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000228 if (curr->IsEliminated()) continue;
229 if (curr->destination().EqualsCanonicalized(move->source())) {
230 DCHECK(!replacement);
231 replacement = curr;
232 if (to_eliminate != nullptr) break;
233 } else if (curr->destination().EqualsCanonicalized(move->destination())) {
234 DCHECK(!to_eliminate);
235 to_eliminate = curr;
236 if (replacement != nullptr) break;
237 }
238 }
239 DCHECK_IMPLIES(replacement == to_eliminate, replacement == nullptr);
240 if (replacement != nullptr) move->set_source(replacement->source());
241 return to_eliminate;
242}
243
244
245ExplicitOperand::ExplicitOperand(LocationKind kind, MachineRepresentation rep,
246 int index)
247 : LocationOperand(EXPLICIT, kind, rep, index) {
248 DCHECK_IMPLIES(kind == REGISTER && !IsFloatingPoint(rep),
249 Register::from_code(index).IsAllocatable());
250 DCHECK_IMPLIES(kind == REGISTER && IsFloatingPoint(rep),
251 DoubleRegister::from_code(index).IsAllocatable());
252}
253
254
255Instruction::Instruction(InstructionCode opcode)
256 : opcode_(opcode),
257 bit_field_(OutputCountField::encode(0) | InputCountField::encode(0) |
258 TempCountField::encode(0) | IsCallField::encode(false)),
259 reference_map_(nullptr) {
260 parallel_moves_[0] = nullptr;
261 parallel_moves_[1] = nullptr;
262}
263
264
265Instruction::Instruction(InstructionCode opcode, size_t output_count,
266 InstructionOperand* outputs, size_t input_count,
267 InstructionOperand* inputs, size_t temp_count,
268 InstructionOperand* temps)
269 : opcode_(opcode),
270 bit_field_(OutputCountField::encode(output_count) |
271 InputCountField::encode(input_count) |
272 TempCountField::encode(temp_count) |
273 IsCallField::encode(false)),
274 reference_map_(nullptr) {
275 parallel_moves_[0] = nullptr;
276 parallel_moves_[1] = nullptr;
277 size_t offset = 0;
278 for (size_t i = 0; i < output_count; ++i) {
279 DCHECK(!outputs[i].IsInvalid());
280 operands_[offset++] = outputs[i];
281 }
282 for (size_t i = 0; i < input_count; ++i) {
283 DCHECK(!inputs[i].IsInvalid());
284 operands_[offset++] = inputs[i];
285 }
286 for (size_t i = 0; i < temp_count; ++i) {
287 DCHECK(!temps[i].IsInvalid());
288 operands_[offset++] = temps[i];
289 }
290}
291
292
293bool Instruction::AreMovesRedundant() const {
294 for (int i = Instruction::FIRST_GAP_POSITION;
295 i <= Instruction::LAST_GAP_POSITION; i++) {
296 if (parallel_moves_[i] != nullptr && !parallel_moves_[i]->IsRedundant()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400297 return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000298 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400299 }
300 return true;
301}
302
303
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000304void Instruction::Print(const RegisterConfiguration* config) const {
305 OFStream os(stdout);
306 PrintableInstruction wrapper;
307 wrapper.instr_ = this;
308 wrapper.register_configuration_ = config;
309 os << wrapper << std::endl;
310}
311
312
313void Instruction::Print() const {
314 const RegisterConfiguration* config =
315 RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN);
316 Print(config);
317}
318
319
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400320std::ostream& operator<<(std::ostream& os,
321 const PrintableParallelMove& printable) {
322 const ParallelMove& pm = *printable.parallel_move_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000323 bool first = true;
Ben Murdochda12d292016-06-02 14:46:10 +0100324 for (MoveOperands* move : pm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000325 if (move->IsEliminated()) continue;
326 if (!first) os << " ";
327 first = false;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400328 PrintableMoveOperands pmo = {printable.register_configuration_, move};
329 os << pmo;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000330 }
331 return os;
332}
333
334
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000335void ReferenceMap::RecordReference(const AllocatedOperand& op) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000336 // Do not record arguments as pointers.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000337 if (op.IsStackSlot() && LocationOperand::cast(op).index() < 0) return;
338 DCHECK(!op.IsDoubleRegister() && !op.IsDoubleStackSlot());
339 reference_operands_.push_back(op);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000340}
341
342
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000343std::ostream& operator<<(std::ostream& os, const ReferenceMap& pm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000344 os << "{";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000345 bool first = true;
346 PrintableInstructionOperand poi = {
347 RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN),
348 InstructionOperand()};
Ben Murdochda12d292016-06-02 14:46:10 +0100349 for (const InstructionOperand& op : pm.reference_operands_) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000350 if (!first) {
351 os << ";";
352 } else {
353 first = false;
354 }
355 poi.op_ = op;
356 os << poi;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000357 }
358 return os << "}";
359}
360
361
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400362std::ostream& operator<<(std::ostream& os, const ArchOpcode& ao) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000363 switch (ao) {
364#define CASE(Name) \
365 case k##Name: \
366 return os << #Name;
367 ARCH_OPCODE_LIST(CASE)
368#undef CASE
369 }
370 UNREACHABLE();
371 return os;
372}
373
374
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400375std::ostream& operator<<(std::ostream& os, const AddressingMode& am) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000376 switch (am) {
377 case kMode_None:
378 return os;
379#define CASE(Name) \
380 case kMode_##Name: \
381 return os << #Name;
382 TARGET_ADDRESSING_MODE_LIST(CASE)
383#undef CASE
384 }
385 UNREACHABLE();
386 return os;
387}
388
389
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400390std::ostream& operator<<(std::ostream& os, const FlagsMode& fm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000391 switch (fm) {
392 case kFlags_none:
393 return os;
394 case kFlags_branch:
395 return os << "branch";
Ben Murdochda12d292016-06-02 14:46:10 +0100396 case kFlags_deoptimize:
397 return os << "deoptimize";
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000398 case kFlags_set:
399 return os << "set";
400 }
401 UNREACHABLE();
402 return os;
403}
404
405
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400406std::ostream& operator<<(std::ostream& os, const FlagsCondition& fc) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000407 switch (fc) {
408 case kEqual:
409 return os << "equal";
410 case kNotEqual:
411 return os << "not equal";
412 case kSignedLessThan:
413 return os << "signed less than";
414 case kSignedGreaterThanOrEqual:
415 return os << "signed greater than or equal";
416 case kSignedLessThanOrEqual:
417 return os << "signed less than or equal";
418 case kSignedGreaterThan:
419 return os << "signed greater than";
420 case kUnsignedLessThan:
421 return os << "unsigned less than";
422 case kUnsignedGreaterThanOrEqual:
423 return os << "unsigned greater than or equal";
424 case kUnsignedLessThanOrEqual:
425 return os << "unsigned less than or equal";
426 case kUnsignedGreaterThan:
427 return os << "unsigned greater than";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000428 case kFloatLessThanOrUnordered:
429 return os << "less than or unordered (FP)";
430 case kFloatGreaterThanOrEqual:
431 return os << "greater than or equal (FP)";
432 case kFloatLessThanOrEqual:
433 return os << "less than or equal (FP)";
434 case kFloatGreaterThanOrUnordered:
435 return os << "greater than or unordered (FP)";
436 case kFloatLessThan:
437 return os << "less than (FP)";
438 case kFloatGreaterThanOrEqualOrUnordered:
439 return os << "greater than, equal or unordered (FP)";
440 case kFloatLessThanOrEqualOrUnordered:
441 return os << "less than, equal or unordered (FP)";
442 case kFloatGreaterThan:
443 return os << "greater than (FP)";
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000444 case kUnorderedEqual:
445 return os << "unordered equal";
446 case kUnorderedNotEqual:
447 return os << "unordered not equal";
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000448 case kOverflow:
449 return os << "overflow";
450 case kNotOverflow:
451 return os << "not overflow";
452 }
453 UNREACHABLE();
454 return os;
455}
456
457
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400458std::ostream& operator<<(std::ostream& os,
459 const PrintableInstruction& printable) {
460 const Instruction& instr = *printable.instr_;
461 PrintableInstructionOperand printable_op = {printable.register_configuration_,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000462 InstructionOperand()};
463 os << "gap ";
464 for (int i = Instruction::FIRST_GAP_POSITION;
465 i <= Instruction::LAST_GAP_POSITION; i++) {
466 os << "(";
467 if (instr.parallel_moves()[i] != nullptr) {
468 PrintableParallelMove ppm = {printable.register_configuration_,
469 instr.parallel_moves()[i]};
470 os << ppm;
471 }
472 os << ") ";
473 }
474 os << "\n ";
475
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000476 if (instr.OutputCount() > 1) os << "(";
477 for (size_t i = 0; i < instr.OutputCount(); i++) {
478 if (i > 0) os << ", ";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000479 printable_op.op_ = *instr.OutputAt(i);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400480 os << printable_op;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000481 }
482
483 if (instr.OutputCount() > 1) os << ") = ";
484 if (instr.OutputCount() == 1) os << " = ";
485
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000486 os << ArchOpcodeField::decode(instr.opcode());
487 AddressingMode am = AddressingModeField::decode(instr.opcode());
488 if (am != kMode_None) {
489 os << " : " << AddressingModeField::decode(instr.opcode());
490 }
491 FlagsMode fm = FlagsModeField::decode(instr.opcode());
492 if (fm != kFlags_none) {
493 os << " && " << fm << " if " << FlagsConditionField::decode(instr.opcode());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000494 }
495 if (instr.InputCount() > 0) {
496 for (size_t i = 0; i < instr.InputCount(); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000497 printable_op.op_ = *instr.InputAt(i);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400498 os << " " << printable_op;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000499 }
500 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400501 return os;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000502}
503
504
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000505Constant::Constant(int32_t v) : type_(kInt32), value_(v) {}
506
507
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400508std::ostream& operator<<(std::ostream& os, const Constant& constant) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000509 switch (constant.type()) {
510 case Constant::kInt32:
511 return os << constant.ToInt32();
512 case Constant::kInt64:
513 return os << constant.ToInt64() << "l";
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400514 case Constant::kFloat32:
515 return os << constant.ToFloat32() << "f";
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000516 case Constant::kFloat64:
517 return os << constant.ToFloat64();
518 case Constant::kExternalReference:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400519 return os << static_cast<const void*>(
520 constant.ToExternalReference().address());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000521 case Constant::kHeapObject:
522 return os << Brief(*constant.ToHeapObject());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400523 case Constant::kRpoNumber:
524 return os << "RPO" << constant.ToRpoNumber().ToInt();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000525 }
526 UNREACHABLE();
527 return os;
528}
529
530
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000531PhiInstruction::PhiInstruction(Zone* zone, int virtual_register,
532 size_t input_count)
533 : virtual_register_(virtual_register),
534 output_(UnallocatedOperand(UnallocatedOperand::NONE, virtual_register)),
535 operands_(input_count, InstructionOperand::kInvalidVirtualRegister,
536 zone) {}
537
538
539void PhiInstruction::SetInput(size_t offset, int virtual_register) {
540 DCHECK_EQ(InstructionOperand::kInvalidVirtualRegister, operands_[offset]);
541 operands_[offset] = virtual_register;
542}
543
544
545InstructionBlock::InstructionBlock(Zone* zone, RpoNumber rpo_number,
546 RpoNumber loop_header, RpoNumber loop_end,
547 bool deferred, bool handler)
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400548 : successors_(zone),
549 predecessors_(zone),
550 phis_(zone),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400551 ao_number_(rpo_number),
552 rpo_number_(rpo_number),
553 loop_header_(loop_header),
554 loop_end_(loop_end),
555 code_start_(-1),
556 code_end_(-1),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000557 deferred_(deferred),
558 handler_(handler),
559 needs_frame_(false),
560 must_construct_frame_(false),
561 must_deconstruct_frame_(false),
562 last_deferred_(RpoNumber::Invalid()) {}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400563
564
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000565size_t InstructionBlock::PredecessorIndexOf(RpoNumber rpo_number) const {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400566 size_t j = 0;
567 for (InstructionBlock::Predecessors::const_iterator i = predecessors_.begin();
568 i != predecessors_.end(); ++i, ++j) {
569 if (*i == rpo_number) break;
570 }
571 return j;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000572}
573
574
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000575static RpoNumber GetRpo(const BasicBlock* block) {
576 if (block == nullptr) return RpoNumber::Invalid();
577 return RpoNumber::FromInt(block->rpo_number());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000578}
579
580
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000581static RpoNumber GetLoopEndRpo(const BasicBlock* block) {
582 if (!block->IsLoopHeader()) return RpoNumber::Invalid();
583 return RpoNumber::FromInt(block->loop_end()->rpo_number());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000584}
585
586
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400587static InstructionBlock* InstructionBlockFor(Zone* zone,
588 const BasicBlock* block) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000589 bool is_handler =
590 !block->empty() && block->front()->opcode() == IrOpcode::kIfException;
591 InstructionBlock* instr_block = new (zone)
592 InstructionBlock(zone, GetRpo(block), GetRpo(block->loop_header()),
593 GetLoopEndRpo(block), block->deferred(), is_handler);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400594 // Map successors and precessors
595 instr_block->successors().reserve(block->SuccessorCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000596 for (BasicBlock* successor : block->successors()) {
597 instr_block->successors().push_back(GetRpo(successor));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400598 }
599 instr_block->predecessors().reserve(block->PredecessorCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000600 for (BasicBlock* predecessor : block->predecessors()) {
601 instr_block->predecessors().push_back(GetRpo(predecessor));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400602 }
603 return instr_block;
604}
605
606
607InstructionBlocks* InstructionSequence::InstructionBlocksFor(
608 Zone* zone, const Schedule* schedule) {
609 InstructionBlocks* blocks = zone->NewArray<InstructionBlocks>(1);
610 new (blocks) InstructionBlocks(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000611 static_cast<int>(schedule->rpo_order()->size()), nullptr, zone);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400612 size_t rpo_number = 0;
613 for (BasicBlockVector::const_iterator it = schedule->rpo_order()->begin();
614 it != schedule->rpo_order()->end(); ++it, ++rpo_number) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000615 DCHECK(!(*blocks)[rpo_number]);
616 DCHECK(GetRpo(*it).ToSize() == rpo_number);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400617 (*blocks)[rpo_number] = InstructionBlockFor(zone, *it);
618 }
619 ComputeAssemblyOrder(blocks);
620 return blocks;
621}
622
Ben Murdochda12d292016-06-02 14:46:10 +0100623void InstructionSequence::ValidateEdgeSplitForm() {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100624 // Validate blocks are in edge-split form: no block with multiple successors
625 // has an edge to a block (== a successor) with more than one predecessors.
626 for (const InstructionBlock* block : instruction_blocks()) {
627 if (block->SuccessorCount() > 1) {
628 for (const RpoNumber& successor_id : block->successors()) {
629 const InstructionBlock* successor = InstructionBlockAt(successor_id);
630 // Expect precisely one predecessor: "block".
631 CHECK(successor->PredecessorCount() == 1 &&
632 successor->predecessors()[0] == block->rpo_number());
633 }
634 }
635 }
636}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400637
Ben Murdochda12d292016-06-02 14:46:10 +0100638void InstructionSequence::ValidateDeferredBlockExitPaths() {
639 // A deferred block with more than one successor must have all its successors
640 // deferred.
641 for (const InstructionBlock* block : instruction_blocks()) {
642 if (!block->IsDeferred() || block->SuccessorCount() <= 1) continue;
643 for (RpoNumber successor_id : block->successors()) {
644 CHECK(InstructionBlockAt(successor_id)->IsDeferred());
645 }
646 }
647}
648
649void InstructionSequence::ValidateSSA() {
650 // TODO(mtrofin): We could use a local zone here instead.
651 BitVector definitions(VirtualRegisterCount(), zone());
652 for (const Instruction* instruction : *this) {
653 for (size_t i = 0; i < instruction->OutputCount(); ++i) {
654 const InstructionOperand* output = instruction->OutputAt(i);
655 int vreg = (output->IsConstant())
656 ? ConstantOperand::cast(output)->virtual_register()
657 : UnallocatedOperand::cast(output)->virtual_register();
658 CHECK(!definitions.Contains(vreg));
659 definitions.Add(vreg);
660 }
661 }
662}
663
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400664void InstructionSequence::ComputeAssemblyOrder(InstructionBlocks* blocks) {
665 int ao = 0;
Ben Murdochda12d292016-06-02 14:46:10 +0100666 for (InstructionBlock* const block : *blocks) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400667 if (!block->IsDeferred()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000668 block->set_ao_number(RpoNumber::FromInt(ao++));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400669 }
670 }
Ben Murdochda12d292016-06-02 14:46:10 +0100671 for (InstructionBlock* const block : *blocks) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400672 if (block->IsDeferred()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000673 block->set_ao_number(RpoNumber::FromInt(ao++));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400674 }
675 }
676}
677
678
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000679InstructionSequence::InstructionSequence(Isolate* isolate,
680 Zone* instruction_zone,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400681 InstructionBlocks* instruction_blocks)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000682 : isolate_(isolate),
683 zone_(instruction_zone),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400684 instruction_blocks_(instruction_blocks),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000685 source_positions_(zone()),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400686 block_starts_(zone()),
687 constants_(ConstantMap::key_compare(),
688 ConstantMap::allocator_type(zone())),
689 immediates_(zone()),
690 instructions_(zone()),
691 next_virtual_register_(0),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000692 reference_maps_(zone()),
693 representations_(zone()),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400694 deoptimization_entries_(zone()) {
695 block_starts_.reserve(instruction_blocks_->size());
696}
697
698
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000699int InstructionSequence::NextVirtualRegister() {
700 int virtual_register = next_virtual_register_++;
701 CHECK_NE(virtual_register, InstructionOperand::kInvalidVirtualRegister);
702 return virtual_register;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400703}
704
705
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000706Instruction* InstructionSequence::GetBlockStart(RpoNumber rpo) const {
707 const InstructionBlock* block = InstructionBlockAt(rpo);
708 return InstructionAt(block->code_start());
709}
710
711
712void InstructionSequence::StartBlock(RpoNumber rpo) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400713 DCHECK(block_starts_.size() == rpo.ToSize());
714 InstructionBlock* block = InstructionBlockAt(rpo);
715 int code_start = static_cast<int>(instructions_.size());
716 block->set_code_start(code_start);
717 block_starts_.push_back(code_start);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400718}
719
720
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000721void InstructionSequence::EndBlock(RpoNumber rpo) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000722 int end = static_cast<int>(instructions_.size());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400723 InstructionBlock* block = InstructionBlockAt(rpo);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000724 if (block->code_start() == end) { // Empty block. Insert a nop.
725 AddInstruction(Instruction::New(zone(), kArchNop));
726 end = static_cast<int>(instructions_.size());
727 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400728 DCHECK(block->code_start() >= 0 && block->code_start() < end);
729 block->set_code_end(end);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000730}
731
732
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400733int InstructionSequence::AddInstruction(Instruction* instr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000734 int index = static_cast<int>(instructions_.size());
735 instructions_.push_back(instr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000736 if (instr->NeedsReferenceMap()) {
737 DCHECK(instr->reference_map() == nullptr);
738 ReferenceMap* reference_map = new (zone()) ReferenceMap(zone());
739 reference_map->set_instruction_position(index);
740 instr->set_reference_map(reference_map);
741 reference_maps_.push_back(reference_map);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000742 }
743 return index;
744}
745
746
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000747InstructionBlock* InstructionSequence::GetInstructionBlock(
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400748 int instruction_index) const {
749 DCHECK(instruction_blocks_->size() == block_starts_.size());
750 auto begin = block_starts_.begin();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000751 auto end = std::lower_bound(begin, block_starts_.end(), instruction_index);
752 // Post condition of std::lower_bound:
753 DCHECK(end == block_starts_.end() || *end >= instruction_index);
754 if (end == block_starts_.end() || *end > instruction_index) --end;
755 DCHECK(*end <= instruction_index);
756 size_t index = std::distance(begin, end);
Ben Murdochda12d292016-06-02 14:46:10 +0100757 InstructionBlock* block = instruction_blocks_->at(index);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400758 DCHECK(block->code_start() <= instruction_index &&
759 instruction_index < block->code_end());
760 return block;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000761}
762
763
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000764static MachineRepresentation FilterRepresentation(MachineRepresentation rep) {
765 switch (rep) {
766 case MachineRepresentation::kBit:
767 case MachineRepresentation::kWord8:
768 case MachineRepresentation::kWord16:
769 return InstructionSequence::DefaultRepresentation();
770 case MachineRepresentation::kWord32:
771 case MachineRepresentation::kWord64:
772 case MachineRepresentation::kFloat32:
773 case MachineRepresentation::kFloat64:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100774 case MachineRepresentation::kSimd128:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000775 case MachineRepresentation::kTagged:
776 return rep;
777 case MachineRepresentation::kNone:
778 break;
779 }
780 UNREACHABLE();
781 return MachineRepresentation::kNone;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000782}
783
784
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000785MachineRepresentation InstructionSequence::GetRepresentation(
786 int virtual_register) const {
787 DCHECK_LE(0, virtual_register);
788 DCHECK_LT(virtual_register, VirtualRegisterCount());
789 if (virtual_register >= static_cast<int>(representations_.size())) {
790 return DefaultRepresentation();
791 }
792 return representations_[virtual_register];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000793}
794
795
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000796void InstructionSequence::MarkAsRepresentation(MachineRepresentation rep,
797 int virtual_register) {
798 DCHECK_LE(0, virtual_register);
799 DCHECK_LT(virtual_register, VirtualRegisterCount());
800 if (virtual_register >= static_cast<int>(representations_.size())) {
801 representations_.resize(VirtualRegisterCount(), DefaultRepresentation());
802 }
803 rep = FilterRepresentation(rep);
804 DCHECK_IMPLIES(representations_[virtual_register] != rep,
805 representations_[virtual_register] == DefaultRepresentation());
806 representations_[virtual_register] = rep;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000807}
808
809
810InstructionSequence::StateId InstructionSequence::AddFrameStateDescriptor(
811 FrameStateDescriptor* descriptor) {
812 int deoptimization_id = static_cast<int>(deoptimization_entries_.size());
813 deoptimization_entries_.push_back(descriptor);
814 return StateId::FromInt(deoptimization_id);
815}
816
817FrameStateDescriptor* InstructionSequence::GetFrameStateDescriptor(
818 InstructionSequence::StateId state_id) {
819 return deoptimization_entries_[state_id.ToInt()];
820}
821
822
823int InstructionSequence::GetFrameStateDescriptorCount() {
824 return static_cast<int>(deoptimization_entries_.size());
825}
826
827
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000828RpoNumber InstructionSequence::InputRpo(Instruction* instr, size_t index) {
829 InstructionOperand* operand = instr->InputAt(index);
830 Constant constant =
831 operand->IsImmediate()
832 ? GetImmediate(ImmediateOperand::cast(operand))
833 : GetConstant(ConstantOperand::cast(operand)->virtual_register());
834 return constant.ToRpoNumber();
835}
836
837
838bool InstructionSequence::GetSourcePosition(const Instruction* instr,
839 SourcePosition* result) const {
840 auto it = source_positions_.find(instr);
841 if (it == source_positions_.end()) return false;
842 *result = it->second;
843 return true;
844}
845
846
847void InstructionSequence::SetSourcePosition(const Instruction* instr,
848 SourcePosition value) {
849 source_positions_.insert(std::make_pair(instr, value));
850}
851
852
853void InstructionSequence::Print(const RegisterConfiguration* config) const {
854 OFStream os(stdout);
855 PrintableInstructionSequence wrapper;
856 wrapper.register_configuration_ = config;
857 wrapper.sequence_ = this;
858 os << wrapper << std::endl;
859}
860
861
862void InstructionSequence::Print() const {
863 const RegisterConfiguration* config =
864 RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN);
865 Print(config);
866}
867
Ben Murdoch097c5b22016-05-18 11:27:45 +0100868void InstructionSequence::PrintBlock(const RegisterConfiguration* config,
869 int block_id) const {
870 OFStream os(stdout);
871 RpoNumber rpo = RpoNumber::FromInt(block_id);
872 const InstructionBlock* block = InstructionBlockAt(rpo);
873 CHECK(block->rpo_number() == rpo);
874
875 os << "B" << block->rpo_number();
876 os << ": AO#" << block->ao_number();
877 if (block->IsDeferred()) os << " (deferred)";
878 if (!block->needs_frame()) os << " (no frame)";
879 if (block->must_construct_frame()) os << " (construct frame)";
880 if (block->must_deconstruct_frame()) os << " (deconstruct frame)";
881 if (block->IsLoopHeader()) {
882 os << " loop blocks: [" << block->rpo_number() << ", " << block->loop_end()
883 << ")";
884 }
885 os << " instructions: [" << block->code_start() << ", " << block->code_end()
886 << ")\n predecessors:";
887
Ben Murdochda12d292016-06-02 14:46:10 +0100888 for (RpoNumber pred : block->predecessors()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100889 os << " B" << pred.ToInt();
890 }
891 os << "\n";
892
Ben Murdochda12d292016-06-02 14:46:10 +0100893 for (const PhiInstruction* phi : block->phis()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100894 PrintableInstructionOperand printable_op = {config, phi->output()};
895 os << " phi: " << printable_op << " =";
Ben Murdochda12d292016-06-02 14:46:10 +0100896 for (int input : phi->operands()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100897 os << " v" << input;
898 }
899 os << "\n";
900 }
901
902 ScopedVector<char> buf(32);
903 PrintableInstruction printable_instr;
904 printable_instr.register_configuration_ = config;
905 for (int j = block->first_instruction_index();
906 j <= block->last_instruction_index(); j++) {
907 // TODO(svenpanne) Add some basic formatting to our streams.
908 SNPrintF(buf, "%5d", j);
909 printable_instr.instr_ = InstructionAt(j);
910 os << " " << buf.start() << ": " << printable_instr << "\n";
911 }
912
Ben Murdochda12d292016-06-02 14:46:10 +0100913 for (RpoNumber succ : block->successors()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100914 os << " B" << succ.ToInt();
915 }
916 os << "\n";
917}
918
919void InstructionSequence::PrintBlock(int block_id) const {
920 const RegisterConfiguration* config =
921 RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN);
922 PrintBlock(config, block_id);
923}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000924
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400925FrameStateDescriptor::FrameStateDescriptor(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000926 Zone* zone, FrameStateType type, BailoutId bailout_id,
927 OutputFrameStateCombine state_combine, size_t parameters_count,
928 size_t locals_count, size_t stack_count,
929 MaybeHandle<SharedFunctionInfo> shared_info,
930 FrameStateDescriptor* outer_state)
931 : type_(type),
932 bailout_id_(bailout_id),
933 frame_state_combine_(state_combine),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400934 parameters_count_(parameters_count),
935 locals_count_(locals_count),
936 stack_count_(stack_count),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000937 values_(zone),
938 shared_info_(shared_info),
939 outer_state_(outer_state) {}
940
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400941
942size_t FrameStateDescriptor::GetSize(OutputFrameStateCombine combine) const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000943 size_t size = 1 + parameters_count() + locals_count() + stack_count() +
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400944 (HasContext() ? 1 : 0);
945 switch (combine.kind()) {
946 case OutputFrameStateCombine::kPushOutput:
947 size += combine.GetPushCount();
948 break;
949 case OutputFrameStateCombine::kPokeAt:
950 break;
951 }
952 return size;
953}
954
955
956size_t FrameStateDescriptor::GetTotalSize() const {
957 size_t total_size = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000958 for (const FrameStateDescriptor* iter = this; iter != nullptr;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400959 iter = iter->outer_state_) {
960 total_size += iter->GetSize();
961 }
962 return total_size;
963}
964
965
966size_t FrameStateDescriptor::GetFrameCount() const {
967 size_t count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000968 for (const FrameStateDescriptor* iter = this; iter != nullptr;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400969 iter = iter->outer_state_) {
970 ++count;
971 }
972 return count;
973}
974
975
976size_t FrameStateDescriptor::GetJSFrameCount() const {
977 size_t count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000978 for (const FrameStateDescriptor* iter = this; iter != nullptr;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400979 iter = iter->outer_state_) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000980 if (FrameStateFunctionInfo::IsJSFunctionType(iter->type_)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400981 ++count;
982 }
983 }
984 return count;
985}
986
987
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000988std::ostream& operator<<(std::ostream& os, const RpoNumber& rpo) {
989 return os << rpo.ToSize();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400990}
991
992
993std::ostream& operator<<(std::ostream& os,
994 const PrintableInstructionSequence& printable) {
995 const InstructionSequence& code = *printable.sequence_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000996 for (size_t i = 0; i < code.immediates_.size(); ++i) {
997 Constant constant = code.immediates_[i];
998 os << "IMM#" << i << ": " << constant << "\n";
999 }
1000 int i = 0;
1001 for (ConstantMap::const_iterator it = code.constants_.begin();
1002 it != code.constants_.end(); ++i, ++it) {
1003 os << "CST#" << i << ": v" << it->first << " = " << it->second << "\n";
1004 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001005 for (int i = 0; i < code.InstructionBlockCount(); i++) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001006 printable.sequence_->PrintBlock(printable.register_configuration_, i);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001007 }
1008 return os;
1009}
1010
1011} // namespace compiler
1012} // namespace internal
1013} // namespace v8