blob: 26aebca9a81660577c4b67e6a543879a24db68de [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();
Ben Murdochc5610432016-08-08 18:44:38 +0100130 } else if (op.IsFPStackSlot()) {
131 os << "[fp_stack:" << LocationOperand::cast(op).index();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000132 } else if (op.IsRegister()) {
133 os << "[" << LocationOperand::cast(op).GetRegister().ToString() << "|R";
134 } else {
Ben Murdochc5610432016-08-08 18:44:38 +0100135 DCHECK(op.IsFPRegister());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000136 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
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000254Instruction::Instruction(InstructionCode opcode)
255 : opcode_(opcode),
256 bit_field_(OutputCountField::encode(0) | InputCountField::encode(0) |
257 TempCountField::encode(0) | IsCallField::encode(false)),
Ben Murdochc5610432016-08-08 18:44:38 +0100258 reference_map_(nullptr),
259 block_(nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000260 parallel_moves_[0] = nullptr;
261 parallel_moves_[1] = nullptr;
262}
263
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000264Instruction::Instruction(InstructionCode opcode, size_t output_count,
265 InstructionOperand* outputs, size_t input_count,
266 InstructionOperand* inputs, size_t temp_count,
267 InstructionOperand* temps)
268 : opcode_(opcode),
269 bit_field_(OutputCountField::encode(output_count) |
270 InputCountField::encode(input_count) |
271 TempCountField::encode(temp_count) |
272 IsCallField::encode(false)),
Ben Murdochc5610432016-08-08 18:44:38 +0100273 reference_map_(nullptr),
274 block_(nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000275 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;
Ben Murdochc5610432016-08-08 18:44:38 +0100338 DCHECK(!op.IsFPRegister() && !op.IsFPStackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000339 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
Ben Murdochc5610432016-08-08 18:44:38 +0100507Constant::Constant(RelocatablePtrConstantInfo info) {
508 if (info.type() == RelocatablePtrConstantInfo::kInt32) {
509 type_ = kInt32;
510 } else if (info.type() == RelocatablePtrConstantInfo::kInt64) {
511 type_ = kInt64;
512 } else {
513 UNREACHABLE();
514 }
515 value_ = info.value();
516 rmode_ = info.rmode();
517}
518
519Handle<HeapObject> Constant::ToHeapObject() const {
520 DCHECK_EQ(kHeapObject, type());
521 Handle<HeapObject> value(
522 bit_cast<HeapObject**>(static_cast<intptr_t>(value_)));
523 if (value->IsConsString()) {
524 value = String::Flatten(Handle<String>::cast(value), TENURED);
525 }
526 return value;
527}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000528
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400529std::ostream& operator<<(std::ostream& os, const Constant& constant) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000530 switch (constant.type()) {
531 case Constant::kInt32:
532 return os << constant.ToInt32();
533 case Constant::kInt64:
534 return os << constant.ToInt64() << "l";
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400535 case Constant::kFloat32:
536 return os << constant.ToFloat32() << "f";
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000537 case Constant::kFloat64:
538 return os << constant.ToFloat64();
539 case Constant::kExternalReference:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400540 return os << static_cast<const void*>(
541 constant.ToExternalReference().address());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000542 case Constant::kHeapObject:
543 return os << Brief(*constant.ToHeapObject());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400544 case Constant::kRpoNumber:
545 return os << "RPO" << constant.ToRpoNumber().ToInt();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000546 }
547 UNREACHABLE();
548 return os;
549}
550
551
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000552PhiInstruction::PhiInstruction(Zone* zone, int virtual_register,
553 size_t input_count)
554 : virtual_register_(virtual_register),
555 output_(UnallocatedOperand(UnallocatedOperand::NONE, virtual_register)),
556 operands_(input_count, InstructionOperand::kInvalidVirtualRegister,
557 zone) {}
558
559
560void PhiInstruction::SetInput(size_t offset, int virtual_register) {
561 DCHECK_EQ(InstructionOperand::kInvalidVirtualRegister, operands_[offset]);
562 operands_[offset] = virtual_register;
563}
564
565
566InstructionBlock::InstructionBlock(Zone* zone, RpoNumber rpo_number,
567 RpoNumber loop_header, RpoNumber loop_end,
568 bool deferred, bool handler)
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400569 : successors_(zone),
570 predecessors_(zone),
571 phis_(zone),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400572 ao_number_(rpo_number),
573 rpo_number_(rpo_number),
574 loop_header_(loop_header),
575 loop_end_(loop_end),
576 code_start_(-1),
577 code_end_(-1),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000578 deferred_(deferred),
579 handler_(handler),
580 needs_frame_(false),
581 must_construct_frame_(false),
582 must_deconstruct_frame_(false),
583 last_deferred_(RpoNumber::Invalid()) {}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400584
585
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000586size_t InstructionBlock::PredecessorIndexOf(RpoNumber rpo_number) const {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400587 size_t j = 0;
588 for (InstructionBlock::Predecessors::const_iterator i = predecessors_.begin();
589 i != predecessors_.end(); ++i, ++j) {
590 if (*i == rpo_number) break;
591 }
592 return j;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000593}
594
595
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000596static RpoNumber GetRpo(const BasicBlock* block) {
597 if (block == nullptr) return RpoNumber::Invalid();
598 return RpoNumber::FromInt(block->rpo_number());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000599}
600
601
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000602static RpoNumber GetLoopEndRpo(const BasicBlock* block) {
603 if (!block->IsLoopHeader()) return RpoNumber::Invalid();
604 return RpoNumber::FromInt(block->loop_end()->rpo_number());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000605}
606
607
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400608static InstructionBlock* InstructionBlockFor(Zone* zone,
609 const BasicBlock* block) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000610 bool is_handler =
611 !block->empty() && block->front()->opcode() == IrOpcode::kIfException;
612 InstructionBlock* instr_block = new (zone)
613 InstructionBlock(zone, GetRpo(block), GetRpo(block->loop_header()),
614 GetLoopEndRpo(block), block->deferred(), is_handler);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400615 // Map successors and precessors
616 instr_block->successors().reserve(block->SuccessorCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000617 for (BasicBlock* successor : block->successors()) {
618 instr_block->successors().push_back(GetRpo(successor));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400619 }
620 instr_block->predecessors().reserve(block->PredecessorCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000621 for (BasicBlock* predecessor : block->predecessors()) {
622 instr_block->predecessors().push_back(GetRpo(predecessor));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400623 }
624 return instr_block;
625}
626
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400627InstructionBlocks* InstructionSequence::InstructionBlocksFor(
628 Zone* zone, const Schedule* schedule) {
629 InstructionBlocks* blocks = zone->NewArray<InstructionBlocks>(1);
630 new (blocks) InstructionBlocks(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000631 static_cast<int>(schedule->rpo_order()->size()), nullptr, zone);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400632 size_t rpo_number = 0;
633 for (BasicBlockVector::const_iterator it = schedule->rpo_order()->begin();
634 it != schedule->rpo_order()->end(); ++it, ++rpo_number) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000635 DCHECK(!(*blocks)[rpo_number]);
636 DCHECK(GetRpo(*it).ToSize() == rpo_number);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400637 (*blocks)[rpo_number] = InstructionBlockFor(zone, *it);
638 }
639 ComputeAssemblyOrder(blocks);
640 return blocks;
641}
642
Ben Murdochc5610432016-08-08 18:44:38 +0100643void InstructionSequence::ValidateEdgeSplitForm() const {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100644 // Validate blocks are in edge-split form: no block with multiple successors
645 // has an edge to a block (== a successor) with more than one predecessors.
646 for (const InstructionBlock* block : instruction_blocks()) {
647 if (block->SuccessorCount() > 1) {
648 for (const RpoNumber& successor_id : block->successors()) {
649 const InstructionBlock* successor = InstructionBlockAt(successor_id);
650 // Expect precisely one predecessor: "block".
651 CHECK(successor->PredecessorCount() == 1 &&
652 successor->predecessors()[0] == block->rpo_number());
653 }
654 }
655 }
656}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400657
Ben Murdochc5610432016-08-08 18:44:38 +0100658void InstructionSequence::ValidateDeferredBlockExitPaths() const {
Ben Murdochda12d292016-06-02 14:46:10 +0100659 // A deferred block with more than one successor must have all its successors
660 // deferred.
661 for (const InstructionBlock* block : instruction_blocks()) {
662 if (!block->IsDeferred() || block->SuccessorCount() <= 1) continue;
663 for (RpoNumber successor_id : block->successors()) {
664 CHECK(InstructionBlockAt(successor_id)->IsDeferred());
665 }
666 }
667}
668
Ben Murdochc5610432016-08-08 18:44:38 +0100669void InstructionSequence::ValidateDeferredBlockEntryPaths() const {
670 // If a deferred block has multiple predecessors, they have to
671 // all be deferred. Otherwise, we can run into a situation where a range
672 // that spills only in deferred blocks inserts its spill in the block, but
673 // other ranges need moves inserted by ResolveControlFlow in the predecessors,
674 // which may clobber the register of this range.
675 for (const InstructionBlock* block : instruction_blocks()) {
676 if (!block->IsDeferred() || block->PredecessorCount() <= 1) continue;
677 for (RpoNumber predecessor_id : block->predecessors()) {
678 CHECK(InstructionBlockAt(predecessor_id)->IsDeferred());
679 }
680 }
681}
682
683void InstructionSequence::ValidateSSA() const {
Ben Murdochda12d292016-06-02 14:46:10 +0100684 // TODO(mtrofin): We could use a local zone here instead.
685 BitVector definitions(VirtualRegisterCount(), zone());
686 for (const Instruction* instruction : *this) {
687 for (size_t i = 0; i < instruction->OutputCount(); ++i) {
688 const InstructionOperand* output = instruction->OutputAt(i);
689 int vreg = (output->IsConstant())
690 ? ConstantOperand::cast(output)->virtual_register()
691 : UnallocatedOperand::cast(output)->virtual_register();
692 CHECK(!definitions.Contains(vreg));
693 definitions.Add(vreg);
694 }
695 }
696}
697
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400698void InstructionSequence::ComputeAssemblyOrder(InstructionBlocks* blocks) {
699 int ao = 0;
Ben Murdochda12d292016-06-02 14:46:10 +0100700 for (InstructionBlock* const block : *blocks) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400701 if (!block->IsDeferred()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000702 block->set_ao_number(RpoNumber::FromInt(ao++));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400703 }
704 }
Ben Murdochda12d292016-06-02 14:46:10 +0100705 for (InstructionBlock* const block : *blocks) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400706 if (block->IsDeferred()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000707 block->set_ao_number(RpoNumber::FromInt(ao++));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400708 }
709 }
710}
711
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000712InstructionSequence::InstructionSequence(Isolate* isolate,
713 Zone* instruction_zone,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400714 InstructionBlocks* instruction_blocks)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000715 : isolate_(isolate),
716 zone_(instruction_zone),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400717 instruction_blocks_(instruction_blocks),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000718 source_positions_(zone()),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400719 constants_(ConstantMap::key_compare(),
720 ConstantMap::allocator_type(zone())),
721 immediates_(zone()),
722 instructions_(zone()),
723 next_virtual_register_(0),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000724 reference_maps_(zone()),
725 representations_(zone()),
Ben Murdochc5610432016-08-08 18:44:38 +0100726 deoptimization_entries_(zone()),
727 current_block_(nullptr) {}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400728
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000729int InstructionSequence::NextVirtualRegister() {
730 int virtual_register = next_virtual_register_++;
731 CHECK_NE(virtual_register, InstructionOperand::kInvalidVirtualRegister);
732 return virtual_register;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400733}
734
735
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000736Instruction* InstructionSequence::GetBlockStart(RpoNumber rpo) const {
737 const InstructionBlock* block = InstructionBlockAt(rpo);
738 return InstructionAt(block->code_start());
739}
740
741
742void InstructionSequence::StartBlock(RpoNumber rpo) {
Ben Murdochc5610432016-08-08 18:44:38 +0100743 DCHECK_NULL(current_block_);
744 current_block_ = InstructionBlockAt(rpo);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400745 int code_start = static_cast<int>(instructions_.size());
Ben Murdochc5610432016-08-08 18:44:38 +0100746 current_block_->set_code_start(code_start);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400747}
748
749
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000750void InstructionSequence::EndBlock(RpoNumber rpo) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000751 int end = static_cast<int>(instructions_.size());
Ben Murdochc5610432016-08-08 18:44:38 +0100752 DCHECK_EQ(current_block_->rpo_number(), rpo);
753 if (current_block_->code_start() == end) { // Empty block. Insert a nop.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000754 AddInstruction(Instruction::New(zone(), kArchNop));
755 end = static_cast<int>(instructions_.size());
756 }
Ben Murdochc5610432016-08-08 18:44:38 +0100757 DCHECK(current_block_->code_start() >= 0 &&
758 current_block_->code_start() < end);
759 current_block_->set_code_end(end);
760 current_block_ = nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000761}
762
763
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400764int InstructionSequence::AddInstruction(Instruction* instr) {
Ben Murdochc5610432016-08-08 18:44:38 +0100765 DCHECK_NOT_NULL(current_block_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000766 int index = static_cast<int>(instructions_.size());
Ben Murdochc5610432016-08-08 18:44:38 +0100767 instr->set_block(current_block_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000768 instructions_.push_back(instr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000769 if (instr->NeedsReferenceMap()) {
770 DCHECK(instr->reference_map() == nullptr);
771 ReferenceMap* reference_map = new (zone()) ReferenceMap(zone());
772 reference_map->set_instruction_position(index);
773 instr->set_reference_map(reference_map);
774 reference_maps_.push_back(reference_map);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000775 }
776 return index;
777}
778
779
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000780InstructionBlock* InstructionSequence::GetInstructionBlock(
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400781 int instruction_index) const {
Ben Murdochc5610432016-08-08 18:44:38 +0100782 return instructions()[instruction_index]->block();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000783}
784
785
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000786static MachineRepresentation FilterRepresentation(MachineRepresentation rep) {
787 switch (rep) {
788 case MachineRepresentation::kBit:
789 case MachineRepresentation::kWord8:
790 case MachineRepresentation::kWord16:
791 return InstructionSequence::DefaultRepresentation();
792 case MachineRepresentation::kWord32:
793 case MachineRepresentation::kWord64:
794 case MachineRepresentation::kFloat32:
795 case MachineRepresentation::kFloat64:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100796 case MachineRepresentation::kSimd128:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000797 case MachineRepresentation::kTagged:
798 return rep;
799 case MachineRepresentation::kNone:
800 break;
801 }
802 UNREACHABLE();
803 return MachineRepresentation::kNone;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000804}
805
806
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000807MachineRepresentation InstructionSequence::GetRepresentation(
808 int virtual_register) const {
809 DCHECK_LE(0, virtual_register);
810 DCHECK_LT(virtual_register, VirtualRegisterCount());
811 if (virtual_register >= static_cast<int>(representations_.size())) {
812 return DefaultRepresentation();
813 }
814 return representations_[virtual_register];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000815}
816
817
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000818void InstructionSequence::MarkAsRepresentation(MachineRepresentation rep,
819 int virtual_register) {
820 DCHECK_LE(0, virtual_register);
821 DCHECK_LT(virtual_register, VirtualRegisterCount());
822 if (virtual_register >= static_cast<int>(representations_.size())) {
823 representations_.resize(VirtualRegisterCount(), DefaultRepresentation());
824 }
825 rep = FilterRepresentation(rep);
826 DCHECK_IMPLIES(representations_[virtual_register] != rep,
827 representations_[virtual_register] == DefaultRepresentation());
828 representations_[virtual_register] = rep;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000829}
830
831
832InstructionSequence::StateId InstructionSequence::AddFrameStateDescriptor(
833 FrameStateDescriptor* descriptor) {
834 int deoptimization_id = static_cast<int>(deoptimization_entries_.size());
835 deoptimization_entries_.push_back(descriptor);
836 return StateId::FromInt(deoptimization_id);
837}
838
839FrameStateDescriptor* InstructionSequence::GetFrameStateDescriptor(
840 InstructionSequence::StateId state_id) {
841 return deoptimization_entries_[state_id.ToInt()];
842}
843
844
845int InstructionSequence::GetFrameStateDescriptorCount() {
846 return static_cast<int>(deoptimization_entries_.size());
847}
848
849
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000850RpoNumber InstructionSequence::InputRpo(Instruction* instr, size_t index) {
851 InstructionOperand* operand = instr->InputAt(index);
852 Constant constant =
853 operand->IsImmediate()
854 ? GetImmediate(ImmediateOperand::cast(operand))
855 : GetConstant(ConstantOperand::cast(operand)->virtual_register());
856 return constant.ToRpoNumber();
857}
858
859
860bool InstructionSequence::GetSourcePosition(const Instruction* instr,
861 SourcePosition* result) const {
862 auto it = source_positions_.find(instr);
863 if (it == source_positions_.end()) return false;
864 *result = it->second;
865 return true;
866}
867
868
869void InstructionSequence::SetSourcePosition(const Instruction* instr,
870 SourcePosition value) {
871 source_positions_.insert(std::make_pair(instr, value));
872}
873
874
875void InstructionSequence::Print(const RegisterConfiguration* config) const {
876 OFStream os(stdout);
877 PrintableInstructionSequence wrapper;
878 wrapper.register_configuration_ = config;
879 wrapper.sequence_ = this;
880 os << wrapper << std::endl;
881}
882
883
884void InstructionSequence::Print() const {
885 const RegisterConfiguration* config =
886 RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN);
887 Print(config);
888}
889
Ben Murdoch097c5b22016-05-18 11:27:45 +0100890void InstructionSequence::PrintBlock(const RegisterConfiguration* config,
891 int block_id) const {
892 OFStream os(stdout);
893 RpoNumber rpo = RpoNumber::FromInt(block_id);
894 const InstructionBlock* block = InstructionBlockAt(rpo);
895 CHECK(block->rpo_number() == rpo);
896
897 os << "B" << block->rpo_number();
898 os << ": AO#" << block->ao_number();
899 if (block->IsDeferred()) os << " (deferred)";
900 if (!block->needs_frame()) os << " (no frame)";
901 if (block->must_construct_frame()) os << " (construct frame)";
902 if (block->must_deconstruct_frame()) os << " (deconstruct frame)";
903 if (block->IsLoopHeader()) {
904 os << " loop blocks: [" << block->rpo_number() << ", " << block->loop_end()
905 << ")";
906 }
907 os << " instructions: [" << block->code_start() << ", " << block->code_end()
908 << ")\n predecessors:";
909
Ben Murdochda12d292016-06-02 14:46:10 +0100910 for (RpoNumber pred : block->predecessors()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100911 os << " B" << pred.ToInt();
912 }
913 os << "\n";
914
Ben Murdochda12d292016-06-02 14:46:10 +0100915 for (const PhiInstruction* phi : block->phis()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100916 PrintableInstructionOperand printable_op = {config, phi->output()};
917 os << " phi: " << printable_op << " =";
Ben Murdochda12d292016-06-02 14:46:10 +0100918 for (int input : phi->operands()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100919 os << " v" << input;
920 }
921 os << "\n";
922 }
923
924 ScopedVector<char> buf(32);
925 PrintableInstruction printable_instr;
926 printable_instr.register_configuration_ = config;
927 for (int j = block->first_instruction_index();
928 j <= block->last_instruction_index(); j++) {
929 // TODO(svenpanne) Add some basic formatting to our streams.
930 SNPrintF(buf, "%5d", j);
931 printable_instr.instr_ = InstructionAt(j);
932 os << " " << buf.start() << ": " << printable_instr << "\n";
933 }
934
Ben Murdochda12d292016-06-02 14:46:10 +0100935 for (RpoNumber succ : block->successors()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100936 os << " B" << succ.ToInt();
937 }
938 os << "\n";
939}
940
941void InstructionSequence::PrintBlock(int block_id) const {
942 const RegisterConfiguration* config =
943 RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN);
944 PrintBlock(config, block_id);
945}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000946
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400947FrameStateDescriptor::FrameStateDescriptor(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000948 Zone* zone, FrameStateType type, BailoutId bailout_id,
949 OutputFrameStateCombine state_combine, size_t parameters_count,
950 size_t locals_count, size_t stack_count,
951 MaybeHandle<SharedFunctionInfo> shared_info,
952 FrameStateDescriptor* outer_state)
953 : type_(type),
954 bailout_id_(bailout_id),
955 frame_state_combine_(state_combine),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400956 parameters_count_(parameters_count),
957 locals_count_(locals_count),
958 stack_count_(stack_count),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000959 values_(zone),
960 shared_info_(shared_info),
961 outer_state_(outer_state) {}
962
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400963
964size_t FrameStateDescriptor::GetSize(OutputFrameStateCombine combine) const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000965 size_t size = 1 + parameters_count() + locals_count() + stack_count() +
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400966 (HasContext() ? 1 : 0);
967 switch (combine.kind()) {
968 case OutputFrameStateCombine::kPushOutput:
969 size += combine.GetPushCount();
970 break;
971 case OutputFrameStateCombine::kPokeAt:
972 break;
973 }
974 return size;
975}
976
977
978size_t FrameStateDescriptor::GetTotalSize() const {
979 size_t total_size = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000980 for (const FrameStateDescriptor* iter = this; iter != nullptr;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400981 iter = iter->outer_state_) {
982 total_size += iter->GetSize();
983 }
984 return total_size;
985}
986
987
988size_t FrameStateDescriptor::GetFrameCount() const {
989 size_t count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000990 for (const FrameStateDescriptor* iter = this; iter != nullptr;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400991 iter = iter->outer_state_) {
992 ++count;
993 }
994 return count;
995}
996
997
998size_t FrameStateDescriptor::GetJSFrameCount() const {
999 size_t count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001000 for (const FrameStateDescriptor* iter = this; iter != nullptr;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001001 iter = iter->outer_state_) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001002 if (FrameStateFunctionInfo::IsJSFunctionType(iter->type_)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001003 ++count;
1004 }
1005 }
1006 return count;
1007}
1008
1009
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001010std::ostream& operator<<(std::ostream& os, const RpoNumber& rpo) {
1011 return os << rpo.ToSize();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001012}
1013
1014
1015std::ostream& operator<<(std::ostream& os,
1016 const PrintableInstructionSequence& printable) {
1017 const InstructionSequence& code = *printable.sequence_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001018 for (size_t i = 0; i < code.immediates_.size(); ++i) {
1019 Constant constant = code.immediates_[i];
1020 os << "IMM#" << i << ": " << constant << "\n";
1021 }
1022 int i = 0;
1023 for (ConstantMap::const_iterator it = code.constants_.begin();
1024 it != code.constants_.end(); ++i, ++it) {
1025 os << "CST#" << i << ": v" << it->first << " = " << it->second << "\n";
1026 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001027 for (int i = 0; i < code.InstructionBlockCount(); i++) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001028 printable.sequence_->PrintBlock(printable.register_configuration_, i);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001029 }
1030 return os;
1031}
1032
1033} // namespace compiler
1034} // namespace internal
1035} // namespace v8