blob: 716723b8a06d47dd03e66109c3dc5d33fd9bc345 [file] [log] [blame]
Ben Murdochc5610432016-08-08 18:44:38 +01001// Copyright 2015 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/compiler/effect-control-linearizer.h"
6
7#include "src/code-factory.h"
8#include "src/compiler/access-builder.h"
9#include "src/compiler/js-graph.h"
10#include "src/compiler/linkage.h"
11#include "src/compiler/node-properties.h"
12#include "src/compiler/node.h"
13#include "src/compiler/schedule.h"
14
15namespace v8 {
16namespace internal {
17namespace compiler {
18
19EffectControlLinearizer::EffectControlLinearizer(JSGraph* js_graph,
20 Schedule* schedule,
21 Zone* temp_zone)
22 : js_graph_(js_graph), schedule_(schedule), temp_zone_(temp_zone) {}
23
24Graph* EffectControlLinearizer::graph() const { return js_graph_->graph(); }
25CommonOperatorBuilder* EffectControlLinearizer::common() const {
26 return js_graph_->common();
27}
28SimplifiedOperatorBuilder* EffectControlLinearizer::simplified() const {
29 return js_graph_->simplified();
30}
31MachineOperatorBuilder* EffectControlLinearizer::machine() const {
32 return js_graph_->machine();
33}
34
35namespace {
36
37struct BlockEffectControlData {
38 Node* current_effect = nullptr; // New effect.
39 Node* current_control = nullptr; // New control.
40};
41
42// Effect phis that need to be updated after the first pass.
43struct PendingEffectPhi {
44 Node* effect_phi;
45 BasicBlock* block;
46
47 PendingEffectPhi(Node* effect_phi, BasicBlock* block)
48 : effect_phi(effect_phi), block(block) {}
49};
50
51void UpdateEffectPhi(Node* node, BasicBlock* block,
52 ZoneVector<BlockEffectControlData>* block_effects) {
53 // Update all inputs to an effect phi with the effects from the given
54 // block->effect map.
55 DCHECK_EQ(IrOpcode::kEffectPhi, node->opcode());
56 DCHECK_EQ(node->op()->EffectInputCount(), block->PredecessorCount());
57 for (int i = 0; i < node->op()->EffectInputCount(); i++) {
58 Node* input = node->InputAt(i);
59 BasicBlock* predecessor = block->PredecessorAt(static_cast<size_t>(i));
60 Node* input_effect =
61 (*block_effects)[predecessor->rpo_number()].current_effect;
62 if (input != input_effect) {
63 node->ReplaceInput(i, input_effect);
64 }
65 }
66}
67
68void UpdateBlockControl(BasicBlock* block,
69 ZoneVector<BlockEffectControlData>* block_effects) {
70 Node* control = block->NodeAt(0);
71 DCHECK(NodeProperties::IsControl(control));
72
73 // Do not rewire the end node.
74 if (control->opcode() == IrOpcode::kEnd) return;
75
76 // Update all inputs to the given control node with the correct control.
77 DCHECK_EQ(control->op()->ControlInputCount(), block->PredecessorCount());
78 for (int i = 0; i < control->op()->ControlInputCount(); i++) {
79 Node* input = NodeProperties::GetControlInput(control, i);
80 BasicBlock* predecessor = block->PredecessorAt(static_cast<size_t>(i));
81 Node* input_control =
82 (*block_effects)[predecessor->rpo_number()].current_control;
83 if (input != input_control) {
84 NodeProperties::ReplaceControlInput(control, input_control, i);
85 }
86 }
87}
88
89bool HasIncomingBackEdges(BasicBlock* block) {
90 for (BasicBlock* pred : block->predecessors()) {
91 if (pred->rpo_number() >= block->rpo_number()) {
92 return true;
93 }
94 }
95 return false;
96}
97
98void RemoveRegionNode(Node* node) {
99 DCHECK(IrOpcode::kFinishRegion == node->opcode() ||
100 IrOpcode::kBeginRegion == node->opcode());
101 // Update the value/context uses to the value input of the finish node and
102 // the effect uses to the effect input.
103 for (Edge edge : node->use_edges()) {
104 DCHECK(!edge.from()->IsDead());
105 if (NodeProperties::IsEffectEdge(edge)) {
106 edge.UpdateTo(NodeProperties::GetEffectInput(node));
107 } else {
108 DCHECK(!NodeProperties::IsControlEdge(edge));
109 DCHECK(!NodeProperties::IsFrameStateEdge(edge));
110 edge.UpdateTo(node->InputAt(0));
111 }
112 }
113 node->Kill();
114}
115
116} // namespace
117
118void EffectControlLinearizer::Run() {
119 ZoneVector<BlockEffectControlData> block_effects(temp_zone());
120 ZoneVector<PendingEffectPhi> pending_effect_phis(temp_zone());
121 ZoneVector<BasicBlock*> pending_block_controls(temp_zone());
122 block_effects.resize(schedule()->RpoBlockCount());
123 NodeVector inputs_buffer(temp_zone());
124
125 for (BasicBlock* block : *(schedule()->rpo_order())) {
126 size_t instr = 0;
127
128 // The control node should be the first.
129 Node* control = block->NodeAt(instr);
130 DCHECK(NodeProperties::IsControl(control));
131 // Update the control inputs.
132 if (HasIncomingBackEdges(block)) {
133 // If there are back edges, we need to update later because we have not
134 // computed the control yet. This should only happen for loops.
135 DCHECK_EQ(IrOpcode::kLoop, control->opcode());
136 pending_block_controls.push_back(block);
137 } else {
138 // If there are no back edges, we can update now.
139 UpdateBlockControl(block, &block_effects);
140 }
141 instr++;
142
143 // Iterate over the phis and update the effect phis.
144 Node* effect = nullptr;
145 Node* terminate = nullptr;
146 for (; instr < block->NodeCount(); instr++) {
147 Node* node = block->NodeAt(instr);
148 // Only go through the phis and effect phis.
149 if (node->opcode() == IrOpcode::kEffectPhi) {
150 // There should be at most one effect phi in a block.
151 DCHECK_NULL(effect);
152 // IfException blocks should not have effect phis.
153 DCHECK_NE(IrOpcode::kIfException, control->opcode());
154 effect = node;
155
156 // Make sure we update the inputs to the incoming blocks' effects.
157 if (HasIncomingBackEdges(block)) {
158 // In case of loops, we do not update the effect phi immediately
159 // because the back predecessor has not been handled yet. We just
160 // record the effect phi for later processing.
161 pending_effect_phis.push_back(PendingEffectPhi(node, block));
162 } else {
163 UpdateEffectPhi(node, block, &block_effects);
164 }
165 } else if (node->opcode() == IrOpcode::kPhi) {
166 // Just skip phis.
167 } else if (node->opcode() == IrOpcode::kTerminate) {
168 DCHECK(terminate == nullptr);
169 terminate = node;
170 } else {
171 break;
172 }
173 }
174
175 if (effect == nullptr) {
176 // There was no effect phi.
177 DCHECK(!HasIncomingBackEdges(block));
178 if (block == schedule()->start()) {
179 // Start block => effect is start.
180 DCHECK_EQ(graph()->start(), control);
181 effect = graph()->start();
182 } else if (control->opcode() == IrOpcode::kEnd) {
183 // End block is just a dummy, no effect needed.
184 DCHECK_EQ(BasicBlock::kNone, block->control());
185 DCHECK_EQ(1u, block->size());
186 effect = nullptr;
187 } else {
188 // If all the predecessors have the same effect, we can use it
189 // as our current effect.
190 int rpo_number = block->PredecessorAt(0)->rpo_number();
191 effect = block_effects[rpo_number].current_effect;
192 for (size_t i = 1; i < block->PredecessorCount(); i++) {
193 int rpo_number = block->PredecessorAt(i)->rpo_number();
194 if (block_effects[rpo_number].current_effect != effect) {
195 effect = nullptr;
196 break;
197 }
198 }
199 if (effect == nullptr) {
200 DCHECK_NE(IrOpcode::kIfException, control->opcode());
201 // The input blocks do not have the same effect. We have
202 // to create an effect phi node.
203 inputs_buffer.clear();
204 inputs_buffer.resize(block->PredecessorCount(), graph()->start());
205 inputs_buffer.push_back(control);
206 effect = graph()->NewNode(
207 common()->EffectPhi(static_cast<int>(block->PredecessorCount())),
208 static_cast<int>(inputs_buffer.size()), &(inputs_buffer.front()));
209 // Let us update the effect phi node later.
210 pending_effect_phis.push_back(PendingEffectPhi(effect, block));
211 } else if (control->opcode() == IrOpcode::kIfException) {
212 // The IfException is connected into the effect chain, so we need
213 // to update the effect here.
214 NodeProperties::ReplaceEffectInput(control, effect);
215 effect = control;
216 }
217 }
218 }
219
220 // Fixup the Terminate node.
221 if (terminate != nullptr) {
222 NodeProperties::ReplaceEffectInput(terminate, effect);
223 }
224
225 // Process the ordinary instructions.
226 for (; instr < block->NodeCount(); instr++) {
227 Node* node = block->NodeAt(instr);
228 ProcessNode(node, &effect, &control);
229 }
230
231 switch (block->control()) {
232 case BasicBlock::kGoto:
233 case BasicBlock::kNone:
234 break;
235
236 case BasicBlock::kCall:
237 case BasicBlock::kTailCall:
238 case BasicBlock::kBranch:
239 case BasicBlock::kSwitch:
240 case BasicBlock::kReturn:
241 case BasicBlock::kDeoptimize:
242 case BasicBlock::kThrow:
243 ProcessNode(block->control_input(), &effect, &control);
244 break;
245 }
246
247 // Store the effect for later use.
248 block_effects[block->rpo_number()].current_effect = effect;
249 block_effects[block->rpo_number()].current_control = control;
250 }
251
252 // Update the incoming edges of the effect phis that could not be processed
253 // during the first pass (because they could have incoming back edges).
254 for (const PendingEffectPhi& pending_effect_phi : pending_effect_phis) {
255 UpdateEffectPhi(pending_effect_phi.effect_phi, pending_effect_phi.block,
256 &block_effects);
257 }
258 for (BasicBlock* pending_block_control : pending_block_controls) {
259 UpdateBlockControl(pending_block_control, &block_effects);
260 }
261}
262
263namespace {
264
265void TryScheduleCallIfSuccess(Node* node, Node** control) {
266 // Schedule the call's IfSuccess node if there is no exception use.
267 if (!NodeProperties::IsExceptionalCall(node)) {
268 for (Edge edge : node->use_edges()) {
269 if (NodeProperties::IsControlEdge(edge) &&
270 edge.from()->opcode() == IrOpcode::kIfSuccess) {
271 *control = edge.from();
272 }
273 }
274 }
275}
276
277} // namespace
278
279void EffectControlLinearizer::ProcessNode(Node* node, Node** effect,
280 Node** control) {
281 // If the node needs to be wired into the effect/control chain, do this
282 // here.
283 if (TryWireInStateEffect(node, effect, control)) {
284 return;
285 }
286
287 // Remove the end markers of 'atomic' allocation region because the
288 // region should be wired-in now.
289 if (node->opcode() == IrOpcode::kFinishRegion ||
290 node->opcode() == IrOpcode::kBeginRegion) {
291 // Update the value uses to the value input of the finish node and
292 // the effect uses to the effect input.
293 return RemoveRegionNode(node);
294 }
295
296 // Special treatment for CheckPoint nodes.
297 // TODO(epertoso): Pickup the current frame state.
298 if (node->opcode() == IrOpcode::kCheckPoint) {
299 // Unlink the check point; effect uses will be updated to the incoming
300 // effect that is passed.
301 node->Kill();
302 return;
303 }
304
305 if (node->opcode() == IrOpcode::kIfSuccess) {
306 // We always schedule IfSuccess with its call, so skip it here.
307 DCHECK_EQ(IrOpcode::kCall, node->InputAt(0)->opcode());
308 // The IfSuccess node should not belong to an exceptional call node
309 // because such IfSuccess nodes should only start a basic block (and
310 // basic block start nodes are not handled in the ProcessNode method).
311 DCHECK(!NodeProperties::IsExceptionalCall(node->InputAt(0)));
312 return;
313 }
314
315 // If the node takes an effect, replace with the current one.
316 if (node->op()->EffectInputCount() > 0) {
317 DCHECK_EQ(1, node->op()->EffectInputCount());
318 Node* input_effect = NodeProperties::GetEffectInput(node);
319
320 if (input_effect != *effect) {
321 NodeProperties::ReplaceEffectInput(node, *effect);
322 }
323
324 // If the node produces an effect, update our current effect. (However,
325 // ignore new effect chains started with ValueEffect.)
326 if (node->op()->EffectOutputCount() > 0) {
327 DCHECK_EQ(1, node->op()->EffectOutputCount());
328 *effect = node;
329 }
330 } else {
331 // New effect chain is only started with a Start or ValueEffect node.
332 DCHECK(node->op()->EffectOutputCount() == 0 ||
333 node->opcode() == IrOpcode::kStart);
334 }
335
336 // Rewire control inputs.
337 for (int i = 0; i < node->op()->ControlInputCount(); i++) {
338 NodeProperties::ReplaceControlInput(node, *control, i);
339 }
340 // Update the current control and wire IfSuccess right after calls.
341 if (node->op()->ControlOutputCount() > 0) {
342 *control = node;
343 if (node->opcode() == IrOpcode::kCall) {
344 // Schedule the call's IfSuccess node (if there is no exception use).
345 TryScheduleCallIfSuccess(node, control);
346 }
347 }
348}
349
350bool EffectControlLinearizer::TryWireInStateEffect(Node* node, Node** effect,
351 Node** control) {
352 ValueEffectControl state(nullptr, nullptr, nullptr);
353 switch (node->opcode()) {
354 case IrOpcode::kTypeGuard:
355 state = LowerTypeGuard(node, *effect, *control);
356 break;
357 case IrOpcode::kChangeBitToTagged:
358 state = LowerChangeBitToTagged(node, *effect, *control);
359 break;
360 case IrOpcode::kChangeInt31ToTaggedSigned:
361 state = LowerChangeInt31ToTaggedSigned(node, *effect, *control);
362 break;
363 case IrOpcode::kChangeInt32ToTagged:
364 state = LowerChangeInt32ToTagged(node, *effect, *control);
365 break;
366 case IrOpcode::kChangeUint32ToTagged:
367 state = LowerChangeUint32ToTagged(node, *effect, *control);
368 break;
369 case IrOpcode::kChangeFloat64ToTagged:
370 state = LowerChangeFloat64ToTagged(node, *effect, *control);
371 break;
372 case IrOpcode::kChangeTaggedSignedToInt32:
373 state = LowerChangeTaggedSignedToInt32(node, *effect, *control);
374 break;
375 case IrOpcode::kChangeTaggedToBit:
376 state = LowerChangeTaggedToBit(node, *effect, *control);
377 break;
378 case IrOpcode::kChangeTaggedToInt32:
379 state = LowerChangeTaggedToInt32(node, *effect, *control);
380 break;
381 case IrOpcode::kChangeTaggedToUint32:
382 state = LowerChangeTaggedToUint32(node, *effect, *control);
383 break;
384 case IrOpcode::kChangeTaggedToFloat64:
385 state = LowerChangeTaggedToFloat64(node, *effect, *control);
386 break;
387 case IrOpcode::kTruncateTaggedToWord32:
388 state = LowerTruncateTaggedToWord32(node, *effect, *control);
389 break;
390 case IrOpcode::kObjectIsCallable:
391 state = LowerObjectIsCallable(node, *effect, *control);
392 break;
393 case IrOpcode::kObjectIsNumber:
394 state = LowerObjectIsNumber(node, *effect, *control);
395 break;
396 case IrOpcode::kObjectIsReceiver:
397 state = LowerObjectIsReceiver(node, *effect, *control);
398 break;
399 case IrOpcode::kObjectIsSmi:
400 state = LowerObjectIsSmi(node, *effect, *control);
401 break;
402 case IrOpcode::kObjectIsString:
403 state = LowerObjectIsString(node, *effect, *control);
404 break;
405 case IrOpcode::kObjectIsUndetectable:
406 state = LowerObjectIsUndetectable(node, *effect, *control);
407 break;
408 default:
409 return false;
410 }
411 NodeProperties::ReplaceUses(node, state.value);
412 *effect = state.effect;
413 *control = state.control;
414 return true;
415}
416
417EffectControlLinearizer::ValueEffectControl
418EffectControlLinearizer::LowerTypeGuard(Node* node, Node* effect,
419 Node* control) {
420 Node* value = node->InputAt(0);
421 return ValueEffectControl(value, effect, control);
422}
423
424EffectControlLinearizer::ValueEffectControl
425EffectControlLinearizer::LowerChangeFloat64ToTagged(Node* node, Node* effect,
426 Node* control) {
427 Node* value = node->InputAt(0);
428
429 Node* value32 = graph()->NewNode(machine()->RoundFloat64ToInt32(), value);
430 Node* check_same = graph()->NewNode(
431 machine()->Float64Equal(), value,
432 graph()->NewNode(machine()->ChangeInt32ToFloat64(), value32));
433 Node* branch_same = graph()->NewNode(common()->Branch(), check_same, control);
434
435 Node* if_smi = graph()->NewNode(common()->IfTrue(), branch_same);
436 Node* vsmi;
437 Node* if_box = graph()->NewNode(common()->IfFalse(), branch_same);
438
439 // Check if {value} is -0.
440 Node* check_zero = graph()->NewNode(machine()->Word32Equal(), value32,
441 jsgraph()->Int32Constant(0));
442 Node* branch_zero = graph()->NewNode(common()->Branch(BranchHint::kFalse),
443 check_zero, if_smi);
444
445 Node* if_zero = graph()->NewNode(common()->IfTrue(), branch_zero);
446 Node* if_notzero = graph()->NewNode(common()->IfFalse(), branch_zero);
447
448 // In case of 0, we need to check the high bits for the IEEE -0 pattern.
449 Node* check_negative = graph()->NewNode(
450 machine()->Int32LessThan(),
451 graph()->NewNode(machine()->Float64ExtractHighWord32(), value),
452 jsgraph()->Int32Constant(0));
453 Node* branch_negative = graph()->NewNode(common()->Branch(BranchHint::kFalse),
454 check_negative, if_zero);
455
456 Node* if_negative = graph()->NewNode(common()->IfTrue(), branch_negative);
457 Node* if_notnegative = graph()->NewNode(common()->IfFalse(), branch_negative);
458
459 // We need to create a box for negative 0.
460 if_smi = graph()->NewNode(common()->Merge(2), if_notzero, if_notnegative);
461 if_box = graph()->NewNode(common()->Merge(2), if_box, if_negative);
462
463 // On 64-bit machines we can just wrap the 32-bit integer in a smi, for 32-bit
464 // machines we need to deal with potential overflow and fallback to boxing.
465 if (machine()->Is64()) {
466 vsmi = ChangeInt32ToSmi(value32);
467 } else {
468 Node* smi_tag =
469 graph()->NewNode(machine()->Int32AddWithOverflow(), value32, value32);
470
471 Node* check_ovf = graph()->NewNode(common()->Projection(1), smi_tag);
472 Node* branch_ovf = graph()->NewNode(common()->Branch(BranchHint::kFalse),
473 check_ovf, if_smi);
474
475 Node* if_ovf = graph()->NewNode(common()->IfTrue(), branch_ovf);
476 if_box = graph()->NewNode(common()->Merge(2), if_ovf, if_box);
477
478 if_smi = graph()->NewNode(common()->IfFalse(), branch_ovf);
479 vsmi = graph()->NewNode(common()->Projection(0), smi_tag);
480 }
481
482 // Allocate the box for the {value}.
483 ValueEffectControl box = AllocateHeapNumberWithValue(value, effect, if_box);
484
485 control = graph()->NewNode(common()->Merge(2), if_smi, box.control);
486 value = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
487 vsmi, box.value, control);
488 effect =
489 graph()->NewNode(common()->EffectPhi(2), effect, box.effect, control);
490 return ValueEffectControl(value, effect, control);
491}
492
493EffectControlLinearizer::ValueEffectControl
494EffectControlLinearizer::LowerChangeBitToTagged(Node* node, Node* effect,
495 Node* control) {
496 Node* value = node->InputAt(0);
497
498 Node* branch = graph()->NewNode(common()->Branch(), value, control);
499
500 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
501 Node* vtrue = jsgraph()->TrueConstant();
502
503 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
504 Node* vfalse = jsgraph()->FalseConstant();
505
506 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
507 value = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
508 vtrue, vfalse, control);
509
510 return ValueEffectControl(value, effect, control);
511}
512
513EffectControlLinearizer::ValueEffectControl
514EffectControlLinearizer::LowerChangeInt31ToTaggedSigned(Node* node,
515 Node* effect,
516 Node* control) {
517 Node* value = node->InputAt(0);
518 value = ChangeInt32ToSmi(value);
519 return ValueEffectControl(value, effect, control);
520}
521
522EffectControlLinearizer::ValueEffectControl
523EffectControlLinearizer::LowerChangeInt32ToTagged(Node* node, Node* effect,
524 Node* control) {
525 Node* value = node->InputAt(0);
526
527 if (machine()->Is64()) {
528 return ValueEffectControl(ChangeInt32ToSmi(value), effect, control);
529 }
530
531 Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), value, value);
532
533 Node* ovf = graph()->NewNode(common()->Projection(1), add);
534 Node* branch =
535 graph()->NewNode(common()->Branch(BranchHint::kFalse), ovf, control);
536
537 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
538 ValueEffectControl alloc =
539 AllocateHeapNumberWithValue(ChangeInt32ToFloat64(value), effect, if_true);
540
541 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
542 Node* vfalse = graph()->NewNode(common()->Projection(0), add);
543
544 Node* merge = graph()->NewNode(common()->Merge(2), alloc.control, if_false);
545 Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
546 alloc.value, vfalse, merge);
547 Node* ephi =
548 graph()->NewNode(common()->EffectPhi(2), alloc.effect, effect, merge);
549
550 return ValueEffectControl(phi, ephi, merge);
551}
552
553EffectControlLinearizer::ValueEffectControl
554EffectControlLinearizer::LowerChangeUint32ToTagged(Node* node, Node* effect,
555 Node* control) {
556 Node* value = node->InputAt(0);
557
558 Node* check = graph()->NewNode(machine()->Uint32LessThanOrEqual(), value,
559 SmiMaxValueConstant());
560 Node* branch =
561 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
562
563 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
564 Node* vtrue = ChangeUint32ToSmi(value);
565
566 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
567 ValueEffectControl alloc = AllocateHeapNumberWithValue(
568 ChangeUint32ToFloat64(value), effect, if_false);
569
570 Node* merge = graph()->NewNode(common()->Merge(2), if_true, alloc.control);
571 Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
572 vtrue, alloc.value, merge);
573 Node* ephi =
574 graph()->NewNode(common()->EffectPhi(2), effect, alloc.effect, merge);
575
576 return ValueEffectControl(phi, ephi, merge);
577}
578
579EffectControlLinearizer::ValueEffectControl
580EffectControlLinearizer::LowerChangeTaggedSignedToInt32(Node* node,
581 Node* effect,
582 Node* control) {
583 Node* value = node->InputAt(0);
584 value = ChangeSmiToInt32(value);
585 return ValueEffectControl(value, effect, control);
586}
587
588EffectControlLinearizer::ValueEffectControl
589EffectControlLinearizer::LowerChangeTaggedToBit(Node* node, Node* effect,
590 Node* control) {
591 Node* value = node->InputAt(0);
592 value = graph()->NewNode(machine()->WordEqual(), value,
593 jsgraph()->TrueConstant());
594 return ValueEffectControl(value, effect, control);
595}
596
597EffectControlLinearizer::ValueEffectControl
598EffectControlLinearizer::LowerChangeTaggedToInt32(Node* node, Node* effect,
599 Node* control) {
600 Node* value = node->InputAt(0);
601
602 Node* check = ObjectIsSmi(value);
603 Node* branch =
604 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
605
606 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
607 Node* etrue = effect;
608 Node* vtrue = ChangeSmiToInt32(value);
609
610 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
611 Node* efalse = effect;
612 Node* vfalse;
613 {
614 STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
615 vfalse = efalse = graph()->NewNode(
616 simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), value,
617 efalse, if_false);
618 vfalse = graph()->NewNode(machine()->ChangeFloat64ToInt32(), vfalse);
619 }
620
621 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
622 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
623 value = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
624 vtrue, vfalse, control);
625
626 return ValueEffectControl(value, effect, control);
627}
628
629EffectControlLinearizer::ValueEffectControl
630EffectControlLinearizer::LowerChangeTaggedToUint32(Node* node, Node* effect,
631 Node* control) {
632 Node* value = node->InputAt(0);
633
634 Node* check = ObjectIsSmi(value);
635 Node* branch =
636 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
637
638 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
639 Node* etrue = effect;
640 Node* vtrue = ChangeSmiToInt32(value);
641
642 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
643 Node* efalse = effect;
644 Node* vfalse;
645 {
646 STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
647 vfalse = efalse = graph()->NewNode(
648 simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), value,
649 efalse, if_false);
650 vfalse = graph()->NewNode(machine()->ChangeFloat64ToUint32(), vfalse);
651 }
652
653 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
654 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
655 value = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
656 vtrue, vfalse, control);
657
658 return ValueEffectControl(value, effect, control);
659}
660
661EffectControlLinearizer::ValueEffectControl
662EffectControlLinearizer::LowerChangeTaggedToFloat64(Node* node, Node* effect,
663 Node* control) {
664 Node* value = node->InputAt(0);
665
666 Node* check = ObjectIsSmi(value);
667 Node* branch =
668 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
669
670 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
671 Node* etrue = effect;
672 Node* vtrue;
673 {
674 vtrue = ChangeSmiToInt32(value);
675 vtrue = graph()->NewNode(machine()->ChangeInt32ToFloat64(), vtrue);
676 }
677
678 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
679 Node* efalse = effect;
680 Node* vfalse;
681 {
682 STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
683 vfalse = efalse = graph()->NewNode(
684 simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), value,
685 efalse, if_false);
686 }
687
688 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
689 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
690 value = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
691 vtrue, vfalse, control);
692
693 return ValueEffectControl(value, effect, control);
694}
695
696EffectControlLinearizer::ValueEffectControl
697EffectControlLinearizer::LowerTruncateTaggedToWord32(Node* node, Node* effect,
698 Node* control) {
699 Node* value = node->InputAt(0);
700
701 Node* check = ObjectIsSmi(value);
702 Node* branch =
703 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
704
705 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
706 Node* etrue = effect;
707 Node* vtrue = ChangeSmiToInt32(value);
708
709 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
710 Node* efalse = effect;
711 Node* vfalse;
712 {
713 STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
714 vfalse = efalse = graph()->NewNode(
715 simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), value,
716 efalse, if_false);
717 vfalse = graph()->NewNode(machine()->TruncateFloat64ToWord32(), vfalse);
718 }
719
720 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
721 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
722 value = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
723 vtrue, vfalse, control);
724
725 return ValueEffectControl(value, effect, control);
726}
727
728EffectControlLinearizer::ValueEffectControl
729EffectControlLinearizer::LowerObjectIsCallable(Node* node, Node* effect,
730 Node* control) {
731 Node* value = node->InputAt(0);
732
733 Node* check = ObjectIsSmi(value);
734 Node* branch =
735 graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
736
737 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
738 Node* etrue = effect;
739 Node* vtrue = jsgraph()->Int32Constant(0);
740
741 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
742 Node* efalse = effect;
743 Node* vfalse;
744 {
745 Node* value_map = efalse =
746 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
747 value, efalse, if_false);
748 Node* value_bit_field = efalse = graph()->NewNode(
749 simplified()->LoadField(AccessBuilder::ForMapBitField()), value_map,
750 efalse, if_false);
751 vfalse = graph()->NewNode(
752 machine()->Word32Equal(),
753 jsgraph()->Int32Constant(1 << Map::kIsCallable),
754 graph()->NewNode(
755 machine()->Word32And(), value_bit_field,
756 jsgraph()->Int32Constant((1 << Map::kIsCallable) |
757 (1 << Map::kIsUndetectable))));
758 }
759
760 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
761 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
762 value = graph()->NewNode(common()->Phi(MachineRepresentation::kBit, 2), vtrue,
763 vfalse, control);
764
765 return ValueEffectControl(value, effect, control);
766}
767
768EffectControlLinearizer::ValueEffectControl
769EffectControlLinearizer::LowerObjectIsNumber(Node* node, Node* effect,
770 Node* control) {
771 Node* value = node->InputAt(0);
772
773 Node* check = ObjectIsSmi(value);
774 Node* branch = graph()->NewNode(common()->Branch(), check, control);
775
776 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
777 Node* etrue = effect;
778 Node* vtrue = jsgraph()->Int32Constant(1);
779
780 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
781 Node* efalse = effect;
782 Node* vfalse;
783 {
784 Node* value_map = efalse =
785 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
786 value, efalse, if_false);
787 vfalse = graph()->NewNode(machine()->WordEqual(), value_map,
788 jsgraph()->HeapNumberMapConstant());
789 }
790
791 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
792 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
793 value = graph()->NewNode(common()->Phi(MachineRepresentation::kBit, 2), vtrue,
794 vfalse, control);
795
796 return ValueEffectControl(value, effect, control);
797}
798
799EffectControlLinearizer::ValueEffectControl
800EffectControlLinearizer::LowerObjectIsReceiver(Node* node, Node* effect,
801 Node* control) {
802 Node* value = node->InputAt(0);
803
804 Node* check = ObjectIsSmi(value);
805 Node* branch =
806 graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
807
808 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
809 Node* etrue = effect;
810 Node* vtrue = jsgraph()->Int32Constant(0);
811
812 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
813 Node* efalse = effect;
814 Node* vfalse;
815 {
816 STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
817 Node* value_map = efalse =
818 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
819 value, efalse, if_false);
820 Node* value_instance_type = efalse = graph()->NewNode(
821 simplified()->LoadField(AccessBuilder::ForMapInstanceType()), value_map,
822 efalse, if_false);
823 vfalse = graph()->NewNode(machine()->Uint32LessThanOrEqual(),
824 jsgraph()->Uint32Constant(FIRST_JS_RECEIVER_TYPE),
825 value_instance_type);
826 }
827
828 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
829 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
830 value = graph()->NewNode(common()->Phi(MachineRepresentation::kBit, 2), vtrue,
831 vfalse, control);
832
833 return ValueEffectControl(value, effect, control);
834}
835
836EffectControlLinearizer::ValueEffectControl
837EffectControlLinearizer::LowerObjectIsSmi(Node* node, Node* effect,
838 Node* control) {
839 Node* value = node->InputAt(0);
840 value = ObjectIsSmi(value);
841 return ValueEffectControl(value, effect, control);
842}
843
844EffectControlLinearizer::ValueEffectControl
845EffectControlLinearizer::LowerObjectIsString(Node* node, Node* effect,
846 Node* control) {
847 Node* value = node->InputAt(0);
848
849 Node* check = ObjectIsSmi(value);
850 Node* branch =
851 graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
852
853 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
854 Node* etrue = effect;
855 Node* vtrue = jsgraph()->Int32Constant(0);
856
857 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
858 Node* efalse = effect;
859 Node* vfalse;
860 {
861 Node* value_map = efalse =
862 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
863 value, efalse, if_false);
864 Node* value_instance_type = efalse = graph()->NewNode(
865 simplified()->LoadField(AccessBuilder::ForMapInstanceType()), value_map,
866 efalse, if_false);
867 vfalse = graph()->NewNode(machine()->Uint32LessThan(), value_instance_type,
868 jsgraph()->Uint32Constant(FIRST_NONSTRING_TYPE));
869 }
870
871 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
872 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
873 value = graph()->NewNode(common()->Phi(MachineRepresentation::kBit, 2), vtrue,
874 vfalse, control);
875
876 return ValueEffectControl(value, effect, control);
877}
878
879EffectControlLinearizer::ValueEffectControl
880EffectControlLinearizer::LowerObjectIsUndetectable(Node* node, Node* effect,
881 Node* control) {
882 Node* value = node->InputAt(0);
883
884 Node* check = ObjectIsSmi(value);
885 Node* branch =
886 graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
887
888 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
889 Node* etrue = effect;
890 Node* vtrue = jsgraph()->Int32Constant(0);
891
892 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
893 Node* efalse = effect;
894 Node* vfalse;
895 {
896 Node* value_map = efalse =
897 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
898 value, efalse, if_false);
899 Node* value_bit_field = efalse = graph()->NewNode(
900 simplified()->LoadField(AccessBuilder::ForMapBitField()), value_map,
901 efalse, if_false);
902 vfalse = graph()->NewNode(
903 machine()->Word32Equal(),
904 graph()->NewNode(
905 machine()->Word32Equal(), jsgraph()->Int32Constant(0),
906 graph()->NewNode(
907 machine()->Word32And(), value_bit_field,
908 jsgraph()->Int32Constant(1 << Map::kIsUndetectable))),
909 jsgraph()->Int32Constant(0));
910 }
911
912 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
913 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
914 value = graph()->NewNode(common()->Phi(MachineRepresentation::kBit, 2), vtrue,
915 vfalse, control);
916
917 return ValueEffectControl(value, effect, control);
918}
919
920EffectControlLinearizer::ValueEffectControl
921EffectControlLinearizer::AllocateHeapNumberWithValue(Node* value, Node* effect,
922 Node* control) {
923 Node* result = effect = graph()->NewNode(
924 simplified()->Allocate(NOT_TENURED),
925 jsgraph()->Int32Constant(HeapNumber::kSize), effect, control);
926 effect = graph()->NewNode(simplified()->StoreField(AccessBuilder::ForMap()),
927 result, jsgraph()->HeapNumberMapConstant(), effect,
928 control);
929 effect = graph()->NewNode(
930 simplified()->StoreField(AccessBuilder::ForHeapNumberValue()), result,
931 value, effect, control);
932 return ValueEffectControl(result, effect, control);
933}
934
935Node* EffectControlLinearizer::ChangeInt32ToSmi(Node* value) {
936 if (machine()->Is64()) {
937 value = graph()->NewNode(machine()->ChangeInt32ToInt64(), value);
938 }
939 return graph()->NewNode(machine()->WordShl(), value, SmiShiftBitsConstant());
940}
941
942Node* EffectControlLinearizer::ChangeUint32ToSmi(Node* value) {
943 if (machine()->Is64()) {
944 value = graph()->NewNode(machine()->ChangeUint32ToUint64(), value);
945 }
946 return graph()->NewNode(machine()->WordShl(), value, SmiShiftBitsConstant());
947}
948
949Node* EffectControlLinearizer::ChangeInt32ToFloat64(Node* value) {
950 return graph()->NewNode(machine()->ChangeInt32ToFloat64(), value);
951}
952
953Node* EffectControlLinearizer::ChangeUint32ToFloat64(Node* value) {
954 return graph()->NewNode(machine()->ChangeUint32ToFloat64(), value);
955}
956
957Node* EffectControlLinearizer::ChangeSmiToInt32(Node* value) {
958 value = graph()->NewNode(machine()->WordSar(), value, SmiShiftBitsConstant());
959 if (machine()->Is64()) {
960 value = graph()->NewNode(machine()->TruncateInt64ToInt32(), value);
961 }
962 return value;
963}
964
965Node* EffectControlLinearizer::ObjectIsSmi(Node* value) {
966 return graph()->NewNode(
967 machine()->WordEqual(),
968 graph()->NewNode(machine()->WordAnd(), value,
969 jsgraph()->IntPtrConstant(kSmiTagMask)),
970 jsgraph()->IntPtrConstant(kSmiTag));
971}
972
973Node* EffectControlLinearizer::SmiMaxValueConstant() {
974 return jsgraph()->Int32Constant(Smi::kMaxValue);
975}
976
977Node* EffectControlLinearizer::SmiShiftBitsConstant() {
978 return jsgraph()->IntPtrConstant(kSmiShiftSize + kSmiTagSize);
979}
980
981} // namespace compiler
982} // namespace internal
983} // namespace v8