blob: ea68c78fc11b984b7714a0918801ea17fdabf524 [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
5#include "src/compiler/instruction-selector.h"
6
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007#include <limits>
8
9#include "src/base/adapters.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010#include "src/compiler/instruction-selector-impl.h"
11#include "src/compiler/node-matchers.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012#include "src/compiler/pipeline.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013#include "src/compiler/schedule.h"
14#include "src/compiler/state-values-utils.h"
15#include "src/deoptimizer.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016
17namespace v8 {
18namespace internal {
19namespace compiler {
20
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021InstructionSelector::InstructionSelector(
22 Zone* zone, size_t node_count, Linkage* linkage,
23 InstructionSequence* sequence, Schedule* schedule,
Ben Murdoch097c5b22016-05-18 11:27:45 +010024 SourcePositionTable* source_positions, Frame* frame,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000025 SourcePositionMode source_position_mode, Features features)
26 : zone_(zone),
Emily Bernierd0a1eb72015-03-24 16:35:39 -040027 linkage_(linkage),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000028 sequence_(sequence),
29 source_positions_(source_positions),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000030 source_position_mode_(source_position_mode),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000031 features_(features),
Emily Bernierd0a1eb72015-03-24 16:35:39 -040032 schedule_(schedule),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000033 current_block_(nullptr),
34 instructions_(zone),
35 defined_(node_count, false, zone),
36 used_(node_count, false, zone),
Ben Murdoch097c5b22016-05-18 11:27:45 +010037 effect_level_(node_count, 0, zone),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000038 virtual_registers_(node_count,
39 InstructionOperand::kInvalidVirtualRegister, zone),
Ben Murdoch097c5b22016-05-18 11:27:45 +010040 scheduler_(nullptr),
41 frame_(frame) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000042 instructions_.reserve(node_count);
43}
Ben Murdochb8a8cc12014-11-26 15:28:44 +000044
45
46void InstructionSelector::SelectInstructions() {
47 // Mark the inputs of all phis in loop headers as used.
48 BasicBlockVector* blocks = schedule()->rpo_order();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000049 for (auto const block : *blocks) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000050 if (!block->IsLoopHeader()) continue;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000051 DCHECK_LE(2u, block->PredecessorCount());
52 for (Node* const phi : *block) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000053 if (phi->opcode() != IrOpcode::kPhi) continue;
54
55 // Mark all inputs as used.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000056 for (Node* const input : phi->inputs()) {
57 MarkAsUsed(input);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000058 }
59 }
60 }
61
62 // Visit each basic block in post order.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000063 for (auto i = blocks->rbegin(); i != blocks->rend(); ++i) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000064 VisitBlock(*i);
65 }
66
67 // Schedule the selected instructions.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000068 if (FLAG_turbo_instruction_scheduling &&
69 InstructionScheduler::SchedulerSupported()) {
70 scheduler_ = new (zone()) InstructionScheduler(zone(), sequence());
71 }
72
73 for (auto const block : *blocks) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040074 InstructionBlock* instruction_block =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000075 sequence()->InstructionBlockAt(RpoNumber::FromInt(block->rpo_number()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -040076 size_t end = instruction_block->code_end();
77 size_t start = instruction_block->code_start();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000078 DCHECK_LE(end, start);
79 StartBlock(RpoNumber::FromInt(block->rpo_number()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000080 while (start-- > end) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000081 AddInstruction(instructions_[start]);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000082 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000083 EndBlock(RpoNumber::FromInt(block->rpo_number()));
84 }
Ben Murdochda12d292016-06-02 14:46:10 +010085#if DEBUG
86 sequence()->ValidateSSA();
87#endif
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000088}
89
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000090void InstructionSelector::StartBlock(RpoNumber rpo) {
91 if (FLAG_turbo_instruction_scheduling &&
92 InstructionScheduler::SchedulerSupported()) {
93 DCHECK_NOT_NULL(scheduler_);
94 scheduler_->StartBlock(rpo);
95 } else {
96 sequence()->StartBlock(rpo);
97 }
98}
99
100
101void InstructionSelector::EndBlock(RpoNumber rpo) {
102 if (FLAG_turbo_instruction_scheduling &&
103 InstructionScheduler::SchedulerSupported()) {
104 DCHECK_NOT_NULL(scheduler_);
105 scheduler_->EndBlock(rpo);
106 } else {
107 sequence()->EndBlock(rpo);
108 }
109}
110
111
112void InstructionSelector::AddInstruction(Instruction* instr) {
113 if (FLAG_turbo_instruction_scheduling &&
114 InstructionScheduler::SchedulerSupported()) {
115 DCHECK_NOT_NULL(scheduler_);
116 scheduler_->AddInstruction(instr);
117 } else {
118 sequence()->AddInstruction(instr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000119 }
120}
121
122
123Instruction* InstructionSelector::Emit(InstructionCode opcode,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000124 InstructionOperand output,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000125 size_t temp_count,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000126 InstructionOperand* temps) {
127 size_t output_count = output.IsInvalid() ? 0 : 1;
128 return Emit(opcode, output_count, &output, 0, nullptr, temp_count, temps);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000129}
130
131
132Instruction* InstructionSelector::Emit(InstructionCode opcode,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000133 InstructionOperand output,
134 InstructionOperand a, size_t temp_count,
135 InstructionOperand* temps) {
136 size_t output_count = output.IsInvalid() ? 0 : 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000137 return Emit(opcode, output_count, &output, 1, &a, temp_count, temps);
138}
139
140
141Instruction* InstructionSelector::Emit(InstructionCode opcode,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000142 InstructionOperand output,
143 InstructionOperand a,
144 InstructionOperand b, size_t temp_count,
145 InstructionOperand* temps) {
146 size_t output_count = output.IsInvalid() ? 0 : 1;
147 InstructionOperand inputs[] = {a, b};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000148 size_t input_count = arraysize(inputs);
149 return Emit(opcode, output_count, &output, input_count, inputs, temp_count,
150 temps);
151}
152
153
154Instruction* InstructionSelector::Emit(InstructionCode opcode,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000155 InstructionOperand output,
156 InstructionOperand a,
157 InstructionOperand b,
158 InstructionOperand c, size_t temp_count,
159 InstructionOperand* temps) {
160 size_t output_count = output.IsInvalid() ? 0 : 1;
161 InstructionOperand inputs[] = {a, b, c};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000162 size_t input_count = arraysize(inputs);
163 return Emit(opcode, output_count, &output, input_count, inputs, temp_count,
164 temps);
165}
166
167
168Instruction* InstructionSelector::Emit(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000169 InstructionCode opcode, InstructionOperand output, InstructionOperand a,
170 InstructionOperand b, InstructionOperand c, InstructionOperand d,
171 size_t temp_count, InstructionOperand* temps) {
172 size_t output_count = output.IsInvalid() ? 0 : 1;
173 InstructionOperand inputs[] = {a, b, c, d};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000174 size_t input_count = arraysize(inputs);
175 return Emit(opcode, output_count, &output, input_count, inputs, temp_count,
176 temps);
177}
178
179
180Instruction* InstructionSelector::Emit(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000181 InstructionCode opcode, InstructionOperand output, InstructionOperand a,
182 InstructionOperand b, InstructionOperand c, InstructionOperand d,
183 InstructionOperand e, size_t temp_count, InstructionOperand* temps) {
184 size_t output_count = output.IsInvalid() ? 0 : 1;
185 InstructionOperand inputs[] = {a, b, c, d, e};
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400186 size_t input_count = arraysize(inputs);
187 return Emit(opcode, output_count, &output, input_count, inputs, temp_count,
188 temps);
189}
190
191
192Instruction* InstructionSelector::Emit(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000193 InstructionCode opcode, InstructionOperand output, InstructionOperand a,
194 InstructionOperand b, InstructionOperand c, InstructionOperand d,
195 InstructionOperand e, InstructionOperand f, size_t temp_count,
196 InstructionOperand* temps) {
197 size_t output_count = output.IsInvalid() ? 0 : 1;
198 InstructionOperand inputs[] = {a, b, c, d, e, f};
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400199 size_t input_count = arraysize(inputs);
200 return Emit(opcode, output_count, &output, input_count, inputs, temp_count,
201 temps);
202}
203
204
205Instruction* InstructionSelector::Emit(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000206 InstructionCode opcode, size_t output_count, InstructionOperand* outputs,
207 size_t input_count, InstructionOperand* inputs, size_t temp_count,
208 InstructionOperand* temps) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000209 Instruction* instr =
210 Instruction::New(instruction_zone(), opcode, output_count, outputs,
211 input_count, inputs, temp_count, temps);
212 return Emit(instr);
213}
214
215
216Instruction* InstructionSelector::Emit(Instruction* instr) {
217 instructions_.push_back(instr);
218 return instr;
219}
220
221
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000222bool InstructionSelector::CanCover(Node* user, Node* node) const {
Ben Murdochda12d292016-06-02 14:46:10 +0100223 // 1. Both {user} and {node} must be in the same basic block.
224 if (schedule()->block(node) != schedule()->block(user)) {
225 return false;
226 }
227 // 2. Pure {node}s must be owned by the {user}.
228 if (node->op()->HasProperty(Operator::kPure)) {
229 return node->OwnedBy(user);
230 }
231 // 3. Impure {node}s must match the effect level of {user}.
232 if (GetEffectLevel(node) != GetEffectLevel(user)) {
233 return false;
234 }
235 // 4. Only {node} must have value edges pointing to {user}.
236 for (Edge const edge : node->use_edges()) {
237 if (edge.from() != user && NodeProperties::IsValueEdge(edge)) {
238 return false;
239 }
240 }
241 return true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000242}
243
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400244int InstructionSelector::GetVirtualRegister(const Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000245 DCHECK_NOT_NULL(node);
246 size_t const id = node->id();
247 DCHECK_LT(id, virtual_registers_.size());
248 int virtual_register = virtual_registers_[id];
249 if (virtual_register == InstructionOperand::kInvalidVirtualRegister) {
250 virtual_register = sequence()->NextVirtualRegister();
251 virtual_registers_[id] = virtual_register;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400252 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000253 return virtual_register;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400254}
255
256
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000257const std::map<NodeId, int> InstructionSelector::GetVirtualRegistersForTesting()
258 const {
259 std::map<NodeId, int> virtual_registers;
260 for (size_t n = 0; n < virtual_registers_.size(); ++n) {
261 if (virtual_registers_[n] != InstructionOperand::kInvalidVirtualRegister) {
262 NodeId const id = static_cast<NodeId>(n);
263 virtual_registers.insert(std::make_pair(id, virtual_registers_[n]));
264 }
265 }
266 return virtual_registers;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400267}
268
269
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000270bool InstructionSelector::IsDefined(Node* node) const {
271 DCHECK_NOT_NULL(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000272 size_t const id = node->id();
273 DCHECK_LT(id, defined_.size());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000274 return defined_[id];
275}
276
277
278void InstructionSelector::MarkAsDefined(Node* node) {
279 DCHECK_NOT_NULL(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000280 size_t const id = node->id();
281 DCHECK_LT(id, defined_.size());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000282 defined_[id] = true;
283}
284
285
286bool InstructionSelector::IsUsed(Node* node) const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000287 DCHECK_NOT_NULL(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000288 if (!node->op()->HasProperty(Operator::kEliminatable)) return true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000289 size_t const id = node->id();
290 DCHECK_LT(id, used_.size());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000291 return used_[id];
292}
293
294
295void InstructionSelector::MarkAsUsed(Node* node) {
296 DCHECK_NOT_NULL(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000297 size_t const id = node->id();
298 DCHECK_LT(id, used_.size());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000299 used_[id] = true;
300}
301
Ben Murdoch097c5b22016-05-18 11:27:45 +0100302int InstructionSelector::GetEffectLevel(Node* node) const {
303 DCHECK_NOT_NULL(node);
304 size_t const id = node->id();
305 DCHECK_LT(id, effect_level_.size());
306 return effect_level_[id];
307}
308
309void InstructionSelector::SetEffectLevel(Node* node, int effect_level) {
310 DCHECK_NOT_NULL(node);
311 size_t const id = node->id();
312 DCHECK_LT(id, effect_level_.size());
313 effect_level_[id] = effect_level;
314}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000315
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000316void InstructionSelector::MarkAsRepresentation(MachineRepresentation rep,
317 const InstructionOperand& op) {
318 UnallocatedOperand unalloc = UnallocatedOperand::cast(op);
319 sequence()->MarkAsRepresentation(rep, unalloc.virtual_register());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000320}
321
322
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000323void InstructionSelector::MarkAsRepresentation(MachineRepresentation rep,
324 Node* node) {
325 sequence()->MarkAsRepresentation(rep, GetVirtualRegister(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000326}
327
328
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000329namespace {
330
331enum class FrameStateInputKind { kAny, kStackSlot };
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000332
333
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000334InstructionOperand OperandForDeopt(OperandGenerator* g, Node* input,
335 FrameStateInputKind kind) {
336 switch (input->opcode()) {
337 case IrOpcode::kInt32Constant:
338 case IrOpcode::kNumberConstant:
339 case IrOpcode::kFloat32Constant:
340 case IrOpcode::kFloat64Constant:
341 case IrOpcode::kHeapConstant:
342 return g->UseImmediate(input);
343 case IrOpcode::kObjectState:
344 UNREACHABLE();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400345 break;
346 default:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000347 switch (kind) {
348 case FrameStateInputKind::kStackSlot:
349 return g->UseUniqueSlot(input);
350 case FrameStateInputKind::kAny:
351 return g->UseAny(input);
352 }
353 }
354 UNREACHABLE();
355 return InstructionOperand();
356}
357
358
359class StateObjectDeduplicator {
360 public:
361 explicit StateObjectDeduplicator(Zone* zone) : objects_(zone) {}
362 static const size_t kNotDuplicated = SIZE_MAX;
363
364 size_t GetObjectId(Node* node) {
365 for (size_t i = 0; i < objects_.size(); ++i) {
366 if (objects_[i] == node) {
367 return i;
368 }
369 }
370 return kNotDuplicated;
371 }
372
373 size_t InsertObject(Node* node) {
374 size_t id = objects_.size();
375 objects_.push_back(node);
376 return id;
377 }
378
379 private:
380 ZoneVector<Node*> objects_;
381};
382
383
384// Returns the number of instruction operands added to inputs.
385size_t AddOperandToStateValueDescriptor(StateValueDescriptor* descriptor,
386 InstructionOperandVector* inputs,
387 OperandGenerator* g,
388 StateObjectDeduplicator* deduplicator,
389 Node* input, MachineType type,
390 FrameStateInputKind kind, Zone* zone) {
391 switch (input->opcode()) {
392 case IrOpcode::kObjectState: {
393 size_t id = deduplicator->GetObjectId(input);
394 if (id == StateObjectDeduplicator::kNotDuplicated) {
395 size_t entries = 0;
396 id = deduplicator->InsertObject(input);
397 descriptor->fields().push_back(
398 StateValueDescriptor::Recursive(zone, id));
399 StateValueDescriptor* new_desc = &descriptor->fields().back();
400 for (Edge edge : input->input_edges()) {
401 entries += AddOperandToStateValueDescriptor(
402 new_desc, inputs, g, deduplicator, edge.to(),
403 MachineType::AnyTagged(), kind, zone);
404 }
405 return entries;
406 } else {
407 // Crankshaft counts duplicate objects for the running id, so we have
408 // to push the input again.
409 deduplicator->InsertObject(input);
410 descriptor->fields().push_back(
411 StateValueDescriptor::Duplicate(zone, id));
412 return 0;
413 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400414 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000415 }
416 default: {
417 inputs->push_back(OperandForDeopt(g, input, kind));
418 descriptor->fields().push_back(StateValueDescriptor::Plain(zone, type));
419 return 1;
420 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400421 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000422}
423
424
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000425// Returns the number of instruction operands added to inputs.
426size_t AddInputsToFrameStateDescriptor(FrameStateDescriptor* descriptor,
427 Node* state, OperandGenerator* g,
428 StateObjectDeduplicator* deduplicator,
429 InstructionOperandVector* inputs,
430 FrameStateInputKind kind, Zone* zone) {
431 DCHECK_EQ(IrOpcode::kFrameState, state->op()->opcode());
432
433 size_t entries = 0;
434 size_t initial_size = inputs->size();
435 USE(initial_size); // initial_size is only used for debug.
436
437 if (descriptor->outer_state()) {
438 entries += AddInputsToFrameStateDescriptor(
439 descriptor->outer_state(), state->InputAt(kFrameStateOuterStateInput),
440 g, deduplicator, inputs, kind, zone);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000441 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000442
443 Node* parameters = state->InputAt(kFrameStateParametersInput);
444 Node* locals = state->InputAt(kFrameStateLocalsInput);
445 Node* stack = state->InputAt(kFrameStateStackInput);
446 Node* context = state->InputAt(kFrameStateContextInput);
447 Node* function = state->InputAt(kFrameStateFunctionInput);
448
449 DCHECK_EQ(descriptor->parameters_count(),
450 StateValuesAccess(parameters).size());
451 DCHECK_EQ(descriptor->locals_count(), StateValuesAccess(locals).size());
452 DCHECK_EQ(descriptor->stack_count(), StateValuesAccess(stack).size());
453
454 StateValueDescriptor* values_descriptor =
455 descriptor->GetStateValueDescriptor();
456 entries += AddOperandToStateValueDescriptor(
457 values_descriptor, inputs, g, deduplicator, function,
458 MachineType::AnyTagged(), FrameStateInputKind::kStackSlot, zone);
459 for (StateValuesAccess::TypedNode input_node :
460 StateValuesAccess(parameters)) {
461 entries += AddOperandToStateValueDescriptor(values_descriptor, inputs, g,
462 deduplicator, input_node.node,
463 input_node.type, kind, zone);
464 }
465 if (descriptor->HasContext()) {
466 entries += AddOperandToStateValueDescriptor(
467 values_descriptor, inputs, g, deduplicator, context,
468 MachineType::AnyTagged(), FrameStateInputKind::kStackSlot, zone);
469 }
470 for (StateValuesAccess::TypedNode input_node : StateValuesAccess(locals)) {
471 entries += AddOperandToStateValueDescriptor(values_descriptor, inputs, g,
472 deduplicator, input_node.node,
473 input_node.type, kind, zone);
474 }
475 for (StateValuesAccess::TypedNode input_node : StateValuesAccess(stack)) {
476 entries += AddOperandToStateValueDescriptor(values_descriptor, inputs, g,
477 deduplicator, input_node.node,
478 input_node.type, kind, zone);
479 }
480 DCHECK_EQ(initial_size + entries, inputs->size());
481 return entries;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000482}
483
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000484} // namespace
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000485
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000486
487// An internal helper class for generating the operands to calls.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000488// TODO(bmeurer): Get rid of the CallBuffer business and make
489// InstructionSelector::VisitCall platform independent instead.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000490struct CallBuffer {
491 CallBuffer(Zone* zone, const CallDescriptor* descriptor,
492 FrameStateDescriptor* frame_state)
493 : descriptor(descriptor),
494 frame_state_descriptor(frame_state),
495 output_nodes(zone),
496 outputs(zone),
497 instruction_args(zone),
498 pushed_nodes(zone) {
499 output_nodes.reserve(descriptor->ReturnCount());
500 outputs.reserve(descriptor->ReturnCount());
501 pushed_nodes.reserve(input_count());
502 instruction_args.reserve(input_count() + frame_state_value_count());
503 }
504
505
506 const CallDescriptor* descriptor;
507 FrameStateDescriptor* frame_state_descriptor;
508 NodeVector output_nodes;
509 InstructionOperandVector outputs;
510 InstructionOperandVector instruction_args;
511 ZoneVector<PushParameter> pushed_nodes;
512
513 size_t input_count() const { return descriptor->InputCount(); }
514
515 size_t frame_state_count() const { return descriptor->FrameStateCount(); }
516
517 size_t frame_state_value_count() const {
518 return (frame_state_descriptor == nullptr)
519 ? 0
520 : (frame_state_descriptor->GetTotalSize() +
521 1); // Include deopt id.
522 }
523};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000524
525
526// TODO(bmeurer): Get rid of the CallBuffer business and make
527// InstructionSelector::VisitCall platform independent instead.
528void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000529 CallBufferFlags flags,
530 int stack_param_delta) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000531 OperandGenerator g(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000532 DCHECK_LE(call->op()->ValueOutputCount(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400533 static_cast<int>(buffer->descriptor->ReturnCount()));
534 DCHECK_EQ(
535 call->op()->ValueInputCount(),
536 static_cast<int>(buffer->input_count() + buffer->frame_state_count()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000537
538 if (buffer->descriptor->ReturnCount() > 0) {
539 // Collect the projections that represent multiple outputs from this call.
540 if (buffer->descriptor->ReturnCount() == 1) {
541 buffer->output_nodes.push_back(call);
542 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000543 buffer->output_nodes.resize(buffer->descriptor->ReturnCount(), nullptr);
544 for (auto use : call->uses()) {
545 if (use->opcode() != IrOpcode::kProjection) continue;
546 size_t const index = ProjectionIndexOf(use->op());
547 DCHECK_LT(index, buffer->output_nodes.size());
548 DCHECK(!buffer->output_nodes[index]);
549 buffer->output_nodes[index] = use;
550 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000551 }
552
553 // Filter out the outputs that aren't live because no projection uses them.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400554 size_t outputs_needed_by_framestate =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000555 buffer->frame_state_descriptor == nullptr
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400556 ? 0
557 : buffer->frame_state_descriptor->state_combine()
558 .ConsumedOutputCount();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000559 for (size_t i = 0; i < buffer->output_nodes.size(); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000560 bool output_is_live = buffer->output_nodes[i] != nullptr ||
561 i < outputs_needed_by_framestate;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400562 if (output_is_live) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000563 MachineType type =
564 buffer->descriptor->GetReturnType(static_cast<int>(i));
565 LinkageLocation location =
566 buffer->descriptor->GetReturnLocation(static_cast<int>(i));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400567
568 Node* output = buffer->output_nodes[i];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000569 InstructionOperand op =
570 output == nullptr
571 ? g.TempLocation(location, type.representation())
572 : g.DefineAsLocation(output, location, type.representation());
573 MarkAsRepresentation(type.representation(), op);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400574
575 buffer->outputs.push_back(op);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000576 }
577 }
578 }
579
580 // The first argument is always the callee code.
581 Node* callee = call->InputAt(0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000582 bool call_code_immediate = (flags & kCallCodeImmediate) != 0;
583 bool call_address_immediate = (flags & kCallAddressImmediate) != 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000584 switch (buffer->descriptor->kind()) {
585 case CallDescriptor::kCallCodeObject:
586 buffer->instruction_args.push_back(
587 (call_code_immediate && callee->opcode() == IrOpcode::kHeapConstant)
588 ? g.UseImmediate(callee)
589 : g.UseRegister(callee));
590 break;
591 case CallDescriptor::kCallAddress:
592 buffer->instruction_args.push_back(
593 (call_address_immediate &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000594 callee->opcode() == IrOpcode::kExternalConstant)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000595 ? g.UseImmediate(callee)
596 : g.UseRegister(callee));
597 break;
598 case CallDescriptor::kCallJSFunction:
599 buffer->instruction_args.push_back(
600 g.UseLocation(callee, buffer->descriptor->GetInputLocation(0),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000601 buffer->descriptor->GetInputType(0).representation()));
602 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000603 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000604 DCHECK_EQ(1u, buffer->instruction_args.size());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000605
606 // If the call needs a frame state, we insert the state information as
607 // follows (n is the number of value inputs to the frame state):
608 // arg 1 : deoptimization id.
609 // arg 2 - arg (n + 1) : value inputs to the frame state.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000610 size_t frame_state_entries = 0;
611 USE(frame_state_entries); // frame_state_entries is only used for debug.
612 if (buffer->frame_state_descriptor != nullptr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100613 Node* frame_state =
614 call->InputAt(static_cast<int>(buffer->descriptor->InputCount()));
615
616 // If it was a syntactic tail call we need to drop the current frame and
Ben Murdochda12d292016-06-02 14:46:10 +0100617 // all the frames on top of it that are either an arguments adaptor frame
618 // or a tail caller frame.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100619 if (buffer->descriptor->SupportsTailCalls()) {
620 frame_state = NodeProperties::GetFrameStateInput(frame_state, 0);
621 buffer->frame_state_descriptor =
622 buffer->frame_state_descriptor->outer_state();
Ben Murdochda12d292016-06-02 14:46:10 +0100623 while (buffer->frame_state_descriptor != nullptr &&
624 (buffer->frame_state_descriptor->type() ==
625 FrameStateType::kArgumentsAdaptor ||
626 buffer->frame_state_descriptor->type() ==
627 FrameStateType::kTailCallerFunction)) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100628 frame_state = NodeProperties::GetFrameStateInput(frame_state, 0);
629 buffer->frame_state_descriptor =
630 buffer->frame_state_descriptor->outer_state();
631 }
632 }
633
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000634 InstructionSequence::StateId state_id =
635 sequence()->AddFrameStateDescriptor(buffer->frame_state_descriptor);
636 buffer->instruction_args.push_back(g.TempImmediate(state_id.ToInt()));
637
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000638 StateObjectDeduplicator deduplicator(instruction_zone());
639
640 frame_state_entries =
641 1 + AddInputsToFrameStateDescriptor(
642 buffer->frame_state_descriptor, frame_state, &g, &deduplicator,
643 &buffer->instruction_args, FrameStateInputKind::kStackSlot,
644 instruction_zone());
645
646 DCHECK_EQ(1 + frame_state_entries, buffer->instruction_args.size());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000647 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000648
649 size_t input_count = static_cast<size_t>(buffer->input_count());
650
651 // Split the arguments into pushed_nodes and instruction_args. Pushed
652 // arguments require an explicit push instruction before the call and do
653 // not appear as arguments to the call. Everything else ends up
654 // as an InstructionOperand argument to the call.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400655 auto iter(call->inputs().begin());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000656 size_t pushed_count = 0;
657 bool call_tail = (flags & kCallTail) != 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000658 for (size_t index = 0; index < input_count; ++iter, ++index) {
659 DCHECK(iter != call->inputs().end());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000660 DCHECK((*iter)->op()->opcode() != IrOpcode::kFrameState);
661 if (index == 0) continue; // The first argument (callee) is already done.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000662
663 LinkageLocation location = buffer->descriptor->GetInputLocation(index);
664 if (call_tail) {
665 location = LinkageLocation::ConvertToTailCallerLocation(
666 location, stack_param_delta);
667 }
668 InstructionOperand op =
669 g.UseLocation(*iter, location,
670 buffer->descriptor->GetInputType(index).representation());
671 if (UnallocatedOperand::cast(op).HasFixedSlotPolicy() && !call_tail) {
672 int stack_index = -UnallocatedOperand::cast(op).fixed_slot_index() - 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000673 if (static_cast<size_t>(stack_index) >= buffer->pushed_nodes.size()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000674 buffer->pushed_nodes.resize(stack_index + 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000675 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000676 PushParameter parameter(*iter, buffer->descriptor->GetInputType(index));
677 buffer->pushed_nodes[stack_index] = parameter;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000678 pushed_count++;
679 } else {
680 buffer->instruction_args.push_back(op);
681 }
682 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000683 DCHECK_EQ(input_count, buffer->instruction_args.size() + pushed_count -
684 frame_state_entries);
685 if (V8_TARGET_ARCH_STORES_RETURN_ADDRESS_ON_STACK && call_tail &&
686 stack_param_delta != 0) {
687 // For tail calls that change the size of their parameter list and keep
688 // their return address on the stack, move the return address to just above
689 // the parameters.
690 LinkageLocation saved_return_location =
691 LinkageLocation::ForSavedCallerReturnAddress();
692 InstructionOperand return_address =
693 g.UsePointerLocation(LinkageLocation::ConvertToTailCallerLocation(
694 saved_return_location, stack_param_delta),
695 saved_return_location);
696 buffer->instruction_args.push_back(return_address);
697 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000698}
699
700
701void InstructionSelector::VisitBlock(BasicBlock* block) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000702 DCHECK(!current_block_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000703 current_block_ = block;
704 int current_block_end = static_cast<int>(instructions_.size());
705
Ben Murdoch097c5b22016-05-18 11:27:45 +0100706 int effect_level = 0;
707 for (Node* const node : *block) {
708 if (node->opcode() == IrOpcode::kStore ||
709 node->opcode() == IrOpcode::kCheckedStore ||
710 node->opcode() == IrOpcode::kCall) {
711 ++effect_level;
712 }
713 SetEffectLevel(node, effect_level);
714 }
715
Ben Murdochc5610432016-08-08 18:44:38 +0100716 // We visit the control first, then the nodes in the block, so the block's
717 // control input should be on the same effect level as the last node.
718 if (block->control_input() != nullptr) {
719 SetEffectLevel(block->control_input(), effect_level);
720 }
721
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000722 // Generate code for the block control "top down", but schedule the code
723 // "bottom up".
724 VisitControl(block);
725 std::reverse(instructions_.begin() + current_block_end, instructions_.end());
726
727 // Visit code in reverse control flow order, because architecture-specific
728 // matching may cover more than one node at a time.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000729 for (auto node : base::Reversed(*block)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000730 // Skip nodes that are unused or already defined.
731 if (!IsUsed(node) || IsDefined(node)) continue;
732 // Generate code for this node "top down", but schedule the code "bottom
733 // up".
734 size_t current_node_end = instructions_.size();
735 VisitNode(node);
736 std::reverse(instructions_.begin() + current_node_end, instructions_.end());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000737 if (instructions_.size() == current_node_end) continue;
738 // Mark source position on first instruction emitted.
739 SourcePosition source_position = source_positions_->GetSourcePosition(node);
740 if (source_position.IsKnown() &&
741 (source_position_mode_ == kAllSourcePositions ||
742 node->opcode() == IrOpcode::kCall)) {
743 sequence()->SetSourcePosition(instructions_[current_node_end],
744 source_position);
745 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000746 }
747
748 // We're done with the block.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400749 InstructionBlock* instruction_block =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000750 sequence()->InstructionBlockAt(RpoNumber::FromInt(block->rpo_number()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400751 instruction_block->set_code_start(static_cast<int>(instructions_.size()));
752 instruction_block->set_code_end(current_block_end);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000753
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000754 current_block_ = nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000755}
756
757
758void InstructionSelector::VisitControl(BasicBlock* block) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000759#ifdef DEBUG
760 // SSA deconstruction requires targets of branches not to have phis.
761 // Edge split form guarantees this property, but is more strict.
762 if (block->SuccessorCount() > 1) {
763 for (BasicBlock* const successor : block->successors()) {
764 for (Node* const node : *successor) {
765 CHECK(!IrOpcode::IsPhiOpcode(node->opcode()));
766 }
767 }
768 }
769#endif
770
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400771 Node* input = block->control_input();
772 switch (block->control()) {
773 case BasicBlock::kGoto:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000774 return VisitGoto(block->SuccessorAt(0));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000775 case BasicBlock::kCall: {
776 DCHECK_EQ(IrOpcode::kCall, input->opcode());
777 BasicBlock* success = block->SuccessorAt(0);
778 BasicBlock* exception = block->SuccessorAt(1);
779 return VisitCall(input, exception), VisitGoto(success);
780 }
781 case BasicBlock::kTailCall: {
782 DCHECK_EQ(IrOpcode::kTailCall, input->opcode());
783 return VisitTailCall(input);
784 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400785 case BasicBlock::kBranch: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000786 DCHECK_EQ(IrOpcode::kBranch, input->opcode());
787 BasicBlock* tbranch = block->SuccessorAt(0);
788 BasicBlock* fbranch = block->SuccessorAt(1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000789 if (tbranch == fbranch) return VisitGoto(tbranch);
790 return VisitBranch(input, tbranch, fbranch);
791 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000792 case BasicBlock::kSwitch: {
793 DCHECK_EQ(IrOpcode::kSwitch, input->opcode());
794 SwitchInfo sw;
795 // Last successor must be Default.
796 sw.default_branch = block->successors().back();
797 DCHECK_EQ(IrOpcode::kIfDefault, sw.default_branch->front()->opcode());
798 // All other successors must be cases.
799 sw.case_count = block->SuccessorCount() - 1;
800 sw.case_branches = &block->successors().front();
801 // Determine case values and their min/max.
802 sw.case_values = zone()->NewArray<int32_t>(sw.case_count);
803 sw.min_value = std::numeric_limits<int32_t>::max();
804 sw.max_value = std::numeric_limits<int32_t>::min();
805 for (size_t index = 0; index < sw.case_count; ++index) {
806 BasicBlock* branch = sw.case_branches[index];
807 int32_t value = OpParameter<int32_t>(branch->front()->op());
808 sw.case_values[index] = value;
809 if (sw.min_value > value) sw.min_value = value;
810 if (sw.max_value < value) sw.max_value = value;
811 }
812 DCHECK_LE(sw.min_value, sw.max_value);
813 // Note that {value_range} can be 0 if {min_value} is -2^31 and
814 // {max_value}
815 // is 2^31-1, so don't assume that it's non-zero below.
816 sw.value_range = 1u + bit_cast<uint32_t>(sw.max_value) -
817 bit_cast<uint32_t>(sw.min_value);
818 return VisitSwitch(input, sw);
819 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400820 case BasicBlock::kReturn: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000821 DCHECK_EQ(IrOpcode::kReturn, input->opcode());
822 return VisitReturn(input);
823 }
824 case BasicBlock::kDeoptimize: {
825 DeoptimizeKind kind = DeoptimizeKindOf(input->op());
826 Node* value = input->InputAt(0);
827 return VisitDeoptimize(kind, value);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000828 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400829 case BasicBlock::kThrow:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000830 DCHECK_EQ(IrOpcode::kThrow, input->opcode());
831 return VisitThrow(input->InputAt(0));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400832 case BasicBlock::kNone: {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100833 // Exit block doesn't have control.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000834 DCHECK_NULL(input);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000835 break;
836 }
837 default:
838 UNREACHABLE();
839 break;
840 }
841}
842
843
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000844void InstructionSelector::VisitNode(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400845 DCHECK_NOT_NULL(schedule()->block(node)); // should only use scheduled nodes.
846 switch (node->opcode()) {
847 case IrOpcode::kStart:
848 case IrOpcode::kLoop:
849 case IrOpcode::kEnd:
850 case IrOpcode::kBranch:
851 case IrOpcode::kIfTrue:
852 case IrOpcode::kIfFalse:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000853 case IrOpcode::kIfSuccess:
854 case IrOpcode::kSwitch:
855 case IrOpcode::kIfValue:
856 case IrOpcode::kIfDefault:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400857 case IrOpcode::kEffectPhi:
858 case IrOpcode::kMerge:
859 case IrOpcode::kTerminate:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000860 case IrOpcode::kBeginRegion:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000861 // No code needed for these graph artifacts.
862 return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000863 case IrOpcode::kIfException:
864 return MarkAsReference(node), VisitIfException(node);
865 case IrOpcode::kFinishRegion:
866 return MarkAsReference(node), VisitFinishRegion(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000867 case IrOpcode::kParameter: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000868 MachineType type =
869 linkage()->GetParameterType(ParameterIndexOf(node->op()));
870 MarkAsRepresentation(type.representation(), node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000871 return VisitParameter(node);
872 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000873 case IrOpcode::kOsrValue:
874 return MarkAsReference(node), VisitOsrValue(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000875 case IrOpcode::kPhi: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000876 MachineRepresentation rep = PhiRepresentationOf(node->op());
877 MarkAsRepresentation(rep, node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000878 return VisitPhi(node);
879 }
880 case IrOpcode::kProjection:
881 return VisitProjection(node);
882 case IrOpcode::kInt32Constant:
883 case IrOpcode::kInt64Constant:
884 case IrOpcode::kExternalConstant:
Ben Murdochc5610432016-08-08 18:44:38 +0100885 case IrOpcode::kRelocatableInt32Constant:
886 case IrOpcode::kRelocatableInt64Constant:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000887 return VisitConstant(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400888 case IrOpcode::kFloat32Constant:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000889 return MarkAsFloat32(node), VisitConstant(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000890 case IrOpcode::kFloat64Constant:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000891 return MarkAsFloat64(node), VisitConstant(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000892 case IrOpcode::kHeapConstant:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000893 return MarkAsReference(node), VisitConstant(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000894 case IrOpcode::kNumberConstant: {
895 double value = OpParameter<double>(node);
896 if (!IsSmiDouble(value)) MarkAsReference(node);
897 return VisitConstant(node);
898 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000899 case IrOpcode::kCall:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400900 return VisitCall(node);
Ben Murdochda12d292016-06-02 14:46:10 +0100901 case IrOpcode::kDeoptimizeIf:
902 return VisitDeoptimizeIf(node);
903 case IrOpcode::kDeoptimizeUnless:
904 return VisitDeoptimizeUnless(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000905 case IrOpcode::kFrameState:
906 case IrOpcode::kStateValues:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000907 case IrOpcode::kObjectState:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000908 return;
909 case IrOpcode::kLoad: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000910 LoadRepresentation type = LoadRepresentationOf(node->op());
911 MarkAsRepresentation(type.representation(), node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000912 return VisitLoad(node);
913 }
914 case IrOpcode::kStore:
915 return VisitStore(node);
916 case IrOpcode::kWord32And:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000917 return MarkAsWord32(node), VisitWord32And(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000918 case IrOpcode::kWord32Or:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000919 return MarkAsWord32(node), VisitWord32Or(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000920 case IrOpcode::kWord32Xor:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000921 return MarkAsWord32(node), VisitWord32Xor(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000922 case IrOpcode::kWord32Shl:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000923 return MarkAsWord32(node), VisitWord32Shl(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000924 case IrOpcode::kWord32Shr:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000925 return MarkAsWord32(node), VisitWord32Shr(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000926 case IrOpcode::kWord32Sar:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000927 return MarkAsWord32(node), VisitWord32Sar(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000928 case IrOpcode::kWord32Ror:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000929 return MarkAsWord32(node), VisitWord32Ror(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000930 case IrOpcode::kWord32Equal:
931 return VisitWord32Equal(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000932 case IrOpcode::kWord32Clz:
933 return MarkAsWord32(node), VisitWord32Clz(node);
934 case IrOpcode::kWord32Ctz:
935 return MarkAsWord32(node), VisitWord32Ctz(node);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100936 case IrOpcode::kWord32ReverseBits:
937 return MarkAsWord32(node), VisitWord32ReverseBits(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000938 case IrOpcode::kWord32Popcnt:
939 return MarkAsWord32(node), VisitWord32Popcnt(node);
940 case IrOpcode::kWord64Popcnt:
941 return MarkAsWord32(node), VisitWord64Popcnt(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000942 case IrOpcode::kWord64And:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000943 return MarkAsWord64(node), VisitWord64And(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000944 case IrOpcode::kWord64Or:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000945 return MarkAsWord64(node), VisitWord64Or(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000946 case IrOpcode::kWord64Xor:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000947 return MarkAsWord64(node), VisitWord64Xor(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000948 case IrOpcode::kWord64Shl:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000949 return MarkAsWord64(node), VisitWord64Shl(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000950 case IrOpcode::kWord64Shr:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000951 return MarkAsWord64(node), VisitWord64Shr(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000952 case IrOpcode::kWord64Sar:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000953 return MarkAsWord64(node), VisitWord64Sar(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000954 case IrOpcode::kWord64Ror:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000955 return MarkAsWord64(node), VisitWord64Ror(node);
956 case IrOpcode::kWord64Clz:
957 return MarkAsWord64(node), VisitWord64Clz(node);
958 case IrOpcode::kWord64Ctz:
959 return MarkAsWord64(node), VisitWord64Ctz(node);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100960 case IrOpcode::kWord64ReverseBits:
961 return MarkAsWord64(node), VisitWord64ReverseBits(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000962 case IrOpcode::kWord64Equal:
963 return VisitWord64Equal(node);
964 case IrOpcode::kInt32Add:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000965 return MarkAsWord32(node), VisitInt32Add(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000966 case IrOpcode::kInt32AddWithOverflow:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000967 return MarkAsWord32(node), VisitInt32AddWithOverflow(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000968 case IrOpcode::kInt32Sub:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000969 return MarkAsWord32(node), VisitInt32Sub(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000970 case IrOpcode::kInt32SubWithOverflow:
971 return VisitInt32SubWithOverflow(node);
972 case IrOpcode::kInt32Mul:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000973 return MarkAsWord32(node), VisitInt32Mul(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400974 case IrOpcode::kInt32MulHigh:
975 return VisitInt32MulHigh(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000976 case IrOpcode::kInt32Div:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000977 return MarkAsWord32(node), VisitInt32Div(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000978 case IrOpcode::kInt32Mod:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000979 return MarkAsWord32(node), VisitInt32Mod(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000980 case IrOpcode::kInt32LessThan:
981 return VisitInt32LessThan(node);
982 case IrOpcode::kInt32LessThanOrEqual:
983 return VisitInt32LessThanOrEqual(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400984 case IrOpcode::kUint32Div:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000985 return MarkAsWord32(node), VisitUint32Div(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000986 case IrOpcode::kUint32LessThan:
987 return VisitUint32LessThan(node);
988 case IrOpcode::kUint32LessThanOrEqual:
989 return VisitUint32LessThanOrEqual(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400990 case IrOpcode::kUint32Mod:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000991 return MarkAsWord32(node), VisitUint32Mod(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400992 case IrOpcode::kUint32MulHigh:
993 return VisitUint32MulHigh(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000994 case IrOpcode::kInt64Add:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000995 return MarkAsWord64(node), VisitInt64Add(node);
996 case IrOpcode::kInt64AddWithOverflow:
997 return MarkAsWord64(node), VisitInt64AddWithOverflow(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000998 case IrOpcode::kInt64Sub:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000999 return MarkAsWord64(node), VisitInt64Sub(node);
1000 case IrOpcode::kInt64SubWithOverflow:
1001 return MarkAsWord64(node), VisitInt64SubWithOverflow(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001002 case IrOpcode::kInt64Mul:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001003 return MarkAsWord64(node), VisitInt64Mul(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001004 case IrOpcode::kInt64Div:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001005 return MarkAsWord64(node), VisitInt64Div(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001006 case IrOpcode::kInt64Mod:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001007 return MarkAsWord64(node), VisitInt64Mod(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001008 case IrOpcode::kInt64LessThan:
1009 return VisitInt64LessThan(node);
1010 case IrOpcode::kInt64LessThanOrEqual:
1011 return VisitInt64LessThanOrEqual(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001012 case IrOpcode::kUint64Div:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001013 return MarkAsWord64(node), VisitUint64Div(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001014 case IrOpcode::kUint64LessThan:
1015 return VisitUint64LessThan(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001016 case IrOpcode::kUint64LessThanOrEqual:
1017 return VisitUint64LessThanOrEqual(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001018 case IrOpcode::kUint64Mod:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001019 return MarkAsWord64(node), VisitUint64Mod(node);
Ben Murdochc5610432016-08-08 18:44:38 +01001020 case IrOpcode::kBitcastWordToTagged:
1021 return MarkAsReference(node), VisitBitcastWordToTagged(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001022 case IrOpcode::kChangeFloat32ToFloat64:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001023 return MarkAsFloat64(node), VisitChangeFloat32ToFloat64(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001024 case IrOpcode::kChangeInt32ToFloat64:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001025 return MarkAsFloat64(node), VisitChangeInt32ToFloat64(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001026 case IrOpcode::kChangeUint32ToFloat64:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001027 return MarkAsFloat64(node), VisitChangeUint32ToFloat64(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001028 case IrOpcode::kChangeFloat64ToInt32:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001029 return MarkAsWord32(node), VisitChangeFloat64ToInt32(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001030 case IrOpcode::kChangeFloat64ToUint32:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001031 return MarkAsWord32(node), VisitChangeFloat64ToUint32(node);
Ben Murdochda12d292016-06-02 14:46:10 +01001032 case IrOpcode::kTruncateFloat64ToUint32:
1033 return MarkAsWord32(node), VisitTruncateFloat64ToUint32(node);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001034 case IrOpcode::kTruncateFloat32ToInt32:
1035 return MarkAsWord32(node), VisitTruncateFloat32ToInt32(node);
1036 case IrOpcode::kTruncateFloat32ToUint32:
1037 return MarkAsWord32(node), VisitTruncateFloat32ToUint32(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001038 case IrOpcode::kTryTruncateFloat32ToInt64:
1039 return MarkAsWord64(node), VisitTryTruncateFloat32ToInt64(node);
1040 case IrOpcode::kTryTruncateFloat64ToInt64:
1041 return MarkAsWord64(node), VisitTryTruncateFloat64ToInt64(node);
1042 case IrOpcode::kTryTruncateFloat32ToUint64:
1043 return MarkAsWord64(node), VisitTryTruncateFloat32ToUint64(node);
1044 case IrOpcode::kTryTruncateFloat64ToUint64:
1045 return MarkAsWord64(node), VisitTryTruncateFloat64ToUint64(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001046 case IrOpcode::kChangeInt32ToInt64:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001047 return MarkAsWord64(node), VisitChangeInt32ToInt64(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001048 case IrOpcode::kChangeUint32ToUint64:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001049 return MarkAsWord64(node), VisitChangeUint32ToUint64(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001050 case IrOpcode::kTruncateFloat64ToFloat32:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001051 return MarkAsFloat32(node), VisitTruncateFloat64ToFloat32(node);
Ben Murdochc5610432016-08-08 18:44:38 +01001052 case IrOpcode::kTruncateFloat64ToWord32:
1053 return MarkAsWord32(node), VisitTruncateFloat64ToWord32(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001054 case IrOpcode::kTruncateInt64ToInt32:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001055 return MarkAsWord32(node), VisitTruncateInt64ToInt32(node);
Ben Murdochc5610432016-08-08 18:44:38 +01001056 case IrOpcode::kRoundFloat64ToInt32:
1057 return MarkAsWord32(node), VisitRoundFloat64ToInt32(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001058 case IrOpcode::kRoundInt64ToFloat32:
1059 return MarkAsFloat32(node), VisitRoundInt64ToFloat32(node);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001060 case IrOpcode::kRoundInt32ToFloat32:
1061 return MarkAsFloat32(node), VisitRoundInt32ToFloat32(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001062 case IrOpcode::kRoundInt64ToFloat64:
1063 return MarkAsFloat64(node), VisitRoundInt64ToFloat64(node);
1064 case IrOpcode::kBitcastFloat32ToInt32:
1065 return MarkAsWord32(node), VisitBitcastFloat32ToInt32(node);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001066 case IrOpcode::kRoundUint32ToFloat32:
1067 return MarkAsFloat32(node), VisitRoundUint32ToFloat32(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001068 case IrOpcode::kRoundUint64ToFloat32:
1069 return MarkAsFloat64(node), VisitRoundUint64ToFloat32(node);
1070 case IrOpcode::kRoundUint64ToFloat64:
1071 return MarkAsFloat64(node), VisitRoundUint64ToFloat64(node);
1072 case IrOpcode::kBitcastFloat64ToInt64:
1073 return MarkAsWord64(node), VisitBitcastFloat64ToInt64(node);
1074 case IrOpcode::kBitcastInt32ToFloat32:
1075 return MarkAsFloat32(node), VisitBitcastInt32ToFloat32(node);
1076 case IrOpcode::kBitcastInt64ToFloat64:
1077 return MarkAsFloat64(node), VisitBitcastInt64ToFloat64(node);
1078 case IrOpcode::kFloat32Add:
1079 return MarkAsFloat32(node), VisitFloat32Add(node);
1080 case IrOpcode::kFloat32Sub:
1081 return MarkAsFloat32(node), VisitFloat32Sub(node);
Ben Murdochc5610432016-08-08 18:44:38 +01001082 case IrOpcode::kFloat32SubPreserveNan:
1083 return MarkAsFloat32(node), VisitFloat32SubPreserveNan(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001084 case IrOpcode::kFloat32Mul:
1085 return MarkAsFloat32(node), VisitFloat32Mul(node);
1086 case IrOpcode::kFloat32Div:
1087 return MarkAsFloat32(node), VisitFloat32Div(node);
1088 case IrOpcode::kFloat32Min:
1089 return MarkAsFloat32(node), VisitFloat32Min(node);
1090 case IrOpcode::kFloat32Max:
1091 return MarkAsFloat32(node), VisitFloat32Max(node);
1092 case IrOpcode::kFloat32Abs:
1093 return MarkAsFloat32(node), VisitFloat32Abs(node);
1094 case IrOpcode::kFloat32Sqrt:
1095 return MarkAsFloat32(node), VisitFloat32Sqrt(node);
1096 case IrOpcode::kFloat32Equal:
1097 return VisitFloat32Equal(node);
1098 case IrOpcode::kFloat32LessThan:
1099 return VisitFloat32LessThan(node);
1100 case IrOpcode::kFloat32LessThanOrEqual:
1101 return VisitFloat32LessThanOrEqual(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001102 case IrOpcode::kFloat64Add:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001103 return MarkAsFloat64(node), VisitFloat64Add(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001104 case IrOpcode::kFloat64Sub:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001105 return MarkAsFloat64(node), VisitFloat64Sub(node);
Ben Murdochc5610432016-08-08 18:44:38 +01001106 case IrOpcode::kFloat64SubPreserveNan:
1107 return MarkAsFloat64(node), VisitFloat64SubPreserveNan(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001108 case IrOpcode::kFloat64Mul:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001109 return MarkAsFloat64(node), VisitFloat64Mul(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001110 case IrOpcode::kFloat64Div:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001111 return MarkAsFloat64(node), VisitFloat64Div(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001112 case IrOpcode::kFloat64Mod:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001113 return MarkAsFloat64(node), VisitFloat64Mod(node);
1114 case IrOpcode::kFloat64Min:
1115 return MarkAsFloat64(node), VisitFloat64Min(node);
1116 case IrOpcode::kFloat64Max:
1117 return MarkAsFloat64(node), VisitFloat64Max(node);
1118 case IrOpcode::kFloat64Abs:
1119 return MarkAsFloat64(node), VisitFloat64Abs(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001120 case IrOpcode::kFloat64Sqrt:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001121 return MarkAsFloat64(node), VisitFloat64Sqrt(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001122 case IrOpcode::kFloat64Equal:
1123 return VisitFloat64Equal(node);
1124 case IrOpcode::kFloat64LessThan:
1125 return VisitFloat64LessThan(node);
1126 case IrOpcode::kFloat64LessThanOrEqual:
1127 return VisitFloat64LessThanOrEqual(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001128 case IrOpcode::kFloat32RoundDown:
1129 return MarkAsFloat32(node), VisitFloat32RoundDown(node);
1130 case IrOpcode::kFloat64RoundDown:
1131 return MarkAsFloat64(node), VisitFloat64RoundDown(node);
1132 case IrOpcode::kFloat32RoundUp:
1133 return MarkAsFloat32(node), VisitFloat32RoundUp(node);
1134 case IrOpcode::kFloat64RoundUp:
1135 return MarkAsFloat64(node), VisitFloat64RoundUp(node);
1136 case IrOpcode::kFloat32RoundTruncate:
1137 return MarkAsFloat32(node), VisitFloat32RoundTruncate(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001138 case IrOpcode::kFloat64RoundTruncate:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001139 return MarkAsFloat64(node), VisitFloat64RoundTruncate(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001140 case IrOpcode::kFloat64RoundTiesAway:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001141 return MarkAsFloat64(node), VisitFloat64RoundTiesAway(node);
1142 case IrOpcode::kFloat32RoundTiesEven:
1143 return MarkAsFloat32(node), VisitFloat32RoundTiesEven(node);
1144 case IrOpcode::kFloat64RoundTiesEven:
1145 return MarkAsFloat64(node), VisitFloat64RoundTiesEven(node);
1146 case IrOpcode::kFloat64ExtractLowWord32:
1147 return MarkAsWord32(node), VisitFloat64ExtractLowWord32(node);
1148 case IrOpcode::kFloat64ExtractHighWord32:
1149 return MarkAsWord32(node), VisitFloat64ExtractHighWord32(node);
1150 case IrOpcode::kFloat64InsertLowWord32:
1151 return MarkAsFloat64(node), VisitFloat64InsertLowWord32(node);
1152 case IrOpcode::kFloat64InsertHighWord32:
1153 return MarkAsFloat64(node), VisitFloat64InsertHighWord32(node);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001154 case IrOpcode::kStackSlot:
1155 return VisitStackSlot(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001156 case IrOpcode::kLoadStackPointer:
1157 return VisitLoadStackPointer(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001158 case IrOpcode::kLoadFramePointer:
1159 return VisitLoadFramePointer(node);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001160 case IrOpcode::kLoadParentFramePointer:
1161 return VisitLoadParentFramePointer(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001162 case IrOpcode::kCheckedLoad: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001163 MachineRepresentation rep =
1164 CheckedLoadRepresentationOf(node->op()).representation();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001165 MarkAsRepresentation(rep, node);
1166 return VisitCheckedLoad(node);
1167 }
1168 case IrOpcode::kCheckedStore:
1169 return VisitCheckedStore(node);
Ben Murdochda12d292016-06-02 14:46:10 +01001170 case IrOpcode::kInt32PairAdd:
1171 MarkAsWord32(NodeProperties::FindProjection(node, 0));
1172 MarkAsWord32(NodeProperties::FindProjection(node, 1));
1173 return VisitInt32PairAdd(node);
1174 case IrOpcode::kInt32PairSub:
1175 MarkAsWord32(NodeProperties::FindProjection(node, 0));
1176 MarkAsWord32(NodeProperties::FindProjection(node, 1));
1177 return VisitInt32PairSub(node);
1178 case IrOpcode::kInt32PairMul:
1179 MarkAsWord32(NodeProperties::FindProjection(node, 0));
1180 MarkAsWord32(NodeProperties::FindProjection(node, 1));
1181 return VisitInt32PairMul(node);
1182 case IrOpcode::kWord32PairShl:
1183 MarkAsWord32(NodeProperties::FindProjection(node, 0));
1184 MarkAsWord32(NodeProperties::FindProjection(node, 1));
1185 return VisitWord32PairShl(node);
1186 case IrOpcode::kWord32PairShr:
1187 MarkAsWord32(NodeProperties::FindProjection(node, 0));
1188 MarkAsWord32(NodeProperties::FindProjection(node, 1));
1189 return VisitWord32PairShr(node);
1190 case IrOpcode::kWord32PairSar:
1191 MarkAsWord32(NodeProperties::FindProjection(node, 0));
1192 MarkAsWord32(NodeProperties::FindProjection(node, 1));
1193 return VisitWord32PairSar(node);
Ben Murdochc5610432016-08-08 18:44:38 +01001194 case IrOpcode::kAtomicLoad: {
1195 LoadRepresentation type = LoadRepresentationOf(node->op());
1196 MarkAsRepresentation(type.representation(), node);
1197 return VisitAtomicLoad(node);
1198 }
1199 case IrOpcode::kAtomicStore:
1200 return VisitAtomicStore(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001201 default:
1202 V8_Fatal(__FILE__, __LINE__, "Unexpected operator #%d:%s @ node #%d",
1203 node->opcode(), node->op()->mnemonic(), node->id());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001204 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001205 }
1206}
1207
1208
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001209void InstructionSelector::VisitLoadStackPointer(Node* node) {
1210 OperandGenerator g(this);
1211 Emit(kArchStackPointer, g.DefineAsRegister(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001212}
1213
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001214
1215void InstructionSelector::VisitLoadFramePointer(Node* node) {
1216 OperandGenerator g(this);
1217 Emit(kArchFramePointer, g.DefineAsRegister(node));
1218}
1219
Ben Murdoch097c5b22016-05-18 11:27:45 +01001220void InstructionSelector::VisitLoadParentFramePointer(Node* node) {
1221 OperandGenerator g(this);
1222 Emit(kArchParentFramePointer, g.DefineAsRegister(node));
1223}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001224
1225void InstructionSelector::EmitTableSwitch(const SwitchInfo& sw,
1226 InstructionOperand& index_operand) {
1227 OperandGenerator g(this);
1228 size_t input_count = 2 + sw.value_range;
1229 auto* inputs = zone()->NewArray<InstructionOperand>(input_count);
1230 inputs[0] = index_operand;
1231 InstructionOperand default_operand = g.Label(sw.default_branch);
1232 std::fill(&inputs[1], &inputs[input_count], default_operand);
1233 for (size_t index = 0; index < sw.case_count; ++index) {
1234 size_t value = sw.case_values[index] - sw.min_value;
1235 BasicBlock* branch = sw.case_branches[index];
1236 DCHECK_LE(0u, value);
1237 DCHECK_LT(value + 2, input_count);
1238 inputs[value + 2] = g.Label(branch);
1239 }
1240 Emit(kArchTableSwitch, 0, nullptr, input_count, inputs, 0, nullptr);
1241}
1242
1243
1244void InstructionSelector::EmitLookupSwitch(const SwitchInfo& sw,
1245 InstructionOperand& value_operand) {
1246 OperandGenerator g(this);
1247 size_t input_count = 2 + sw.case_count * 2;
1248 auto* inputs = zone()->NewArray<InstructionOperand>(input_count);
1249 inputs[0] = value_operand;
1250 inputs[1] = g.Label(sw.default_branch);
1251 for (size_t index = 0; index < sw.case_count; ++index) {
1252 int32_t value = sw.case_values[index];
1253 BasicBlock* branch = sw.case_branches[index];
1254 inputs[index * 2 + 2 + 0] = g.TempImmediate(value);
1255 inputs[index * 2 + 2 + 1] = g.Label(branch);
1256 }
1257 Emit(kArchLookupSwitch, 0, nullptr, input_count, inputs, 0, nullptr);
1258}
1259
Ben Murdoch097c5b22016-05-18 11:27:45 +01001260void InstructionSelector::VisitStackSlot(Node* node) {
1261 int size = 1 << ElementSizeLog2Of(StackSlotRepresentationOf(node->op()));
1262 int slot = frame_->AllocateSpillSlot(size);
1263 OperandGenerator g(this);
1264
1265 Emit(kArchStackSlot, g.DefineAsRegister(node),
1266 sequence()->AddImmediate(Constant(slot)), 0, nullptr);
1267}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001268
Ben Murdochc5610432016-08-08 18:44:38 +01001269void InstructionSelector::VisitBitcastWordToTagged(Node* node) {
1270 OperandGenerator g(this);
1271 Node* value = node->InputAt(0);
1272 Emit(kArchNop, g.DefineSameAsFirst(node), g.Use(value));
1273}
1274
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001275// 32 bit targets do not implement the following instructions.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001276#if V8_TARGET_ARCH_32_BIT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001277
1278void InstructionSelector::VisitWord64And(Node* node) { UNIMPLEMENTED(); }
1279
1280
1281void InstructionSelector::VisitWord64Or(Node* node) { UNIMPLEMENTED(); }
1282
1283
1284void InstructionSelector::VisitWord64Xor(Node* node) { UNIMPLEMENTED(); }
1285
1286
1287void InstructionSelector::VisitWord64Shl(Node* node) { UNIMPLEMENTED(); }
1288
1289
1290void InstructionSelector::VisitWord64Shr(Node* node) { UNIMPLEMENTED(); }
1291
1292
1293void InstructionSelector::VisitWord64Sar(Node* node) { UNIMPLEMENTED(); }
1294
1295
1296void InstructionSelector::VisitWord64Ror(Node* node) { UNIMPLEMENTED(); }
1297
1298
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001299void InstructionSelector::VisitWord64Clz(Node* node) { UNIMPLEMENTED(); }
1300
1301
1302void InstructionSelector::VisitWord64Ctz(Node* node) { UNIMPLEMENTED(); }
1303
1304
Ben Murdoch097c5b22016-05-18 11:27:45 +01001305void InstructionSelector::VisitWord64ReverseBits(Node* node) {
1306 UNIMPLEMENTED();
1307}
1308
1309
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001310void InstructionSelector::VisitWord64Popcnt(Node* node) { UNIMPLEMENTED(); }
1311
1312
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001313void InstructionSelector::VisitWord64Equal(Node* node) { UNIMPLEMENTED(); }
1314
1315
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001316void InstructionSelector::VisitInt64Add(Node* node) { UNIMPLEMENTED(); }
1317
1318
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001319void InstructionSelector::VisitInt64AddWithOverflow(Node* node) {
1320 UNIMPLEMENTED();
1321}
1322
1323
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001324void InstructionSelector::VisitInt64Sub(Node* node) { UNIMPLEMENTED(); }
1325
1326
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001327void InstructionSelector::VisitInt64SubWithOverflow(Node* node) {
1328 UNIMPLEMENTED();
1329}
1330
1331
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001332void InstructionSelector::VisitInt64Mul(Node* node) { UNIMPLEMENTED(); }
1333
1334
1335void InstructionSelector::VisitInt64Div(Node* node) { UNIMPLEMENTED(); }
1336
1337
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001338void InstructionSelector::VisitInt64LessThan(Node* node) { UNIMPLEMENTED(); }
1339
1340
1341void InstructionSelector::VisitInt64LessThanOrEqual(Node* node) {
1342 UNIMPLEMENTED();
1343}
1344
1345
1346void InstructionSelector::VisitUint64Div(Node* node) { UNIMPLEMENTED(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001347
1348
1349void InstructionSelector::VisitInt64Mod(Node* node) { UNIMPLEMENTED(); }
1350
1351
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001352void InstructionSelector::VisitUint64LessThan(Node* node) { UNIMPLEMENTED(); }
1353
1354
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001355void InstructionSelector::VisitUint64LessThanOrEqual(Node* node) {
1356 UNIMPLEMENTED();
1357}
1358
1359
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001360void InstructionSelector::VisitUint64Mod(Node* node) { UNIMPLEMENTED(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001361
1362
1363void InstructionSelector::VisitChangeInt32ToInt64(Node* node) {
1364 UNIMPLEMENTED();
1365}
1366
1367
1368void InstructionSelector::VisitChangeUint32ToUint64(Node* node) {
1369 UNIMPLEMENTED();
1370}
1371
1372
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001373void InstructionSelector::VisitTryTruncateFloat32ToInt64(Node* node) {
1374 UNIMPLEMENTED();
1375}
1376
1377
1378void InstructionSelector::VisitTryTruncateFloat64ToInt64(Node* node) {
1379 UNIMPLEMENTED();
1380}
1381
1382
1383void InstructionSelector::VisitTryTruncateFloat32ToUint64(Node* node) {
1384 UNIMPLEMENTED();
1385}
1386
1387
1388void InstructionSelector::VisitTryTruncateFloat64ToUint64(Node* node) {
1389 UNIMPLEMENTED();
1390}
1391
1392
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001393void InstructionSelector::VisitTruncateInt64ToInt32(Node* node) {
1394 UNIMPLEMENTED();
1395}
1396
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001397
1398void InstructionSelector::VisitRoundInt64ToFloat32(Node* node) {
1399 UNIMPLEMENTED();
1400}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001401
1402
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001403void InstructionSelector::VisitRoundInt64ToFloat64(Node* node) {
1404 UNIMPLEMENTED();
1405}
1406
1407
1408void InstructionSelector::VisitRoundUint64ToFloat32(Node* node) {
1409 UNIMPLEMENTED();
1410}
1411
1412
1413void InstructionSelector::VisitRoundUint64ToFloat64(Node* node) {
1414 UNIMPLEMENTED();
1415}
1416
1417
1418void InstructionSelector::VisitBitcastFloat64ToInt64(Node* node) {
1419 UNIMPLEMENTED();
1420}
1421
1422
1423void InstructionSelector::VisitBitcastInt64ToFloat64(Node* node) {
1424 UNIMPLEMENTED();
1425}
1426
1427#endif // V8_TARGET_ARCH_32_BIT
1428
Ben Murdochda12d292016-06-02 14:46:10 +01001429// 64 bit targets do not implement the following instructions.
1430#if V8_TARGET_ARCH_64_BIT
1431void InstructionSelector::VisitInt32PairAdd(Node* node) { UNIMPLEMENTED(); }
1432
1433void InstructionSelector::VisitInt32PairSub(Node* node) { UNIMPLEMENTED(); }
1434
1435void InstructionSelector::VisitInt32PairMul(Node* node) { UNIMPLEMENTED(); }
1436
1437void InstructionSelector::VisitWord32PairShl(Node* node) { UNIMPLEMENTED(); }
1438
1439void InstructionSelector::VisitWord32PairShr(Node* node) { UNIMPLEMENTED(); }
1440
1441void InstructionSelector::VisitWord32PairSar(Node* node) { UNIMPLEMENTED(); }
1442#endif // V8_TARGET_ARCH_64_BIT
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001443
1444void InstructionSelector::VisitFinishRegion(Node* node) {
1445 OperandGenerator g(this);
1446 Node* value = node->InputAt(0);
1447 Emit(kArchNop, g.DefineSameAsFirst(node), g.Use(value));
1448}
1449
1450
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001451void InstructionSelector::VisitParameter(Node* node) {
1452 OperandGenerator g(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001453 int index = ParameterIndexOf(node->op());
1454 InstructionOperand op =
1455 linkage()->ParameterHasSecondaryLocation(index)
1456 ? g.DefineAsDualLocation(
1457 node, linkage()->GetParameterLocation(index),
1458 linkage()->GetParameterSecondaryLocation(index))
1459 : g.DefineAsLocation(
1460 node, linkage()->GetParameterLocation(index),
1461 linkage()->GetParameterType(index).representation());
1462
1463 Emit(kArchNop, op);
1464}
1465
1466
1467void InstructionSelector::VisitIfException(Node* node) {
1468 OperandGenerator g(this);
1469 Node* call = node->InputAt(1);
1470 DCHECK_EQ(IrOpcode::kCall, call->opcode());
Ben Murdochc5610432016-08-08 18:44:38 +01001471 const CallDescriptor* descriptor = CallDescriptorOf(call->op());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001472 Emit(kArchNop,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001473 g.DefineAsLocation(node, descriptor->GetReturnLocation(0),
1474 descriptor->GetReturnType(0).representation()));
1475}
1476
1477
1478void InstructionSelector::VisitOsrValue(Node* node) {
1479 OperandGenerator g(this);
1480 int index = OpParameter<int>(node);
1481 Emit(kArchNop, g.DefineAsLocation(node, linkage()->GetOsrValueLocation(index),
1482 MachineRepresentation::kTagged));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001483}
1484
1485
1486void InstructionSelector::VisitPhi(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001487 const int input_count = node->op()->ValueInputCount();
1488 PhiInstruction* phi = new (instruction_zone())
1489 PhiInstruction(instruction_zone(), GetVirtualRegister(node),
1490 static_cast<size_t>(input_count));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001491 sequence()
1492 ->InstructionBlockAt(RpoNumber::FromInt(current_block_->rpo_number()))
1493 ->AddPhi(phi);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001494 for (int i = 0; i < input_count; ++i) {
1495 Node* const input = node->InputAt(i);
1496 MarkAsUsed(input);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001497 phi->SetInput(static_cast<size_t>(i), GetVirtualRegister(input));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001498 }
1499}
1500
1501
1502void InstructionSelector::VisitProjection(Node* node) {
1503 OperandGenerator g(this);
1504 Node* value = node->InputAt(0);
1505 switch (value->opcode()) {
1506 case IrOpcode::kInt32AddWithOverflow:
1507 case IrOpcode::kInt32SubWithOverflow:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001508 case IrOpcode::kInt64AddWithOverflow:
1509 case IrOpcode::kInt64SubWithOverflow:
1510 case IrOpcode::kTryTruncateFloat32ToInt64:
1511 case IrOpcode::kTryTruncateFloat64ToInt64:
1512 case IrOpcode::kTryTruncateFloat32ToUint64:
1513 case IrOpcode::kTryTruncateFloat64ToUint64:
Ben Murdochda12d292016-06-02 14:46:10 +01001514 case IrOpcode::kInt32PairAdd:
1515 case IrOpcode::kInt32PairSub:
1516 case IrOpcode::kInt32PairMul:
1517 case IrOpcode::kWord32PairShl:
1518 case IrOpcode::kWord32PairShr:
1519 case IrOpcode::kWord32PairSar:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001520 if (ProjectionIndexOf(node->op()) == 0u) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001521 Emit(kArchNop, g.DefineSameAsFirst(node), g.Use(value));
1522 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001523 DCHECK(ProjectionIndexOf(node->op()) == 1u);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001524 MarkAsUsed(value);
1525 }
1526 break;
1527 default:
1528 break;
1529 }
1530}
1531
1532
1533void InstructionSelector::VisitConstant(Node* node) {
1534 // We must emit a NOP here because every live range needs a defining
1535 // instruction in the register allocator.
1536 OperandGenerator g(this);
1537 Emit(kArchNop, g.DefineAsConstant(node));
1538}
1539
1540
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001541void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001542 OperandGenerator g(this);
Ben Murdochc5610432016-08-08 18:44:38 +01001543 const CallDescriptor* descriptor = CallDescriptorOf(node->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001544
1545 FrameStateDescriptor* frame_state_descriptor = nullptr;
1546 if (descriptor->NeedsFrameState()) {
1547 frame_state_descriptor = GetFrameStateDescriptor(
1548 node->InputAt(static_cast<int>(descriptor->InputCount())));
1549 }
1550
1551 CallBuffer buffer(zone(), descriptor, frame_state_descriptor);
1552
1553 // Compute InstructionOperands for inputs and outputs.
1554 // TODO(turbofan): on some architectures it's probably better to use
1555 // the code object in a register if there are multiple uses of it.
1556 // Improve constant pool and the heuristics in the register allocator
1557 // for where to emit constants.
1558 CallBufferFlags call_buffer_flags(kCallCodeImmediate | kCallAddressImmediate);
1559 InitializeCallBuffer(node, &buffer, call_buffer_flags);
1560
1561 EmitPrepareArguments(&(buffer.pushed_nodes), descriptor, node);
1562
1563 // Pass label of exception handler block.
1564 CallDescriptor::Flags flags = descriptor->flags();
1565 if (handler) {
1566 DCHECK_EQ(IrOpcode::kIfException, handler->front()->opcode());
1567 IfExceptionHint hint = OpParameter<IfExceptionHint>(handler->front());
1568 if (hint == IfExceptionHint::kLocallyCaught) {
1569 flags |= CallDescriptor::kHasLocalCatchHandler;
1570 }
1571 flags |= CallDescriptor::kHasExceptionHandler;
1572 buffer.instruction_args.push_back(g.Label(handler));
1573 }
1574
Ben Murdochda12d292016-06-02 14:46:10 +01001575 bool from_native_stack = linkage()->GetIncomingDescriptor()->UseNativeStack();
1576 bool to_native_stack = descriptor->UseNativeStack();
1577 if (from_native_stack != to_native_stack) {
1578 // (arm64 only) Mismatch in the use of stack pointers. One or the other
1579 // has to be restored manually by the code generator.
1580 flags |= to_native_stack ? CallDescriptor::kRestoreJSSP
1581 : CallDescriptor::kRestoreCSP;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001582 }
1583
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001584 // Select the appropriate opcode based on the call type.
1585 InstructionCode opcode = kArchNop;
1586 switch (descriptor->kind()) {
1587 case CallDescriptor::kCallAddress:
1588 opcode =
1589 kArchCallCFunction |
1590 MiscField::encode(static_cast<int>(descriptor->CParameterCount()));
1591 break;
1592 case CallDescriptor::kCallCodeObject:
1593 opcode = kArchCallCodeObject | MiscField::encode(flags);
1594 break;
1595 case CallDescriptor::kCallJSFunction:
1596 opcode = kArchCallJSFunction | MiscField::encode(flags);
1597 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001598 }
1599
1600 // Emit the call instruction.
1601 size_t const output_count = buffer.outputs.size();
1602 auto* outputs = output_count ? &buffer.outputs.front() : nullptr;
1603 Emit(opcode, output_count, outputs, buffer.instruction_args.size(),
1604 &buffer.instruction_args.front())
1605 ->MarkAsCall();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001606}
1607
1608
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001609void InstructionSelector::VisitTailCall(Node* node) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001610 OperandGenerator g(this);
Ben Murdochc5610432016-08-08 18:44:38 +01001611 CallDescriptor const* descriptor = CallDescriptorOf(node->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001612 DCHECK_NE(0, descriptor->flags() & CallDescriptor::kSupportsTailCalls);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001613
1614 // TODO(turbofan): Relax restriction for stack parameters.
1615
1616 int stack_param_delta = 0;
1617 if (linkage()->GetIncomingDescriptor()->CanTailCall(node,
1618 &stack_param_delta)) {
1619 CallBuffer buffer(zone(), descriptor, nullptr);
1620
1621 // Compute InstructionOperands for inputs and outputs.
1622 CallBufferFlags flags(kCallCodeImmediate | kCallTail);
1623 if (IsTailCallAddressImmediate()) {
1624 flags |= kCallAddressImmediate;
1625 }
1626 InitializeCallBuffer(node, &buffer, flags, stack_param_delta);
1627
1628 // Select the appropriate opcode based on the call type.
1629 InstructionCode opcode;
Ben Murdochda12d292016-06-02 14:46:10 +01001630 InstructionOperandVector temps(zone());
1631 if (linkage()->GetIncomingDescriptor()->IsJSFunctionCall()) {
1632 switch (descriptor->kind()) {
1633 case CallDescriptor::kCallCodeObject:
1634 opcode = kArchTailCallCodeObjectFromJSFunction;
1635 break;
1636 case CallDescriptor::kCallJSFunction:
1637 opcode = kArchTailCallJSFunctionFromJSFunction;
1638 break;
1639 default:
1640 UNREACHABLE();
1641 return;
1642 }
1643 int temps_count = GetTempsCountForTailCallFromJSFunction();
1644 for (int i = 0; i < temps_count; i++) {
1645 temps.push_back(g.TempRegister());
1646 }
1647 } else {
1648 switch (descriptor->kind()) {
1649 case CallDescriptor::kCallCodeObject:
1650 opcode = kArchTailCallCodeObject;
1651 break;
1652 case CallDescriptor::kCallJSFunction:
1653 opcode = kArchTailCallJSFunction;
1654 break;
Ben Murdochc5610432016-08-08 18:44:38 +01001655 case CallDescriptor::kCallAddress:
1656 opcode = kArchTailCallAddress;
1657 break;
Ben Murdochda12d292016-06-02 14:46:10 +01001658 default:
1659 UNREACHABLE();
1660 return;
1661 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001662 }
1663 opcode |= MiscField::encode(descriptor->flags());
1664
1665 buffer.instruction_args.push_back(g.TempImmediate(stack_param_delta));
1666
1667 Emit(kArchPrepareTailCall, g.NoOutput(),
1668 g.TempImmediate(stack_param_delta));
1669
1670 // Emit the tailcall instruction.
1671 Emit(opcode, 0, nullptr, buffer.instruction_args.size(),
Ben Murdochda12d292016-06-02 14:46:10 +01001672 &buffer.instruction_args.front(), temps.size(),
1673 temps.empty() ? nullptr : &temps.front());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001674 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001675 FrameStateDescriptor* frame_state_descriptor =
1676 descriptor->NeedsFrameState()
1677 ? GetFrameStateDescriptor(
1678 node->InputAt(static_cast<int>(descriptor->InputCount())))
1679 : nullptr;
1680
1681 CallBuffer buffer(zone(), descriptor, frame_state_descriptor);
1682
1683 // Compute InstructionOperands for inputs and outputs.
1684 CallBufferFlags flags = kCallCodeImmediate;
1685 if (IsTailCallAddressImmediate()) {
1686 flags |= kCallAddressImmediate;
1687 }
1688 InitializeCallBuffer(node, &buffer, flags);
1689
1690 EmitPrepareArguments(&(buffer.pushed_nodes), descriptor, node);
1691
1692 // Select the appropriate opcode based on the call type.
1693 InstructionCode opcode;
1694 switch (descriptor->kind()) {
1695 case CallDescriptor::kCallCodeObject:
1696 opcode = kArchCallCodeObject;
1697 break;
1698 case CallDescriptor::kCallJSFunction:
1699 opcode = kArchCallJSFunction;
1700 break;
1701 default:
1702 UNREACHABLE();
1703 return;
1704 }
1705 opcode |= MiscField::encode(descriptor->flags());
1706
1707 // Emit the call instruction.
1708 size_t output_count = buffer.outputs.size();
1709 auto* outputs = &buffer.outputs.front();
1710 Emit(opcode, output_count, outputs, buffer.instruction_args.size(),
1711 &buffer.instruction_args.front())
1712 ->MarkAsCall();
1713 Emit(kArchRet, 0, nullptr, output_count, outputs);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001714 }
1715}
1716
1717
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001718void InstructionSelector::VisitGoto(BasicBlock* target) {
1719 // jump to the next block.
1720 OperandGenerator g(this);
1721 Emit(kArchJmp, g.NoOutput(), g.Label(target));
1722}
1723
1724
1725void InstructionSelector::VisitReturn(Node* ret) {
1726 OperandGenerator g(this);
1727 if (linkage()->GetIncomingDescriptor()->ReturnCount() == 0) {
1728 Emit(kArchRet, g.NoOutput());
1729 } else {
1730 const int ret_count = ret->op()->ValueInputCount();
1731 auto value_locations = zone()->NewArray<InstructionOperand>(ret_count);
1732 for (int i = 0; i < ret_count; ++i) {
1733 value_locations[i] =
1734 g.UseLocation(ret->InputAt(i), linkage()->GetReturnLocation(i),
1735 linkage()->GetReturnType(i).representation());
1736 }
1737 Emit(kArchRet, 0, nullptr, ret_count, value_locations);
1738 }
1739}
1740
Ben Murdochda12d292016-06-02 14:46:10 +01001741Instruction* InstructionSelector::EmitDeoptimize(InstructionCode opcode,
1742 InstructionOperand output,
1743 InstructionOperand a,
1744 InstructionOperand b,
1745 Node* frame_state) {
1746 size_t output_count = output.IsInvalid() ? 0 : 1;
1747 InstructionOperand inputs[] = {a, b};
1748 size_t input_count = arraysize(inputs);
1749 return EmitDeoptimize(opcode, output_count, &output, input_count, inputs,
1750 frame_state);
1751}
1752
1753Instruction* InstructionSelector::EmitDeoptimize(
1754 InstructionCode opcode, size_t output_count, InstructionOperand* outputs,
1755 size_t input_count, InstructionOperand* inputs, Node* frame_state) {
1756 OperandGenerator g(this);
1757 FrameStateDescriptor* const descriptor = GetFrameStateDescriptor(frame_state);
1758 InstructionOperandVector args(instruction_zone());
1759 args.reserve(input_count + 1 + descriptor->GetTotalSize());
1760 for (size_t i = 0; i < input_count; ++i) {
1761 args.push_back(inputs[i]);
1762 }
1763 opcode |= MiscField::encode(static_cast<int>(input_count));
1764 InstructionSequence::StateId const state_id =
1765 sequence()->AddFrameStateDescriptor(descriptor);
1766 args.push_back(g.TempImmediate(state_id.ToInt()));
1767 StateObjectDeduplicator deduplicator(instruction_zone());
1768 AddInputsToFrameStateDescriptor(descriptor, frame_state, &g, &deduplicator,
1769 &args, FrameStateInputKind::kAny,
1770 instruction_zone());
1771 return Emit(opcode, output_count, outputs, args.size(), &args.front(), 0,
1772 nullptr);
1773}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001774
1775void InstructionSelector::VisitDeoptimize(DeoptimizeKind kind, Node* value) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001776 InstructionCode opcode = kArchDeoptimize;
1777 switch (kind) {
1778 case DeoptimizeKind::kEager:
1779 opcode |= MiscField::encode(Deoptimizer::EAGER);
1780 break;
1781 case DeoptimizeKind::kSoft:
1782 opcode |= MiscField::encode(Deoptimizer::SOFT);
1783 break;
1784 }
Ben Murdochda12d292016-06-02 14:46:10 +01001785 EmitDeoptimize(opcode, 0, nullptr, 0, nullptr, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001786}
1787
1788
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001789void InstructionSelector::VisitThrow(Node* value) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001790 OperandGenerator g(this);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001791 Emit(kArchThrowTerminator, g.NoOutput());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001792}
1793
1794
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001795FrameStateDescriptor* InstructionSelector::GetFrameStateDescriptor(
1796 Node* state) {
1797 DCHECK(state->opcode() == IrOpcode::kFrameState);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001798 DCHECK_EQ(kFrameStateInputCount, state->InputCount());
1799 FrameStateInfo state_info = OpParameter<FrameStateInfo>(state);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001800
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001801 int parameters = static_cast<int>(
1802 StateValuesAccess(state->InputAt(kFrameStateParametersInput)).size());
1803 int locals = static_cast<int>(
1804 StateValuesAccess(state->InputAt(kFrameStateLocalsInput)).size());
1805 int stack = static_cast<int>(
1806 StateValuesAccess(state->InputAt(kFrameStateStackInput)).size());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001807
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001808 DCHECK_EQ(parameters, state_info.parameter_count());
1809 DCHECK_EQ(locals, state_info.local_count());
1810
1811 FrameStateDescriptor* outer_state = nullptr;
1812 Node* outer_node = state->InputAt(kFrameStateOuterStateInput);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001813 if (outer_node->opcode() == IrOpcode::kFrameState) {
1814 outer_state = GetFrameStateDescriptor(outer_node);
1815 }
1816
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001817 return new (instruction_zone()) FrameStateDescriptor(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001818 instruction_zone(), state_info.type(), state_info.bailout_id(),
1819 state_info.state_combine(), parameters, locals, stack,
1820 state_info.shared_info(), outer_state);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001821}
1822
1823
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001824} // namespace compiler
1825} // namespace internal
1826} // namespace v8