1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
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/compiler-source-position-table.h"
10 #include "src/compiler/js-graph.h"
11 #include "src/compiler/linkage.h"
12 #include "src/compiler/node-matchers.h"
13 #include "src/compiler/node-properties.h"
14 #include "src/compiler/node.h"
15 #include "src/compiler/schedule.h"
16
17 namespace v8 {
18 namespace internal {
19 namespace compiler {
20
EffectControlLinearizer(JSGraph * js_graph,Schedule * schedule,Zone * temp_zone,SourcePositionTable * source_positions)21 EffectControlLinearizer::EffectControlLinearizer(
22 JSGraph* js_graph, Schedule* schedule, Zone* temp_zone,
23 SourcePositionTable* source_positions)
24 : js_graph_(js_graph),
25 schedule_(schedule),
26 temp_zone_(temp_zone),
27 source_positions_(source_positions) {}
28
graph() const29 Graph* EffectControlLinearizer::graph() const { return js_graph_->graph(); }
common() const30 CommonOperatorBuilder* EffectControlLinearizer::common() const {
31 return js_graph_->common();
32 }
simplified() const33 SimplifiedOperatorBuilder* EffectControlLinearizer::simplified() const {
34 return js_graph_->simplified();
35 }
machine() const36 MachineOperatorBuilder* EffectControlLinearizer::machine() const {
37 return js_graph_->machine();
38 }
39
40 namespace {
41
42 struct BlockEffectControlData {
43 Node* current_effect = nullptr; // New effect.
44 Node* current_control = nullptr; // New control.
45 Node* current_frame_state = nullptr; // New frame state.
46 };
47
48 class BlockEffectControlMap {
49 public:
BlockEffectControlMap(Zone * temp_zone)50 explicit BlockEffectControlMap(Zone* temp_zone) : map_(temp_zone) {}
51
For(BasicBlock * from,BasicBlock * to)52 BlockEffectControlData& For(BasicBlock* from, BasicBlock* to) {
53 return map_[std::make_pair(from->rpo_number(), to->rpo_number())];
54 }
55
For(BasicBlock * from,BasicBlock * to) const56 const BlockEffectControlData& For(BasicBlock* from, BasicBlock* to) const {
57 return map_.at(std::make_pair(from->rpo_number(), to->rpo_number()));
58 }
59
60 private:
61 typedef std::pair<int32_t, int32_t> Key;
62 typedef ZoneMap<Key, BlockEffectControlData> Map;
63
64 Map map_;
65 };
66
67 // Effect phis that need to be updated after the first pass.
68 struct PendingEffectPhi {
69 Node* effect_phi;
70 BasicBlock* block;
71
PendingEffectPhiv8::internal::compiler::__anon37f087a00111::PendingEffectPhi72 PendingEffectPhi(Node* effect_phi, BasicBlock* block)
73 : effect_phi(effect_phi), block(block) {}
74 };
75
UpdateEffectPhi(Node * node,BasicBlock * block,BlockEffectControlMap * block_effects)76 void UpdateEffectPhi(Node* node, BasicBlock* block,
77 BlockEffectControlMap* block_effects) {
78 // Update all inputs to an effect phi with the effects from the given
79 // block->effect map.
80 DCHECK_EQ(IrOpcode::kEffectPhi, node->opcode());
81 DCHECK_EQ(static_cast<size_t>(node->op()->EffectInputCount()),
82 block->PredecessorCount());
83 for (int i = 0; i < node->op()->EffectInputCount(); i++) {
84 Node* input = node->InputAt(i);
85 BasicBlock* predecessor = block->PredecessorAt(static_cast<size_t>(i));
86 const BlockEffectControlData& block_effect =
87 block_effects->For(predecessor, block);
88 if (input != block_effect.current_effect) {
89 node->ReplaceInput(i, block_effect.current_effect);
90 }
91 }
92 }
93
UpdateBlockControl(BasicBlock * block,BlockEffectControlMap * block_effects)94 void UpdateBlockControl(BasicBlock* block,
95 BlockEffectControlMap* block_effects) {
96 Node* control = block->NodeAt(0);
97 DCHECK(NodeProperties::IsControl(control));
98
99 // Do not rewire the end node.
100 if (control->opcode() == IrOpcode::kEnd) return;
101
102 // Update all inputs to the given control node with the correct control.
103 DCHECK(control->opcode() == IrOpcode::kMerge ||
104 static_cast<size_t>(control->op()->ControlInputCount()) ==
105 block->PredecessorCount());
106 if (static_cast<size_t>(control->op()->ControlInputCount()) !=
107 block->PredecessorCount()) {
108 return; // We already re-wired the control inputs of this node.
109 }
110 for (int i = 0; i < control->op()->ControlInputCount(); i++) {
111 Node* input = NodeProperties::GetControlInput(control, i);
112 BasicBlock* predecessor = block->PredecessorAt(static_cast<size_t>(i));
113 const BlockEffectControlData& block_effect =
114 block_effects->For(predecessor, block);
115 if (input != block_effect.current_control) {
116 NodeProperties::ReplaceControlInput(control, block_effect.current_control,
117 i);
118 }
119 }
120 }
121
HasIncomingBackEdges(BasicBlock * block)122 bool HasIncomingBackEdges(BasicBlock* block) {
123 for (BasicBlock* pred : block->predecessors()) {
124 if (pred->rpo_number() >= block->rpo_number()) {
125 return true;
126 }
127 }
128 return false;
129 }
130
RemoveRegionNode(Node * node)131 void RemoveRegionNode(Node* node) {
132 DCHECK(IrOpcode::kFinishRegion == node->opcode() ||
133 IrOpcode::kBeginRegion == node->opcode());
134 // Update the value/context uses to the value input of the finish node and
135 // the effect uses to the effect input.
136 for (Edge edge : node->use_edges()) {
137 DCHECK(!edge.from()->IsDead());
138 if (NodeProperties::IsEffectEdge(edge)) {
139 edge.UpdateTo(NodeProperties::GetEffectInput(node));
140 } else {
141 DCHECK(!NodeProperties::IsControlEdge(edge));
142 DCHECK(!NodeProperties::IsFrameStateEdge(edge));
143 edge.UpdateTo(node->InputAt(0));
144 }
145 }
146 node->Kill();
147 }
148
TryCloneBranch(Node * node,BasicBlock * block,Graph * graph,CommonOperatorBuilder * common,BlockEffectControlMap * block_effects,SourcePositionTable * source_positions)149 void TryCloneBranch(Node* node, BasicBlock* block, Graph* graph,
150 CommonOperatorBuilder* common,
151 BlockEffectControlMap* block_effects,
152 SourcePositionTable* source_positions) {
153 DCHECK_EQ(IrOpcode::kBranch, node->opcode());
154
155 // This optimization is a special case of (super)block cloning. It takes an
156 // input graph as shown below and clones the Branch node for every predecessor
157 // to the Merge, essentially removing the Merge completely. This avoids
158 // materializing the bit for the Phi and may offer potential for further
159 // branch folding optimizations (i.e. because one or more inputs to the Phi is
160 // a constant). Note that there may be more Phi nodes hanging off the Merge,
161 // but we can only a certain subset of them currently (actually only Phi and
162 // EffectPhi nodes whose uses have either the IfTrue or IfFalse as control
163 // input).
164
165 // Control1 ... ControlN
166 // ^ ^
167 // | | Cond1 ... CondN
168 // +----+ +----+ ^ ^
169 // | | | |
170 // | | +----+ |
171 // Merge<--+ | +------------+
172 // ^ \|/
173 // | Phi
174 // | |
175 // Branch----+
176 // ^
177 // |
178 // +-----+-----+
179 // | |
180 // IfTrue IfFalse
181 // ^ ^
182 // | |
183
184 // The resulting graph (modulo the Phi and EffectPhi nodes) looks like this:
185
186 // Control1 Cond1 ... ControlN CondN
187 // ^ ^ ^ ^
188 // \ / \ /
189 // Branch ... Branch
190 // ^ ^
191 // | |
192 // +---+---+ +---+----+
193 // | | | |
194 // IfTrue IfFalse ... IfTrue IfFalse
195 // ^ ^ ^ ^
196 // | | | |
197 // +--+ +-------------+ |
198 // | | +--------------+ +--+
199 // | | | |
200 // Merge Merge
201 // ^ ^
202 // | |
203
204 SourcePositionTable::Scope scope(source_positions,
205 source_positions->GetSourcePosition(node));
206 Node* branch = node;
207 Node* cond = NodeProperties::GetValueInput(branch, 0);
208 if (!cond->OwnedBy(branch) || cond->opcode() != IrOpcode::kPhi) return;
209 Node* merge = NodeProperties::GetControlInput(branch);
210 if (merge->opcode() != IrOpcode::kMerge ||
211 NodeProperties::GetControlInput(cond) != merge) {
212 return;
213 }
214 // Grab the IfTrue/IfFalse projections of the Branch.
215 BranchMatcher matcher(branch);
216 // Check/collect other Phi/EffectPhi nodes hanging off the Merge.
217 NodeVector phis(graph->zone());
218 for (Node* const use : merge->uses()) {
219 if (use == branch || use == cond) continue;
220 // We cannot currently deal with non-Phi/EffectPhi nodes hanging off the
221 // Merge. Ideally, we would just clone the nodes (and everything that
222 // depends on it to some distant join point), but that requires knowledge
223 // about dominance/post-dominance.
224 if (!NodeProperties::IsPhi(use)) return;
225 for (Edge edge : use->use_edges()) {
226 // Right now we can only handle Phi/EffectPhi nodes whose uses are
227 // directly control-dependend on either the IfTrue or the IfFalse
228 // successor, because we know exactly how to update those uses.
229 if (edge.from()->op()->ControlInputCount() != 1) return;
230 Node* control = NodeProperties::GetControlInput(edge.from());
231 if (NodeProperties::IsPhi(edge.from())) {
232 control = NodeProperties::GetControlInput(control, edge.index());
233 }
234 if (control != matcher.IfTrue() && control != matcher.IfFalse()) return;
235 }
236 phis.push_back(use);
237 }
238 BranchHint const hint = BranchHintOf(branch->op());
239 int const input_count = merge->op()->ControlInputCount();
240 DCHECK_LE(1, input_count);
241 Node** const inputs = graph->zone()->NewArray<Node*>(2 * input_count);
242 Node** const merge_true_inputs = &inputs[0];
243 Node** const merge_false_inputs = &inputs[input_count];
244 for (int index = 0; index < input_count; ++index) {
245 Node* cond1 = NodeProperties::GetValueInput(cond, index);
246 Node* control1 = NodeProperties::GetControlInput(merge, index);
247 Node* branch1 = graph->NewNode(common->Branch(hint), cond1, control1);
248 merge_true_inputs[index] = graph->NewNode(common->IfTrue(), branch1);
249 merge_false_inputs[index] = graph->NewNode(common->IfFalse(), branch1);
250 }
251 Node* const merge_true = matcher.IfTrue();
252 Node* const merge_false = matcher.IfFalse();
253 merge_true->TrimInputCount(0);
254 merge_false->TrimInputCount(0);
255 for (int i = 0; i < input_count; ++i) {
256 merge_true->AppendInput(graph->zone(), merge_true_inputs[i]);
257 merge_false->AppendInput(graph->zone(), merge_false_inputs[i]);
258 }
259 DCHECK_EQ(2u, block->SuccessorCount());
260 NodeProperties::ChangeOp(matcher.IfTrue(), common->Merge(input_count));
261 NodeProperties::ChangeOp(matcher.IfFalse(), common->Merge(input_count));
262 int const true_index =
263 block->SuccessorAt(0)->NodeAt(0) == matcher.IfTrue() ? 0 : 1;
264 BlockEffectControlData* true_block_data =
265 &block_effects->For(block, block->SuccessorAt(true_index));
266 BlockEffectControlData* false_block_data =
267 &block_effects->For(block, block->SuccessorAt(true_index ^ 1));
268 for (Node* const phi : phis) {
269 for (int index = 0; index < input_count; ++index) {
270 inputs[index] = phi->InputAt(index);
271 }
272 inputs[input_count] = merge_true;
273 Node* phi_true = graph->NewNode(phi->op(), input_count + 1, inputs);
274 inputs[input_count] = merge_false;
275 Node* phi_false = graph->NewNode(phi->op(), input_count + 1, inputs);
276 if (phi->UseCount() == 0) {
277 DCHECK_EQ(phi->opcode(), IrOpcode::kEffectPhi);
278 } else {
279 for (Edge edge : phi->use_edges()) {
280 Node* control = NodeProperties::GetControlInput(edge.from());
281 if (NodeProperties::IsPhi(edge.from())) {
282 control = NodeProperties::GetControlInput(control, edge.index());
283 }
284 DCHECK(control == matcher.IfTrue() || control == matcher.IfFalse());
285 edge.UpdateTo((control == matcher.IfTrue()) ? phi_true : phi_false);
286 }
287 }
288 if (phi->opcode() == IrOpcode::kEffectPhi) {
289 true_block_data->current_effect = phi_true;
290 false_block_data->current_effect = phi_false;
291 }
292 phi->Kill();
293 }
294 // Fix up IfTrue and IfFalse and kill all dead nodes.
295 if (branch == block->control_input()) {
296 true_block_data->current_control = merge_true;
297 false_block_data->current_control = merge_false;
298 }
299 branch->Kill();
300 cond->Kill();
301 merge->Kill();
302 }
303 } // namespace
304
Run()305 void EffectControlLinearizer::Run() {
306 BlockEffectControlMap block_effects(temp_zone());
307 ZoneVector<PendingEffectPhi> pending_effect_phis(temp_zone());
308 ZoneVector<BasicBlock*> pending_block_controls(temp_zone());
309 NodeVector inputs_buffer(temp_zone());
310
311 for (BasicBlock* block : *(schedule()->rpo_order())) {
312 size_t instr = 0;
313
314 // The control node should be the first.
315 Node* control = block->NodeAt(instr);
316 DCHECK(NodeProperties::IsControl(control));
317 // Update the control inputs.
318 if (HasIncomingBackEdges(block)) {
319 // If there are back edges, we need to update later because we have not
320 // computed the control yet. This should only happen for loops.
321 DCHECK_EQ(IrOpcode::kLoop, control->opcode());
322 pending_block_controls.push_back(block);
323 } else {
324 // If there are no back edges, we can update now.
325 UpdateBlockControl(block, &block_effects);
326 }
327 instr++;
328
329 // Iterate over the phis and update the effect phis.
330 Node* effect = nullptr;
331 Node* terminate = nullptr;
332 for (; instr < block->NodeCount(); instr++) {
333 Node* node = block->NodeAt(instr);
334 // Only go through the phis and effect phis.
335 if (node->opcode() == IrOpcode::kEffectPhi) {
336 // There should be at most one effect phi in a block.
337 DCHECK_NULL(effect);
338 // IfException blocks should not have effect phis.
339 DCHECK_NE(IrOpcode::kIfException, control->opcode());
340 effect = node;
341
342 // Make sure we update the inputs to the incoming blocks' effects.
343 if (HasIncomingBackEdges(block)) {
344 // In case of loops, we do not update the effect phi immediately
345 // because the back predecessor has not been handled yet. We just
346 // record the effect phi for later processing.
347 pending_effect_phis.push_back(PendingEffectPhi(node, block));
348 } else {
349 UpdateEffectPhi(node, block, &block_effects);
350 }
351 } else if (node->opcode() == IrOpcode::kPhi) {
352 // Just skip phis.
353 } else if (node->opcode() == IrOpcode::kTerminate) {
354 DCHECK(terminate == nullptr);
355 terminate = node;
356 } else {
357 break;
358 }
359 }
360
361 if (effect == nullptr) {
362 // There was no effect phi.
363 DCHECK(!HasIncomingBackEdges(block));
364 if (block == schedule()->start()) {
365 // Start block => effect is start.
366 DCHECK_EQ(graph()->start(), control);
367 effect = graph()->start();
368 } else if (control->opcode() == IrOpcode::kEnd) {
369 // End block is just a dummy, no effect needed.
370 DCHECK_EQ(BasicBlock::kNone, block->control());
371 DCHECK_EQ(1u, block->size());
372 effect = nullptr;
373 } else {
374 // If all the predecessors have the same effect, we can use it as our
375 // current effect.
376 effect =
377 block_effects.For(block->PredecessorAt(0), block).current_effect;
378 for (size_t i = 1; i < block->PredecessorCount(); ++i) {
379 if (block_effects.For(block->PredecessorAt(i), block)
380 .current_effect != effect) {
381 effect = nullptr;
382 break;
383 }
384 }
385 if (effect == nullptr) {
386 DCHECK_NE(IrOpcode::kIfException, control->opcode());
387 // The input blocks do not have the same effect. We have
388 // to create an effect phi node.
389 inputs_buffer.clear();
390 inputs_buffer.resize(block->PredecessorCount(), jsgraph()->Dead());
391 inputs_buffer.push_back(control);
392 effect = graph()->NewNode(
393 common()->EffectPhi(static_cast<int>(block->PredecessorCount())),
394 static_cast<int>(inputs_buffer.size()), &(inputs_buffer.front()));
395 // For loops, we update the effect phi node later to break cycles.
396 if (control->opcode() == IrOpcode::kLoop) {
397 pending_effect_phis.push_back(PendingEffectPhi(effect, block));
398 } else {
399 UpdateEffectPhi(effect, block, &block_effects);
400 }
401 } else if (control->opcode() == IrOpcode::kIfException) {
402 // The IfException is connected into the effect chain, so we need
403 // to update the effect here.
404 NodeProperties::ReplaceEffectInput(control, effect);
405 effect = control;
406 }
407 }
408 }
409
410 // Fixup the Terminate node.
411 if (terminate != nullptr) {
412 NodeProperties::ReplaceEffectInput(terminate, effect);
413 }
414
415 // The frame state at block entry is determined by the frame states leaving
416 // all predecessors. In case there is no frame state dominating this block,
417 // we can rely on a checkpoint being present before the next deoptimization.
418 // TODO(mstarzinger): Eventually we will need to go hunt for a frame state
419 // once deoptimizing nodes roam freely through the schedule.
420 Node* frame_state = nullptr;
421 if (block != schedule()->start()) {
422 // If all the predecessors have the same effect, we can use it
423 // as our current effect.
424 frame_state =
425 block_effects.For(block->PredecessorAt(0), block).current_frame_state;
426 for (size_t i = 1; i < block->PredecessorCount(); i++) {
427 if (block_effects.For(block->PredecessorAt(i), block)
428 .current_frame_state != frame_state) {
429 frame_state = nullptr;
430 break;
431 }
432 }
433 }
434
435 // Process the ordinary instructions.
436 for (; instr < block->NodeCount(); instr++) {
437 Node* node = block->NodeAt(instr);
438 ProcessNode(node, &frame_state, &effect, &control);
439 }
440
441 switch (block->control()) {
442 case BasicBlock::kGoto:
443 case BasicBlock::kNone:
444 break;
445
446 case BasicBlock::kCall:
447 case BasicBlock::kTailCall:
448 case BasicBlock::kSwitch:
449 case BasicBlock::kReturn:
450 case BasicBlock::kDeoptimize:
451 case BasicBlock::kThrow:
452 ProcessNode(block->control_input(), &frame_state, &effect, &control);
453 break;
454
455 case BasicBlock::kBranch:
456 ProcessNode(block->control_input(), &frame_state, &effect, &control);
457 TryCloneBranch(block->control_input(), block, graph(), common(),
458 &block_effects, source_positions_);
459 break;
460 }
461
462 // Store the effect, control and frame state for later use.
463 for (BasicBlock* successor : block->successors()) {
464 BlockEffectControlData* data = &block_effects.For(block, successor);
465 if (data->current_effect == nullptr) {
466 data->current_effect = effect;
467 }
468 if (data->current_control == nullptr) {
469 data->current_control = control;
470 }
471 data->current_frame_state = frame_state;
472 }
473 }
474
475 // Update the incoming edges of the effect phis that could not be processed
476 // during the first pass (because they could have incoming back edges).
477 for (const PendingEffectPhi& pending_effect_phi : pending_effect_phis) {
478 UpdateEffectPhi(pending_effect_phi.effect_phi, pending_effect_phi.block,
479 &block_effects);
480 }
481 for (BasicBlock* pending_block_control : pending_block_controls) {
482 UpdateBlockControl(pending_block_control, &block_effects);
483 }
484 }
485
486 namespace {
487
TryScheduleCallIfSuccess(Node * node,Node ** control)488 void TryScheduleCallIfSuccess(Node* node, Node** control) {
489 // Schedule the call's IfSuccess node if there is no exception use.
490 if (!NodeProperties::IsExceptionalCall(node)) {
491 for (Edge edge : node->use_edges()) {
492 if (NodeProperties::IsControlEdge(edge) &&
493 edge.from()->opcode() == IrOpcode::kIfSuccess) {
494 *control = edge.from();
495 }
496 }
497 }
498 }
499
500 } // namespace
501
ProcessNode(Node * node,Node ** frame_state,Node ** effect,Node ** control)502 void EffectControlLinearizer::ProcessNode(Node* node, Node** frame_state,
503 Node** effect, Node** control) {
504 SourcePositionTable::Scope scope(source_positions_,
505 source_positions_->GetSourcePosition(node));
506
507 // If the node needs to be wired into the effect/control chain, do this
508 // here. Pass current frame state for lowering to eager deoptimization.
509 if (TryWireInStateEffect(node, *frame_state, effect, control)) {
510 return;
511 }
512
513 // If the node has a visible effect, then there must be a checkpoint in the
514 // effect chain before we are allowed to place another eager deoptimization
515 // point. We zap the frame state to ensure this invariant is maintained.
516 if (region_observability_ == RegionObservability::kObservable &&
517 !node->op()->HasProperty(Operator::kNoWrite)) {
518 *frame_state = nullptr;
519 }
520
521 // Remove the end markers of 'atomic' allocation region because the
522 // region should be wired-in now.
523 if (node->opcode() == IrOpcode::kFinishRegion) {
524 // Reset the current region observability.
525 region_observability_ = RegionObservability::kObservable;
526 // Update the value uses to the value input of the finish node and
527 // the effect uses to the effect input.
528 return RemoveRegionNode(node);
529 }
530 if (node->opcode() == IrOpcode::kBeginRegion) {
531 // Determine the observability for this region and use that for all
532 // nodes inside the region (i.e. ignore the absence of kNoWrite on
533 // StoreField and other operators).
534 DCHECK_NE(RegionObservability::kNotObservable, region_observability_);
535 region_observability_ = RegionObservabilityOf(node->op());
536 // Update the value uses to the value input of the finish node and
537 // the effect uses to the effect input.
538 return RemoveRegionNode(node);
539 }
540
541 // Special treatment for checkpoint nodes.
542 if (node->opcode() == IrOpcode::kCheckpoint) {
543 // Unlink the check point; effect uses will be updated to the incoming
544 // effect that is passed. The frame state is preserved for lowering.
545 DCHECK_EQ(RegionObservability::kObservable, region_observability_);
546 *frame_state = NodeProperties::GetFrameStateInput(node);
547 return;
548 }
549
550 if (node->opcode() == IrOpcode::kIfSuccess) {
551 // We always schedule IfSuccess with its call, so skip it here.
552 DCHECK_EQ(IrOpcode::kCall, node->InputAt(0)->opcode());
553 // The IfSuccess node should not belong to an exceptional call node
554 // because such IfSuccess nodes should only start a basic block (and
555 // basic block start nodes are not handled in the ProcessNode method).
556 DCHECK(!NodeProperties::IsExceptionalCall(node->InputAt(0)));
557 return;
558 }
559
560 // If the node takes an effect, replace with the current one.
561 if (node->op()->EffectInputCount() > 0) {
562 DCHECK_EQ(1, node->op()->EffectInputCount());
563 Node* input_effect = NodeProperties::GetEffectInput(node);
564
565 if (input_effect != *effect) {
566 NodeProperties::ReplaceEffectInput(node, *effect);
567 }
568
569 // If the node produces an effect, update our current effect. (However,
570 // ignore new effect chains started with ValueEffect.)
571 if (node->op()->EffectOutputCount() > 0) {
572 DCHECK_EQ(1, node->op()->EffectOutputCount());
573 *effect = node;
574 }
575 } else {
576 // New effect chain is only started with a Start or ValueEffect node.
577 DCHECK(node->op()->EffectOutputCount() == 0 ||
578 node->opcode() == IrOpcode::kStart);
579 }
580
581 // Rewire control inputs.
582 for (int i = 0; i < node->op()->ControlInputCount(); i++) {
583 NodeProperties::ReplaceControlInput(node, *control, i);
584 }
585 // Update the current control and wire IfSuccess right after calls.
586 if (node->op()->ControlOutputCount() > 0) {
587 *control = node;
588 if (node->opcode() == IrOpcode::kCall) {
589 // Schedule the call's IfSuccess node (if there is no exception use).
590 TryScheduleCallIfSuccess(node, control);
591 }
592 }
593 }
594
TryWireInStateEffect(Node * node,Node * frame_state,Node ** effect,Node ** control)595 bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
596 Node* frame_state,
597 Node** effect,
598 Node** control) {
599 ValueEffectControl state(nullptr, nullptr, nullptr);
600 switch (node->opcode()) {
601 case IrOpcode::kChangeBitToTagged:
602 state = LowerChangeBitToTagged(node, *effect, *control);
603 break;
604 case IrOpcode::kChangeInt31ToTaggedSigned:
605 state = LowerChangeInt31ToTaggedSigned(node, *effect, *control);
606 break;
607 case IrOpcode::kChangeInt32ToTagged:
608 state = LowerChangeInt32ToTagged(node, *effect, *control);
609 break;
610 case IrOpcode::kChangeUint32ToTagged:
611 state = LowerChangeUint32ToTagged(node, *effect, *control);
612 break;
613 case IrOpcode::kChangeFloat64ToTagged:
614 state = LowerChangeFloat64ToTagged(node, *effect, *control);
615 break;
616 case IrOpcode::kChangeFloat64ToTaggedPointer:
617 state = LowerChangeFloat64ToTaggedPointer(node, *effect, *control);
618 break;
619 case IrOpcode::kChangeTaggedSignedToInt32:
620 state = LowerChangeTaggedSignedToInt32(node, *effect, *control);
621 break;
622 case IrOpcode::kChangeTaggedToBit:
623 state = LowerChangeTaggedToBit(node, *effect, *control);
624 break;
625 case IrOpcode::kChangeTaggedToInt32:
626 state = LowerChangeTaggedToInt32(node, *effect, *control);
627 break;
628 case IrOpcode::kChangeTaggedToUint32:
629 state = LowerChangeTaggedToUint32(node, *effect, *control);
630 break;
631 case IrOpcode::kChangeTaggedToFloat64:
632 state = LowerChangeTaggedToFloat64(node, *effect, *control);
633 break;
634 case IrOpcode::kTruncateTaggedToBit:
635 state = LowerTruncateTaggedToBit(node, *effect, *control);
636 break;
637 case IrOpcode::kTruncateTaggedToFloat64:
638 state = LowerTruncateTaggedToFloat64(node, *effect, *control);
639 break;
640 case IrOpcode::kCheckBounds:
641 state = LowerCheckBounds(node, frame_state, *effect, *control);
642 break;
643 case IrOpcode::kCheckMaps:
644 state = LowerCheckMaps(node, frame_state, *effect, *control);
645 break;
646 case IrOpcode::kCheckNumber:
647 state = LowerCheckNumber(node, frame_state, *effect, *control);
648 break;
649 case IrOpcode::kCheckString:
650 state = LowerCheckString(node, frame_state, *effect, *control);
651 break;
652 case IrOpcode::kCheckIf:
653 state = LowerCheckIf(node, frame_state, *effect, *control);
654 break;
655 case IrOpcode::kCheckedInt32Add:
656 state = LowerCheckedInt32Add(node, frame_state, *effect, *control);
657 break;
658 case IrOpcode::kCheckedInt32Sub:
659 state = LowerCheckedInt32Sub(node, frame_state, *effect, *control);
660 break;
661 case IrOpcode::kCheckedInt32Div:
662 state = LowerCheckedInt32Div(node, frame_state, *effect, *control);
663 break;
664 case IrOpcode::kCheckedInt32Mod:
665 state = LowerCheckedInt32Mod(node, frame_state, *effect, *control);
666 break;
667 case IrOpcode::kCheckedUint32Div:
668 state = LowerCheckedUint32Div(node, frame_state, *effect, *control);
669 break;
670 case IrOpcode::kCheckedUint32Mod:
671 state = LowerCheckedUint32Mod(node, frame_state, *effect, *control);
672 break;
673 case IrOpcode::kCheckedInt32Mul:
674 state = LowerCheckedInt32Mul(node, frame_state, *effect, *control);
675 break;
676 case IrOpcode::kCheckedInt32ToTaggedSigned:
677 state =
678 LowerCheckedInt32ToTaggedSigned(node, frame_state, *effect, *control);
679 break;
680 case IrOpcode::kCheckedUint32ToInt32:
681 state = LowerCheckedUint32ToInt32(node, frame_state, *effect, *control);
682 break;
683 case IrOpcode::kCheckedUint32ToTaggedSigned:
684 state = LowerCheckedUint32ToTaggedSigned(node, frame_state, *effect,
685 *control);
686 break;
687 case IrOpcode::kCheckedFloat64ToInt32:
688 state = LowerCheckedFloat64ToInt32(node, frame_state, *effect, *control);
689 break;
690 case IrOpcode::kCheckedTaggedSignedToInt32:
691 state =
692 LowerCheckedTaggedSignedToInt32(node, frame_state, *effect, *control);
693 break;
694 case IrOpcode::kCheckedTaggedToInt32:
695 state = LowerCheckedTaggedToInt32(node, frame_state, *effect, *control);
696 break;
697 case IrOpcode::kCheckedTaggedToFloat64:
698 state = LowerCheckedTaggedToFloat64(node, frame_state, *effect, *control);
699 break;
700 case IrOpcode::kCheckedTaggedToTaggedSigned:
701 state = LowerCheckedTaggedToTaggedSigned(node, frame_state, *effect,
702 *control);
703 break;
704 case IrOpcode::kCheckedTaggedToTaggedPointer:
705 state = LowerCheckedTaggedToTaggedPointer(node, frame_state, *effect,
706 *control);
707 break;
708 case IrOpcode::kTruncateTaggedToWord32:
709 state = LowerTruncateTaggedToWord32(node, *effect, *control);
710 break;
711 case IrOpcode::kCheckedTruncateTaggedToWord32:
712 state = LowerCheckedTruncateTaggedToWord32(node, frame_state, *effect,
713 *control);
714 break;
715 case IrOpcode::kObjectIsCallable:
716 state = LowerObjectIsCallable(node, *effect, *control);
717 break;
718 case IrOpcode::kObjectIsNumber:
719 state = LowerObjectIsNumber(node, *effect, *control);
720 break;
721 case IrOpcode::kObjectIsReceiver:
722 state = LowerObjectIsReceiver(node, *effect, *control);
723 break;
724 case IrOpcode::kObjectIsSmi:
725 state = LowerObjectIsSmi(node, *effect, *control);
726 break;
727 case IrOpcode::kObjectIsString:
728 state = LowerObjectIsString(node, *effect, *control);
729 break;
730 case IrOpcode::kObjectIsUndetectable:
731 state = LowerObjectIsUndetectable(node, *effect, *control);
732 break;
733 case IrOpcode::kArrayBufferWasNeutered:
734 state = LowerArrayBufferWasNeutered(node, *effect, *control);
735 break;
736 case IrOpcode::kStringFromCharCode:
737 state = LowerStringFromCharCode(node, *effect, *control);
738 break;
739 case IrOpcode::kStringFromCodePoint:
740 state = LowerStringFromCodePoint(node, *effect, *control);
741 break;
742 case IrOpcode::kStringCharCodeAt:
743 state = LowerStringCharCodeAt(node, *effect, *control);
744 break;
745 case IrOpcode::kStringEqual:
746 state = LowerStringEqual(node, *effect, *control);
747 break;
748 case IrOpcode::kStringLessThan:
749 state = LowerStringLessThan(node, *effect, *control);
750 break;
751 case IrOpcode::kStringLessThanOrEqual:
752 state = LowerStringLessThanOrEqual(node, *effect, *control);
753 break;
754 case IrOpcode::kCheckFloat64Hole:
755 state = LowerCheckFloat64Hole(node, frame_state, *effect, *control);
756 break;
757 case IrOpcode::kCheckTaggedHole:
758 state = LowerCheckTaggedHole(node, frame_state, *effect, *control);
759 break;
760 case IrOpcode::kConvertTaggedHoleToUndefined:
761 state = LowerConvertTaggedHoleToUndefined(node, *effect, *control);
762 break;
763 case IrOpcode::kPlainPrimitiveToNumber:
764 state = LowerPlainPrimitiveToNumber(node, *effect, *control);
765 break;
766 case IrOpcode::kPlainPrimitiveToWord32:
767 state = LowerPlainPrimitiveToWord32(node, *effect, *control);
768 break;
769 case IrOpcode::kPlainPrimitiveToFloat64:
770 state = LowerPlainPrimitiveToFloat64(node, *effect, *control);
771 break;
772 case IrOpcode::kEnsureWritableFastElements:
773 state = LowerEnsureWritableFastElements(node, *effect, *control);
774 break;
775 case IrOpcode::kMaybeGrowFastElements:
776 state = LowerMaybeGrowFastElements(node, frame_state, *effect, *control);
777 break;
778 case IrOpcode::kTransitionElementsKind:
779 state = LowerTransitionElementsKind(node, *effect, *control);
780 break;
781 case IrOpcode::kLoadTypedElement:
782 state = LowerLoadTypedElement(node, *effect, *control);
783 break;
784 case IrOpcode::kStoreTypedElement:
785 state = LowerStoreTypedElement(node, *effect, *control);
786 break;
787 case IrOpcode::kFloat64RoundUp:
788 state = LowerFloat64RoundUp(node, *effect, *control);
789 break;
790 case IrOpcode::kFloat64RoundDown:
791 state = LowerFloat64RoundDown(node, *effect, *control);
792 break;
793 case IrOpcode::kFloat64RoundTruncate:
794 state = LowerFloat64RoundTruncate(node, *effect, *control);
795 break;
796 case IrOpcode::kFloat64RoundTiesEven:
797 state = LowerFloat64RoundTiesEven(node, *effect, *control);
798 break;
799 default:
800 return false;
801 }
802 NodeProperties::ReplaceUses(node, state.value, state.effect, state.control);
803 *effect = state.effect;
804 *control = state.control;
805 return true;
806 }
807
808 EffectControlLinearizer::ValueEffectControl
LowerChangeFloat64ToTagged(Node * node,Node * effect,Node * control)809 EffectControlLinearizer::LowerChangeFloat64ToTagged(Node* node, Node* effect,
810 Node* control) {
811 Node* value = node->InputAt(0);
812 return AllocateHeapNumberWithValue(value, effect, control);
813 }
814
815 EffectControlLinearizer::ValueEffectControl
LowerChangeFloat64ToTaggedPointer(Node * node,Node * effect,Node * control)816 EffectControlLinearizer::LowerChangeFloat64ToTaggedPointer(Node* node,
817 Node* effect,
818 Node* control) {
819 Node* value = node->InputAt(0);
820 return AllocateHeapNumberWithValue(value, effect, control);
821 }
822
823 EffectControlLinearizer::ValueEffectControl
LowerChangeBitToTagged(Node * node,Node * effect,Node * control)824 EffectControlLinearizer::LowerChangeBitToTagged(Node* node, Node* effect,
825 Node* control) {
826 Node* value = node->InputAt(0);
827
828 Node* branch = graph()->NewNode(common()->Branch(), value, control);
829
830 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
831 Node* vtrue = jsgraph()->TrueConstant();
832
833 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
834 Node* vfalse = jsgraph()->FalseConstant();
835
836 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
837 value = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
838 vtrue, vfalse, control);
839
840 return ValueEffectControl(value, effect, control);
841 }
842
843 EffectControlLinearizer::ValueEffectControl
LowerChangeInt31ToTaggedSigned(Node * node,Node * effect,Node * control)844 EffectControlLinearizer::LowerChangeInt31ToTaggedSigned(Node* node,
845 Node* effect,
846 Node* control) {
847 Node* value = node->InputAt(0);
848 value = ChangeInt32ToSmi(value);
849 return ValueEffectControl(value, effect, control);
850 }
851
852 EffectControlLinearizer::ValueEffectControl
LowerChangeInt32ToTagged(Node * node,Node * effect,Node * control)853 EffectControlLinearizer::LowerChangeInt32ToTagged(Node* node, Node* effect,
854 Node* control) {
855 Node* value = node->InputAt(0);
856
857 if (machine()->Is64()) {
858 return ValueEffectControl(ChangeInt32ToSmi(value), effect, control);
859 }
860
861 Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), value, value,
862 control);
863
864 Node* ovf = graph()->NewNode(common()->Projection(1), add, control);
865 Node* branch =
866 graph()->NewNode(common()->Branch(BranchHint::kFalse), ovf, control);
867
868 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
869 ValueEffectControl alloc =
870 AllocateHeapNumberWithValue(ChangeInt32ToFloat64(value), effect, if_true);
871
872 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
873 Node* vfalse = graph()->NewNode(common()->Projection(0), add, if_false);
874
875 Node* merge = graph()->NewNode(common()->Merge(2), alloc.control, if_false);
876 Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
877 alloc.value, vfalse, merge);
878 Node* ephi =
879 graph()->NewNode(common()->EffectPhi(2), alloc.effect, effect, merge);
880
881 return ValueEffectControl(phi, ephi, merge);
882 }
883
884 EffectControlLinearizer::ValueEffectControl
LowerChangeUint32ToTagged(Node * node,Node * effect,Node * control)885 EffectControlLinearizer::LowerChangeUint32ToTagged(Node* node, Node* effect,
886 Node* control) {
887 Node* value = node->InputAt(0);
888
889 Node* check = graph()->NewNode(machine()->Uint32LessThanOrEqual(), value,
890 SmiMaxValueConstant());
891 Node* branch =
892 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
893
894 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
895 Node* vtrue = ChangeUint32ToSmi(value);
896
897 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
898 ValueEffectControl alloc = AllocateHeapNumberWithValue(
899 ChangeUint32ToFloat64(value), effect, if_false);
900
901 Node* merge = graph()->NewNode(common()->Merge(2), if_true, alloc.control);
902 Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
903 vtrue, alloc.value, merge);
904 Node* ephi =
905 graph()->NewNode(common()->EffectPhi(2), effect, alloc.effect, merge);
906
907 return ValueEffectControl(phi, ephi, merge);
908 }
909
910 EffectControlLinearizer::ValueEffectControl
LowerChangeTaggedSignedToInt32(Node * node,Node * effect,Node * control)911 EffectControlLinearizer::LowerChangeTaggedSignedToInt32(Node* node,
912 Node* effect,
913 Node* control) {
914 Node* value = node->InputAt(0);
915 value = ChangeSmiToInt32(value);
916 return ValueEffectControl(value, effect, control);
917 }
918
919 EffectControlLinearizer::ValueEffectControl
LowerChangeTaggedToBit(Node * node,Node * effect,Node * control)920 EffectControlLinearizer::LowerChangeTaggedToBit(Node* node, Node* effect,
921 Node* control) {
922 Node* value = node->InputAt(0);
923 value = graph()->NewNode(machine()->WordEqual(), value,
924 jsgraph()->TrueConstant());
925 return ValueEffectControl(value, effect, control);
926 }
927
928 EffectControlLinearizer::ValueEffectControl
LowerTruncateTaggedToBit(Node * node,Node * effect,Node * control)929 EffectControlLinearizer::LowerTruncateTaggedToBit(Node* node, Node* effect,
930 Node* control) {
931 Node* value = node->InputAt(0);
932 Node* zero = jsgraph()->Int32Constant(0);
933 Node* fzero = jsgraph()->Float64Constant(0.0);
934
935 // Collect effect/control/value triples.
936 int count = 0;
937 Node* values[6];
938 Node* effects[6];
939 Node* controls[5];
940
941 // Check if {value} is a Smi.
942 Node* check_smi = ObjectIsSmi(value);
943 Node* branch_smi = graph()->NewNode(common()->Branch(BranchHint::kFalse),
944 check_smi, control);
945
946 // If {value} is a Smi, then we only need to check that it's not zero.
947 Node* if_smi = graph()->NewNode(common()->IfTrue(), branch_smi);
948 Node* esmi = effect;
949 {
950 controls[count] = if_smi;
951 effects[count] = esmi;
952 values[count] =
953 graph()->NewNode(machine()->Word32Equal(),
954 graph()->NewNode(machine()->WordEqual(), value,
955 jsgraph()->IntPtrConstant(0)),
956 zero);
957 count++;
958 }
959 control = graph()->NewNode(common()->IfFalse(), branch_smi);
960
961 // Load the map instance type of {value}.
962 Node* value_map = effect = graph()->NewNode(
963 simplified()->LoadField(AccessBuilder::ForMap()), value, effect, control);
964 Node* value_instance_type = effect = graph()->NewNode(
965 simplified()->LoadField(AccessBuilder::ForMapInstanceType()), value_map,
966 effect, control);
967
968 // Check if {value} is an Oddball.
969 Node* check_oddball =
970 graph()->NewNode(machine()->Word32Equal(), value_instance_type,
971 jsgraph()->Int32Constant(ODDBALL_TYPE));
972 Node* branch_oddball = graph()->NewNode(common()->Branch(BranchHint::kTrue),
973 check_oddball, control);
974
975 // The only Oddball {value} that is trueish is true itself.
976 Node* if_oddball = graph()->NewNode(common()->IfTrue(), branch_oddball);
977 Node* eoddball = effect;
978 {
979 controls[count] = if_oddball;
980 effects[count] = eoddball;
981 values[count] = graph()->NewNode(machine()->WordEqual(), value,
982 jsgraph()->TrueConstant());
983 count++;
984 }
985 control = graph()->NewNode(common()->IfFalse(), branch_oddball);
986
987 // Check if {value} is a String.
988 Node* check_string =
989 graph()->NewNode(machine()->Int32LessThan(), value_instance_type,
990 jsgraph()->Int32Constant(FIRST_NONSTRING_TYPE));
991 Node* branch_string =
992 graph()->NewNode(common()->Branch(), check_string, control);
993
994 // For String {value}, we need to check that the length is not zero.
995 Node* if_string = graph()->NewNode(common()->IfTrue(), branch_string);
996 Node* estring = effect;
997 {
998 // Load the {value} length.
999 Node* value_length = estring = graph()->NewNode(
1000 simplified()->LoadField(AccessBuilder::ForStringLength()), value,
1001 estring, if_string);
1002
1003 controls[count] = if_string;
1004 effects[count] = estring;
1005 values[count] =
1006 graph()->NewNode(machine()->Word32Equal(),
1007 graph()->NewNode(machine()->WordEqual(), value_length,
1008 jsgraph()->IntPtrConstant(0)),
1009 zero);
1010 count++;
1011 }
1012 control = graph()->NewNode(common()->IfFalse(), branch_string);
1013
1014 // Check if {value} is a HeapNumber.
1015 Node* check_heapnumber =
1016 graph()->NewNode(machine()->Word32Equal(), value_instance_type,
1017 jsgraph()->Int32Constant(HEAP_NUMBER_TYPE));
1018 Node* branch_heapnumber =
1019 graph()->NewNode(common()->Branch(), check_heapnumber, control);
1020
1021 // For HeapNumber {value}, just check that its value is not 0.0, -0.0 or NaN.
1022 Node* if_heapnumber = graph()->NewNode(common()->IfTrue(), branch_heapnumber);
1023 Node* eheapnumber = effect;
1024 {
1025 // Load the raw value of {value}.
1026 Node* value_value = eheapnumber = graph()->NewNode(
1027 simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), value,
1028 eheapnumber, if_heapnumber);
1029
1030 // Check if {value} is not one of 0, -0, or NaN.
1031 controls[count] = if_heapnumber;
1032 effects[count] = eheapnumber;
1033 values[count] = graph()->NewNode(
1034 machine()->Float64LessThan(), fzero,
1035 graph()->NewNode(machine()->Float64Abs(), value_value));
1036 count++;
1037 }
1038 control = graph()->NewNode(common()->IfFalse(), branch_heapnumber);
1039
1040 // The {value} is either a JSReceiver, a Symbol or some Simd128Value. In
1041 // those cases we can just the undetectable bit on the map, which will only
1042 // be set for certain JSReceivers, i.e. document.all.
1043 {
1044 // Load the {value} map bit field.
1045 Node* value_map_bitfield = effect = graph()->NewNode(
1046 simplified()->LoadField(AccessBuilder::ForMapBitField()), value_map,
1047 effect, control);
1048
1049 controls[count] = control;
1050 effects[count] = effect;
1051 values[count] = graph()->NewNode(
1052 machine()->Word32Equal(),
1053 graph()->NewNode(machine()->Word32And(), value_map_bitfield,
1054 jsgraph()->Int32Constant(1 << Map::kIsUndetectable)),
1055 zero);
1056 count++;
1057 }
1058
1059 // Merge the different controls.
1060 control = graph()->NewNode(common()->Merge(count), count, controls);
1061 effects[count] = control;
1062 effect = graph()->NewNode(common()->EffectPhi(count), count + 1, effects);
1063 values[count] = control;
1064 value = graph()->NewNode(common()->Phi(MachineRepresentation::kBit, count),
1065 count + 1, values);
1066
1067 return ValueEffectControl(value, effect, control);
1068 }
1069
1070 EffectControlLinearizer::ValueEffectControl
LowerChangeTaggedToInt32(Node * node,Node * effect,Node * control)1071 EffectControlLinearizer::LowerChangeTaggedToInt32(Node* node, Node* effect,
1072 Node* control) {
1073 Node* value = node->InputAt(0);
1074
1075 Node* check = ObjectIsSmi(value);
1076 Node* branch =
1077 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
1078
1079 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
1080 Node* etrue = effect;
1081 Node* vtrue = ChangeSmiToInt32(value);
1082
1083 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
1084 Node* efalse = effect;
1085 Node* vfalse;
1086 {
1087 STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
1088 vfalse = efalse = graph()->NewNode(
1089 simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), value,
1090 efalse, if_false);
1091 vfalse = graph()->NewNode(machine()->ChangeFloat64ToInt32(), vfalse);
1092 }
1093
1094 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
1095 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
1096 value = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
1097 vtrue, vfalse, control);
1098
1099 return ValueEffectControl(value, effect, control);
1100 }
1101
1102 EffectControlLinearizer::ValueEffectControl
LowerChangeTaggedToUint32(Node * node,Node * effect,Node * control)1103 EffectControlLinearizer::LowerChangeTaggedToUint32(Node* node, Node* effect,
1104 Node* control) {
1105 Node* value = node->InputAt(0);
1106
1107 Node* check = ObjectIsSmi(value);
1108 Node* branch =
1109 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
1110
1111 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
1112 Node* etrue = effect;
1113 Node* vtrue = ChangeSmiToInt32(value);
1114
1115 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
1116 Node* efalse = effect;
1117 Node* vfalse;
1118 {
1119 STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
1120 vfalse = efalse = graph()->NewNode(
1121 simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), value,
1122 efalse, if_false);
1123 vfalse = graph()->NewNode(machine()->ChangeFloat64ToUint32(), vfalse);
1124 }
1125
1126 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
1127 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
1128 value = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
1129 vtrue, vfalse, control);
1130
1131 return ValueEffectControl(value, effect, control);
1132 }
1133
1134 EffectControlLinearizer::ValueEffectControl
LowerChangeTaggedToFloat64(Node * node,Node * effect,Node * control)1135 EffectControlLinearizer::LowerChangeTaggedToFloat64(Node* node, Node* effect,
1136 Node* control) {
1137 return LowerTruncateTaggedToFloat64(node, effect, control);
1138 }
1139
1140 EffectControlLinearizer::ValueEffectControl
LowerTruncateTaggedToFloat64(Node * node,Node * effect,Node * control)1141 EffectControlLinearizer::LowerTruncateTaggedToFloat64(Node* node, Node* effect,
1142 Node* control) {
1143 Node* value = node->InputAt(0);
1144
1145 Node* check = ObjectIsSmi(value);
1146 Node* branch =
1147 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
1148
1149 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
1150 Node* etrue = effect;
1151 Node* vtrue;
1152 {
1153 vtrue = ChangeSmiToInt32(value);
1154 vtrue = graph()->NewNode(machine()->ChangeInt32ToFloat64(), vtrue);
1155 }
1156
1157 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
1158 Node* efalse = effect;
1159 Node* vfalse;
1160 {
1161 STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
1162 vfalse = efalse = graph()->NewNode(
1163 simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), value,
1164 efalse, if_false);
1165 }
1166
1167 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
1168 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
1169 value = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
1170 vtrue, vfalse, control);
1171
1172 return ValueEffectControl(value, effect, control);
1173 }
1174
1175 EffectControlLinearizer::ValueEffectControl
LowerCheckBounds(Node * node,Node * frame_state,Node * effect,Node * control)1176 EffectControlLinearizer::LowerCheckBounds(Node* node, Node* frame_state,
1177 Node* effect, Node* control) {
1178 Node* index = node->InputAt(0);
1179 Node* limit = node->InputAt(1);
1180
1181 Node* check = graph()->NewNode(machine()->Uint32LessThan(), index, limit);
1182 control = effect = graph()->NewNode(
1183 common()->DeoptimizeUnless(DeoptimizeReason::kOutOfBounds), check,
1184 frame_state, effect, control);
1185
1186 return ValueEffectControl(index, effect, control);
1187 }
1188
1189 EffectControlLinearizer::ValueEffectControl
LowerCheckMaps(Node * node,Node * frame_state,Node * effect,Node * control)1190 EffectControlLinearizer::LowerCheckMaps(Node* node, Node* frame_state,
1191 Node* effect, Node* control) {
1192 Node* value = node->InputAt(0);
1193
1194 // Load the current map of the {value}.
1195 Node* value_map = effect = graph()->NewNode(
1196 simplified()->LoadField(AccessBuilder::ForMap()), value, effect, control);
1197
1198 int const map_count = node->op()->ValueInputCount() - 1;
1199 Node** controls = temp_zone()->NewArray<Node*>(map_count);
1200 Node** effects = temp_zone()->NewArray<Node*>(map_count + 1);
1201
1202 for (int i = 0; i < map_count; ++i) {
1203 Node* map = node->InputAt(1 + i);
1204
1205 Node* check = graph()->NewNode(machine()->WordEqual(), value_map, map);
1206 if (i == map_count - 1) {
1207 controls[i] = effects[i] = graph()->NewNode(
1208 common()->DeoptimizeUnless(DeoptimizeReason::kWrongMap), check,
1209 frame_state, effect, control);
1210 } else {
1211 control = graph()->NewNode(common()->Branch(), check, control);
1212 controls[i] = graph()->NewNode(common()->IfTrue(), control);
1213 control = graph()->NewNode(common()->IfFalse(), control);
1214 effects[i] = effect;
1215 }
1216 }
1217
1218 control = graph()->NewNode(common()->Merge(map_count), map_count, controls);
1219 effects[map_count] = control;
1220 effect =
1221 graph()->NewNode(common()->EffectPhi(map_count), map_count + 1, effects);
1222
1223 return ValueEffectControl(value, effect, control);
1224 }
1225
1226 EffectControlLinearizer::ValueEffectControl
LowerCheckNumber(Node * node,Node * frame_state,Node * effect,Node * control)1227 EffectControlLinearizer::LowerCheckNumber(Node* node, Node* frame_state,
1228 Node* effect, Node* control) {
1229 Node* value = node->InputAt(0);
1230
1231 Node* check0 = ObjectIsSmi(value);
1232 Node* branch0 =
1233 graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
1234
1235 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
1236 Node* etrue0 = effect;
1237
1238 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
1239 Node* efalse0 = effect;
1240 {
1241 Node* value_map = efalse0 =
1242 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
1243 value, efalse0, if_false0);
1244 Node* check1 = graph()->NewNode(machine()->WordEqual(), value_map,
1245 jsgraph()->HeapNumberMapConstant());
1246 if_false0 = efalse0 = graph()->NewNode(
1247 common()->DeoptimizeUnless(DeoptimizeReason::kNotAHeapNumber), check1,
1248 frame_state, efalse0, if_false0);
1249 }
1250
1251 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
1252 effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
1253
1254 return ValueEffectControl(value, effect, control);
1255 }
1256
1257 EffectControlLinearizer::ValueEffectControl
LowerCheckString(Node * node,Node * frame_state,Node * effect,Node * control)1258 EffectControlLinearizer::LowerCheckString(Node* node, Node* frame_state,
1259 Node* effect, Node* control) {
1260 Node* value = node->InputAt(0);
1261
1262 Node* check0 = ObjectIsSmi(value);
1263 control = effect =
1264 graph()->NewNode(common()->DeoptimizeIf(DeoptimizeReason::kSmi), check0,
1265 frame_state, effect, control);
1266
1267 Node* value_map = effect = graph()->NewNode(
1268 simplified()->LoadField(AccessBuilder::ForMap()), value, effect, control);
1269 Node* value_instance_type = effect = graph()->NewNode(
1270 simplified()->LoadField(AccessBuilder::ForMapInstanceType()), value_map,
1271 effect, control);
1272
1273 Node* check1 =
1274 graph()->NewNode(machine()->Uint32LessThan(), value_instance_type,
1275 jsgraph()->Uint32Constant(FIRST_NONSTRING_TYPE));
1276 control = effect = graph()->NewNode(
1277 common()->DeoptimizeUnless(DeoptimizeReason::kWrongInstanceType), check1,
1278 frame_state, effect, control);
1279
1280 return ValueEffectControl(value, effect, control);
1281 }
1282
1283 EffectControlLinearizer::ValueEffectControl
LowerCheckIf(Node * node,Node * frame_state,Node * effect,Node * control)1284 EffectControlLinearizer::LowerCheckIf(Node* node, Node* frame_state,
1285 Node* effect, Node* control) {
1286 Node* value = node->InputAt(0);
1287
1288 control = effect =
1289 graph()->NewNode(common()->DeoptimizeUnless(DeoptimizeReason::kNoReason),
1290 value, frame_state, effect, control);
1291
1292 return ValueEffectControl(value, effect, control);
1293 }
1294
1295 EffectControlLinearizer::ValueEffectControl
LowerCheckedInt32Add(Node * node,Node * frame_state,Node * effect,Node * control)1296 EffectControlLinearizer::LowerCheckedInt32Add(Node* node, Node* frame_state,
1297 Node* effect, Node* control) {
1298 Node* lhs = node->InputAt(0);
1299 Node* rhs = node->InputAt(1);
1300
1301 Node* value =
1302 graph()->NewNode(machine()->Int32AddWithOverflow(), lhs, rhs, control);
1303
1304 Node* check = graph()->NewNode(common()->Projection(1), value, control);
1305 control = effect =
1306 graph()->NewNode(common()->DeoptimizeIf(DeoptimizeReason::kOverflow),
1307 check, frame_state, effect, control);
1308
1309 value = graph()->NewNode(common()->Projection(0), value, control);
1310
1311 return ValueEffectControl(value, effect, control);
1312 }
1313
1314 EffectControlLinearizer::ValueEffectControl
LowerCheckedInt32Sub(Node * node,Node * frame_state,Node * effect,Node * control)1315 EffectControlLinearizer::LowerCheckedInt32Sub(Node* node, Node* frame_state,
1316 Node* effect, Node* control) {
1317 Node* lhs = node->InputAt(0);
1318 Node* rhs = node->InputAt(1);
1319
1320 Node* value =
1321 graph()->NewNode(machine()->Int32SubWithOverflow(), lhs, rhs, control);
1322
1323 Node* check = graph()->NewNode(common()->Projection(1), value, control);
1324 control = effect =
1325 graph()->NewNode(common()->DeoptimizeIf(DeoptimizeReason::kOverflow),
1326 check, frame_state, effect, control);
1327
1328 value = graph()->NewNode(common()->Projection(0), value, control);
1329
1330 return ValueEffectControl(value, effect, control);
1331 }
1332
1333 EffectControlLinearizer::ValueEffectControl
LowerCheckedInt32Div(Node * node,Node * frame_state,Node * effect,Node * control)1334 EffectControlLinearizer::LowerCheckedInt32Div(Node* node, Node* frame_state,
1335 Node* effect, Node* control) {
1336 Node* zero = jsgraph()->Int32Constant(0);
1337 Node* minusone = jsgraph()->Int32Constant(-1);
1338 Node* minint = jsgraph()->Int32Constant(std::numeric_limits<int32_t>::min());
1339
1340 Node* lhs = node->InputAt(0);
1341 Node* rhs = node->InputAt(1);
1342
1343 // Check if {rhs} is positive (and not zero).
1344 Node* check0 = graph()->NewNode(machine()->Int32LessThan(), zero, rhs);
1345 Node* branch0 =
1346 graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
1347
1348 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
1349 Node* etrue0 = effect;
1350 Node* vtrue0;
1351 {
1352 // Fast case, no additional checking required.
1353 vtrue0 = graph()->NewNode(machine()->Int32Div(), lhs, rhs, if_true0);
1354 }
1355
1356 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
1357 Node* efalse0 = effect;
1358 Node* vfalse0;
1359 {
1360 // Check if {rhs} is zero.
1361 Node* check = graph()->NewNode(machine()->Word32Equal(), rhs, zero);
1362 if_false0 = efalse0 = graph()->NewNode(
1363 common()->DeoptimizeIf(DeoptimizeReason::kDivisionByZero), check,
1364 frame_state, efalse0, if_false0);
1365
1366 // Check if {lhs} is zero, as that would produce minus zero.
1367 check = graph()->NewNode(machine()->Word32Equal(), lhs, zero);
1368 if_false0 = efalse0 =
1369 graph()->NewNode(common()->DeoptimizeIf(DeoptimizeReason::kMinusZero),
1370 check, frame_state, efalse0, if_false0);
1371
1372 // Check if {lhs} is kMinInt and {rhs} is -1, in which case we'd have
1373 // to return -kMinInt, which is not representable.
1374 Node* check1 = graph()->NewNode(machine()->Word32Equal(), lhs, minint);
1375 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
1376 check1, if_false0);
1377
1378 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
1379 Node* etrue1 = efalse0;
1380 {
1381 // Check if {rhs} is -1.
1382 Node* check = graph()->NewNode(machine()->Word32Equal(), rhs, minusone);
1383 if_true1 = etrue1 =
1384 graph()->NewNode(common()->DeoptimizeIf(DeoptimizeReason::kOverflow),
1385 check, frame_state, etrue1, if_true1);
1386 }
1387
1388 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
1389 Node* efalse1 = efalse0;
1390
1391 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
1392 efalse0 =
1393 graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0);
1394
1395 // Perform the actual integer division.
1396 vfalse0 = graph()->NewNode(machine()->Int32Div(), lhs, rhs, if_false0);
1397 }
1398
1399 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
1400 effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
1401 Node* value =
1402 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), vtrue0,
1403 vfalse0, control);
1404
1405 // Check if the remainder is non-zero.
1406 Node* check =
1407 graph()->NewNode(machine()->Word32Equal(), lhs,
1408 graph()->NewNode(machine()->Int32Mul(), rhs, value));
1409 control = effect = graph()->NewNode(
1410 common()->DeoptimizeUnless(DeoptimizeReason::kLostPrecision), check,
1411 frame_state, effect, control);
1412
1413 return ValueEffectControl(value, effect, control);
1414 }
1415
1416 EffectControlLinearizer::ValueEffectControl
LowerCheckedInt32Mod(Node * node,Node * frame_state,Node * effect,Node * control)1417 EffectControlLinearizer::LowerCheckedInt32Mod(Node* node, Node* frame_state,
1418 Node* effect, Node* control) {
1419 Node* zero = jsgraph()->Int32Constant(0);
1420 Node* one = jsgraph()->Int32Constant(1);
1421
1422 // General case for signed integer modulus, with optimization for (unknown)
1423 // power of 2 right hand side.
1424 //
1425 // if rhs <= 0 then
1426 // rhs = -rhs
1427 // deopt if rhs == 0
1428 // if lhs < 0 then
1429 // let res = lhs % rhs in
1430 // deopt if res == 0
1431 // res
1432 // else
1433 // let msk = rhs - 1 in
1434 // if rhs & msk == 0 then
1435 // lhs & msk
1436 // else
1437 // lhs % rhs
1438 //
1439 Node* lhs = node->InputAt(0);
1440 Node* rhs = node->InputAt(1);
1441
1442 // Check if {rhs} is not strictly positive.
1443 Node* check0 = graph()->NewNode(machine()->Int32LessThanOrEqual(), rhs, zero);
1444 Node* branch0 =
1445 graph()->NewNode(common()->Branch(BranchHint::kFalse), check0, control);
1446
1447 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
1448 Node* etrue0 = effect;
1449 Node* vtrue0;
1450 {
1451 // Negate {rhs}, might still produce a negative result in case of
1452 // -2^31, but that is handled safely below.
1453 vtrue0 = graph()->NewNode(machine()->Int32Sub(), zero, rhs);
1454
1455 // Ensure that {rhs} is not zero, otherwise we'd have to return NaN.
1456 Node* check = graph()->NewNode(machine()->Word32Equal(), vtrue0, zero);
1457 if_true0 = etrue0 = graph()->NewNode(
1458 common()->DeoptimizeIf(DeoptimizeReason::kDivisionByZero), check,
1459 frame_state, etrue0, if_true0);
1460 }
1461
1462 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
1463 Node* efalse0 = effect;
1464 Node* vfalse0 = rhs;
1465
1466 // At this point {rhs} is either greater than zero or -2^31, both are
1467 // fine for the code that follows.
1468 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
1469 effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
1470 rhs = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
1471 vtrue0, vfalse0, control);
1472
1473 // Check if {lhs} is negative.
1474 Node* check1 = graph()->NewNode(machine()->Int32LessThan(), lhs, zero);
1475 Node* branch1 =
1476 graph()->NewNode(common()->Branch(BranchHint::kFalse), check1, control);
1477
1478 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
1479 Node* etrue1 = effect;
1480 Node* vtrue1;
1481 {
1482 // Compute the remainder using {lhs % msk}.
1483 vtrue1 = graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_true1);
1484
1485 // Check if we would have to return -0.
1486 Node* check = graph()->NewNode(machine()->Word32Equal(), vtrue1, zero);
1487 if_true1 = etrue1 =
1488 graph()->NewNode(common()->DeoptimizeIf(DeoptimizeReason::kMinusZero),
1489 check, frame_state, etrue1, if_true1);
1490 }
1491
1492 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
1493 Node* efalse1 = effect;
1494 Node* vfalse1;
1495 {
1496 Node* msk = graph()->NewNode(machine()->Int32Sub(), rhs, one);
1497
1498 // Check if {rhs} minus one is a valid mask.
1499 Node* check2 = graph()->NewNode(
1500 machine()->Word32Equal(),
1501 graph()->NewNode(machine()->Word32And(), rhs, msk), zero);
1502 Node* branch2 = graph()->NewNode(common()->Branch(), check2, if_false1);
1503
1504 // Compute the remainder using {lhs & msk}.
1505 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
1506 Node* vtrue2 = graph()->NewNode(machine()->Word32And(), lhs, msk);
1507
1508 // Compute the remainder using the generic {lhs % rhs}.
1509 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
1510 Node* vfalse2 =
1511 graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_false2);
1512
1513 if_false1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2);
1514 vfalse1 = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
1515 vtrue2, vfalse2, if_false1);
1516 }
1517
1518 control = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
1519 effect = graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, control);
1520 Node* value =
1521 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), vtrue1,
1522 vfalse1, control);
1523
1524 return ValueEffectControl(value, effect, control);
1525 }
1526
1527 EffectControlLinearizer::ValueEffectControl
LowerCheckedUint32Div(Node * node,Node * frame_state,Node * effect,Node * control)1528 EffectControlLinearizer::LowerCheckedUint32Div(Node* node, Node* frame_state,
1529 Node* effect, Node* control) {
1530 Node* zero = jsgraph()->Int32Constant(0);
1531
1532 Node* lhs = node->InputAt(0);
1533 Node* rhs = node->InputAt(1);
1534
1535 // Ensure that {rhs} is not zero, otherwise we'd have to return NaN.
1536 Node* check = graph()->NewNode(machine()->Word32Equal(), rhs, zero);
1537 control = effect = graph()->NewNode(
1538 common()->DeoptimizeIf(DeoptimizeReason::kDivisionByZero), check,
1539 frame_state, effect, control);
1540
1541 // Perform the actual unsigned integer division.
1542 Node* value = graph()->NewNode(machine()->Uint32Div(), lhs, rhs, control);
1543
1544 // Check if the remainder is non-zero.
1545 check = graph()->NewNode(machine()->Word32Equal(), lhs,
1546 graph()->NewNode(machine()->Int32Mul(), rhs, value));
1547 control = effect = graph()->NewNode(
1548 common()->DeoptimizeUnless(DeoptimizeReason::kLostPrecision), check,
1549 frame_state, effect, control);
1550
1551 return ValueEffectControl(value, effect, control);
1552 }
1553
1554 EffectControlLinearizer::ValueEffectControl
LowerCheckedUint32Mod(Node * node,Node * frame_state,Node * effect,Node * control)1555 EffectControlLinearizer::LowerCheckedUint32Mod(Node* node, Node* frame_state,
1556 Node* effect, Node* control) {
1557 Node* zero = jsgraph()->Int32Constant(0);
1558
1559 Node* lhs = node->InputAt(0);
1560 Node* rhs = node->InputAt(1);
1561
1562 // Ensure that {rhs} is not zero, otherwise we'd have to return NaN.
1563 Node* check = graph()->NewNode(machine()->Word32Equal(), rhs, zero);
1564 control = effect = graph()->NewNode(
1565 common()->DeoptimizeIf(DeoptimizeReason::kDivisionByZero), check,
1566 frame_state, effect, control);
1567
1568 // Perform the actual unsigned integer modulus.
1569 Node* value = graph()->NewNode(machine()->Uint32Mod(), lhs, rhs, control);
1570
1571 return ValueEffectControl(value, effect, control);
1572 }
1573
1574 EffectControlLinearizer::ValueEffectControl
LowerCheckedInt32Mul(Node * node,Node * frame_state,Node * effect,Node * control)1575 EffectControlLinearizer::LowerCheckedInt32Mul(Node* node, Node* frame_state,
1576 Node* effect, Node* control) {
1577 CheckForMinusZeroMode mode = CheckMinusZeroModeOf(node->op());
1578 Node* zero = jsgraph()->Int32Constant(0);
1579 Node* lhs = node->InputAt(0);
1580 Node* rhs = node->InputAt(1);
1581
1582 Node* projection =
1583 graph()->NewNode(machine()->Int32MulWithOverflow(), lhs, rhs, control);
1584
1585 Node* check = graph()->NewNode(common()->Projection(1), projection, control);
1586 control = effect =
1587 graph()->NewNode(common()->DeoptimizeIf(DeoptimizeReason::kOverflow),
1588 check, frame_state, effect, control);
1589
1590 Node* value = graph()->NewNode(common()->Projection(0), projection, control);
1591
1592 if (mode == CheckForMinusZeroMode::kCheckForMinusZero) {
1593 Node* check_zero = graph()->NewNode(machine()->Word32Equal(), value, zero);
1594 Node* branch_zero = graph()->NewNode(common()->Branch(BranchHint::kFalse),
1595 check_zero, control);
1596
1597 Node* if_zero = graph()->NewNode(common()->IfTrue(), branch_zero);
1598 Node* e_if_zero = effect;
1599 {
1600 // We may need to return negative zero.
1601 Node* or_inputs = graph()->NewNode(machine()->Word32Or(), lhs, rhs);
1602 Node* check_or =
1603 graph()->NewNode(machine()->Int32LessThan(), or_inputs, zero);
1604 if_zero = e_if_zero =
1605 graph()->NewNode(common()->DeoptimizeIf(DeoptimizeReason::kMinusZero),
1606 check_or, frame_state, e_if_zero, if_zero);
1607 }
1608
1609 Node* if_not_zero = graph()->NewNode(common()->IfFalse(), branch_zero);
1610 Node* e_if_not_zero = effect;
1611
1612 control = graph()->NewNode(common()->Merge(2), if_zero, if_not_zero);
1613 effect = graph()->NewNode(common()->EffectPhi(2), e_if_zero, e_if_not_zero,
1614 control);
1615 }
1616
1617 return ValueEffectControl(value, effect, control);
1618 }
1619
1620 EffectControlLinearizer::ValueEffectControl
LowerCheckedInt32ToTaggedSigned(Node * node,Node * frame_state,Node * effect,Node * control)1621 EffectControlLinearizer::LowerCheckedInt32ToTaggedSigned(Node* node,
1622 Node* frame_state,
1623 Node* effect,
1624 Node* control) {
1625 DCHECK(SmiValuesAre31Bits());
1626 Node* value = node->InputAt(0);
1627
1628 Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), value, value,
1629 control);
1630
1631 Node* check = graph()->NewNode(common()->Projection(1), add, control);
1632 control = effect =
1633 graph()->NewNode(common()->DeoptimizeIf(DeoptimizeReason::kOverflow),
1634 check, frame_state, effect, control);
1635
1636 value = graph()->NewNode(common()->Projection(0), add, control);
1637
1638 return ValueEffectControl(value, effect, control);
1639 }
1640
1641 EffectControlLinearizer::ValueEffectControl
LowerCheckedUint32ToInt32(Node * node,Node * frame_state,Node * effect,Node * control)1642 EffectControlLinearizer::LowerCheckedUint32ToInt32(Node* node,
1643 Node* frame_state,
1644 Node* effect,
1645 Node* control) {
1646 Node* value = node->InputAt(0);
1647 Node* max_int = jsgraph()->Int32Constant(std::numeric_limits<int32_t>::max());
1648 Node* is_safe =
1649 graph()->NewNode(machine()->Uint32LessThanOrEqual(), value, max_int);
1650 control = effect = graph()->NewNode(
1651 common()->DeoptimizeUnless(DeoptimizeReason::kLostPrecision), is_safe,
1652 frame_state, effect, control);
1653
1654 return ValueEffectControl(value, effect, control);
1655 }
1656
1657 EffectControlLinearizer::ValueEffectControl
LowerCheckedUint32ToTaggedSigned(Node * node,Node * frame_state,Node * effect,Node * control)1658 EffectControlLinearizer::LowerCheckedUint32ToTaggedSigned(Node* node,
1659 Node* frame_state,
1660 Node* effect,
1661 Node* control) {
1662 Node* value = node->InputAt(0);
1663 Node* check = graph()->NewNode(machine()->Uint32LessThanOrEqual(), value,
1664 SmiMaxValueConstant());
1665 control = effect = graph()->NewNode(
1666 common()->DeoptimizeUnless(DeoptimizeReason::kLostPrecision), check,
1667 frame_state, effect, control);
1668 value = ChangeUint32ToSmi(value);
1669
1670 return ValueEffectControl(value, effect, control);
1671 }
1672
1673 EffectControlLinearizer::ValueEffectControl
BuildCheckedFloat64ToInt32(CheckForMinusZeroMode mode,Node * value,Node * frame_state,Node * effect,Node * control)1674 EffectControlLinearizer::BuildCheckedFloat64ToInt32(CheckForMinusZeroMode mode,
1675 Node* value,
1676 Node* frame_state,
1677 Node* effect,
1678 Node* control) {
1679 Node* value32 = graph()->NewNode(machine()->RoundFloat64ToInt32(), value);
1680 Node* check_same = graph()->NewNode(
1681 machine()->Float64Equal(), value,
1682 graph()->NewNode(machine()->ChangeInt32ToFloat64(), value32));
1683 control = effect = graph()->NewNode(
1684 common()->DeoptimizeUnless(DeoptimizeReason::kLostPrecisionOrNaN),
1685 check_same, frame_state, effect, control);
1686
1687 if (mode == CheckForMinusZeroMode::kCheckForMinusZero) {
1688 // Check if {value} is -0.
1689 Node* check_zero = graph()->NewNode(machine()->Word32Equal(), value32,
1690 jsgraph()->Int32Constant(0));
1691 Node* branch_zero = graph()->NewNode(common()->Branch(BranchHint::kFalse),
1692 check_zero, control);
1693
1694 Node* if_zero = graph()->NewNode(common()->IfTrue(), branch_zero);
1695 Node* if_notzero = graph()->NewNode(common()->IfFalse(), branch_zero);
1696
1697 // In case of 0, we need to check the high bits for the IEEE -0 pattern.
1698 Node* check_negative = graph()->NewNode(
1699 machine()->Int32LessThan(),
1700 graph()->NewNode(machine()->Float64ExtractHighWord32(), value),
1701 jsgraph()->Int32Constant(0));
1702
1703 Node* deopt_minus_zero =
1704 graph()->NewNode(common()->DeoptimizeIf(DeoptimizeReason::kMinusZero),
1705 check_negative, frame_state, effect, if_zero);
1706
1707 control =
1708 graph()->NewNode(common()->Merge(2), deopt_minus_zero, if_notzero);
1709 effect = graph()->NewNode(common()->EffectPhi(2), deopt_minus_zero, effect,
1710 control);
1711 }
1712
1713 return ValueEffectControl(value32, effect, control);
1714 }
1715
1716 EffectControlLinearizer::ValueEffectControl
LowerCheckedFloat64ToInt32(Node * node,Node * frame_state,Node * effect,Node * control)1717 EffectControlLinearizer::LowerCheckedFloat64ToInt32(Node* node,
1718 Node* frame_state,
1719 Node* effect,
1720 Node* control) {
1721 CheckForMinusZeroMode mode = CheckMinusZeroModeOf(node->op());
1722 Node* value = node->InputAt(0);
1723
1724 return BuildCheckedFloat64ToInt32(mode, value, frame_state, effect, control);
1725 }
1726
1727 EffectControlLinearizer::ValueEffectControl
LowerCheckedTaggedSignedToInt32(Node * node,Node * frame_state,Node * effect,Node * control)1728 EffectControlLinearizer::LowerCheckedTaggedSignedToInt32(Node* node,
1729 Node* frame_state,
1730 Node* effect,
1731 Node* control) {
1732 Node* value = node->InputAt(0);
1733
1734 Node* check = ObjectIsSmi(value);
1735 control = effect =
1736 graph()->NewNode(common()->DeoptimizeUnless(DeoptimizeReason::kNotASmi),
1737 check, frame_state, effect, control);
1738 value = ChangeSmiToInt32(value);
1739
1740 return ValueEffectControl(value, effect, control);
1741 }
1742
1743 EffectControlLinearizer::ValueEffectControl
LowerCheckedTaggedToInt32(Node * node,Node * frame_state,Node * effect,Node * control)1744 EffectControlLinearizer::LowerCheckedTaggedToInt32(Node* node,
1745 Node* frame_state,
1746 Node* effect,
1747 Node* control) {
1748 CheckForMinusZeroMode mode = CheckMinusZeroModeOf(node->op());
1749 Node* value = node->InputAt(0);
1750
1751 Node* check = ObjectIsSmi(value);
1752 Node* branch =
1753 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
1754
1755 // In the Smi case, just convert to int32.
1756 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
1757 Node* etrue = effect;
1758 Node* vtrue = ChangeSmiToInt32(value);
1759
1760 // In the non-Smi case, check the heap numberness, load the number and convert
1761 // to int32.
1762 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
1763 Node* efalse = effect;
1764 Node* vfalse;
1765 {
1766 Node* value_map = efalse =
1767 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
1768 value, efalse, if_false);
1769 Node* check = graph()->NewNode(machine()->WordEqual(), value_map,
1770 jsgraph()->HeapNumberMapConstant());
1771 if_false = efalse = graph()->NewNode(
1772 common()->DeoptimizeUnless(DeoptimizeReason::kNotAHeapNumber), check,
1773 frame_state, efalse, if_false);
1774 vfalse = efalse = graph()->NewNode(
1775 simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), value,
1776 efalse, if_false);
1777 ValueEffectControl state =
1778 BuildCheckedFloat64ToInt32(mode, vfalse, frame_state, efalse, if_false);
1779 if_false = state.control;
1780 efalse = state.effect;
1781 vfalse = state.value;
1782 }
1783
1784 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
1785 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
1786 value = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
1787 vtrue, vfalse, control);
1788
1789 return ValueEffectControl(value, effect, control);
1790 }
1791
1792 EffectControlLinearizer::ValueEffectControl
BuildCheckedHeapNumberOrOddballToFloat64(CheckTaggedInputMode mode,Node * value,Node * frame_state,Node * effect,Node * control)1793 EffectControlLinearizer::BuildCheckedHeapNumberOrOddballToFloat64(
1794 CheckTaggedInputMode mode, Node* value, Node* frame_state, Node* effect,
1795 Node* control) {
1796 Node* value_map = effect = graph()->NewNode(
1797 simplified()->LoadField(AccessBuilder::ForMap()), value, effect, control);
1798
1799 Node* check_number = graph()->NewNode(machine()->WordEqual(), value_map,
1800 jsgraph()->HeapNumberMapConstant());
1801
1802 switch (mode) {
1803 case CheckTaggedInputMode::kNumber: {
1804 control = effect = graph()->NewNode(
1805 common()->DeoptimizeUnless(DeoptimizeReason::kNotAHeapNumber),
1806 check_number, frame_state, effect, control);
1807 break;
1808 }
1809 case CheckTaggedInputMode::kNumberOrOddball: {
1810 Node* branch =
1811 graph()->NewNode(common()->Branch(), check_number, control);
1812
1813 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
1814 Node* etrue = effect;
1815
1816 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
1817 // For oddballs also contain the numeric value, let us just check that
1818 // we have an oddball here.
1819 Node* efalse = effect;
1820 Node* instance_type = efalse = graph()->NewNode(
1821 simplified()->LoadField(AccessBuilder::ForMapInstanceType()),
1822 value_map, efalse, if_false);
1823 Node* check_oddball =
1824 graph()->NewNode(machine()->Word32Equal(), instance_type,
1825 jsgraph()->Int32Constant(ODDBALL_TYPE));
1826 if_false = efalse = graph()->NewNode(
1827 common()->DeoptimizeUnless(DeoptimizeReason::kNotANumberOrOddball),
1828 check_oddball, frame_state, efalse, if_false);
1829 STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
1830
1831 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
1832 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
1833 break;
1834 }
1835 }
1836
1837 value = effect = graph()->NewNode(
1838 simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), value,
1839 effect, control);
1840 return ValueEffectControl(value, effect, control);
1841 }
1842
1843 EffectControlLinearizer::ValueEffectControl
LowerCheckedTaggedToFloat64(Node * node,Node * frame_state,Node * effect,Node * control)1844 EffectControlLinearizer::LowerCheckedTaggedToFloat64(Node* node,
1845 Node* frame_state,
1846 Node* effect,
1847 Node* control) {
1848 CheckTaggedInputMode mode = CheckTaggedInputModeOf(node->op());
1849 Node* value = node->InputAt(0);
1850
1851 Node* check = ObjectIsSmi(value);
1852 Node* branch = graph()->NewNode(common()->Branch(), check, control);
1853
1854 // In the Smi case, just convert to int32 and then float64.
1855 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
1856 Node* etrue = effect;
1857 Node* vtrue = ChangeSmiToInt32(value);
1858 vtrue = graph()->NewNode(machine()->ChangeInt32ToFloat64(), vtrue);
1859
1860 // Otherwise, check heap numberness and load the number.
1861 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
1862 ValueEffectControl number_state = BuildCheckedHeapNumberOrOddballToFloat64(
1863 mode, value, frame_state, effect, if_false);
1864
1865 Node* merge =
1866 graph()->NewNode(common()->Merge(2), if_true, number_state.control);
1867 Node* effect_phi = graph()->NewNode(common()->EffectPhi(2), etrue,
1868 number_state.effect, merge);
1869 Node* result =
1870 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), vtrue,
1871 number_state.value, merge);
1872
1873 return ValueEffectControl(result, effect_phi, merge);
1874 }
1875
1876 EffectControlLinearizer::ValueEffectControl
LowerCheckedTaggedToTaggedSigned(Node * node,Node * frame_state,Node * effect,Node * control)1877 EffectControlLinearizer::LowerCheckedTaggedToTaggedSigned(Node* node,
1878 Node* frame_state,
1879 Node* effect,
1880 Node* control) {
1881 Node* value = node->InputAt(0);
1882
1883 Node* check = ObjectIsSmi(value);
1884 control = effect =
1885 graph()->NewNode(common()->DeoptimizeUnless(DeoptimizeReason::kNotASmi),
1886 check, frame_state, effect, control);
1887
1888 return ValueEffectControl(value, effect, control);
1889 }
1890
1891 EffectControlLinearizer::ValueEffectControl
LowerCheckedTaggedToTaggedPointer(Node * node,Node * frame_state,Node * effect,Node * control)1892 EffectControlLinearizer::LowerCheckedTaggedToTaggedPointer(Node* node,
1893 Node* frame_state,
1894 Node* effect,
1895 Node* control) {
1896 Node* value = node->InputAt(0);
1897
1898 Node* check = ObjectIsSmi(value);
1899 control = effect =
1900 graph()->NewNode(common()->DeoptimizeIf(DeoptimizeReason::kSmi), check,
1901 frame_state, effect, control);
1902
1903 return ValueEffectControl(value, effect, control);
1904 }
1905
1906 EffectControlLinearizer::ValueEffectControl
LowerTruncateTaggedToWord32(Node * node,Node * effect,Node * control)1907 EffectControlLinearizer::LowerTruncateTaggedToWord32(Node* node, Node* effect,
1908 Node* control) {
1909 Node* value = node->InputAt(0);
1910
1911 Node* check = ObjectIsSmi(value);
1912 Node* branch =
1913 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
1914
1915 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
1916 Node* etrue = effect;
1917 Node* vtrue = ChangeSmiToInt32(value);
1918
1919 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
1920 Node* efalse = effect;
1921 Node* vfalse;
1922 {
1923 STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
1924 vfalse = efalse = graph()->NewNode(
1925 simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), value,
1926 efalse, if_false);
1927 vfalse = graph()->NewNode(machine()->TruncateFloat64ToWord32(), vfalse);
1928 }
1929
1930 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
1931 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
1932 value = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
1933 vtrue, vfalse, control);
1934
1935 return ValueEffectControl(value, effect, control);
1936 }
1937
1938 EffectControlLinearizer::ValueEffectControl
LowerCheckedTruncateTaggedToWord32(Node * node,Node * frame_state,Node * effect,Node * control)1939 EffectControlLinearizer::LowerCheckedTruncateTaggedToWord32(Node* node,
1940 Node* frame_state,
1941 Node* effect,
1942 Node* control) {
1943 Node* value = node->InputAt(0);
1944
1945 Node* check = ObjectIsSmi(value);
1946 Node* branch =
1947 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
1948
1949 // In the Smi case, just convert to int32.
1950 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
1951 Node* etrue = effect;
1952 Node* vtrue = ChangeSmiToInt32(value);
1953
1954 // Otherwise, check that it's a heap number or oddball and truncate the value
1955 // to int32.
1956 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
1957 ValueEffectControl false_state = BuildCheckedHeapNumberOrOddballToFloat64(
1958 CheckTaggedInputMode::kNumberOrOddball, value, frame_state, effect,
1959 if_false);
1960 false_state.value =
1961 graph()->NewNode(machine()->TruncateFloat64ToWord32(), false_state.value);
1962
1963 Node* merge =
1964 graph()->NewNode(common()->Merge(2), if_true, false_state.control);
1965 Node* effect_phi = graph()->NewNode(common()->EffectPhi(2), etrue,
1966 false_state.effect, merge);
1967 Node* result =
1968 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), vtrue,
1969 false_state.value, merge);
1970
1971 return ValueEffectControl(result, effect_phi, merge);
1972 }
1973
1974 EffectControlLinearizer::ValueEffectControl
LowerObjectIsCallable(Node * node,Node * effect,Node * control)1975 EffectControlLinearizer::LowerObjectIsCallable(Node* node, Node* effect,
1976 Node* control) {
1977 Node* value = node->InputAt(0);
1978
1979 Node* check = ObjectIsSmi(value);
1980 Node* branch =
1981 graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
1982
1983 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
1984 Node* etrue = effect;
1985 Node* vtrue = jsgraph()->Int32Constant(0);
1986
1987 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
1988 Node* efalse = effect;
1989 Node* vfalse;
1990 {
1991 Node* value_map = efalse =
1992 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
1993 value, efalse, if_false);
1994 Node* value_bit_field = efalse = graph()->NewNode(
1995 simplified()->LoadField(AccessBuilder::ForMapBitField()), value_map,
1996 efalse, if_false);
1997 vfalse = graph()->NewNode(
1998 machine()->Word32Equal(),
1999 jsgraph()->Int32Constant(1 << Map::kIsCallable),
2000 graph()->NewNode(
2001 machine()->Word32And(), value_bit_field,
2002 jsgraph()->Int32Constant((1 << Map::kIsCallable) |
2003 (1 << Map::kIsUndetectable))));
2004 }
2005
2006 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
2007 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
2008 value = graph()->NewNode(common()->Phi(MachineRepresentation::kBit, 2), vtrue,
2009 vfalse, control);
2010
2011 return ValueEffectControl(value, effect, control);
2012 }
2013
2014 EffectControlLinearizer::ValueEffectControl
LowerObjectIsNumber(Node * node,Node * effect,Node * control)2015 EffectControlLinearizer::LowerObjectIsNumber(Node* node, Node* effect,
2016 Node* control) {
2017 Node* value = node->InputAt(0);
2018
2019 Node* check = ObjectIsSmi(value);
2020 Node* branch = graph()->NewNode(common()->Branch(), check, control);
2021
2022 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
2023 Node* etrue = effect;
2024 Node* vtrue = jsgraph()->Int32Constant(1);
2025
2026 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
2027 Node* efalse = effect;
2028 Node* vfalse;
2029 {
2030 Node* value_map = efalse =
2031 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
2032 value, efalse, if_false);
2033 vfalse = graph()->NewNode(machine()->WordEqual(), value_map,
2034 jsgraph()->HeapNumberMapConstant());
2035 }
2036
2037 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
2038 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
2039 value = graph()->NewNode(common()->Phi(MachineRepresentation::kBit, 2), vtrue,
2040 vfalse, control);
2041
2042 return ValueEffectControl(value, effect, control);
2043 }
2044
2045 EffectControlLinearizer::ValueEffectControl
LowerObjectIsReceiver(Node * node,Node * effect,Node * control)2046 EffectControlLinearizer::LowerObjectIsReceiver(Node* node, Node* effect,
2047 Node* control) {
2048 Node* value = node->InputAt(0);
2049
2050 Node* check = ObjectIsSmi(value);
2051 Node* branch =
2052 graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
2053
2054 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
2055 Node* etrue = effect;
2056 Node* vtrue = jsgraph()->Int32Constant(0);
2057
2058 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
2059 Node* efalse = effect;
2060 Node* vfalse;
2061 {
2062 STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
2063 Node* value_map = efalse =
2064 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
2065 value, efalse, if_false);
2066 Node* value_instance_type = efalse = graph()->NewNode(
2067 simplified()->LoadField(AccessBuilder::ForMapInstanceType()), value_map,
2068 efalse, if_false);
2069 vfalse = graph()->NewNode(machine()->Uint32LessThanOrEqual(),
2070 jsgraph()->Uint32Constant(FIRST_JS_RECEIVER_TYPE),
2071 value_instance_type);
2072 }
2073
2074 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
2075 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
2076 value = graph()->NewNode(common()->Phi(MachineRepresentation::kBit, 2), vtrue,
2077 vfalse, control);
2078
2079 return ValueEffectControl(value, effect, control);
2080 }
2081
2082 EffectControlLinearizer::ValueEffectControl
LowerObjectIsSmi(Node * node,Node * effect,Node * control)2083 EffectControlLinearizer::LowerObjectIsSmi(Node* node, Node* effect,
2084 Node* control) {
2085 Node* value = node->InputAt(0);
2086 value = ObjectIsSmi(value);
2087 return ValueEffectControl(value, effect, control);
2088 }
2089
2090 EffectControlLinearizer::ValueEffectControl
LowerObjectIsString(Node * node,Node * effect,Node * control)2091 EffectControlLinearizer::LowerObjectIsString(Node* node, Node* effect,
2092 Node* control) {
2093 Node* value = node->InputAt(0);
2094
2095 Node* check = ObjectIsSmi(value);
2096 Node* branch =
2097 graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
2098
2099 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
2100 Node* etrue = effect;
2101 Node* vtrue = jsgraph()->Int32Constant(0);
2102
2103 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
2104 Node* efalse = effect;
2105 Node* vfalse;
2106 {
2107 Node* value_map = efalse =
2108 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
2109 value, efalse, if_false);
2110 Node* value_instance_type = efalse = graph()->NewNode(
2111 simplified()->LoadField(AccessBuilder::ForMapInstanceType()), value_map,
2112 efalse, if_false);
2113 vfalse = graph()->NewNode(machine()->Uint32LessThan(), value_instance_type,
2114 jsgraph()->Uint32Constant(FIRST_NONSTRING_TYPE));
2115 }
2116
2117 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
2118 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
2119 value = graph()->NewNode(common()->Phi(MachineRepresentation::kBit, 2), vtrue,
2120 vfalse, control);
2121
2122 return ValueEffectControl(value, effect, control);
2123 }
2124
2125 EffectControlLinearizer::ValueEffectControl
LowerObjectIsUndetectable(Node * node,Node * effect,Node * control)2126 EffectControlLinearizer::LowerObjectIsUndetectable(Node* node, Node* effect,
2127 Node* control) {
2128 Node* value = node->InputAt(0);
2129
2130 Node* check = ObjectIsSmi(value);
2131 Node* branch =
2132 graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
2133
2134 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
2135 Node* etrue = effect;
2136 Node* vtrue = jsgraph()->Int32Constant(0);
2137
2138 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
2139 Node* efalse = effect;
2140 Node* vfalse;
2141 {
2142 Node* value_map = efalse =
2143 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
2144 value, efalse, if_false);
2145 Node* value_bit_field = efalse = graph()->NewNode(
2146 simplified()->LoadField(AccessBuilder::ForMapBitField()), value_map,
2147 efalse, if_false);
2148 vfalse = graph()->NewNode(
2149 machine()->Word32Equal(),
2150 graph()->NewNode(
2151 machine()->Word32Equal(), jsgraph()->Int32Constant(0),
2152 graph()->NewNode(
2153 machine()->Word32And(), value_bit_field,
2154 jsgraph()->Int32Constant(1 << Map::kIsUndetectable))),
2155 jsgraph()->Int32Constant(0));
2156 }
2157
2158 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
2159 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
2160 value = graph()->NewNode(common()->Phi(MachineRepresentation::kBit, 2), vtrue,
2161 vfalse, control);
2162
2163 return ValueEffectControl(value, effect, control);
2164 }
2165
2166 EffectControlLinearizer::ValueEffectControl
LowerArrayBufferWasNeutered(Node * node,Node * effect,Node * control)2167 EffectControlLinearizer::LowerArrayBufferWasNeutered(Node* node, Node* effect,
2168 Node* control) {
2169 Node* value = node->InputAt(0);
2170
2171 Node* value_bit_field = effect = graph()->NewNode(
2172 simplified()->LoadField(AccessBuilder::ForJSArrayBufferBitField()), value,
2173 effect, control);
2174 value = graph()->NewNode(
2175 machine()->Word32Equal(),
2176 graph()->NewNode(machine()->Word32Equal(),
2177 graph()->NewNode(machine()->Word32And(), value_bit_field,
2178 jsgraph()->Int32Constant(
2179 JSArrayBuffer::WasNeutered::kMask)),
2180 jsgraph()->Int32Constant(0)),
2181 jsgraph()->Int32Constant(0));
2182
2183 return ValueEffectControl(value, effect, control);
2184 }
2185
2186 EffectControlLinearizer::ValueEffectControl
LowerStringCharCodeAt(Node * node,Node * effect,Node * control)2187 EffectControlLinearizer::LowerStringCharCodeAt(Node* node, Node* effect,
2188 Node* control) {
2189 Node* subject = node->InputAt(0);
2190 Node* index = node->InputAt(1);
2191
2192 // We may need to loop several times for ConsString/SlicedString {subject}s.
2193 Node* loop =
2194 graph()->NewNode(common()->Loop(4), control, control, control, control);
2195 Node* lsubject =
2196 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 4),
2197 subject, subject, subject, subject, loop);
2198 Node* lindex =
2199 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 4), index,
2200 index, index, index, loop);
2201 Node* leffect = graph()->NewNode(common()->EffectPhi(4), effect, effect,
2202 effect, effect, loop);
2203
2204 control = loop;
2205 effect = leffect;
2206
2207 // Determine the instance type of {lsubject}.
2208 Node* lsubject_map = effect =
2209 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
2210 lsubject, effect, control);
2211 Node* lsubject_instance_type = effect = graph()->NewNode(
2212 simplified()->LoadField(AccessBuilder::ForMapInstanceType()),
2213 lsubject_map, effect, control);
2214
2215 // Check if {lsubject} is a SeqString.
2216 Node* check0 = graph()->NewNode(
2217 machine()->Word32Equal(),
2218 graph()->NewNode(machine()->Word32And(), lsubject_instance_type,
2219 jsgraph()->Int32Constant(kStringRepresentationMask)),
2220 jsgraph()->Int32Constant(kSeqStringTag));
2221 Node* branch0 = graph()->NewNode(common()->Branch(), check0, control);
2222
2223 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
2224 Node* etrue0 = effect;
2225 Node* vtrue0;
2226 {
2227 // Check if the {lsubject} is a TwoByteSeqString or a OneByteSeqString.
2228 Node* check1 = graph()->NewNode(
2229 machine()->Word32Equal(),
2230 graph()->NewNode(machine()->Word32And(), lsubject_instance_type,
2231 jsgraph()->Int32Constant(kStringEncodingMask)),
2232 jsgraph()->Int32Constant(kTwoByteStringTag));
2233 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0);
2234
2235 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
2236 Node* etrue1 = etrue0;
2237 Node* vtrue1 = etrue1 =
2238 graph()->NewNode(simplified()->LoadElement(
2239 AccessBuilder::ForSeqTwoByteStringCharacter()),
2240 lsubject, lindex, etrue1, if_true1);
2241
2242 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
2243 Node* efalse1 = etrue0;
2244 Node* vfalse1 = efalse1 =
2245 graph()->NewNode(simplified()->LoadElement(
2246 AccessBuilder::ForSeqOneByteStringCharacter()),
2247 lsubject, lindex, efalse1, if_false1);
2248
2249 if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
2250 etrue0 =
2251 graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_true0);
2252 vtrue0 = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
2253 vtrue1, vfalse1, if_true0);
2254 }
2255
2256 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
2257 Node* efalse0 = effect;
2258 Node* vfalse0;
2259 {
2260 // Check if the {lsubject} is a ConsString.
2261 Node* check1 = graph()->NewNode(
2262 machine()->Word32Equal(),
2263 graph()->NewNode(machine()->Word32And(), lsubject_instance_type,
2264 jsgraph()->Int32Constant(kStringRepresentationMask)),
2265 jsgraph()->Int32Constant(kConsStringTag));
2266 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
2267
2268 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
2269 Node* etrue1 = efalse0;
2270 {
2271 // Load the right hand side of the {lsubject} ConsString.
2272 Node* lsubject_second = etrue1 = graph()->NewNode(
2273 simplified()->LoadField(AccessBuilder::ForConsStringSecond()),
2274 lsubject, etrue1, if_true1);
2275
2276 // Check whether the right hand side is the empty string (i.e. if
2277 // this is really a flat string in a cons string). If that is not
2278 // the case we flatten the string first.
2279 Node* check2 = graph()->NewNode(machine()->WordEqual(), lsubject_second,
2280 jsgraph()->EmptyStringConstant());
2281 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
2282 check2, if_true1);
2283
2284 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
2285 Node* etrue2 = etrue1;
2286 Node* vtrue2 = etrue2 = graph()->NewNode(
2287 simplified()->LoadField(AccessBuilder::ForConsStringFirst()),
2288 lsubject, etrue2, if_true2);
2289
2290 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
2291 Node* efalse2 = etrue1;
2292 Node* vfalse2;
2293 {
2294 // Flatten the {lsubject} ConsString first.
2295 Operator::Properties properties =
2296 Operator::kNoDeopt | Operator::kNoThrow;
2297 Runtime::FunctionId id = Runtime::kFlattenString;
2298 CallDescriptor const* desc = Linkage::GetRuntimeCallDescriptor(
2299 graph()->zone(), id, 1, properties, CallDescriptor::kNoFlags);
2300 vfalse2 = efalse2 = graph()->NewNode(
2301 common()->Call(desc), jsgraph()->CEntryStubConstant(1), lsubject,
2302 jsgraph()->ExternalConstant(ExternalReference(id, isolate())),
2303 jsgraph()->Int32Constant(1), jsgraph()->NoContextConstant(),
2304 efalse2, if_false2);
2305 }
2306
2307 // Retry the {loop} with the new subject.
2308 loop->ReplaceInput(1, if_true2);
2309 lindex->ReplaceInput(1, lindex);
2310 leffect->ReplaceInput(1, etrue2);
2311 lsubject->ReplaceInput(1, vtrue2);
2312 loop->ReplaceInput(2, if_false2);
2313 lindex->ReplaceInput(2, lindex);
2314 leffect->ReplaceInput(2, efalse2);
2315 lsubject->ReplaceInput(2, vfalse2);
2316 }
2317
2318 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
2319 Node* efalse1 = efalse0;
2320 Node* vfalse1;
2321 {
2322 // Check if the {lsubject} is an ExternalString.
2323 Node* check2 = graph()->NewNode(
2324 machine()->Word32Equal(),
2325 graph()->NewNode(machine()->Word32And(), lsubject_instance_type,
2326 jsgraph()->Int32Constant(kStringRepresentationMask)),
2327 jsgraph()->Int32Constant(kExternalStringTag));
2328 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
2329 check2, if_false1);
2330
2331 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
2332 Node* etrue2 = efalse1;
2333 Node* vtrue2;
2334 {
2335 // Check if the {lsubject} is a short external string.
2336 Node* check3 = graph()->NewNode(
2337 machine()->Word32Equal(),
2338 graph()->NewNode(
2339 machine()->Word32And(), lsubject_instance_type,
2340 jsgraph()->Int32Constant(kShortExternalStringMask)),
2341 jsgraph()->Int32Constant(0));
2342 Node* branch3 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
2343 check3, if_true2);
2344
2345 Node* if_true3 = graph()->NewNode(common()->IfTrue(), branch3);
2346 Node* etrue3 = etrue2;
2347 Node* vtrue3;
2348 {
2349 // Load the actual resource data from the {lsubject}.
2350 Node* lsubject_resource_data = etrue3 = graph()->NewNode(
2351 simplified()->LoadField(
2352 AccessBuilder::ForExternalStringResourceData()),
2353 lsubject, etrue3, if_true3);
2354
2355 // Check if the {lsubject} is a TwoByteExternalString or a
2356 // OneByteExternalString.
2357 Node* check4 = graph()->NewNode(
2358 machine()->Word32Equal(),
2359 graph()->NewNode(machine()->Word32And(), lsubject_instance_type,
2360 jsgraph()->Int32Constant(kStringEncodingMask)),
2361 jsgraph()->Int32Constant(kTwoByteStringTag));
2362 Node* branch4 =
2363 graph()->NewNode(common()->Branch(), check4, if_true3);
2364
2365 Node* if_true4 = graph()->NewNode(common()->IfTrue(), branch4);
2366 Node* etrue4 = etrue3;
2367 Node* vtrue4 = etrue4 = graph()->NewNode(
2368 simplified()->LoadElement(
2369 AccessBuilder::ForExternalTwoByteStringCharacter()),
2370 lsubject_resource_data, lindex, etrue4, if_true4);
2371
2372 Node* if_false4 = graph()->NewNode(common()->IfFalse(), branch4);
2373 Node* efalse4 = etrue3;
2374 Node* vfalse4 = efalse4 = graph()->NewNode(
2375 simplified()->LoadElement(
2376 AccessBuilder::ForExternalOneByteStringCharacter()),
2377 lsubject_resource_data, lindex, efalse4, if_false4);
2378
2379 if_true3 = graph()->NewNode(common()->Merge(2), if_true4, if_false4);
2380 etrue3 = graph()->NewNode(common()->EffectPhi(2), etrue4, efalse4,
2381 if_true3);
2382 vtrue3 =
2383 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
2384 vtrue4, vfalse4, if_true3);
2385 }
2386
2387 Node* if_false3 = graph()->NewNode(common()->IfFalse(), branch3);
2388 Node* efalse3 = etrue2;
2389 Node* vfalse3;
2390 {
2391 // The {lsubject} might be compressed, call the runtime.
2392 Operator::Properties properties =
2393 Operator::kNoDeopt | Operator::kNoThrow;
2394 Runtime::FunctionId id = Runtime::kExternalStringGetChar;
2395 CallDescriptor const* desc = Linkage::GetRuntimeCallDescriptor(
2396 graph()->zone(), id, 2, properties, CallDescriptor::kNoFlags);
2397 vfalse3 = efalse3 = graph()->NewNode(
2398 common()->Call(desc), jsgraph()->CEntryStubConstant(1), lsubject,
2399 ChangeInt32ToSmi(lindex),
2400 jsgraph()->ExternalConstant(ExternalReference(id, isolate())),
2401 jsgraph()->Int32Constant(2), jsgraph()->NoContextConstant(),
2402 efalse3, if_false3);
2403 vfalse3 = ChangeSmiToInt32(vfalse3);
2404 }
2405
2406 if_true2 = graph()->NewNode(common()->Merge(2), if_true3, if_false3);
2407 etrue2 =
2408 graph()->NewNode(common()->EffectPhi(2), etrue3, efalse3, if_true2);
2409 vtrue2 =
2410 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
2411 vtrue3, vfalse3, if_true2);
2412 }
2413
2414 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
2415 Node* efalse2 = efalse1;
2416 {
2417 // The {lsubject} is a SlicedString, continue with its parent.
2418 Node* lsubject_parent = efalse2 = graph()->NewNode(
2419 simplified()->LoadField(AccessBuilder::ForSlicedStringParent()),
2420 lsubject, efalse2, if_false2);
2421 Node* lsubject_offset = efalse2 = graph()->NewNode(
2422 simplified()->LoadField(AccessBuilder::ForSlicedStringOffset()),
2423 lsubject, efalse2, if_false2);
2424 Node* lsubject_index = graph()->NewNode(
2425 machine()->Int32Add(), lindex, ChangeSmiToInt32(lsubject_offset));
2426
2427 // Retry the {loop} with the parent subject.
2428 loop->ReplaceInput(3, if_false2);
2429 leffect->ReplaceInput(3, efalse2);
2430 lindex->ReplaceInput(3, lsubject_index);
2431 lsubject->ReplaceInput(3, lsubject_parent);
2432 }
2433
2434 if_false1 = if_true2;
2435 efalse1 = etrue2;
2436 vfalse1 = vtrue2;
2437 }
2438
2439 if_false0 = if_false1;
2440 efalse0 = efalse1;
2441 vfalse0 = vfalse1;
2442 }
2443
2444 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
2445 effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
2446 Node* value =
2447 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), vtrue0,
2448 vfalse0, control);
2449
2450 return ValueEffectControl(value, effect, control);
2451 }
2452
2453 EffectControlLinearizer::ValueEffectControl
LowerStringFromCharCode(Node * node,Node * effect,Node * control)2454 EffectControlLinearizer::LowerStringFromCharCode(Node* node, Node* effect,
2455 Node* control) {
2456 Node* value = node->InputAt(0);
2457
2458 // Compute the character code.
2459 Node* code =
2460 graph()->NewNode(machine()->Word32And(), value,
2461 jsgraph()->Int32Constant(String::kMaxUtf16CodeUnit));
2462
2463 // Check if the {code} is a one-byte char code.
2464 Node* check0 =
2465 graph()->NewNode(machine()->Int32LessThanOrEqual(), code,
2466 jsgraph()->Int32Constant(String::kMaxOneByteCharCode));
2467 Node* branch0 =
2468 graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
2469
2470 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
2471 Node* efalse0 = effect;
2472
2473 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
2474 Node* etrue0 = effect;
2475
2476 // Load the isolate wide single character string cache.
2477 Node* cache =
2478 jsgraph()->HeapConstant(factory()->single_character_string_cache());
2479
2480 // Compute the {cache} index for {code}.
2481 Node* index = machine()->Is32()
2482 ? code
2483 : graph()->NewNode(machine()->ChangeUint32ToUint64(), code);
2484
2485 // Check if we have an entry for the {code} in the single character string
2486 // cache already.
2487 Node* entry = etrue0 = graph()->NewNode(
2488 simplified()->LoadElement(AccessBuilder::ForFixedArrayElement()), cache,
2489 index, etrue0, if_true0);
2490
2491 Node* check1 = graph()->NewNode(machine()->WordEqual(), entry,
2492 jsgraph()->UndefinedConstant());
2493 Node* branch1 =
2494 graph()->NewNode(common()->Branch(BranchHint::kFalse), check1, if_true0);
2495
2496 // Use the {entry} from the {cache}.
2497 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
2498 Node* efalse1 = etrue0;
2499 Node* vfalse1 = entry;
2500
2501 // Let %StringFromCharCode handle this case.
2502 // TODO(turbofan): At some point we may consider adding a stub for this
2503 // deferred case, so that we don't need to call to C++ here.
2504 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
2505 Node* etrue1 = etrue0;
2506 Node* vtrue1;
2507 {
2508 if_true1 = graph()->NewNode(common()->Merge(2), if_true1, if_false0);
2509 etrue1 =
2510 graph()->NewNode(common()->EffectPhi(2), etrue1, efalse0, if_true1);
2511 Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow;
2512 Runtime::FunctionId id = Runtime::kStringCharFromCode;
2513 CallDescriptor const* desc = Linkage::GetRuntimeCallDescriptor(
2514 graph()->zone(), id, 1, properties, CallDescriptor::kNoFlags);
2515 vtrue1 = etrue1 = graph()->NewNode(
2516 common()->Call(desc), jsgraph()->CEntryStubConstant(1),
2517 ChangeInt32ToSmi(code),
2518 jsgraph()->ExternalConstant(ExternalReference(id, isolate())),
2519 jsgraph()->Int32Constant(1), jsgraph()->NoContextConstant(), etrue1,
2520 if_true1);
2521 }
2522
2523 control = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
2524 effect = graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, control);
2525 value = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
2526 vtrue1, vfalse1, control);
2527
2528 return ValueEffectControl(value, effect, control);
2529 }
2530
2531 EffectControlLinearizer::ValueEffectControl
LowerStringFromCodePoint(Node * node,Node * effect,Node * control)2532 EffectControlLinearizer::LowerStringFromCodePoint(Node* node, Node* effect,
2533 Node* control) {
2534 Node* value = node->InputAt(0);
2535 Node* code = value;
2536
2537 Node* etrue0 = effect;
2538 Node* vtrue0;
2539
2540 // Check if the {code} is a single code unit
2541 Node* check0 = graph()->NewNode(machine()->Uint32LessThanOrEqual(), code,
2542 jsgraph()->Uint32Constant(0xFFFF));
2543 Node* branch0 =
2544 graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
2545
2546 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
2547 {
2548 // Check if the {code} is a one byte character
2549 Node* check1 = graph()->NewNode(
2550 machine()->Uint32LessThanOrEqual(), code,
2551 jsgraph()->Uint32Constant(String::kMaxOneByteCharCode));
2552 Node* branch1 =
2553 graph()->NewNode(common()->Branch(BranchHint::kTrue), check1, if_true0);
2554
2555 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
2556 Node* etrue1 = etrue0;
2557 Node* vtrue1;
2558 {
2559 // Load the isolate wide single character string cache.
2560 Node* cache =
2561 jsgraph()->HeapConstant(factory()->single_character_string_cache());
2562
2563 // Compute the {cache} index for {code}.
2564 Node* index =
2565 machine()->Is32()
2566 ? code
2567 : graph()->NewNode(machine()->ChangeUint32ToUint64(), code);
2568
2569 // Check if we have an entry for the {code} in the single character string
2570 // cache already.
2571 Node* entry = etrue1 = graph()->NewNode(
2572 simplified()->LoadElement(AccessBuilder::ForFixedArrayElement()),
2573 cache, index, etrue1, if_true1);
2574
2575 Node* check2 = graph()->NewNode(machine()->WordEqual(), entry,
2576 jsgraph()->UndefinedConstant());
2577 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
2578 check2, if_true1);
2579
2580 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
2581 Node* etrue2 = etrue1;
2582 Node* vtrue2;
2583 {
2584 // Allocate a new SeqOneByteString for {code}.
2585 vtrue2 = etrue2 = graph()->NewNode(
2586 simplified()->Allocate(NOT_TENURED),
2587 jsgraph()->Int32Constant(SeqOneByteString::SizeFor(1)), etrue2,
2588 if_true2);
2589 etrue2 = graph()->NewNode(
2590 simplified()->StoreField(AccessBuilder::ForMap()), vtrue2,
2591 jsgraph()->HeapConstant(factory()->one_byte_string_map()), etrue2,
2592 if_true2);
2593 etrue2 = graph()->NewNode(
2594 simplified()->StoreField(AccessBuilder::ForNameHashField()), vtrue2,
2595 jsgraph()->IntPtrConstant(Name::kEmptyHashField), etrue2, if_true2);
2596 etrue2 = graph()->NewNode(
2597 simplified()->StoreField(AccessBuilder::ForStringLength()), vtrue2,
2598 jsgraph()->SmiConstant(1), etrue2, if_true2);
2599 etrue2 = graph()->NewNode(
2600 machine()->Store(StoreRepresentation(MachineRepresentation::kWord8,
2601 kNoWriteBarrier)),
2602 vtrue2, jsgraph()->IntPtrConstant(SeqOneByteString::kHeaderSize -
2603 kHeapObjectTag),
2604 code, etrue2, if_true2);
2605
2606 // Remember it in the {cache}.
2607 etrue2 = graph()->NewNode(
2608 simplified()->StoreElement(AccessBuilder::ForFixedArrayElement()),
2609 cache, index, vtrue2, etrue2, if_true2);
2610 }
2611
2612 // Use the {entry} from the {cache}.
2613 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
2614 Node* efalse2 = etrue0;
2615 Node* vfalse2 = entry;
2616
2617 if_true1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2);
2618 etrue1 =
2619 graph()->NewNode(common()->EffectPhi(2), etrue2, efalse2, if_true1);
2620 vtrue1 =
2621 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
2622 vtrue2, vfalse2, if_true1);
2623 }
2624
2625 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
2626 Node* efalse1 = effect;
2627 Node* vfalse1;
2628 {
2629 // Allocate a new SeqTwoByteString for {code}.
2630 vfalse1 = efalse1 = graph()->NewNode(
2631 simplified()->Allocate(NOT_TENURED),
2632 jsgraph()->Int32Constant(SeqTwoByteString::SizeFor(1)), efalse1,
2633 if_false1);
2634 efalse1 = graph()->NewNode(
2635 simplified()->StoreField(AccessBuilder::ForMap()), vfalse1,
2636 jsgraph()->HeapConstant(factory()->string_map()), efalse1, if_false1);
2637 efalse1 = graph()->NewNode(
2638 simplified()->StoreField(AccessBuilder::ForNameHashField()), vfalse1,
2639 jsgraph()->IntPtrConstant(Name::kEmptyHashField), efalse1, if_false1);
2640 efalse1 = graph()->NewNode(
2641 simplified()->StoreField(AccessBuilder::ForStringLength()), vfalse1,
2642 jsgraph()->SmiConstant(1), efalse1, if_false1);
2643 efalse1 = graph()->NewNode(
2644 machine()->Store(StoreRepresentation(MachineRepresentation::kWord16,
2645 kNoWriteBarrier)),
2646 vfalse1, jsgraph()->IntPtrConstant(SeqTwoByteString::kHeaderSize -
2647 kHeapObjectTag),
2648 code, efalse1, if_false1);
2649 }
2650
2651 if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
2652 etrue0 =
2653 graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_true0);
2654 vtrue0 = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
2655 vtrue1, vfalse1, if_true0);
2656 }
2657
2658 // Generate surrogate pair string
2659 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
2660 Node* efalse0 = effect;
2661 Node* vfalse0;
2662 {
2663 switch (UnicodeEncodingOf(node->op())) {
2664 case UnicodeEncoding::UTF16:
2665 break;
2666
2667 case UnicodeEncoding::UTF32: {
2668 // Convert UTF32 to UTF16 code units, and store as a 32 bit word.
2669 Node* lead_offset = jsgraph()->Int32Constant(0xD800 - (0x10000 >> 10));
2670
2671 // lead = (codepoint >> 10) + LEAD_OFFSET
2672 Node* lead =
2673 graph()->NewNode(machine()->Int32Add(),
2674 graph()->NewNode(machine()->Word32Shr(), code,
2675 jsgraph()->Int32Constant(10)),
2676 lead_offset);
2677
2678 // trail = (codepoint & 0x3FF) + 0xDC00;
2679 Node* trail =
2680 graph()->NewNode(machine()->Int32Add(),
2681 graph()->NewNode(machine()->Word32And(), code,
2682 jsgraph()->Int32Constant(0x3FF)),
2683 jsgraph()->Int32Constant(0xDC00));
2684
2685 // codpoint = (trail << 16) | lead;
2686 code = graph()->NewNode(machine()->Word32Or(),
2687 graph()->NewNode(machine()->Word32Shl(), trail,
2688 jsgraph()->Int32Constant(16)),
2689 lead);
2690 break;
2691 }
2692 }
2693
2694 // Allocate a new SeqTwoByteString for {code}.
2695 vfalse0 = efalse0 =
2696 graph()->NewNode(simplified()->Allocate(NOT_TENURED),
2697 jsgraph()->Int32Constant(SeqTwoByteString::SizeFor(2)),
2698 efalse0, if_false0);
2699 efalse0 = graph()->NewNode(
2700 simplified()->StoreField(AccessBuilder::ForMap()), vfalse0,
2701 jsgraph()->HeapConstant(factory()->string_map()), efalse0, if_false0);
2702 efalse0 = graph()->NewNode(
2703 simplified()->StoreField(AccessBuilder::ForNameHashField()), vfalse0,
2704 jsgraph()->IntPtrConstant(Name::kEmptyHashField), efalse0, if_false0);
2705 efalse0 = graph()->NewNode(
2706 simplified()->StoreField(AccessBuilder::ForStringLength()), vfalse0,
2707 jsgraph()->SmiConstant(2), efalse0, if_false0);
2708 efalse0 = graph()->NewNode(
2709 machine()->Store(StoreRepresentation(MachineRepresentation::kWord32,
2710 kNoWriteBarrier)),
2711 vfalse0, jsgraph()->IntPtrConstant(SeqTwoByteString::kHeaderSize -
2712 kHeapObjectTag),
2713 code, efalse0, if_false0);
2714 }
2715
2716 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
2717 effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
2718 value = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
2719 vtrue0, vfalse0, control);
2720
2721 return ValueEffectControl(value, effect, control);
2722 }
2723
2724 EffectControlLinearizer::ValueEffectControl
LowerStringComparison(Callable const & callable,Node * node,Node * effect,Node * control)2725 EffectControlLinearizer::LowerStringComparison(Callable const& callable,
2726 Node* node, Node* effect,
2727 Node* control) {
2728 Operator::Properties properties = Operator::kEliminatable;
2729 CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
2730 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
2731 isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties);
2732 node->InsertInput(graph()->zone(), 0,
2733 jsgraph()->HeapConstant(callable.code()));
2734 node->AppendInput(graph()->zone(), jsgraph()->NoContextConstant());
2735 node->AppendInput(graph()->zone(), effect);
2736 NodeProperties::ChangeOp(node, common()->Call(desc));
2737 return ValueEffectControl(node, node, control);
2738 }
2739
2740 EffectControlLinearizer::ValueEffectControl
LowerStringEqual(Node * node,Node * effect,Node * control)2741 EffectControlLinearizer::LowerStringEqual(Node* node, Node* effect,
2742 Node* control) {
2743 return LowerStringComparison(CodeFactory::StringEqual(isolate()), node,
2744 effect, control);
2745 }
2746
2747 EffectControlLinearizer::ValueEffectControl
LowerStringLessThan(Node * node,Node * effect,Node * control)2748 EffectControlLinearizer::LowerStringLessThan(Node* node, Node* effect,
2749 Node* control) {
2750 return LowerStringComparison(CodeFactory::StringLessThan(isolate()), node,
2751 effect, control);
2752 }
2753
2754 EffectControlLinearizer::ValueEffectControl
LowerStringLessThanOrEqual(Node * node,Node * effect,Node * control)2755 EffectControlLinearizer::LowerStringLessThanOrEqual(Node* node, Node* effect,
2756 Node* control) {
2757 return LowerStringComparison(CodeFactory::StringLessThanOrEqual(isolate()),
2758 node, effect, control);
2759 }
2760
2761 EffectControlLinearizer::ValueEffectControl
LowerCheckFloat64Hole(Node * node,Node * frame_state,Node * effect,Node * control)2762 EffectControlLinearizer::LowerCheckFloat64Hole(Node* node, Node* frame_state,
2763 Node* effect, Node* control) {
2764 // If we reach this point w/o eliminating the {node} that's marked
2765 // with allow-return-hole, we cannot do anything, so just deoptimize
2766 // in case of the hole NaN (similar to Crankshaft).
2767 Node* value = node->InputAt(0);
2768 Node* check = graph()->NewNode(
2769 machine()->Word32Equal(),
2770 graph()->NewNode(machine()->Float64ExtractHighWord32(), value),
2771 jsgraph()->Int32Constant(kHoleNanUpper32));
2772 control = effect =
2773 graph()->NewNode(common()->DeoptimizeIf(DeoptimizeReason::kHole), check,
2774 frame_state, effect, control);
2775
2776 return ValueEffectControl(value, effect, control);
2777 }
2778
2779 EffectControlLinearizer::ValueEffectControl
LowerCheckTaggedHole(Node * node,Node * frame_state,Node * effect,Node * control)2780 EffectControlLinearizer::LowerCheckTaggedHole(Node* node, Node* frame_state,
2781 Node* effect, Node* control) {
2782 Node* value = node->InputAt(0);
2783 Node* check = graph()->NewNode(machine()->WordEqual(), value,
2784 jsgraph()->TheHoleConstant());
2785 control = effect =
2786 graph()->NewNode(common()->DeoptimizeIf(DeoptimizeReason::kHole), check,
2787 frame_state, effect, control);
2788
2789 return ValueEffectControl(value, effect, control);
2790 }
2791
2792 EffectControlLinearizer::ValueEffectControl
LowerConvertTaggedHoleToUndefined(Node * node,Node * effect,Node * control)2793 EffectControlLinearizer::LowerConvertTaggedHoleToUndefined(Node* node,
2794 Node* effect,
2795 Node* control) {
2796 Node* value = node->InputAt(0);
2797 Node* check = graph()->NewNode(machine()->WordEqual(), value,
2798 jsgraph()->TheHoleConstant());
2799 Node* branch =
2800 graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
2801
2802 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
2803 Node* vtrue = jsgraph()->UndefinedConstant();
2804
2805 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
2806 Node* vfalse = value;
2807
2808 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
2809 value = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
2810 vtrue, vfalse, control);
2811
2812 return ValueEffectControl(value, effect, control);
2813 }
2814
2815 EffectControlLinearizer::ValueEffectControl
AllocateHeapNumberWithValue(Node * value,Node * effect,Node * control)2816 EffectControlLinearizer::AllocateHeapNumberWithValue(Node* value, Node* effect,
2817 Node* control) {
2818 Node* result = effect = graph()->NewNode(
2819 simplified()->Allocate(NOT_TENURED),
2820 jsgraph()->Int32Constant(HeapNumber::kSize), effect, control);
2821 effect = graph()->NewNode(simplified()->StoreField(AccessBuilder::ForMap()),
2822 result, jsgraph()->HeapNumberMapConstant(), effect,
2823 control);
2824 effect = graph()->NewNode(
2825 simplified()->StoreField(AccessBuilder::ForHeapNumberValue()), result,
2826 value, effect, control);
2827 return ValueEffectControl(result, effect, control);
2828 }
2829
ChangeInt32ToSmi(Node * value)2830 Node* EffectControlLinearizer::ChangeInt32ToSmi(Node* value) {
2831 if (machine()->Is64()) {
2832 value = graph()->NewNode(machine()->ChangeInt32ToInt64(), value);
2833 }
2834 return graph()->NewNode(machine()->WordShl(), value, SmiShiftBitsConstant());
2835 }
2836
ChangeUint32ToSmi(Node * value)2837 Node* EffectControlLinearizer::ChangeUint32ToSmi(Node* value) {
2838 if (machine()->Is64()) {
2839 value = graph()->NewNode(machine()->ChangeUint32ToUint64(), value);
2840 }
2841 return graph()->NewNode(machine()->WordShl(), value, SmiShiftBitsConstant());
2842 }
2843
ChangeInt32ToFloat64(Node * value)2844 Node* EffectControlLinearizer::ChangeInt32ToFloat64(Node* value) {
2845 return graph()->NewNode(machine()->ChangeInt32ToFloat64(), value);
2846 }
2847
ChangeUint32ToFloat64(Node * value)2848 Node* EffectControlLinearizer::ChangeUint32ToFloat64(Node* value) {
2849 return graph()->NewNode(machine()->ChangeUint32ToFloat64(), value);
2850 }
2851
ChangeSmiToInt32(Node * value)2852 Node* EffectControlLinearizer::ChangeSmiToInt32(Node* value) {
2853 value = graph()->NewNode(machine()->WordSar(), value, SmiShiftBitsConstant());
2854 if (machine()->Is64()) {
2855 value = graph()->NewNode(machine()->TruncateInt64ToInt32(), value);
2856 }
2857 return value;
2858 }
ObjectIsSmi(Node * value)2859 Node* EffectControlLinearizer::ObjectIsSmi(Node* value) {
2860 return graph()->NewNode(
2861 machine()->WordEqual(),
2862 graph()->NewNode(machine()->WordAnd(), value,
2863 jsgraph()->IntPtrConstant(kSmiTagMask)),
2864 jsgraph()->IntPtrConstant(kSmiTag));
2865 }
2866
SmiMaxValueConstant()2867 Node* EffectControlLinearizer::SmiMaxValueConstant() {
2868 return jsgraph()->Int32Constant(Smi::kMaxValue);
2869 }
2870
SmiShiftBitsConstant()2871 Node* EffectControlLinearizer::SmiShiftBitsConstant() {
2872 return jsgraph()->IntPtrConstant(kSmiShiftSize + kSmiTagSize);
2873 }
2874
2875 EffectControlLinearizer::ValueEffectControl
LowerPlainPrimitiveToNumber(Node * node,Node * effect,Node * control)2876 EffectControlLinearizer::LowerPlainPrimitiveToNumber(Node* node, Node* effect,
2877 Node* control) {
2878 Node* value = node->InputAt(0);
2879 Node* result = effect =
2880 graph()->NewNode(ToNumberOperator(), jsgraph()->ToNumberBuiltinConstant(),
2881 value, jsgraph()->NoContextConstant(), effect);
2882 return ValueEffectControl(result, effect, control);
2883 }
2884
2885 EffectControlLinearizer::ValueEffectControl
LowerPlainPrimitiveToWord32(Node * node,Node * effect,Node * control)2886 EffectControlLinearizer::LowerPlainPrimitiveToWord32(Node* node, Node* effect,
2887 Node* control) {
2888 Node* value = node->InputAt(0);
2889
2890 Node* check0 = ObjectIsSmi(value);
2891 Node* branch0 =
2892 graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
2893
2894 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
2895 Node* etrue0 = effect;
2896 Node* vtrue0 = ChangeSmiToInt32(value);
2897
2898 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
2899 Node* efalse0 = effect;
2900 Node* vfalse0;
2901 {
2902 vfalse0 = efalse0 = graph()->NewNode(
2903 ToNumberOperator(), jsgraph()->ToNumberBuiltinConstant(), value,
2904 jsgraph()->NoContextConstant(), efalse0);
2905
2906 Node* check1 = ObjectIsSmi(vfalse0);
2907 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
2908
2909 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
2910 Node* etrue1 = efalse0;
2911 Node* vtrue1 = ChangeSmiToInt32(vfalse0);
2912
2913 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
2914 Node* efalse1 = efalse0;
2915 Node* vfalse1;
2916 {
2917 vfalse1 = efalse1 = graph()->NewNode(
2918 simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), efalse0,
2919 efalse1, if_false1);
2920 vfalse1 = graph()->NewNode(machine()->TruncateFloat64ToWord32(), vfalse1);
2921 }
2922
2923 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
2924 efalse0 =
2925 graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0);
2926 vfalse0 = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
2927 vtrue1, vfalse1, if_false0);
2928 }
2929
2930 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
2931 effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
2932 value = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
2933 vtrue0, vfalse0, control);
2934 return ValueEffectControl(value, effect, control);
2935 }
2936
2937 EffectControlLinearizer::ValueEffectControl
LowerPlainPrimitiveToFloat64(Node * node,Node * effect,Node * control)2938 EffectControlLinearizer::LowerPlainPrimitiveToFloat64(Node* node, Node* effect,
2939 Node* control) {
2940 Node* value = node->InputAt(0);
2941
2942 Node* check0 = ObjectIsSmi(value);
2943 Node* branch0 =
2944 graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
2945
2946 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
2947 Node* etrue0 = effect;
2948 Node* vtrue0;
2949 {
2950 vtrue0 = ChangeSmiToInt32(value);
2951 vtrue0 = graph()->NewNode(machine()->ChangeInt32ToFloat64(), vtrue0);
2952 }
2953
2954 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
2955 Node* efalse0 = effect;
2956 Node* vfalse0;
2957 {
2958 vfalse0 = efalse0 = graph()->NewNode(
2959 ToNumberOperator(), jsgraph()->ToNumberBuiltinConstant(), value,
2960 jsgraph()->NoContextConstant(), efalse0);
2961
2962 Node* check1 = ObjectIsSmi(vfalse0);
2963 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
2964
2965 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
2966 Node* etrue1 = efalse0;
2967 Node* vtrue1;
2968 {
2969 vtrue1 = ChangeSmiToInt32(vfalse0);
2970 vtrue1 = graph()->NewNode(machine()->ChangeInt32ToFloat64(), vtrue1);
2971 }
2972
2973 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
2974 Node* efalse1 = efalse0;
2975 Node* vfalse1;
2976 {
2977 vfalse1 = efalse1 = graph()->NewNode(
2978 simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), efalse0,
2979 efalse1, if_false1);
2980 }
2981
2982 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
2983 efalse0 =
2984 graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0);
2985 vfalse0 =
2986 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
2987 vtrue1, vfalse1, if_false0);
2988 }
2989
2990 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
2991 effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
2992 value = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
2993 vtrue0, vfalse0, control);
2994 return ValueEffectControl(value, effect, control);
2995 }
2996
2997 EffectControlLinearizer::ValueEffectControl
LowerEnsureWritableFastElements(Node * node,Node * effect,Node * control)2998 EffectControlLinearizer::LowerEnsureWritableFastElements(Node* node,
2999 Node* effect,
3000 Node* control) {
3001 Node* object = node->InputAt(0);
3002 Node* elements = node->InputAt(1);
3003
3004 // Load the current map of {elements}.
3005 Node* elements_map = effect =
3006 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
3007 elements, effect, control);
3008
3009 // Check if {elements} is not a copy-on-write FixedArray.
3010 Node* check = graph()->NewNode(machine()->WordEqual(), elements_map,
3011 jsgraph()->FixedArrayMapConstant());
3012 Node* branch =
3013 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
3014
3015 // Nothing to do if the {elements} are not copy-on-write.
3016 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
3017 Node* etrue = effect;
3018 Node* vtrue = elements;
3019
3020 // We need to take a copy of the {elements} and set them up for {object}.
3021 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
3022 Node* efalse = effect;
3023 Node* vfalse;
3024 {
3025 // We need to create a copy of the {elements} for {object}.
3026 Operator::Properties properties = Operator::kEliminatable;
3027 Callable callable = CodeFactory::CopyFastSmiOrObjectElements(isolate());
3028 CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
3029 CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
3030 isolate(), graph()->zone(), callable.descriptor(), 0, flags,
3031 properties);
3032 vfalse = efalse = graph()->NewNode(
3033 common()->Call(desc), jsgraph()->HeapConstant(callable.code()), object,
3034 jsgraph()->NoContextConstant(), efalse);
3035 }
3036
3037 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
3038 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
3039 Node* value = graph()->NewNode(
3040 common()->Phi(MachineRepresentation::kTagged, 2), vtrue, vfalse, control);
3041
3042 return ValueEffectControl(value, effect, control);
3043 }
3044
3045 EffectControlLinearizer::ValueEffectControl
LowerMaybeGrowFastElements(Node * node,Node * frame_state,Node * effect,Node * control)3046 EffectControlLinearizer::LowerMaybeGrowFastElements(Node* node,
3047 Node* frame_state,
3048 Node* effect,
3049 Node* control) {
3050 GrowFastElementsFlags flags = GrowFastElementsFlagsOf(node->op());
3051 Node* object = node->InputAt(0);
3052 Node* elements = node->InputAt(1);
3053 Node* index = node->InputAt(2);
3054 Node* length = node->InputAt(3);
3055
3056 Node* check0 = graph()->NewNode((flags & GrowFastElementsFlag::kHoleyElements)
3057 ? machine()->Uint32LessThanOrEqual()
3058 : machine()->Word32Equal(),
3059 length, index);
3060 Node* branch0 = graph()->NewNode(common()->Branch(), check0, control);
3061
3062 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
3063 Node* etrue0 = effect;
3064 Node* vtrue0 = elements;
3065 {
3066 // Load the length of the {elements} backing store.
3067 Node* elements_length = etrue0 = graph()->NewNode(
3068 simplified()->LoadField(AccessBuilder::ForFixedArrayLength()), elements,
3069 etrue0, if_true0);
3070 elements_length = ChangeSmiToInt32(elements_length);
3071
3072 // Check if we need to grow the {elements} backing store.
3073 Node* check1 =
3074 graph()->NewNode(machine()->Uint32LessThan(), index, elements_length);
3075 Node* branch1 =
3076 graph()->NewNode(common()->Branch(BranchHint::kTrue), check1, if_true0);
3077
3078 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
3079 Node* etrue1 = etrue0;
3080 Node* vtrue1 = vtrue0;
3081
3082 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
3083 Node* efalse1 = etrue0;
3084 Node* vfalse1 = vtrue0;
3085 {
3086 // We need to grow the {elements} for {object}.
3087 Operator::Properties properties = Operator::kEliminatable;
3088 Callable callable =
3089 (flags & GrowFastElementsFlag::kDoubleElements)
3090 ? CodeFactory::GrowFastDoubleElements(isolate())
3091 : CodeFactory::GrowFastSmiOrObjectElements(isolate());
3092 CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
3093 CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
3094 isolate(), graph()->zone(), callable.descriptor(), 0, flags,
3095 properties);
3096 vfalse1 = efalse1 = graph()->NewNode(
3097 common()->Call(desc), jsgraph()->HeapConstant(callable.code()),
3098 object, ChangeInt32ToSmi(index), jsgraph()->NoContextConstant(),
3099 efalse1);
3100
3101 // Ensure that we were able to grow the {elements}.
3102 // TODO(turbofan): We use kSmi as reason here similar to Crankshaft,
3103 // but maybe we should just introduce a reason that makes sense.
3104 efalse1 = if_false1 = graph()->NewNode(
3105 common()->DeoptimizeIf(DeoptimizeReason::kSmi), ObjectIsSmi(vfalse1),
3106 frame_state, efalse1, if_false1);
3107 }
3108
3109 if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
3110 etrue0 =
3111 graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_true0);
3112 vtrue0 = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
3113 vtrue1, vfalse1, if_true0);
3114
3115 // For JSArray {object}s we also need to update the "length".
3116 if (flags & GrowFastElementsFlag::kArrayObject) {
3117 // Compute the new {length}.
3118 Node* object_length = ChangeInt32ToSmi(graph()->NewNode(
3119 machine()->Int32Add(), index, jsgraph()->Int32Constant(1)));
3120
3121 // Update the "length" property of the {object}.
3122 etrue0 =
3123 graph()->NewNode(simplified()->StoreField(
3124 AccessBuilder::ForJSArrayLength(FAST_ELEMENTS)),
3125 object, object_length, etrue0, if_true0);
3126 }
3127 }
3128
3129 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
3130 Node* efalse0 = effect;
3131 Node* vfalse0 = elements;
3132 {
3133 // In case of non-holey {elements}, we need to verify that the {index} is
3134 // in-bounds, otherwise for holey {elements}, the check above already
3135 // guards the index (and the operator forces {index} to be unsigned).
3136 if (!(flags & GrowFastElementsFlag::kHoleyElements)) {
3137 Node* check1 =
3138 graph()->NewNode(machine()->Uint32LessThan(), index, length);
3139 efalse0 = if_false0 = graph()->NewNode(
3140 common()->DeoptimizeUnless(DeoptimizeReason::kOutOfBounds), check1,
3141 frame_state, efalse0, if_false0);
3142 }
3143 }
3144
3145 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
3146 effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
3147 Node* value =
3148 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), vtrue0,
3149 vfalse0, control);
3150
3151 return ValueEffectControl(value, effect, control);
3152 }
3153
3154 EffectControlLinearizer::ValueEffectControl
LowerTransitionElementsKind(Node * node,Node * effect,Node * control)3155 EffectControlLinearizer::LowerTransitionElementsKind(Node* node, Node* effect,
3156 Node* control) {
3157 ElementsTransition const transition = ElementsTransitionOf(node->op());
3158 Node* object = node->InputAt(0);
3159 Node* source_map = node->InputAt(1);
3160 Node* target_map = node->InputAt(2);
3161
3162 // Load the current map of {object}.
3163 Node* object_map = effect =
3164 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), object,
3165 effect, control);
3166
3167 // Check if {object_map} is the same as {source_map}.
3168 Node* check =
3169 graph()->NewNode(machine()->WordEqual(), object_map, source_map);
3170 Node* branch =
3171 graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
3172
3173 // Migrate the {object} from {source_map} to {target_map}.
3174 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
3175 Node* etrue = effect;
3176 {
3177 switch (transition) {
3178 case ElementsTransition::kFastTransition: {
3179 // In-place migration of {object}, just store the {target_map}.
3180 etrue =
3181 graph()->NewNode(simplified()->StoreField(AccessBuilder::ForMap()),
3182 object, target_map, etrue, if_true);
3183 break;
3184 }
3185 case ElementsTransition::kSlowTransition: {
3186 // Instance migration, call out to the runtime for {object}.
3187 Operator::Properties properties =
3188 Operator::kNoDeopt | Operator::kNoThrow;
3189 Runtime::FunctionId id = Runtime::kTransitionElementsKind;
3190 CallDescriptor const* desc = Linkage::GetRuntimeCallDescriptor(
3191 graph()->zone(), id, 2, properties, CallDescriptor::kNoFlags);
3192 etrue = graph()->NewNode(
3193 common()->Call(desc), jsgraph()->CEntryStubConstant(1), object,
3194 target_map,
3195 jsgraph()->ExternalConstant(ExternalReference(id, isolate())),
3196 jsgraph()->Int32Constant(2), jsgraph()->NoContextConstant(), etrue,
3197 if_true);
3198 break;
3199 }
3200 }
3201 }
3202
3203 // Nothing to do if the {object} doesn't have the {source_map}.
3204 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
3205 Node* efalse = effect;
3206
3207 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
3208 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
3209
3210 return ValueEffectControl(nullptr, effect, control);
3211 }
3212
3213 EffectControlLinearizer::ValueEffectControl
LowerLoadTypedElement(Node * node,Node * effect,Node * control)3214 EffectControlLinearizer::LowerLoadTypedElement(Node* node, Node* effect,
3215 Node* control) {
3216 ExternalArrayType array_type = ExternalArrayTypeOf(node->op());
3217 Node* buffer = node->InputAt(0);
3218 Node* base = node->InputAt(1);
3219 Node* external = node->InputAt(2);
3220 Node* index = node->InputAt(3);
3221
3222 // We need to keep the {buffer} alive so that the GC will not release the
3223 // ArrayBuffer (if there's any) as long as we are still operating on it.
3224 effect = graph()->NewNode(common()->Retain(), buffer, effect);
3225
3226 // Compute the effective storage pointer.
3227 Node* storage = effect = graph()->NewNode(machine()->UnsafePointerAdd(), base,
3228 external, effect, control);
3229
3230 // Perform the actual typed element access.
3231 Node* value = effect = graph()->NewNode(
3232 simplified()->LoadElement(
3233 AccessBuilder::ForTypedArrayElement(array_type, true)),
3234 storage, index, effect, control);
3235
3236 return ValueEffectControl(value, effect, control);
3237 }
3238
3239 EffectControlLinearizer::ValueEffectControl
LowerStoreTypedElement(Node * node,Node * effect,Node * control)3240 EffectControlLinearizer::LowerStoreTypedElement(Node* node, Node* effect,
3241 Node* control) {
3242 ExternalArrayType array_type = ExternalArrayTypeOf(node->op());
3243 Node* buffer = node->InputAt(0);
3244 Node* base = node->InputAt(1);
3245 Node* external = node->InputAt(2);
3246 Node* index = node->InputAt(3);
3247 Node* value = node->InputAt(4);
3248
3249 // We need to keep the {buffer} alive so that the GC will not release the
3250 // ArrayBuffer (if there's any) as long as we are still operating on it.
3251 effect = graph()->NewNode(common()->Retain(), buffer, effect);
3252
3253 // Compute the effective storage pointer.
3254 Node* storage = effect = graph()->NewNode(machine()->UnsafePointerAdd(), base,
3255 external, effect, control);
3256
3257 // Perform the actual typed element access.
3258 effect = graph()->NewNode(
3259 simplified()->StoreElement(
3260 AccessBuilder::ForTypedArrayElement(array_type, true)),
3261 storage, index, value, effect, control);
3262
3263 return ValueEffectControl(nullptr, effect, control);
3264 }
3265
3266 EffectControlLinearizer::ValueEffectControl
LowerFloat64RoundUp(Node * node,Node * effect,Node * control)3267 EffectControlLinearizer::LowerFloat64RoundUp(Node* node, Node* effect,
3268 Node* control) {
3269 // Nothing to be done if a fast hardware instruction is available.
3270 if (machine()->Float64RoundUp().IsSupported()) {
3271 return ValueEffectControl(node, effect, control);
3272 }
3273
3274 Node* const one = jsgraph()->Float64Constant(1.0);
3275 Node* const zero = jsgraph()->Float64Constant(0.0);
3276 Node* const minus_zero = jsgraph()->Float64Constant(-0.0);
3277 Node* const two_52 = jsgraph()->Float64Constant(4503599627370496.0E0);
3278 Node* const minus_two_52 = jsgraph()->Float64Constant(-4503599627370496.0E0);
3279 Node* const input = node->InputAt(0);
3280
3281 // General case for ceil.
3282 //
3283 // if 0.0 < input then
3284 // if 2^52 <= input then
3285 // input
3286 // else
3287 // let temp1 = (2^52 + input) - 2^52 in
3288 // if temp1 < input then
3289 // temp1 + 1
3290 // else
3291 // temp1
3292 // else
3293 // if input == 0 then
3294 // input
3295 // else
3296 // if input <= -2^52 then
3297 // input
3298 // else
3299 // let temp1 = -0 - input in
3300 // let temp2 = (2^52 + temp1) - 2^52 in
3301 // let temp3 = (if temp1 < temp2 then temp2 - 1 else temp2) in
3302 // -0 - temp3
3303 //
3304 // Note: We do not use the Diamond helper class here, because it really hurts
3305 // readability with nested diamonds.
3306
3307 Node* check0 = graph()->NewNode(machine()->Float64LessThan(), zero, input);
3308 Node* branch0 =
3309 graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
3310
3311 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
3312 Node* vtrue0;
3313 {
3314 Node* check1 =
3315 graph()->NewNode(machine()->Float64LessThanOrEqual(), two_52, input);
3316 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0);
3317
3318 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
3319 Node* vtrue1 = input;
3320
3321 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
3322 Node* vfalse1;
3323 {
3324 Node* temp1 = graph()->NewNode(
3325 machine()->Float64Sub(),
3326 graph()->NewNode(machine()->Float64Add(), two_52, input), two_52);
3327 vfalse1 = graph()->NewNode(
3328 common()->Select(MachineRepresentation::kFloat64),
3329 graph()->NewNode(machine()->Float64LessThan(), temp1, input),
3330 graph()->NewNode(machine()->Float64Add(), temp1, one), temp1);
3331 }
3332
3333 if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
3334 vtrue0 = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
3335 vtrue1, vfalse1, if_true0);
3336 }
3337
3338 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
3339 Node* vfalse0;
3340 {
3341 Node* check1 = graph()->NewNode(machine()->Float64Equal(), input, zero);
3342 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
3343 check1, if_false0);
3344
3345 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
3346 Node* vtrue1 = input;
3347
3348 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
3349 Node* vfalse1;
3350 {
3351 Node* check2 = graph()->NewNode(machine()->Float64LessThanOrEqual(),
3352 input, minus_two_52);
3353 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
3354 check2, if_false1);
3355
3356 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
3357 Node* vtrue2 = input;
3358
3359 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
3360 Node* vfalse2;
3361 {
3362 Node* temp1 =
3363 graph()->NewNode(machine()->Float64Sub(), minus_zero, input);
3364 Node* temp2 = graph()->NewNode(
3365 machine()->Float64Sub(),
3366 graph()->NewNode(machine()->Float64Add(), two_52, temp1), two_52);
3367 Node* temp3 = graph()->NewNode(
3368 common()->Select(MachineRepresentation::kFloat64),
3369 graph()->NewNode(machine()->Float64LessThan(), temp1, temp2),
3370 graph()->NewNode(machine()->Float64Sub(), temp2, one), temp2);
3371 vfalse2 = graph()->NewNode(machine()->Float64Sub(), minus_zero, temp3);
3372 }
3373
3374 if_false1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2);
3375 vfalse1 =
3376 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
3377 vtrue2, vfalse2, if_false1);
3378 }
3379
3380 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
3381 vfalse0 =
3382 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
3383 vtrue1, vfalse1, if_false0);
3384 }
3385
3386 Node* merge0 = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
3387 Node* value =
3388 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
3389 vtrue0, vfalse0, merge0);
3390 return ValueEffectControl(value, effect, merge0);
3391 }
3392
3393 EffectControlLinearizer::ValueEffectControl
BuildFloat64RoundDown(Node * value,Node * effect,Node * control)3394 EffectControlLinearizer::BuildFloat64RoundDown(Node* value, Node* effect,
3395 Node* control) {
3396 if (machine()->Float64RoundDown().IsSupported()) {
3397 value = graph()->NewNode(machine()->Float64RoundDown().op(), value);
3398 } else {
3399 Node* const one = jsgraph()->Float64Constant(1.0);
3400 Node* const zero = jsgraph()->Float64Constant(0.0);
3401 Node* const minus_one = jsgraph()->Float64Constant(-1.0);
3402 Node* const minus_zero = jsgraph()->Float64Constant(-0.0);
3403 Node* const two_52 = jsgraph()->Float64Constant(4503599627370496.0E0);
3404 Node* const minus_two_52 =
3405 jsgraph()->Float64Constant(-4503599627370496.0E0);
3406 Node* const input = value;
3407
3408 // General case for floor.
3409 //
3410 // if 0.0 < input then
3411 // if 2^52 <= input then
3412 // input
3413 // else
3414 // let temp1 = (2^52 + input) - 2^52 in
3415 // if input < temp1 then
3416 // temp1 - 1
3417 // else
3418 // temp1
3419 // else
3420 // if input == 0 then
3421 // input
3422 // else
3423 // if input <= -2^52 then
3424 // input
3425 // else
3426 // let temp1 = -0 - input in
3427 // let temp2 = (2^52 + temp1) - 2^52 in
3428 // if temp2 < temp1 then
3429 // -1 - temp2
3430 // else
3431 // -0 - temp2
3432 //
3433 // Note: We do not use the Diamond helper class here, because it really
3434 // hurts
3435 // readability with nested diamonds.
3436
3437 Node* check0 = graph()->NewNode(machine()->Float64LessThan(), zero, input);
3438 Node* branch0 =
3439 graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
3440
3441 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
3442 Node* vtrue0;
3443 {
3444 Node* check1 =
3445 graph()->NewNode(machine()->Float64LessThanOrEqual(), two_52, input);
3446 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0);
3447
3448 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
3449 Node* vtrue1 = input;
3450
3451 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
3452 Node* vfalse1;
3453 {
3454 Node* temp1 = graph()->NewNode(
3455 machine()->Float64Sub(),
3456 graph()->NewNode(machine()->Float64Add(), two_52, input), two_52);
3457 vfalse1 = graph()->NewNode(
3458 common()->Select(MachineRepresentation::kFloat64),
3459 graph()->NewNode(machine()->Float64LessThan(), input, temp1),
3460 graph()->NewNode(machine()->Float64Sub(), temp1, one), temp1);
3461 }
3462
3463 if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
3464 vtrue0 =
3465 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
3466 vtrue1, vfalse1, if_true0);
3467 }
3468
3469 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
3470 Node* vfalse0;
3471 {
3472 Node* check1 = graph()->NewNode(machine()->Float64Equal(), input, zero);
3473 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
3474 check1, if_false0);
3475
3476 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
3477 Node* vtrue1 = input;
3478
3479 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
3480 Node* vfalse1;
3481 {
3482 Node* check2 = graph()->NewNode(machine()->Float64LessThanOrEqual(),
3483 input, minus_two_52);
3484 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
3485 check2, if_false1);
3486
3487 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
3488 Node* vtrue2 = input;
3489
3490 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
3491 Node* vfalse2;
3492 {
3493 Node* temp1 =
3494 graph()->NewNode(machine()->Float64Sub(), minus_zero, input);
3495 Node* temp2 = graph()->NewNode(
3496 machine()->Float64Sub(),
3497 graph()->NewNode(machine()->Float64Add(), two_52, temp1), two_52);
3498 vfalse2 = graph()->NewNode(
3499 common()->Select(MachineRepresentation::kFloat64),
3500 graph()->NewNode(machine()->Float64LessThan(), temp2, temp1),
3501 graph()->NewNode(machine()->Float64Sub(), minus_one, temp2),
3502 graph()->NewNode(machine()->Float64Sub(), minus_zero, temp2));
3503 }
3504
3505 if_false1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2);
3506 vfalse1 =
3507 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
3508 vtrue2, vfalse2, if_false1);
3509 }
3510
3511 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
3512 vfalse0 =
3513 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
3514 vtrue1, vfalse1, if_false0);
3515 }
3516
3517 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
3518 value = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
3519 vtrue0, vfalse0, control);
3520 }
3521 return ValueEffectControl(value, effect, control);
3522 }
3523
3524 EffectControlLinearizer::ValueEffectControl
LowerFloat64RoundDown(Node * node,Node * effect,Node * control)3525 EffectControlLinearizer::LowerFloat64RoundDown(Node* node, Node* effect,
3526 Node* control) {
3527 // Nothing to be done if a fast hardware instruction is available.
3528 if (machine()->Float64RoundDown().IsSupported()) {
3529 return ValueEffectControl(node, effect, control);
3530 }
3531
3532 Node* const input = node->InputAt(0);
3533 return BuildFloat64RoundDown(input, effect, control);
3534 }
3535
3536 EffectControlLinearizer::ValueEffectControl
LowerFloat64RoundTiesEven(Node * node,Node * effect,Node * control)3537 EffectControlLinearizer::LowerFloat64RoundTiesEven(Node* node, Node* effect,
3538 Node* control) {
3539 // Nothing to be done if a fast hardware instruction is available.
3540 if (machine()->Float64RoundTiesEven().IsSupported()) {
3541 return ValueEffectControl(node, effect, control);
3542 }
3543
3544 Node* const one = jsgraph()->Float64Constant(1.0);
3545 Node* const two = jsgraph()->Float64Constant(2.0);
3546 Node* const half = jsgraph()->Float64Constant(0.5);
3547 Node* const zero = jsgraph()->Float64Constant(0.0);
3548 Node* const input = node->InputAt(0);
3549
3550 // Generate case for round ties to even:
3551 //
3552 // let value = floor(input) in
3553 // let temp1 = input - value in
3554 // if temp1 < 0.5 then
3555 // value
3556 // else if 0.5 < temp1 then
3557 // value + 1.0
3558 // else
3559 // let temp2 = value % 2.0 in
3560 // if temp2 == 0.0 then
3561 // value
3562 // else
3563 // value + 1.0
3564 //
3565 // Note: We do not use the Diamond helper class here, because it really hurts
3566 // readability with nested diamonds.
3567
3568 ValueEffectControl continuation =
3569 BuildFloat64RoundDown(input, effect, control);
3570 Node* value = continuation.value;
3571 effect = continuation.effect;
3572 control = continuation.control;
3573
3574 Node* temp1 = graph()->NewNode(machine()->Float64Sub(), input, value);
3575
3576 Node* check0 = graph()->NewNode(machine()->Float64LessThan(), temp1, half);
3577 Node* branch0 = graph()->NewNode(common()->Branch(), check0, control);
3578
3579 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
3580 Node* vtrue0 = value;
3581
3582 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
3583 Node* vfalse0;
3584 {
3585 Node* check1 = graph()->NewNode(machine()->Float64LessThan(), half, temp1);
3586 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
3587
3588 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
3589 Node* vtrue1 = graph()->NewNode(machine()->Float64Add(), value, one);
3590
3591 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
3592 Node* vfalse1;
3593 {
3594 Node* temp2 = graph()->NewNode(machine()->Float64Mod(), value, two);
3595
3596 Node* check2 = graph()->NewNode(machine()->Float64Equal(), temp2, zero);
3597 Node* branch2 = graph()->NewNode(common()->Branch(), check2, if_false1);
3598
3599 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
3600 Node* vtrue2 = value;
3601
3602 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
3603 Node* vfalse2 = graph()->NewNode(machine()->Float64Add(), value, one);
3604
3605 if_false1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2);
3606 vfalse1 =
3607 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
3608 vtrue2, vfalse2, if_false1);
3609 }
3610
3611 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
3612 vfalse0 =
3613 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
3614 vtrue1, vfalse1, if_false0);
3615 }
3616
3617 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
3618 value = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
3619 vtrue0, vfalse0, control);
3620
3621 return ValueEffectControl(value, effect, control);
3622 }
3623
3624 EffectControlLinearizer::ValueEffectControl
LowerFloat64RoundTruncate(Node * node,Node * effect,Node * control)3625 EffectControlLinearizer::LowerFloat64RoundTruncate(Node* node, Node* effect,
3626 Node* control) {
3627 // Nothing to be done if a fast hardware instruction is available.
3628 if (machine()->Float64RoundTruncate().IsSupported()) {
3629 return ValueEffectControl(node, effect, control);
3630 }
3631
3632 Node* const one = jsgraph()->Float64Constant(1.0);
3633 Node* const zero = jsgraph()->Float64Constant(0.0);
3634 Node* const minus_zero = jsgraph()->Float64Constant(-0.0);
3635 Node* const two_52 = jsgraph()->Float64Constant(4503599627370496.0E0);
3636 Node* const minus_two_52 = jsgraph()->Float64Constant(-4503599627370496.0E0);
3637 Node* const input = node->InputAt(0);
3638
3639 // General case for trunc.
3640 //
3641 // if 0.0 < input then
3642 // if 2^52 <= input then
3643 // input
3644 // else
3645 // let temp1 = (2^52 + input) - 2^52 in
3646 // if input < temp1 then
3647 // temp1 - 1
3648 // else
3649 // temp1
3650 // else
3651 // if input == 0 then
3652 // input
3653 // else
3654 // if input <= -2^52 then
3655 // input
3656 // else
3657 // let temp1 = -0 - input in
3658 // let temp2 = (2^52 + temp1) - 2^52 in
3659 // let temp3 = (if temp1 < temp2 then temp2 - 1 else temp2) in
3660 // -0 - temp3
3661 //
3662 // Note: We do not use the Diamond helper class here, because it really hurts
3663 // readability with nested diamonds.
3664
3665 Node* check0 = graph()->NewNode(machine()->Float64LessThan(), zero, input);
3666 Node* branch0 =
3667 graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
3668
3669 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
3670 Node* vtrue0;
3671 {
3672 Node* check1 =
3673 graph()->NewNode(machine()->Float64LessThanOrEqual(), two_52, input);
3674 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0);
3675
3676 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
3677 Node* vtrue1 = input;
3678
3679 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
3680 Node* vfalse1;
3681 {
3682 Node* temp1 = graph()->NewNode(
3683 machine()->Float64Sub(),
3684 graph()->NewNode(machine()->Float64Add(), two_52, input), two_52);
3685 vfalse1 = graph()->NewNode(
3686 common()->Select(MachineRepresentation::kFloat64),
3687 graph()->NewNode(machine()->Float64LessThan(), input, temp1),
3688 graph()->NewNode(machine()->Float64Sub(), temp1, one), temp1);
3689 }
3690
3691 if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
3692 vtrue0 = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
3693 vtrue1, vfalse1, if_true0);
3694 }
3695
3696 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
3697 Node* vfalse0;
3698 {
3699 Node* check1 = graph()->NewNode(machine()->Float64Equal(), input, zero);
3700 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
3701 check1, if_false0);
3702
3703 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
3704 Node* vtrue1 = input;
3705
3706 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
3707 Node* vfalse1;
3708 {
3709 Node* check2 = graph()->NewNode(machine()->Float64LessThanOrEqual(),
3710 input, minus_two_52);
3711 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
3712 check2, if_false1);
3713
3714 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
3715 Node* vtrue2 = input;
3716
3717 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
3718 Node* vfalse2;
3719 {
3720 Node* temp1 =
3721 graph()->NewNode(machine()->Float64Sub(), minus_zero, input);
3722 Node* temp2 = graph()->NewNode(
3723 machine()->Float64Sub(),
3724 graph()->NewNode(machine()->Float64Add(), two_52, temp1), two_52);
3725 Node* temp3 = graph()->NewNode(
3726 common()->Select(MachineRepresentation::kFloat64),
3727 graph()->NewNode(machine()->Float64LessThan(), temp1, temp2),
3728 graph()->NewNode(machine()->Float64Sub(), temp2, one), temp2);
3729 vfalse2 = graph()->NewNode(machine()->Float64Sub(), minus_zero, temp3);
3730 }
3731
3732 if_false1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2);
3733 vfalse1 =
3734 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
3735 vtrue2, vfalse2, if_false1);
3736 }
3737
3738 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
3739 vfalse0 =
3740 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
3741 vtrue1, vfalse1, if_false0);
3742 }
3743
3744 Node* merge0 = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
3745 Node* value =
3746 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
3747 vtrue0, vfalse0, merge0);
3748 return ValueEffectControl(value, effect, merge0);
3749 }
3750
factory() const3751 Factory* EffectControlLinearizer::factory() const {
3752 return isolate()->factory();
3753 }
3754
isolate() const3755 Isolate* EffectControlLinearizer::isolate() const {
3756 return jsgraph()->isolate();
3757 }
3758
ToNumberOperator()3759 Operator const* EffectControlLinearizer::ToNumberOperator() {
3760 if (!to_number_operator_.is_set()) {
3761 Callable callable = CodeFactory::ToNumber(isolate());
3762 CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
3763 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
3764 isolate(), graph()->zone(), callable.descriptor(), 0, flags,
3765 Operator::kEliminatable);
3766 to_number_operator_.set(common()->Call(desc));
3767 }
3768 return to_number_operator_.get();
3769 }
3770
3771 } // namespace compiler
3772 } // namespace internal
3773 } // namespace v8
3774