blob: 865e909ad83108c3657eae7a53eeb276999c122a [file] [log] [blame]
Ben Murdochbcf72ee2016-08-08 18:44:38 +01001// Copyright 2015 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/compiler/effect-control-linearizer.h"
6
7#include "src/code-factory.h"
8#include "src/compiler/access-builder.h"
Ben Murdochc8c1d9e2017-03-08 14:04:23 +00009#include "src/compiler/compiler-source-position-table.h"
Ben Murdochbcf72ee2016-08-08 18:44:38 +010010#include "src/compiler/js-graph.h"
11#include "src/compiler/linkage.h"
Ben Murdochf91f0612016-11-29 16:50:11 +000012#include "src/compiler/node-matchers.h"
Ben Murdochbcf72ee2016-08-08 18:44:38 +010013#include "src/compiler/node-properties.h"
14#include "src/compiler/node.h"
15#include "src/compiler/schedule.h"
Ben Murdoch62ed6312017-06-06 11:06:27 +010016#include "src/objects-inl.h"
Ben Murdochbcf72ee2016-08-08 18:44:38 +010017
18namespace v8 {
19namespace internal {
20namespace compiler {
21
Ben Murdochc8c1d9e2017-03-08 14:04:23 +000022EffectControlLinearizer::EffectControlLinearizer(
23 JSGraph* js_graph, Schedule* schedule, Zone* temp_zone,
24 SourcePositionTable* source_positions)
25 : js_graph_(js_graph),
26 schedule_(schedule),
27 temp_zone_(temp_zone),
Ben Murdoch62ed6312017-06-06 11:06:27 +010028 source_positions_(source_positions),
29 graph_assembler_(js_graph, nullptr, nullptr, temp_zone) {}
Ben Murdochbcf72ee2016-08-08 18:44:38 +010030
31Graph* EffectControlLinearizer::graph() const { return js_graph_->graph(); }
32CommonOperatorBuilder* EffectControlLinearizer::common() const {
33 return js_graph_->common();
34}
35SimplifiedOperatorBuilder* EffectControlLinearizer::simplified() const {
36 return js_graph_->simplified();
37}
38MachineOperatorBuilder* EffectControlLinearizer::machine() const {
39 return js_graph_->machine();
40}
41
42namespace {
43
44struct BlockEffectControlData {
Ben Murdochf91f0612016-11-29 16:50:11 +000045 Node* current_effect = nullptr; // New effect.
46 Node* current_control = nullptr; // New control.
Ben Murdoch13e2dad2016-09-16 13:49:30 +010047 Node* current_frame_state = nullptr; // New frame state.
Ben Murdochbcf72ee2016-08-08 18:44:38 +010048};
49
Ben Murdochf91f0612016-11-29 16:50:11 +000050class BlockEffectControlMap {
51 public:
52 explicit BlockEffectControlMap(Zone* temp_zone) : map_(temp_zone) {}
53
54 BlockEffectControlData& For(BasicBlock* from, BasicBlock* to) {
55 return map_[std::make_pair(from->rpo_number(), to->rpo_number())];
56 }
57
58 const BlockEffectControlData& For(BasicBlock* from, BasicBlock* to) const {
59 return map_.at(std::make_pair(from->rpo_number(), to->rpo_number()));
60 }
61
62 private:
63 typedef std::pair<int32_t, int32_t> Key;
64 typedef ZoneMap<Key, BlockEffectControlData> Map;
65
66 Map map_;
67};
68
Ben Murdochbcf72ee2016-08-08 18:44:38 +010069// Effect phis that need to be updated after the first pass.
70struct PendingEffectPhi {
71 Node* effect_phi;
72 BasicBlock* block;
73
74 PendingEffectPhi(Node* effect_phi, BasicBlock* block)
75 : effect_phi(effect_phi), block(block) {}
76};
77
78void UpdateEffectPhi(Node* node, BasicBlock* block,
Ben Murdochf91f0612016-11-29 16:50:11 +000079 BlockEffectControlMap* block_effects) {
Ben Murdochbcf72ee2016-08-08 18:44:38 +010080 // Update all inputs to an effect phi with the effects from the given
81 // block->effect map.
82 DCHECK_EQ(IrOpcode::kEffectPhi, node->opcode());
Ben Murdochc8c1d9e2017-03-08 14:04:23 +000083 DCHECK_EQ(static_cast<size_t>(node->op()->EffectInputCount()),
84 block->PredecessorCount());
Ben Murdochbcf72ee2016-08-08 18:44:38 +010085 for (int i = 0; i < node->op()->EffectInputCount(); i++) {
86 Node* input = node->InputAt(i);
87 BasicBlock* predecessor = block->PredecessorAt(static_cast<size_t>(i));
Ben Murdochf91f0612016-11-29 16:50:11 +000088 const BlockEffectControlData& block_effect =
89 block_effects->For(predecessor, block);
90 if (input != block_effect.current_effect) {
91 node->ReplaceInput(i, block_effect.current_effect);
Ben Murdochbcf72ee2016-08-08 18:44:38 +010092 }
93 }
94}
95
96void UpdateBlockControl(BasicBlock* block,
Ben Murdochf91f0612016-11-29 16:50:11 +000097 BlockEffectControlMap* block_effects) {
Ben Murdochbcf72ee2016-08-08 18:44:38 +010098 Node* control = block->NodeAt(0);
99 DCHECK(NodeProperties::IsControl(control));
100
101 // Do not rewire the end node.
102 if (control->opcode() == IrOpcode::kEnd) return;
103
104 // Update all inputs to the given control node with the correct control.
Ben Murdochf91f0612016-11-29 16:50:11 +0000105 DCHECK(control->opcode() == IrOpcode::kMerge ||
Ben Murdochc8c1d9e2017-03-08 14:04:23 +0000106 static_cast<size_t>(control->op()->ControlInputCount()) ==
107 block->PredecessorCount());
108 if (static_cast<size_t>(control->op()->ControlInputCount()) !=
109 block->PredecessorCount()) {
Ben Murdochf91f0612016-11-29 16:50:11 +0000110 return; // We already re-wired the control inputs of this node.
111 }
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100112 for (int i = 0; i < control->op()->ControlInputCount(); i++) {
113 Node* input = NodeProperties::GetControlInput(control, i);
114 BasicBlock* predecessor = block->PredecessorAt(static_cast<size_t>(i));
Ben Murdochf91f0612016-11-29 16:50:11 +0000115 const BlockEffectControlData& block_effect =
116 block_effects->For(predecessor, block);
117 if (input != block_effect.current_control) {
118 NodeProperties::ReplaceControlInput(control, block_effect.current_control,
119 i);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100120 }
121 }
122}
123
124bool HasIncomingBackEdges(BasicBlock* block) {
125 for (BasicBlock* pred : block->predecessors()) {
126 if (pred->rpo_number() >= block->rpo_number()) {
127 return true;
128 }
129 }
130 return false;
131}
132
133void RemoveRegionNode(Node* node) {
134 DCHECK(IrOpcode::kFinishRegion == node->opcode() ||
135 IrOpcode::kBeginRegion == node->opcode());
136 // Update the value/context uses to the value input of the finish node and
137 // the effect uses to the effect input.
138 for (Edge edge : node->use_edges()) {
139 DCHECK(!edge.from()->IsDead());
140 if (NodeProperties::IsEffectEdge(edge)) {
141 edge.UpdateTo(NodeProperties::GetEffectInput(node));
142 } else {
143 DCHECK(!NodeProperties::IsControlEdge(edge));
144 DCHECK(!NodeProperties::IsFrameStateEdge(edge));
145 edge.UpdateTo(node->InputAt(0));
146 }
147 }
148 node->Kill();
149}
150
Ben Murdochf91f0612016-11-29 16:50:11 +0000151void TryCloneBranch(Node* node, BasicBlock* block, Graph* graph,
152 CommonOperatorBuilder* common,
Ben Murdochc8c1d9e2017-03-08 14:04:23 +0000153 BlockEffectControlMap* block_effects,
154 SourcePositionTable* source_positions) {
Ben Murdochf91f0612016-11-29 16:50:11 +0000155 DCHECK_EQ(IrOpcode::kBranch, node->opcode());
156
157 // This optimization is a special case of (super)block cloning. It takes an
158 // input graph as shown below and clones the Branch node for every predecessor
159 // to the Merge, essentially removing the Merge completely. This avoids
160 // materializing the bit for the Phi and may offer potential for further
161 // branch folding optimizations (i.e. because one or more inputs to the Phi is
162 // a constant). Note that there may be more Phi nodes hanging off the Merge,
163 // but we can only a certain subset of them currently (actually only Phi and
164 // EffectPhi nodes whose uses have either the IfTrue or IfFalse as control
165 // input).
166
167 // Control1 ... ControlN
168 // ^ ^
169 // | | Cond1 ... CondN
170 // +----+ +----+ ^ ^
171 // | | | |
172 // | | +----+ |
173 // Merge<--+ | +------------+
174 // ^ \|/
175 // | Phi
176 // | |
177 // Branch----+
178 // ^
179 // |
180 // +-----+-----+
181 // | |
182 // IfTrue IfFalse
183 // ^ ^
184 // | |
185
186 // The resulting graph (modulo the Phi and EffectPhi nodes) looks like this:
187
188 // Control1 Cond1 ... ControlN CondN
189 // ^ ^ ^ ^
190 // \ / \ /
191 // Branch ... Branch
192 // ^ ^
193 // | |
194 // +---+---+ +---+----+
195 // | | | |
196 // IfTrue IfFalse ... IfTrue IfFalse
197 // ^ ^ ^ ^
198 // | | | |
199 // +--+ +-------------+ |
200 // | | +--------------+ +--+
201 // | | | |
202 // Merge Merge
203 // ^ ^
204 // | |
205
Ben Murdochc8c1d9e2017-03-08 14:04:23 +0000206 SourcePositionTable::Scope scope(source_positions,
207 source_positions->GetSourcePosition(node));
Ben Murdochf91f0612016-11-29 16:50:11 +0000208 Node* branch = node;
209 Node* cond = NodeProperties::GetValueInput(branch, 0);
210 if (!cond->OwnedBy(branch) || cond->opcode() != IrOpcode::kPhi) return;
211 Node* merge = NodeProperties::GetControlInput(branch);
212 if (merge->opcode() != IrOpcode::kMerge ||
213 NodeProperties::GetControlInput(cond) != merge) {
214 return;
215 }
216 // Grab the IfTrue/IfFalse projections of the Branch.
217 BranchMatcher matcher(branch);
218 // Check/collect other Phi/EffectPhi nodes hanging off the Merge.
219 NodeVector phis(graph->zone());
220 for (Node* const use : merge->uses()) {
221 if (use == branch || use == cond) continue;
222 // We cannot currently deal with non-Phi/EffectPhi nodes hanging off the
223 // Merge. Ideally, we would just clone the nodes (and everything that
224 // depends on it to some distant join point), but that requires knowledge
225 // about dominance/post-dominance.
226 if (!NodeProperties::IsPhi(use)) return;
227 for (Edge edge : use->use_edges()) {
228 // Right now we can only handle Phi/EffectPhi nodes whose uses are
229 // directly control-dependend on either the IfTrue or the IfFalse
230 // successor, because we know exactly how to update those uses.
231 if (edge.from()->op()->ControlInputCount() != 1) return;
232 Node* control = NodeProperties::GetControlInput(edge.from());
233 if (NodeProperties::IsPhi(edge.from())) {
234 control = NodeProperties::GetControlInput(control, edge.index());
235 }
236 if (control != matcher.IfTrue() && control != matcher.IfFalse()) return;
237 }
238 phis.push_back(use);
239 }
240 BranchHint const hint = BranchHintOf(branch->op());
241 int const input_count = merge->op()->ControlInputCount();
242 DCHECK_LE(1, input_count);
243 Node** const inputs = graph->zone()->NewArray<Node*>(2 * input_count);
244 Node** const merge_true_inputs = &inputs[0];
245 Node** const merge_false_inputs = &inputs[input_count];
246 for (int index = 0; index < input_count; ++index) {
247 Node* cond1 = NodeProperties::GetValueInput(cond, index);
248 Node* control1 = NodeProperties::GetControlInput(merge, index);
249 Node* branch1 = graph->NewNode(common->Branch(hint), cond1, control1);
250 merge_true_inputs[index] = graph->NewNode(common->IfTrue(), branch1);
251 merge_false_inputs[index] = graph->NewNode(common->IfFalse(), branch1);
252 }
253 Node* const merge_true = matcher.IfTrue();
254 Node* const merge_false = matcher.IfFalse();
255 merge_true->TrimInputCount(0);
256 merge_false->TrimInputCount(0);
257 for (int i = 0; i < input_count; ++i) {
258 merge_true->AppendInput(graph->zone(), merge_true_inputs[i]);
259 merge_false->AppendInput(graph->zone(), merge_false_inputs[i]);
260 }
Ben Murdochc8c1d9e2017-03-08 14:04:23 +0000261 DCHECK_EQ(2u, block->SuccessorCount());
Ben Murdochf91f0612016-11-29 16:50:11 +0000262 NodeProperties::ChangeOp(matcher.IfTrue(), common->Merge(input_count));
263 NodeProperties::ChangeOp(matcher.IfFalse(), common->Merge(input_count));
264 int const true_index =
265 block->SuccessorAt(0)->NodeAt(0) == matcher.IfTrue() ? 0 : 1;
266 BlockEffectControlData* true_block_data =
267 &block_effects->For(block, block->SuccessorAt(true_index));
268 BlockEffectControlData* false_block_data =
269 &block_effects->For(block, block->SuccessorAt(true_index ^ 1));
270 for (Node* const phi : phis) {
271 for (int index = 0; index < input_count; ++index) {
272 inputs[index] = phi->InputAt(index);
273 }
274 inputs[input_count] = merge_true;
275 Node* phi_true = graph->NewNode(phi->op(), input_count + 1, inputs);
276 inputs[input_count] = merge_false;
277 Node* phi_false = graph->NewNode(phi->op(), input_count + 1, inputs);
278 if (phi->UseCount() == 0) {
279 DCHECK_EQ(phi->opcode(), IrOpcode::kEffectPhi);
Ben Murdochf91f0612016-11-29 16:50:11 +0000280 } else {
281 for (Edge edge : phi->use_edges()) {
282 Node* control = NodeProperties::GetControlInput(edge.from());
283 if (NodeProperties::IsPhi(edge.from())) {
284 control = NodeProperties::GetControlInput(control, edge.index());
285 }
286 DCHECK(control == matcher.IfTrue() || control == matcher.IfFalse());
287 edge.UpdateTo((control == matcher.IfTrue()) ? phi_true : phi_false);
288 }
289 }
290 if (phi->opcode() == IrOpcode::kEffectPhi) {
291 true_block_data->current_effect = phi_true;
292 false_block_data->current_effect = phi_false;
293 }
294 phi->Kill();
295 }
296 // Fix up IfTrue and IfFalse and kill all dead nodes.
297 if (branch == block->control_input()) {
298 true_block_data->current_control = merge_true;
299 false_block_data->current_control = merge_false;
300 }
301 branch->Kill();
302 cond->Kill();
303 merge->Kill();
304}
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100305} // namespace
306
307void EffectControlLinearizer::Run() {
Ben Murdochf91f0612016-11-29 16:50:11 +0000308 BlockEffectControlMap block_effects(temp_zone());
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100309 ZoneVector<PendingEffectPhi> pending_effect_phis(temp_zone());
310 ZoneVector<BasicBlock*> pending_block_controls(temp_zone());
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100311 NodeVector inputs_buffer(temp_zone());
312
313 for (BasicBlock* block : *(schedule()->rpo_order())) {
314 size_t instr = 0;
315
316 // The control node should be the first.
317 Node* control = block->NodeAt(instr);
318 DCHECK(NodeProperties::IsControl(control));
319 // Update the control inputs.
320 if (HasIncomingBackEdges(block)) {
321 // If there are back edges, we need to update later because we have not
322 // computed the control yet. This should only happen for loops.
323 DCHECK_EQ(IrOpcode::kLoop, control->opcode());
324 pending_block_controls.push_back(block);
325 } else {
326 // If there are no back edges, we can update now.
327 UpdateBlockControl(block, &block_effects);
328 }
329 instr++;
330
331 // Iterate over the phis and update the effect phis.
332 Node* effect = nullptr;
333 Node* terminate = nullptr;
334 for (; instr < block->NodeCount(); instr++) {
335 Node* node = block->NodeAt(instr);
336 // Only go through the phis and effect phis.
337 if (node->opcode() == IrOpcode::kEffectPhi) {
338 // There should be at most one effect phi in a block.
339 DCHECK_NULL(effect);
340 // IfException blocks should not have effect phis.
341 DCHECK_NE(IrOpcode::kIfException, control->opcode());
342 effect = node;
343
344 // Make sure we update the inputs to the incoming blocks' effects.
345 if (HasIncomingBackEdges(block)) {
346 // In case of loops, we do not update the effect phi immediately
347 // because the back predecessor has not been handled yet. We just
348 // record the effect phi for later processing.
349 pending_effect_phis.push_back(PendingEffectPhi(node, block));
350 } else {
351 UpdateEffectPhi(node, block, &block_effects);
352 }
353 } else if (node->opcode() == IrOpcode::kPhi) {
354 // Just skip phis.
355 } else if (node->opcode() == IrOpcode::kTerminate) {
356 DCHECK(terminate == nullptr);
357 terminate = node;
358 } else {
359 break;
360 }
361 }
362
363 if (effect == nullptr) {
364 // There was no effect phi.
365 DCHECK(!HasIncomingBackEdges(block));
366 if (block == schedule()->start()) {
367 // Start block => effect is start.
368 DCHECK_EQ(graph()->start(), control);
369 effect = graph()->start();
370 } else if (control->opcode() == IrOpcode::kEnd) {
371 // End block is just a dummy, no effect needed.
372 DCHECK_EQ(BasicBlock::kNone, block->control());
373 DCHECK_EQ(1u, block->size());
374 effect = nullptr;
375 } else {
Ben Murdochf91f0612016-11-29 16:50:11 +0000376 // If all the predecessors have the same effect, we can use it as our
377 // current effect.
378 effect =
379 block_effects.For(block->PredecessorAt(0), block).current_effect;
380 for (size_t i = 1; i < block->PredecessorCount(); ++i) {
381 if (block_effects.For(block->PredecessorAt(i), block)
382 .current_effect != effect) {
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100383 effect = nullptr;
384 break;
385 }
386 }
387 if (effect == nullptr) {
388 DCHECK_NE(IrOpcode::kIfException, control->opcode());
389 // The input blocks do not have the same effect. We have
390 // to create an effect phi node.
391 inputs_buffer.clear();
Ben Murdochf91f0612016-11-29 16:50:11 +0000392 inputs_buffer.resize(block->PredecessorCount(), jsgraph()->Dead());
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100393 inputs_buffer.push_back(control);
394 effect = graph()->NewNode(
395 common()->EffectPhi(static_cast<int>(block->PredecessorCount())),
396 static_cast<int>(inputs_buffer.size()), &(inputs_buffer.front()));
Ben Murdochf91f0612016-11-29 16:50:11 +0000397 // For loops, we update the effect phi node later to break cycles.
398 if (control->opcode() == IrOpcode::kLoop) {
399 pending_effect_phis.push_back(PendingEffectPhi(effect, block));
400 } else {
401 UpdateEffectPhi(effect, block, &block_effects);
402 }
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100403 } else if (control->opcode() == IrOpcode::kIfException) {
404 // The IfException is connected into the effect chain, so we need
405 // to update the effect here.
406 NodeProperties::ReplaceEffectInput(control, effect);
407 effect = control;
408 }
409 }
410 }
411
412 // Fixup the Terminate node.
413 if (terminate != nullptr) {
414 NodeProperties::ReplaceEffectInput(terminate, effect);
415 }
416
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100417 // The frame state at block entry is determined by the frame states leaving
418 // all predecessors. In case there is no frame state dominating this block,
419 // we can rely on a checkpoint being present before the next deoptimization.
420 // TODO(mstarzinger): Eventually we will need to go hunt for a frame state
421 // once deoptimizing nodes roam freely through the schedule.
422 Node* frame_state = nullptr;
423 if (block != schedule()->start()) {
424 // If all the predecessors have the same effect, we can use it
425 // as our current effect.
Ben Murdochf91f0612016-11-29 16:50:11 +0000426 frame_state =
427 block_effects.For(block->PredecessorAt(0), block).current_frame_state;
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100428 for (size_t i = 1; i < block->PredecessorCount(); i++) {
Ben Murdochf91f0612016-11-29 16:50:11 +0000429 if (block_effects.For(block->PredecessorAt(i), block)
430 .current_frame_state != frame_state) {
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100431 frame_state = nullptr;
432 break;
433 }
434 }
435 }
436
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100437 // Process the ordinary instructions.
438 for (; instr < block->NodeCount(); instr++) {
439 Node* node = block->NodeAt(instr);
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100440 ProcessNode(node, &frame_state, &effect, &control);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100441 }
442
443 switch (block->control()) {
444 case BasicBlock::kGoto:
445 case BasicBlock::kNone:
446 break;
447
448 case BasicBlock::kCall:
449 case BasicBlock::kTailCall:
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100450 case BasicBlock::kSwitch:
451 case BasicBlock::kReturn:
452 case BasicBlock::kDeoptimize:
453 case BasicBlock::kThrow:
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100454 ProcessNode(block->control_input(), &frame_state, &effect, &control);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100455 break;
Ben Murdochf91f0612016-11-29 16:50:11 +0000456
457 case BasicBlock::kBranch:
458 ProcessNode(block->control_input(), &frame_state, &effect, &control);
459 TryCloneBranch(block->control_input(), block, graph(), common(),
Ben Murdochc8c1d9e2017-03-08 14:04:23 +0000460 &block_effects, source_positions_);
Ben Murdochf91f0612016-11-29 16:50:11 +0000461 break;
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100462 }
463
Ben Murdochf91f0612016-11-29 16:50:11 +0000464 // Store the effect, control and frame state for later use.
465 for (BasicBlock* successor : block->successors()) {
466 BlockEffectControlData* data = &block_effects.For(block, successor);
467 if (data->current_effect == nullptr) {
468 data->current_effect = effect;
469 }
470 if (data->current_control == nullptr) {
471 data->current_control = control;
472 }
473 data->current_frame_state = frame_state;
474 }
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100475 }
476
477 // Update the incoming edges of the effect phis that could not be processed
478 // during the first pass (because they could have incoming back edges).
479 for (const PendingEffectPhi& pending_effect_phi : pending_effect_phis) {
480 UpdateEffectPhi(pending_effect_phi.effect_phi, pending_effect_phi.block,
481 &block_effects);
482 }
483 for (BasicBlock* pending_block_control : pending_block_controls) {
484 UpdateBlockControl(pending_block_control, &block_effects);
485 }
486}
487
488namespace {
489
490void TryScheduleCallIfSuccess(Node* node, Node** control) {
491 // Schedule the call's IfSuccess node if there is no exception use.
492 if (!NodeProperties::IsExceptionalCall(node)) {
493 for (Edge edge : node->use_edges()) {
494 if (NodeProperties::IsControlEdge(edge) &&
495 edge.from()->opcode() == IrOpcode::kIfSuccess) {
496 *control = edge.from();
497 }
498 }
499 }
500}
501
502} // namespace
503
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100504void EffectControlLinearizer::ProcessNode(Node* node, Node** frame_state,
505 Node** effect, Node** control) {
Ben Murdochc8c1d9e2017-03-08 14:04:23 +0000506 SourcePositionTable::Scope scope(source_positions_,
507 source_positions_->GetSourcePosition(node));
508
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100509 // If the node needs to be wired into the effect/control chain, do this
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100510 // here. Pass current frame state for lowering to eager deoptimization.
511 if (TryWireInStateEffect(node, *frame_state, effect, control)) {
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100512 return;
513 }
514
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100515 // If the node has a visible effect, then there must be a checkpoint in the
516 // effect chain before we are allowed to place another eager deoptimization
517 // point. We zap the frame state to ensure this invariant is maintained.
518 if (region_observability_ == RegionObservability::kObservable &&
519 !node->op()->HasProperty(Operator::kNoWrite)) {
520 *frame_state = nullptr;
521 }
522
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100523 // Remove the end markers of 'atomic' allocation region because the
524 // region should be wired-in now.
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100525 if (node->opcode() == IrOpcode::kFinishRegion) {
526 // Reset the current region observability.
527 region_observability_ = RegionObservability::kObservable;
528 // Update the value uses to the value input of the finish node and
529 // the effect uses to the effect input.
530 return RemoveRegionNode(node);
531 }
532 if (node->opcode() == IrOpcode::kBeginRegion) {
533 // Determine the observability for this region and use that for all
534 // nodes inside the region (i.e. ignore the absence of kNoWrite on
535 // StoreField and other operators).
536 DCHECK_NE(RegionObservability::kNotObservable, region_observability_);
537 region_observability_ = RegionObservabilityOf(node->op());
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100538 // Update the value uses to the value input of the finish node and
539 // the effect uses to the effect input.
540 return RemoveRegionNode(node);
541 }
542
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100543 // Special treatment for checkpoint nodes.
544 if (node->opcode() == IrOpcode::kCheckpoint) {
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100545 // Unlink the check point; effect uses will be updated to the incoming
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100546 // effect that is passed. The frame state is preserved for lowering.
547 DCHECK_EQ(RegionObservability::kObservable, region_observability_);
Ben Murdochf91f0612016-11-29 16:50:11 +0000548 *frame_state = NodeProperties::GetFrameStateInput(node);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100549 return;
550 }
551
552 if (node->opcode() == IrOpcode::kIfSuccess) {
553 // We always schedule IfSuccess with its call, so skip it here.
554 DCHECK_EQ(IrOpcode::kCall, node->InputAt(0)->opcode());
555 // The IfSuccess node should not belong to an exceptional call node
556 // because such IfSuccess nodes should only start a basic block (and
557 // basic block start nodes are not handled in the ProcessNode method).
558 DCHECK(!NodeProperties::IsExceptionalCall(node->InputAt(0)));
559 return;
560 }
561
562 // If the node takes an effect, replace with the current one.
563 if (node->op()->EffectInputCount() > 0) {
564 DCHECK_EQ(1, node->op()->EffectInputCount());
565 Node* input_effect = NodeProperties::GetEffectInput(node);
566
567 if (input_effect != *effect) {
568 NodeProperties::ReplaceEffectInput(node, *effect);
569 }
570
571 // If the node produces an effect, update our current effect. (However,
572 // ignore new effect chains started with ValueEffect.)
573 if (node->op()->EffectOutputCount() > 0) {
574 DCHECK_EQ(1, node->op()->EffectOutputCount());
575 *effect = node;
576 }
577 } else {
578 // New effect chain is only started with a Start or ValueEffect node.
579 DCHECK(node->op()->EffectOutputCount() == 0 ||
580 node->opcode() == IrOpcode::kStart);
581 }
582
583 // Rewire control inputs.
584 for (int i = 0; i < node->op()->ControlInputCount(); i++) {
585 NodeProperties::ReplaceControlInput(node, *control, i);
586 }
587 // Update the current control and wire IfSuccess right after calls.
588 if (node->op()->ControlOutputCount() > 0) {
589 *control = node;
590 if (node->opcode() == IrOpcode::kCall) {
591 // Schedule the call's IfSuccess node (if there is no exception use).
592 TryScheduleCallIfSuccess(node, control);
593 }
594 }
595}
596
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100597bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
598 Node* frame_state,
599 Node** effect,
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100600 Node** control) {
Ben Murdoch62ed6312017-06-06 11:06:27 +0100601 gasm()->Reset(*effect, *control);
602 Node* result = nullptr;
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100603 switch (node->opcode()) {
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100604 case IrOpcode::kChangeBitToTagged:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100605 result = LowerChangeBitToTagged(node);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100606 break;
607 case IrOpcode::kChangeInt31ToTaggedSigned:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100608 result = LowerChangeInt31ToTaggedSigned(node);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100609 break;
610 case IrOpcode::kChangeInt32ToTagged:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100611 result = LowerChangeInt32ToTagged(node);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100612 break;
613 case IrOpcode::kChangeUint32ToTagged:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100614 result = LowerChangeUint32ToTagged(node);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100615 break;
616 case IrOpcode::kChangeFloat64ToTagged:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100617 result = LowerChangeFloat64ToTagged(node);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100618 break;
Ben Murdochc8c1d9e2017-03-08 14:04:23 +0000619 case IrOpcode::kChangeFloat64ToTaggedPointer:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100620 result = LowerChangeFloat64ToTaggedPointer(node);
Ben Murdochc8c1d9e2017-03-08 14:04:23 +0000621 break;
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100622 case IrOpcode::kChangeTaggedSignedToInt32:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100623 result = LowerChangeTaggedSignedToInt32(node);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100624 break;
625 case IrOpcode::kChangeTaggedToBit:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100626 result = LowerChangeTaggedToBit(node);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100627 break;
628 case IrOpcode::kChangeTaggedToInt32:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100629 result = LowerChangeTaggedToInt32(node);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100630 break;
631 case IrOpcode::kChangeTaggedToUint32:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100632 result = LowerChangeTaggedToUint32(node);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100633 break;
634 case IrOpcode::kChangeTaggedToFloat64:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100635 result = LowerChangeTaggedToFloat64(node);
636 break;
637 case IrOpcode::kChangeTaggedToTaggedSigned:
638 result = LowerChangeTaggedToTaggedSigned(node);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100639 break;
Ben Murdochf3b273f2017-01-17 12:11:28 +0000640 case IrOpcode::kTruncateTaggedToBit:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100641 result = LowerTruncateTaggedToBit(node);
Ben Murdochf3b273f2017-01-17 12:11:28 +0000642 break;
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100643 case IrOpcode::kTruncateTaggedToFloat64:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100644 result = LowerTruncateTaggedToFloat64(node);
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100645 break;
646 case IrOpcode::kCheckBounds:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100647 result = LowerCheckBounds(node, frame_state);
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100648 break;
Ben Murdochf91f0612016-11-29 16:50:11 +0000649 case IrOpcode::kCheckMaps:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100650 result = LowerCheckMaps(node, frame_state);
Ben Murdochf91f0612016-11-29 16:50:11 +0000651 break;
652 case IrOpcode::kCheckNumber:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100653 result = LowerCheckNumber(node, frame_state);
654 break;
655 case IrOpcode::kCheckReceiver:
656 result = LowerCheckReceiver(node, frame_state);
Ben Murdochf91f0612016-11-29 16:50:11 +0000657 break;
658 case IrOpcode::kCheckString:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100659 result = LowerCheckString(node, frame_state);
660 break;
661 case IrOpcode::kCheckInternalizedString:
662 result = LowerCheckInternalizedString(node, frame_state);
Ben Murdochf91f0612016-11-29 16:50:11 +0000663 break;
664 case IrOpcode::kCheckIf:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100665 result = LowerCheckIf(node, frame_state);
Ben Murdochf91f0612016-11-29 16:50:11 +0000666 break;
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100667 case IrOpcode::kCheckedInt32Add:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100668 result = LowerCheckedInt32Add(node, frame_state);
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100669 break;
670 case IrOpcode::kCheckedInt32Sub:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100671 result = LowerCheckedInt32Sub(node, frame_state);
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100672 break;
Ben Murdochf91f0612016-11-29 16:50:11 +0000673 case IrOpcode::kCheckedInt32Div:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100674 result = LowerCheckedInt32Div(node, frame_state);
Ben Murdochf91f0612016-11-29 16:50:11 +0000675 break;
676 case IrOpcode::kCheckedInt32Mod:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100677 result = LowerCheckedInt32Mod(node, frame_state);
Ben Murdochf91f0612016-11-29 16:50:11 +0000678 break;
679 case IrOpcode::kCheckedUint32Div:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100680 result = LowerCheckedUint32Div(node, frame_state);
Ben Murdochf91f0612016-11-29 16:50:11 +0000681 break;
682 case IrOpcode::kCheckedUint32Mod:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100683 result = LowerCheckedUint32Mod(node, frame_state);
Ben Murdochf91f0612016-11-29 16:50:11 +0000684 break;
685 case IrOpcode::kCheckedInt32Mul:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100686 result = LowerCheckedInt32Mul(node, frame_state);
Ben Murdochf91f0612016-11-29 16:50:11 +0000687 break;
Ben Murdochf3b273f2017-01-17 12:11:28 +0000688 case IrOpcode::kCheckedInt32ToTaggedSigned:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100689 result = LowerCheckedInt32ToTaggedSigned(node, frame_state);
Ben Murdochf3b273f2017-01-17 12:11:28 +0000690 break;
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100691 case IrOpcode::kCheckedUint32ToInt32:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100692 result = LowerCheckedUint32ToInt32(node, frame_state);
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100693 break;
Ben Murdochf3b273f2017-01-17 12:11:28 +0000694 case IrOpcode::kCheckedUint32ToTaggedSigned:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100695 result = LowerCheckedUint32ToTaggedSigned(node, frame_state);
Ben Murdochf3b273f2017-01-17 12:11:28 +0000696 break;
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100697 case IrOpcode::kCheckedFloat64ToInt32:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100698 result = LowerCheckedFloat64ToInt32(node, frame_state);
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100699 break;
Ben Murdochf91f0612016-11-29 16:50:11 +0000700 case IrOpcode::kCheckedTaggedSignedToInt32:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100701 result = LowerCheckedTaggedSignedToInt32(node, frame_state);
Ben Murdochf91f0612016-11-29 16:50:11 +0000702 break;
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100703 case IrOpcode::kCheckedTaggedToInt32:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100704 result = LowerCheckedTaggedToInt32(node, frame_state);
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100705 break;
706 case IrOpcode::kCheckedTaggedToFloat64:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100707 result = LowerCheckedTaggedToFloat64(node, frame_state);
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100708 break;
Ben Murdochf3b273f2017-01-17 12:11:28 +0000709 case IrOpcode::kCheckedTaggedToTaggedSigned:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100710 result = LowerCheckedTaggedToTaggedSigned(node, frame_state);
Ben Murdochf3b273f2017-01-17 12:11:28 +0000711 break;
Ben Murdochc8c1d9e2017-03-08 14:04:23 +0000712 case IrOpcode::kCheckedTaggedToTaggedPointer:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100713 result = LowerCheckedTaggedToTaggedPointer(node, frame_state);
Ben Murdochc8c1d9e2017-03-08 14:04:23 +0000714 break;
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100715 case IrOpcode::kTruncateTaggedToWord32:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100716 result = LowerTruncateTaggedToWord32(node);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100717 break;
Ben Murdochf91f0612016-11-29 16:50:11 +0000718 case IrOpcode::kCheckedTruncateTaggedToWord32:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100719 result = LowerCheckedTruncateTaggedToWord32(node, frame_state);
Ben Murdochf91f0612016-11-29 16:50:11 +0000720 break;
Ben Murdoch62ed6312017-06-06 11:06:27 +0100721 case IrOpcode::kObjectIsDetectableCallable:
722 result = LowerObjectIsDetectableCallable(node);
723 break;
724 case IrOpcode::kObjectIsNonCallable:
725 result = LowerObjectIsNonCallable(node);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100726 break;
727 case IrOpcode::kObjectIsNumber:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100728 result = LowerObjectIsNumber(node);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100729 break;
730 case IrOpcode::kObjectIsReceiver:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100731 result = LowerObjectIsReceiver(node);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100732 break;
733 case IrOpcode::kObjectIsSmi:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100734 result = LowerObjectIsSmi(node);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100735 break;
736 case IrOpcode::kObjectIsString:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100737 result = LowerObjectIsString(node);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100738 break;
739 case IrOpcode::kObjectIsUndetectable:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100740 result = LowerObjectIsUndetectable(node);
741 break;
742 case IrOpcode::kNewRestParameterElements:
743 result = LowerNewRestParameterElements(node);
744 break;
745 case IrOpcode::kNewUnmappedArgumentsElements:
746 result = LowerNewUnmappedArgumentsElements(node);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100747 break;
Ben Murdochf3b273f2017-01-17 12:11:28 +0000748 case IrOpcode::kArrayBufferWasNeutered:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100749 result = LowerArrayBufferWasNeutered(node);
Ben Murdochf3b273f2017-01-17 12:11:28 +0000750 break;
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100751 case IrOpcode::kStringFromCharCode:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100752 result = LowerStringFromCharCode(node);
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100753 break;
Ben Murdochf3b273f2017-01-17 12:11:28 +0000754 case IrOpcode::kStringFromCodePoint:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100755 result = LowerStringFromCodePoint(node);
756 break;
757 case IrOpcode::kStringIndexOf:
758 result = LowerStringIndexOf(node);
759 break;
760 case IrOpcode::kStringCharAt:
761 result = LowerStringCharAt(node);
Ben Murdochf3b273f2017-01-17 12:11:28 +0000762 break;
Ben Murdochf91f0612016-11-29 16:50:11 +0000763 case IrOpcode::kStringCharCodeAt:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100764 result = LowerStringCharCodeAt(node);
Ben Murdochf91f0612016-11-29 16:50:11 +0000765 break;
Ben Murdochf3b273f2017-01-17 12:11:28 +0000766 case IrOpcode::kStringEqual:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100767 result = LowerStringEqual(node);
Ben Murdochf3b273f2017-01-17 12:11:28 +0000768 break;
769 case IrOpcode::kStringLessThan:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100770 result = LowerStringLessThan(node);
Ben Murdochf3b273f2017-01-17 12:11:28 +0000771 break;
772 case IrOpcode::kStringLessThanOrEqual:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100773 result = LowerStringLessThanOrEqual(node);
Ben Murdochf3b273f2017-01-17 12:11:28 +0000774 break;
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100775 case IrOpcode::kCheckFloat64Hole:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100776 result = LowerCheckFloat64Hole(node, frame_state);
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100777 break;
778 case IrOpcode::kCheckTaggedHole:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100779 result = LowerCheckTaggedHole(node, frame_state);
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100780 break;
Ben Murdochf91f0612016-11-29 16:50:11 +0000781 case IrOpcode::kConvertTaggedHoleToUndefined:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100782 result = LowerConvertTaggedHoleToUndefined(node);
Ben Murdochf91f0612016-11-29 16:50:11 +0000783 break;
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100784 case IrOpcode::kPlainPrimitiveToNumber:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100785 result = LowerPlainPrimitiveToNumber(node);
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100786 break;
787 case IrOpcode::kPlainPrimitiveToWord32:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100788 result = LowerPlainPrimitiveToWord32(node);
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100789 break;
790 case IrOpcode::kPlainPrimitiveToFloat64:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100791 result = LowerPlainPrimitiveToFloat64(node);
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100792 break;
Ben Murdochf91f0612016-11-29 16:50:11 +0000793 case IrOpcode::kEnsureWritableFastElements:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100794 result = LowerEnsureWritableFastElements(node);
Ben Murdochf91f0612016-11-29 16:50:11 +0000795 break;
796 case IrOpcode::kMaybeGrowFastElements:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100797 result = LowerMaybeGrowFastElements(node, frame_state);
Ben Murdochf91f0612016-11-29 16:50:11 +0000798 break;
799 case IrOpcode::kTransitionElementsKind:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100800 LowerTransitionElementsKind(node);
Ben Murdochf91f0612016-11-29 16:50:11 +0000801 break;
802 case IrOpcode::kLoadTypedElement:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100803 result = LowerLoadTypedElement(node);
Ben Murdochf91f0612016-11-29 16:50:11 +0000804 break;
805 case IrOpcode::kStoreTypedElement:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100806 LowerStoreTypedElement(node);
Ben Murdochf91f0612016-11-29 16:50:11 +0000807 break;
808 case IrOpcode::kFloat64RoundUp:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100809 if (!LowerFloat64RoundUp(node).To(&result)) {
810 return false;
811 }
Ben Murdochf91f0612016-11-29 16:50:11 +0000812 break;
813 case IrOpcode::kFloat64RoundDown:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100814 if (!LowerFloat64RoundDown(node).To(&result)) {
815 return false;
816 }
Ben Murdochf91f0612016-11-29 16:50:11 +0000817 break;
818 case IrOpcode::kFloat64RoundTruncate:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100819 if (!LowerFloat64RoundTruncate(node).To(&result)) {
820 return false;
821 }
Ben Murdochf91f0612016-11-29 16:50:11 +0000822 break;
Ben Murdochc8c1d9e2017-03-08 14:04:23 +0000823 case IrOpcode::kFloat64RoundTiesEven:
Ben Murdoch62ed6312017-06-06 11:06:27 +0100824 if (!LowerFloat64RoundTiesEven(node).To(&result)) {
825 return false;
826 }
Ben Murdochc8c1d9e2017-03-08 14:04:23 +0000827 break;
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100828 default:
829 return false;
830 }
Ben Murdoch62ed6312017-06-06 11:06:27 +0100831 *effect = gasm()->ExtractCurrentEffect();
832 *control = gasm()->ExtractCurrentControl();
833 NodeProperties::ReplaceUses(node, result, *effect, *control);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100834 return true;
835}
836
Ben Murdoch62ed6312017-06-06 11:06:27 +0100837#define __ gasm()->
838
839Node* EffectControlLinearizer::LowerChangeFloat64ToTagged(Node* node) {
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100840 Node* value = node->InputAt(0);
Ben Murdoch62ed6312017-06-06 11:06:27 +0100841 return AllocateHeapNumberWithValue(value);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100842}
843
Ben Murdoch62ed6312017-06-06 11:06:27 +0100844Node* EffectControlLinearizer::LowerChangeFloat64ToTaggedPointer(Node* node) {
Ben Murdochc8c1d9e2017-03-08 14:04:23 +0000845 Node* value = node->InputAt(0);
Ben Murdoch62ed6312017-06-06 11:06:27 +0100846 return AllocateHeapNumberWithValue(value);
Ben Murdochc8c1d9e2017-03-08 14:04:23 +0000847}
848
Ben Murdoch62ed6312017-06-06 11:06:27 +0100849Node* EffectControlLinearizer::LowerChangeBitToTagged(Node* node) {
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100850 Node* value = node->InputAt(0);
851
Ben Murdoch62ed6312017-06-06 11:06:27 +0100852 auto if_true = __ MakeLabel<1>();
853 auto done = __ MakeLabel<2>(MachineRepresentation::kTagged);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100854
Ben Murdoch62ed6312017-06-06 11:06:27 +0100855 __ GotoIf(value, &if_true);
856 __ Goto(&done, __ FalseConstant());
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100857
Ben Murdoch62ed6312017-06-06 11:06:27 +0100858 __ Bind(&if_true);
859 __ Goto(&done, __ TrueConstant());
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100860
Ben Murdoch62ed6312017-06-06 11:06:27 +0100861 __ Bind(&done);
862 return done.PhiAt(0);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100863}
864
Ben Murdoch62ed6312017-06-06 11:06:27 +0100865Node* EffectControlLinearizer::LowerChangeInt31ToTaggedSigned(Node* node) {
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100866 Node* value = node->InputAt(0);
Ben Murdoch62ed6312017-06-06 11:06:27 +0100867 return ChangeInt32ToSmi(value);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100868}
869
Ben Murdoch62ed6312017-06-06 11:06:27 +0100870Node* EffectControlLinearizer::LowerChangeInt32ToTagged(Node* node) {
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100871 Node* value = node->InputAt(0);
872
873 if (machine()->Is64()) {
Ben Murdoch62ed6312017-06-06 11:06:27 +0100874 return ChangeInt32ToSmi(value);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100875 }
876
Ben Murdoch62ed6312017-06-06 11:06:27 +0100877 auto if_overflow = __ MakeDeferredLabel<1>();
878 auto done = __ MakeLabel<2>(MachineRepresentation::kTagged);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100879
Ben Murdoch62ed6312017-06-06 11:06:27 +0100880 Node* add = __ Int32AddWithOverflow(value, value);
881 Node* ovf = __ Projection(1, add);
882 __ GotoIf(ovf, &if_overflow);
883 __ Goto(&done, __ Projection(0, add));
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100884
Ben Murdoch62ed6312017-06-06 11:06:27 +0100885 __ Bind(&if_overflow);
886 Node* number = AllocateHeapNumberWithValue(__ ChangeInt32ToFloat64(value));
887 __ Goto(&done, number);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100888
Ben Murdoch62ed6312017-06-06 11:06:27 +0100889 __ Bind(&done);
890 return done.PhiAt(0);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100891}
892
Ben Murdoch62ed6312017-06-06 11:06:27 +0100893Node* EffectControlLinearizer::LowerChangeUint32ToTagged(Node* node) {
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100894 Node* value = node->InputAt(0);
895
Ben Murdoch62ed6312017-06-06 11:06:27 +0100896 auto if_not_in_smi_range = __ MakeDeferredLabel<1>();
897 auto done = __ MakeLabel<2>(MachineRepresentation::kTagged);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100898
Ben Murdoch62ed6312017-06-06 11:06:27 +0100899 Node* check = __ Uint32LessThanOrEqual(value, SmiMaxValueConstant());
900 __ GotoUnless(check, &if_not_in_smi_range);
901 __ Goto(&done, ChangeUint32ToSmi(value));
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100902
Ben Murdoch62ed6312017-06-06 11:06:27 +0100903 __ Bind(&if_not_in_smi_range);
904 Node* number = AllocateHeapNumberWithValue(__ ChangeUint32ToFloat64(value));
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100905
Ben Murdoch62ed6312017-06-06 11:06:27 +0100906 __ Goto(&done, number);
907 __ Bind(&done);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100908
Ben Murdoch62ed6312017-06-06 11:06:27 +0100909 return done.PhiAt(0);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100910}
911
Ben Murdoch62ed6312017-06-06 11:06:27 +0100912Node* EffectControlLinearizer::LowerChangeTaggedSignedToInt32(Node* node) {
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100913 Node* value = node->InputAt(0);
Ben Murdoch62ed6312017-06-06 11:06:27 +0100914 return ChangeSmiToInt32(value);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100915}
916
Ben Murdoch62ed6312017-06-06 11:06:27 +0100917Node* EffectControlLinearizer::LowerChangeTaggedToBit(Node* node) {
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100918 Node* value = node->InputAt(0);
Ben Murdoch62ed6312017-06-06 11:06:27 +0100919 return __ WordEqual(value, __ TrueConstant());
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100920}
921
Ben Murdoch62ed6312017-06-06 11:06:27 +0100922Node* EffectControlLinearizer::LowerTruncateTaggedToBit(Node* node) {
Ben Murdochf3b273f2017-01-17 12:11:28 +0000923 Node* value = node->InputAt(0);
Ben Murdochf3b273f2017-01-17 12:11:28 +0000924
Ben Murdoch62ed6312017-06-06 11:06:27 +0100925 auto if_smi = __ MakeDeferredLabel<1>();
926 auto if_heapnumber = __ MakeDeferredLabel<1>();
927 auto done = __ MakeLabel<6>(MachineRepresentation::kBit);
928
929 Node* zero = __ Int32Constant(0);
930 Node* fzero = __ Float64Constant(0.0);
931
932 // Check if {value} is false.
933 __ GotoIf(__ WordEqual(value, __ FalseConstant()), &done, zero);
Ben Murdochf3b273f2017-01-17 12:11:28 +0000934
935 // Check if {value} is a Smi.
936 Node* check_smi = ObjectIsSmi(value);
Ben Murdoch62ed6312017-06-06 11:06:27 +0100937 __ GotoIf(check_smi, &if_smi);
Ben Murdochf3b273f2017-01-17 12:11:28 +0000938
Ben Murdoch62ed6312017-06-06 11:06:27 +0100939 // Check if {value} is the empty string.
940 __ GotoIf(__ WordEqual(value, __ EmptyStringConstant()), &done, zero);
Ben Murdochf3b273f2017-01-17 12:11:28 +0000941
Ben Murdoch62ed6312017-06-06 11:06:27 +0100942 // Load the map of {value}.
943 Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
Ben Murdochf3b273f2017-01-17 12:11:28 +0000944
Ben Murdoch62ed6312017-06-06 11:06:27 +0100945 // Check if the {value} is undetectable and immediately return false.
946 Node* value_map_bitfield =
947 __ LoadField(AccessBuilder::ForMapBitField(), value_map);
948 __ GotoUnless(
949 __ Word32Equal(__ Word32And(value_map_bitfield,
950 __ Int32Constant(1 << Map::kIsUndetectable)),
951 zero),
952 &done, zero);
Ben Murdochf3b273f2017-01-17 12:11:28 +0000953
954 // Check if {value} is a HeapNumber.
Ben Murdoch62ed6312017-06-06 11:06:27 +0100955 __ GotoIf(__ WordEqual(value_map, __ HeapNumberMapConstant()),
956 &if_heapnumber);
Ben Murdochf3b273f2017-01-17 12:11:28 +0000957
Ben Murdoch62ed6312017-06-06 11:06:27 +0100958 // All other values that reach here are true.
959 __ Goto(&done, __ Int32Constant(1));
960
961 __ Bind(&if_heapnumber);
Ben Murdochf3b273f2017-01-17 12:11:28 +0000962 {
Ben Murdoch62ed6312017-06-06 11:06:27 +0100963 // For HeapNumber {value}, just check that its value is not 0.0, -0.0 or
964 // NaN.
965 Node* value_value =
966 __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
967 __ Goto(&done, __ Float64LessThan(fzero, __ Float64Abs(value_value)));
Ben Murdochf3b273f2017-01-17 12:11:28 +0000968 }
969
Ben Murdoch62ed6312017-06-06 11:06:27 +0100970 __ Bind(&if_smi);
971 {
972 // If {value} is a Smi, then we only need to check that it's not zero.
973 __ Goto(&done,
974 __ Word32Equal(__ WordEqual(value, __ IntPtrConstant(0)), zero));
975 }
Ben Murdochf3b273f2017-01-17 12:11:28 +0000976
Ben Murdoch62ed6312017-06-06 11:06:27 +0100977 __ Bind(&done);
978 return done.PhiAt(0);
Ben Murdochf3b273f2017-01-17 12:11:28 +0000979}
980
Ben Murdoch62ed6312017-06-06 11:06:27 +0100981Node* EffectControlLinearizer::LowerChangeTaggedToInt32(Node* node) {
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100982 Node* value = node->InputAt(0);
983
Ben Murdoch62ed6312017-06-06 11:06:27 +0100984 auto if_not_smi = __ MakeDeferredLabel<1>();
985 auto done = __ MakeLabel<2>(MachineRepresentation::kWord32);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100986
Ben Murdoch62ed6312017-06-06 11:06:27 +0100987 Node* check = ObjectIsSmi(value);
988 __ GotoUnless(check, &if_not_smi);
989 __ Goto(&done, ChangeSmiToInt32(value));
990
991 __ Bind(&if_not_smi);
992 STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
993 Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
994 vfalse = __ ChangeFloat64ToInt32(vfalse);
995 __ Goto(&done, vfalse);
996
997 __ Bind(&done);
998 return done.PhiAt(0);
999}
1000
1001Node* EffectControlLinearizer::LowerChangeTaggedToUint32(Node* node) {
1002 Node* value = node->InputAt(0);
1003
1004 auto if_not_smi = __ MakeDeferredLabel<1>();
1005 auto done = __ MakeLabel<2>(MachineRepresentation::kWord32);
1006
1007 Node* check = ObjectIsSmi(value);
1008 __ GotoUnless(check, &if_not_smi);
1009 __ Goto(&done, ChangeSmiToInt32(value));
1010
1011 __ Bind(&if_not_smi);
1012 STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
1013 Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
1014 vfalse = __ ChangeFloat64ToUint32(vfalse);
1015 __ Goto(&done, vfalse);
1016
1017 __ Bind(&done);
1018 return done.PhiAt(0);
1019}
1020
1021Node* EffectControlLinearizer::LowerChangeTaggedToFloat64(Node* node) {
1022 return LowerTruncateTaggedToFloat64(node);
1023}
1024
1025Node* EffectControlLinearizer::LowerChangeTaggedToTaggedSigned(Node* node) {
1026 Node* value = node->InputAt(0);
1027
1028 auto if_not_smi = __ MakeDeferredLabel<1>();
1029 auto done = __ MakeLabel<2>(MachineRepresentation::kWord32);
1030
1031 Node* check = ObjectIsSmi(value);
1032 __ GotoUnless(check, &if_not_smi);
1033 __ Goto(&done, value);
1034
1035 __ Bind(&if_not_smi);
1036 STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
1037 Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
1038 vfalse = __ ChangeFloat64ToInt32(vfalse);
1039 vfalse = ChangeInt32ToSmi(vfalse);
1040 __ Goto(&done, vfalse);
1041
1042 __ Bind(&done);
1043 return done.PhiAt(0);
1044}
1045
1046Node* EffectControlLinearizer::LowerTruncateTaggedToFloat64(Node* node) {
1047 Node* value = node->InputAt(0);
1048
1049 auto if_not_smi = __ MakeDeferredLabel<1>();
1050 auto done = __ MakeLabel<2>(MachineRepresentation::kFloat64);
1051
1052 Node* check = ObjectIsSmi(value);
1053 __ GotoUnless(check, &if_not_smi);
Ben Murdochbcf72ee2016-08-08 18:44:38 +01001054 Node* vtrue = ChangeSmiToInt32(value);
Ben Murdoch62ed6312017-06-06 11:06:27 +01001055 vtrue = __ ChangeInt32ToFloat64(vtrue);
1056 __ Goto(&done, vtrue);
Ben Murdochbcf72ee2016-08-08 18:44:38 +01001057
Ben Murdoch62ed6312017-06-06 11:06:27 +01001058 __ Bind(&if_not_smi);
1059 STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
1060 Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
1061 __ Goto(&done, vfalse);
Ben Murdochbcf72ee2016-08-08 18:44:38 +01001062
Ben Murdoch62ed6312017-06-06 11:06:27 +01001063 __ Bind(&done);
1064 return done.PhiAt(0);
Ben Murdochbcf72ee2016-08-08 18:44:38 +01001065}
1066
Ben Murdoch62ed6312017-06-06 11:06:27 +01001067Node* EffectControlLinearizer::LowerCheckBounds(Node* node, Node* frame_state) {
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001068 Node* index = node->InputAt(0);
1069 Node* limit = node->InputAt(1);
1070
Ben Murdoch62ed6312017-06-06 11:06:27 +01001071 Node* check = __ Uint32LessThan(index, limit);
1072 __ DeoptimizeUnless(DeoptimizeReason::kOutOfBounds, check, frame_state);
1073 return index;
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001074}
1075
Ben Murdoch62ed6312017-06-06 11:06:27 +01001076Node* EffectControlLinearizer::LowerCheckMaps(Node* node, Node* frame_state) {
1077 CheckMapsParameters const& p = CheckMapsParametersOf(node->op());
Ben Murdochf91f0612016-11-29 16:50:11 +00001078 Node* value = node->InputAt(0);
1079
Ben Murdoch62ed6312017-06-06 11:06:27 +01001080 ZoneHandleSet<Map> const& maps = p.maps();
1081 size_t const map_count = maps.size();
Ben Murdochf91f0612016-11-29 16:50:11 +00001082
Ben Murdoch62ed6312017-06-06 11:06:27 +01001083 if (p.flags() & CheckMapsFlag::kTryMigrateInstance) {
1084 auto done =
1085 __ MakeLabelFor(GraphAssemblerLabelType::kNonDeferred, map_count * 2);
1086 auto migrate = __ MakeDeferredLabel<1>();
Ben Murdochf91f0612016-11-29 16:50:11 +00001087
Ben Murdoch62ed6312017-06-06 11:06:27 +01001088 // Load the current map of the {value}.
1089 Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
Ben Murdochf91f0612016-11-29 16:50:11 +00001090
Ben Murdoch62ed6312017-06-06 11:06:27 +01001091 // Perform the map checks.
1092 for (size_t i = 0; i < map_count; ++i) {
1093 Node* map = __ HeapConstant(maps[i]);
1094 Node* check = __ WordEqual(value_map, map);
1095 if (i == map_count - 1) {
1096 __ GotoUnless(check, &migrate);
1097 __ Goto(&done);
1098 } else {
1099 __ GotoIf(check, &done);
1100 }
Ben Murdochf91f0612016-11-29 16:50:11 +00001101 }
Ben Murdoch62ed6312017-06-06 11:06:27 +01001102
1103 // Perform the (deferred) instance migration.
1104 __ Bind(&migrate);
1105 {
1106 // If map is not deprecated the migration attempt does not make sense.
1107 Node* bitfield3 =
1108 __ LoadField(AccessBuilder::ForMapBitField3(), value_map);
1109 Node* if_not_deprecated = __ WordEqual(
1110 __ Word32And(bitfield3, __ Int32Constant(Map::Deprecated::kMask)),
1111 __ Int32Constant(0));
1112 __ DeoptimizeIf(DeoptimizeReason::kWrongMap, if_not_deprecated,
1113 frame_state);
1114
1115 Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow;
1116 Runtime::FunctionId id = Runtime::kTryMigrateInstance;
1117 CallDescriptor const* desc = Linkage::GetRuntimeCallDescriptor(
1118 graph()->zone(), id, 1, properties, CallDescriptor::kNoFlags);
1119 Node* result =
1120 __ Call(desc, __ CEntryStubConstant(1), value,
1121 __ ExternalConstant(ExternalReference(id, isolate())),
1122 __ Int32Constant(1), __ NoContextConstant());
1123 Node* check = ObjectIsSmi(result);
1124 __ DeoptimizeIf(DeoptimizeReason::kInstanceMigrationFailed, check,
1125 frame_state);
1126 }
1127
1128 // Reload the current map of the {value}.
1129 value_map = __ LoadField(AccessBuilder::ForMap(), value);
1130
1131 // Perform the map checks again.
1132 for (size_t i = 0; i < map_count; ++i) {
1133 Node* map = __ HeapConstant(maps[i]);
1134 Node* check = __ WordEqual(value_map, map);
1135 if (i == map_count - 1) {
1136 __ DeoptimizeUnless(DeoptimizeReason::kWrongMap, check, frame_state);
1137 } else {
1138 __ GotoIf(check, &done);
1139 }
1140 }
1141
1142 __ Goto(&done);
1143 __ Bind(&done);
1144 } else {
1145 auto done =
1146 __ MakeLabelFor(GraphAssemblerLabelType::kNonDeferred, map_count);
1147
1148 // Load the current map of the {value}.
1149 Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
1150
1151 for (size_t i = 0; i < map_count; ++i) {
1152 Node* map = __ HeapConstant(maps[i]);
1153 Node* check = __ WordEqual(value_map, map);
1154 if (i == map_count - 1) {
1155 __ DeoptimizeUnless(DeoptimizeReason::kWrongMap, check, frame_state);
1156 } else {
1157 __ GotoIf(check, &done);
1158 }
1159 }
1160 __ Goto(&done);
1161 __ Bind(&done);
Ben Murdochf91f0612016-11-29 16:50:11 +00001162 }
Ben Murdoch62ed6312017-06-06 11:06:27 +01001163 return value;
Ben Murdochf91f0612016-11-29 16:50:11 +00001164}
1165
Ben Murdoch62ed6312017-06-06 11:06:27 +01001166Node* EffectControlLinearizer::LowerCheckNumber(Node* node, Node* frame_state) {
Ben Murdochf91f0612016-11-29 16:50:11 +00001167 Node* value = node->InputAt(0);
1168
Ben Murdoch62ed6312017-06-06 11:06:27 +01001169 auto if_not_smi = __ MakeDeferredLabel<1>();
1170 auto done = __ MakeLabel<2>();
1171
Ben Murdochf91f0612016-11-29 16:50:11 +00001172 Node* check0 = ObjectIsSmi(value);
Ben Murdoch62ed6312017-06-06 11:06:27 +01001173 __ GotoUnless(check0, &if_not_smi);
1174 __ Goto(&done);
Ben Murdochf91f0612016-11-29 16:50:11 +00001175
Ben Murdoch62ed6312017-06-06 11:06:27 +01001176 __ Bind(&if_not_smi);
1177 Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
1178 Node* check1 = __ WordEqual(value_map, __ HeapNumberMapConstant());
1179 __ DeoptimizeUnless(DeoptimizeReason::kNotAHeapNumber, check1, frame_state);
1180 __ Goto(&done);
Ben Murdochf91f0612016-11-29 16:50:11 +00001181
Ben Murdoch62ed6312017-06-06 11:06:27 +01001182 __ Bind(&done);
1183 return value;
Ben Murdochf91f0612016-11-29 16:50:11 +00001184}
1185
Ben Murdoch62ed6312017-06-06 11:06:27 +01001186Node* EffectControlLinearizer::LowerCheckReceiver(Node* node,
1187 Node* frame_state) {
Ben Murdochf91f0612016-11-29 16:50:11 +00001188 Node* value = node->InputAt(0);
1189
Ben Murdoch62ed6312017-06-06 11:06:27 +01001190 Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
1191 Node* value_instance_type =
1192 __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
Ben Murdochf91f0612016-11-29 16:50:11 +00001193
Ben Murdoch62ed6312017-06-06 11:06:27 +01001194 STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
1195 Node* check = __ Uint32LessThanOrEqual(
1196 __ Uint32Constant(FIRST_JS_RECEIVER_TYPE), value_instance_type);
1197 __ DeoptimizeUnless(DeoptimizeReason::kNotAJavaScriptObject, check,
1198 frame_state);
1199 return value;
Ben Murdochf91f0612016-11-29 16:50:11 +00001200}
1201
Ben Murdoch62ed6312017-06-06 11:06:27 +01001202Node* EffectControlLinearizer::LowerCheckString(Node* node, Node* frame_state) {
Ben Murdochf91f0612016-11-29 16:50:11 +00001203 Node* value = node->InputAt(0);
1204
Ben Murdoch62ed6312017-06-06 11:06:27 +01001205 Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
1206 Node* value_instance_type =
1207 __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
Ben Murdochf91f0612016-11-29 16:50:11 +00001208
Ben Murdoch62ed6312017-06-06 11:06:27 +01001209 Node* check = __ Uint32LessThan(value_instance_type,
1210 __ Uint32Constant(FIRST_NONSTRING_TYPE));
1211 __ DeoptimizeUnless(DeoptimizeReason::kWrongInstanceType, check, frame_state);
1212 return value;
Ben Murdochf91f0612016-11-29 16:50:11 +00001213}
1214
Ben Murdoch62ed6312017-06-06 11:06:27 +01001215Node* EffectControlLinearizer::LowerCheckInternalizedString(Node* node,
1216 Node* frame_state) {
1217 Node* value = node->InputAt(0);
1218
1219 Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
1220 Node* value_instance_type =
1221 __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
1222
1223 Node* check = __ Word32Equal(
1224 __ Word32And(value_instance_type,
1225 __ Int32Constant(kIsNotStringMask | kIsNotInternalizedMask)),
1226 __ Int32Constant(kInternalizedTag));
1227 __ DeoptimizeUnless(DeoptimizeReason::kWrongInstanceType, check, frame_state);
1228
1229 return value;
1230}
1231
1232Node* EffectControlLinearizer::LowerCheckIf(Node* node, Node* frame_state) {
1233 Node* value = node->InputAt(0);
1234 __ DeoptimizeUnless(DeoptimizeKind::kEager, DeoptimizeReason::kNoReason,
1235 value, frame_state);
1236 return value;
1237}
1238
1239Node* EffectControlLinearizer::LowerCheckedInt32Add(Node* node,
1240 Node* frame_state) {
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001241 Node* lhs = node->InputAt(0);
1242 Node* rhs = node->InputAt(1);
1243
Ben Murdoch62ed6312017-06-06 11:06:27 +01001244 Node* value = __ Int32AddWithOverflow(lhs, rhs);
1245 Node* check = __ Projection(1, value);
1246 __ DeoptimizeIf(DeoptimizeReason::kOverflow, check, frame_state);
1247 return __ Projection(0, value);
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001248}
1249
Ben Murdoch62ed6312017-06-06 11:06:27 +01001250Node* EffectControlLinearizer::LowerCheckedInt32Sub(Node* node,
1251 Node* frame_state) {
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001252 Node* lhs = node->InputAt(0);
1253 Node* rhs = node->InputAt(1);
1254
Ben Murdoch62ed6312017-06-06 11:06:27 +01001255 Node* value = __ Int32SubWithOverflow(lhs, rhs);
1256 Node* check = __ Projection(1, value);
1257 __ DeoptimizeIf(DeoptimizeReason::kOverflow, check, frame_state);
1258 return __ Projection(0, value);
Ben Murdochf91f0612016-11-29 16:50:11 +00001259}
1260
Ben Murdoch62ed6312017-06-06 11:06:27 +01001261Node* EffectControlLinearizer::LowerCheckedInt32Div(Node* node,
1262 Node* frame_state) {
Ben Murdochf91f0612016-11-29 16:50:11 +00001263 Node* lhs = node->InputAt(0);
1264 Node* rhs = node->InputAt(1);
1265
Ben Murdoch62ed6312017-06-06 11:06:27 +01001266 auto if_not_positive = __ MakeDeferredLabel<1>();
1267 auto if_is_minint = __ MakeDeferredLabel<1>();
1268 auto done = __ MakeLabel<2>(MachineRepresentation::kWord32);
1269 auto minint_check_done = __ MakeLabel<2>();
1270
1271 Node* zero = __ Int32Constant(0);
1272
Ben Murdochf91f0612016-11-29 16:50:11 +00001273 // Check if {rhs} is positive (and not zero).
Ben Murdoch62ed6312017-06-06 11:06:27 +01001274 Node* check0 = __ Int32LessThan(zero, rhs);
1275 __ GotoUnless(check0, &if_not_positive);
Ben Murdochf91f0612016-11-29 16:50:11 +00001276
Ben Murdoch62ed6312017-06-06 11:06:27 +01001277 // Fast case, no additional checking required.
1278 __ Goto(&done, __ Int32Div(lhs, rhs));
Ben Murdochf91f0612016-11-29 16:50:11 +00001279
Ben Murdochf91f0612016-11-29 16:50:11 +00001280 {
Ben Murdoch62ed6312017-06-06 11:06:27 +01001281 __ Bind(&if_not_positive);
1282
Ben Murdochf91f0612016-11-29 16:50:11 +00001283 // Check if {rhs} is zero.
Ben Murdoch62ed6312017-06-06 11:06:27 +01001284 Node* check = __ Word32Equal(rhs, zero);
1285 __ DeoptimizeIf(DeoptimizeReason::kDivisionByZero, check, frame_state);
Ben Murdochf91f0612016-11-29 16:50:11 +00001286
1287 // Check if {lhs} is zero, as that would produce minus zero.
Ben Murdoch62ed6312017-06-06 11:06:27 +01001288 check = __ Word32Equal(lhs, zero);
1289 __ DeoptimizeIf(DeoptimizeReason::kMinusZero, check, frame_state);
Ben Murdochf91f0612016-11-29 16:50:11 +00001290
1291 // Check if {lhs} is kMinInt and {rhs} is -1, in which case we'd have
1292 // to return -kMinInt, which is not representable.
Ben Murdoch62ed6312017-06-06 11:06:27 +01001293 Node* minint = __ Int32Constant(std::numeric_limits<int32_t>::min());
Ben Murdochf91f0612016-11-29 16:50:11 +00001294 Node* check1 = graph()->NewNode(machine()->Word32Equal(), lhs, minint);
Ben Murdoch62ed6312017-06-06 11:06:27 +01001295 __ GotoIf(check1, &if_is_minint);
1296 __ Goto(&minint_check_done);
Ben Murdochf91f0612016-11-29 16:50:11 +00001297
Ben Murdoch62ed6312017-06-06 11:06:27 +01001298 __ Bind(&if_is_minint);
1299 // Check if {rhs} is -1.
1300 Node* minusone = __ Int32Constant(-1);
1301 Node* is_minus_one = __ Word32Equal(rhs, minusone);
1302 __ DeoptimizeIf(DeoptimizeReason::kOverflow, is_minus_one, frame_state);
1303 __ Goto(&minint_check_done);
Ben Murdochf91f0612016-11-29 16:50:11 +00001304
Ben Murdoch62ed6312017-06-06 11:06:27 +01001305 __ Bind(&minint_check_done);
Ben Murdochf91f0612016-11-29 16:50:11 +00001306 // Perform the actual integer division.
Ben Murdoch62ed6312017-06-06 11:06:27 +01001307 __ Goto(&done, __ Int32Div(lhs, rhs));
Ben Murdochf91f0612016-11-29 16:50:11 +00001308 }
1309
Ben Murdoch62ed6312017-06-06 11:06:27 +01001310 __ Bind(&done);
1311 Node* value = done.PhiAt(0);
Ben Murdochf91f0612016-11-29 16:50:11 +00001312
1313 // Check if the remainder is non-zero.
Ben Murdoch62ed6312017-06-06 11:06:27 +01001314 Node* check = __ Word32Equal(lhs, __ Int32Mul(rhs, value));
1315 __ DeoptimizeUnless(DeoptimizeReason::kLostPrecision, check, frame_state);
Ben Murdochf91f0612016-11-29 16:50:11 +00001316
Ben Murdoch62ed6312017-06-06 11:06:27 +01001317 return value;
Ben Murdochf91f0612016-11-29 16:50:11 +00001318}
1319
Ben Murdoch62ed6312017-06-06 11:06:27 +01001320Node* EffectControlLinearizer::LowerCheckedInt32Mod(Node* node,
1321 Node* frame_state) {
Ben Murdochf91f0612016-11-29 16:50:11 +00001322 // General case for signed integer modulus, with optimization for (unknown)
1323 // power of 2 right hand side.
1324 //
1325 // if rhs <= 0 then
1326 // rhs = -rhs
1327 // deopt if rhs == 0
1328 // if lhs < 0 then
1329 // let res = lhs % rhs in
1330 // deopt if res == 0
1331 // res
1332 // else
1333 // let msk = rhs - 1 in
1334 // if rhs & msk == 0 then
1335 // lhs & msk
1336 // else
1337 // lhs % rhs
1338 //
1339 Node* lhs = node->InputAt(0);
1340 Node* rhs = node->InputAt(1);
1341
Ben Murdoch62ed6312017-06-06 11:06:27 +01001342 auto if_rhs_not_positive = __ MakeDeferredLabel<1>();
1343 auto if_lhs_negative = __ MakeDeferredLabel<1>();
1344 auto if_power_of_two = __ MakeLabel<1>();
1345 auto rhs_checked = __ MakeLabel<2>(MachineRepresentation::kWord32);
1346 auto done = __ MakeLabel<3>(MachineRepresentation::kWord32);
Ben Murdochf91f0612016-11-29 16:50:11 +00001347
Ben Murdoch62ed6312017-06-06 11:06:27 +01001348 Node* zero = __ Int32Constant(0);
1349
1350 // Check if {rhs} is not strictly positive.
1351 Node* check0 = __ Int32LessThanOrEqual(rhs, zero);
1352 __ GotoIf(check0, &if_rhs_not_positive);
1353 __ Goto(&rhs_checked, rhs);
1354
1355 __ Bind(&if_rhs_not_positive);
Ben Murdochf91f0612016-11-29 16:50:11 +00001356 {
1357 // Negate {rhs}, might still produce a negative result in case of
1358 // -2^31, but that is handled safely below.
Ben Murdoch62ed6312017-06-06 11:06:27 +01001359 Node* vtrue0 = __ Int32Sub(zero, rhs);
Ben Murdochf91f0612016-11-29 16:50:11 +00001360
1361 // Ensure that {rhs} is not zero, otherwise we'd have to return NaN.
Ben Murdoch62ed6312017-06-06 11:06:27 +01001362 Node* check = __ Word32Equal(vtrue0, zero);
1363 __ DeoptimizeIf(DeoptimizeReason::kDivisionByZero, check, frame_state);
1364 __ Goto(&rhs_checked, vtrue0);
Ben Murdochf91f0612016-11-29 16:50:11 +00001365 }
1366
Ben Murdoch62ed6312017-06-06 11:06:27 +01001367 __ Bind(&rhs_checked);
1368 rhs = rhs_checked.PhiAt(0);
Ben Murdochf91f0612016-11-29 16:50:11 +00001369
1370 // Check if {lhs} is negative.
Ben Murdoch62ed6312017-06-06 11:06:27 +01001371 Node* check1 = __ Int32LessThan(lhs, zero);
1372 __ GotoIf(check1, &if_lhs_negative);
Ben Murdochf91f0612016-11-29 16:50:11 +00001373
Ben Murdoch62ed6312017-06-06 11:06:27 +01001374 // {lhs} non-negative.
Ben Murdochf91f0612016-11-29 16:50:11 +00001375 {
Ben Murdoch62ed6312017-06-06 11:06:27 +01001376 Node* one = __ Int32Constant(1);
1377 Node* msk = __ Int32Sub(rhs, one);
Ben Murdochf91f0612016-11-29 16:50:11 +00001378
1379 // Check if {rhs} minus one is a valid mask.
Ben Murdoch62ed6312017-06-06 11:06:27 +01001380 Node* check2 = __ Word32Equal(__ Word32And(rhs, msk), zero);
1381 __ GotoIf(check2, &if_power_of_two);
Ben Murdochf91f0612016-11-29 16:50:11 +00001382 // Compute the remainder using the generic {lhs % rhs}.
Ben Murdoch62ed6312017-06-06 11:06:27 +01001383 __ Goto(&done, __ Int32Mod(lhs, rhs));
Ben Murdochf91f0612016-11-29 16:50:11 +00001384
Ben Murdoch62ed6312017-06-06 11:06:27 +01001385 __ Bind(&if_power_of_two);
1386 // Compute the remainder using {lhs & msk}.
1387 __ Goto(&done, __ Word32And(lhs, msk));
Ben Murdochf91f0612016-11-29 16:50:11 +00001388 }
1389
Ben Murdoch62ed6312017-06-06 11:06:27 +01001390 __ Bind(&if_lhs_negative);
1391 {
1392 // Compute the remainder using {lhs % msk}.
1393 Node* vtrue1 = __ Int32Mod(lhs, rhs);
Ben Murdochf91f0612016-11-29 16:50:11 +00001394
Ben Murdoch62ed6312017-06-06 11:06:27 +01001395 // Check if we would have to return -0.
1396 Node* check = __ Word32Equal(vtrue1, zero);
1397 __ DeoptimizeIf(DeoptimizeReason::kMinusZero, check, frame_state);
1398 __ Goto(&done, vtrue1);
1399 }
1400
1401 __ Bind(&done);
1402 return done.PhiAt(0);
Ben Murdochf91f0612016-11-29 16:50:11 +00001403}
1404
Ben Murdoch62ed6312017-06-06 11:06:27 +01001405Node* EffectControlLinearizer::LowerCheckedUint32Div(Node* node,
1406 Node* frame_state) {
Ben Murdochf91f0612016-11-29 16:50:11 +00001407 Node* lhs = node->InputAt(0);
1408 Node* rhs = node->InputAt(1);
1409
Ben Murdoch62ed6312017-06-06 11:06:27 +01001410 Node* zero = __ Int32Constant(0);
1411
Ben Murdochf91f0612016-11-29 16:50:11 +00001412 // Ensure that {rhs} is not zero, otherwise we'd have to return NaN.
Ben Murdoch62ed6312017-06-06 11:06:27 +01001413 Node* check = __ Word32Equal(rhs, zero);
1414 __ DeoptimizeIf(DeoptimizeReason::kDivisionByZero, check, frame_state);
Ben Murdochf91f0612016-11-29 16:50:11 +00001415
1416 // Perform the actual unsigned integer division.
Ben Murdoch62ed6312017-06-06 11:06:27 +01001417 Node* value = __ Uint32Div(lhs, rhs);
Ben Murdochf91f0612016-11-29 16:50:11 +00001418
1419 // Check if the remainder is non-zero.
Ben Murdoch62ed6312017-06-06 11:06:27 +01001420 check = __ Word32Equal(lhs, __ Int32Mul(rhs, value));
1421 __ DeoptimizeUnless(DeoptimizeReason::kLostPrecision, check, frame_state);
1422 return value;
Ben Murdochf91f0612016-11-29 16:50:11 +00001423}
1424
Ben Murdoch62ed6312017-06-06 11:06:27 +01001425Node* EffectControlLinearizer::LowerCheckedUint32Mod(Node* node,
1426 Node* frame_state) {
Ben Murdochf91f0612016-11-29 16:50:11 +00001427 Node* lhs = node->InputAt(0);
1428 Node* rhs = node->InputAt(1);
1429
Ben Murdoch62ed6312017-06-06 11:06:27 +01001430 Node* zero = __ Int32Constant(0);
1431
Ben Murdochf91f0612016-11-29 16:50:11 +00001432 // Ensure that {rhs} is not zero, otherwise we'd have to return NaN.
Ben Murdoch62ed6312017-06-06 11:06:27 +01001433 Node* check = __ Word32Equal(rhs, zero);
1434 __ DeoptimizeIf(DeoptimizeReason::kDivisionByZero, check, frame_state);
Ben Murdochf91f0612016-11-29 16:50:11 +00001435
1436 // Perform the actual unsigned integer modulus.
Ben Murdoch62ed6312017-06-06 11:06:27 +01001437 return __ Uint32Mod(lhs, rhs);
Ben Murdochf91f0612016-11-29 16:50:11 +00001438}
1439
Ben Murdoch62ed6312017-06-06 11:06:27 +01001440Node* EffectControlLinearizer::LowerCheckedInt32Mul(Node* node,
1441 Node* frame_state) {
Ben Murdochf91f0612016-11-29 16:50:11 +00001442 CheckForMinusZeroMode mode = CheckMinusZeroModeOf(node->op());
Ben Murdochf91f0612016-11-29 16:50:11 +00001443 Node* lhs = node->InputAt(0);
1444 Node* rhs = node->InputAt(1);
1445
Ben Murdoch62ed6312017-06-06 11:06:27 +01001446 Node* projection = __ Int32MulWithOverflow(lhs, rhs);
1447 Node* check = __ Projection(1, projection);
1448 __ DeoptimizeIf(DeoptimizeReason::kOverflow, check, frame_state);
Ben Murdochf91f0612016-11-29 16:50:11 +00001449
Ben Murdoch62ed6312017-06-06 11:06:27 +01001450 Node* value = __ Projection(0, projection);
Ben Murdochf91f0612016-11-29 16:50:11 +00001451
1452 if (mode == CheckForMinusZeroMode::kCheckForMinusZero) {
Ben Murdoch62ed6312017-06-06 11:06:27 +01001453 auto if_zero = __ MakeDeferredLabel<1>();
1454 auto check_done = __ MakeLabel<2>();
1455 Node* zero = __ Int32Constant(0);
1456 Node* check_zero = __ Word32Equal(value, zero);
1457 __ GotoIf(check_zero, &if_zero);
1458 __ Goto(&check_done);
Ben Murdochf91f0612016-11-29 16:50:11 +00001459
Ben Murdoch62ed6312017-06-06 11:06:27 +01001460 __ Bind(&if_zero);
1461 // We may need to return negative zero.
1462 Node* check_or = __ Int32LessThan(__ Word32Or(lhs, rhs), zero);
1463 __ DeoptimizeIf(DeoptimizeReason::kMinusZero, check_or, frame_state);
1464 __ Goto(&check_done);
Ben Murdochf91f0612016-11-29 16:50:11 +00001465
Ben Murdoch62ed6312017-06-06 11:06:27 +01001466 __ Bind(&check_done);
Ben Murdochf91f0612016-11-29 16:50:11 +00001467 }
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001468
Ben Murdoch62ed6312017-06-06 11:06:27 +01001469 return value;
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001470}
1471
Ben Murdoch62ed6312017-06-06 11:06:27 +01001472Node* EffectControlLinearizer::LowerCheckedInt32ToTaggedSigned(
1473 Node* node, Node* frame_state) {
Ben Murdochf3b273f2017-01-17 12:11:28 +00001474 DCHECK(SmiValuesAre31Bits());
1475 Node* value = node->InputAt(0);
1476
Ben Murdoch62ed6312017-06-06 11:06:27 +01001477 Node* add = __ Int32AddWithOverflow(value, value);
1478 Node* check = __ Projection(1, add);
1479 __ DeoptimizeIf(DeoptimizeReason::kOverflow, check, frame_state);
1480 return __ Projection(0, add);
Ben Murdochf3b273f2017-01-17 12:11:28 +00001481}
1482
Ben Murdoch62ed6312017-06-06 11:06:27 +01001483Node* EffectControlLinearizer::LowerCheckedUint32ToInt32(Node* node,
1484 Node* frame_state) {
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001485 Node* value = node->InputAt(0);
Ben Murdoch62ed6312017-06-06 11:06:27 +01001486 Node* max_int = __ Int32Constant(std::numeric_limits<int32_t>::max());
1487 Node* is_safe = __ Uint32LessThanOrEqual(value, max_int);
1488 __ DeoptimizeUnless(DeoptimizeReason::kLostPrecision, is_safe, frame_state);
1489 return value;
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001490}
1491
Ben Murdoch62ed6312017-06-06 11:06:27 +01001492Node* EffectControlLinearizer::LowerCheckedUint32ToTaggedSigned(
1493 Node* node, Node* frame_state) {
Ben Murdochf3b273f2017-01-17 12:11:28 +00001494 Node* value = node->InputAt(0);
Ben Murdoch62ed6312017-06-06 11:06:27 +01001495 Node* check = __ Uint32LessThanOrEqual(value, SmiMaxValueConstant());
1496 __ DeoptimizeUnless(DeoptimizeReason::kLostPrecision, check, frame_state);
1497 return ChangeUint32ToSmi(value);
Ben Murdochf3b273f2017-01-17 12:11:28 +00001498}
1499
Ben Murdoch62ed6312017-06-06 11:06:27 +01001500Node* EffectControlLinearizer::BuildCheckedFloat64ToInt32(
1501 CheckForMinusZeroMode mode, Node* value, Node* frame_state) {
1502 Node* value32 = __ RoundFloat64ToInt32(value);
1503 Node* check_same = __ Float64Equal(value, __ ChangeInt32ToFloat64(value32));
1504 __ DeoptimizeUnless(DeoptimizeReason::kLostPrecisionOrNaN, check_same,
1505 frame_state);
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001506
Ben Murdochf91f0612016-11-29 16:50:11 +00001507 if (mode == CheckForMinusZeroMode::kCheckForMinusZero) {
1508 // Check if {value} is -0.
Ben Murdoch62ed6312017-06-06 11:06:27 +01001509 auto if_zero = __ MakeDeferredLabel<1>();
1510 auto check_done = __ MakeLabel<2>();
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001511
Ben Murdoch62ed6312017-06-06 11:06:27 +01001512 Node* check_zero = __ Word32Equal(value32, __ Int32Constant(0));
1513 __ GotoIf(check_zero, &if_zero);
1514 __ Goto(&check_done);
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001515
Ben Murdoch62ed6312017-06-06 11:06:27 +01001516 __ Bind(&if_zero);
Ben Murdochf91f0612016-11-29 16:50:11 +00001517 // In case of 0, we need to check the high bits for the IEEE -0 pattern.
Ben Murdoch62ed6312017-06-06 11:06:27 +01001518 Node* check_negative = __ Int32LessThan(__ Float64ExtractHighWord32(value),
1519 __ Int32Constant(0));
1520 __ DeoptimizeIf(DeoptimizeReason::kMinusZero, check_negative, frame_state);
1521 __ Goto(&check_done);
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001522
Ben Murdoch62ed6312017-06-06 11:06:27 +01001523 __ Bind(&check_done);
Ben Murdochf91f0612016-11-29 16:50:11 +00001524 }
Ben Murdoch62ed6312017-06-06 11:06:27 +01001525 return value32;
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001526}
1527
Ben Murdoch62ed6312017-06-06 11:06:27 +01001528Node* EffectControlLinearizer::LowerCheckedFloat64ToInt32(Node* node,
1529 Node* frame_state) {
1530 CheckForMinusZeroMode mode = CheckMinusZeroModeOf(node->op());
1531 Node* value = node->InputAt(0);
1532 return BuildCheckedFloat64ToInt32(mode, value, frame_state);
1533}
1534
1535Node* EffectControlLinearizer::LowerCheckedTaggedSignedToInt32(
1536 Node* node, Node* frame_state) {
1537 Node* value = node->InputAt(0);
1538 Node* check = ObjectIsSmi(value);
1539 __ DeoptimizeUnless(DeoptimizeReason::kNotASmi, check, frame_state);
1540 return ChangeSmiToInt32(value);
1541}
1542
1543Node* EffectControlLinearizer::LowerCheckedTaggedToInt32(Node* node,
1544 Node* frame_state) {
Ben Murdochf91f0612016-11-29 16:50:11 +00001545 CheckForMinusZeroMode mode = CheckMinusZeroModeOf(node->op());
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001546 Node* value = node->InputAt(0);
1547
Ben Murdoch62ed6312017-06-06 11:06:27 +01001548 auto if_not_smi = __ MakeDeferredLabel<1>();
1549 auto done = __ MakeLabel<2>(MachineRepresentation::kWord32);
Ben Murdochf91f0612016-11-29 16:50:11 +00001550
1551 Node* check = ObjectIsSmi(value);
Ben Murdoch62ed6312017-06-06 11:06:27 +01001552 __ GotoUnless(check, &if_not_smi);
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001553 // In the Smi case, just convert to int32.
Ben Murdoch62ed6312017-06-06 11:06:27 +01001554 __ Goto(&done, ChangeSmiToInt32(value));
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001555
1556 // In the non-Smi case, check the heap numberness, load the number and convert
1557 // to int32.
Ben Murdoch62ed6312017-06-06 11:06:27 +01001558 __ Bind(&if_not_smi);
1559 Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
1560 Node* check_map = __ WordEqual(value_map, __ HeapNumberMapConstant());
1561 __ DeoptimizeUnless(DeoptimizeReason::kNotAHeapNumber, check_map,
1562 frame_state);
1563 Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
1564 vfalse = BuildCheckedFloat64ToInt32(mode, vfalse, frame_state);
1565 __ Goto(&done, vfalse);
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001566
Ben Murdoch62ed6312017-06-06 11:06:27 +01001567 __ Bind(&done);
1568 return done.PhiAt(0);
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001569}
1570
Ben Murdoch62ed6312017-06-06 11:06:27 +01001571Node* EffectControlLinearizer::BuildCheckedHeapNumberOrOddballToFloat64(
1572 CheckTaggedInputMode mode, Node* value, Node* frame_state) {
1573 Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
1574 Node* check_number = __ WordEqual(value_map, __ HeapNumberMapConstant());
Ben Murdochf91f0612016-11-29 16:50:11 +00001575 switch (mode) {
1576 case CheckTaggedInputMode::kNumber: {
Ben Murdoch62ed6312017-06-06 11:06:27 +01001577 __ DeoptimizeUnless(DeoptimizeReason::kNotAHeapNumber, check_number,
1578 frame_state);
Ben Murdochf91f0612016-11-29 16:50:11 +00001579 break;
1580 }
1581 case CheckTaggedInputMode::kNumberOrOddball: {
Ben Murdoch62ed6312017-06-06 11:06:27 +01001582 auto check_done = __ MakeLabel<2>();
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001583
Ben Murdoch62ed6312017-06-06 11:06:27 +01001584 __ GotoIf(check_number, &check_done);
Ben Murdochf91f0612016-11-29 16:50:11 +00001585 // For oddballs also contain the numeric value, let us just check that
1586 // we have an oddball here.
Ben Murdoch62ed6312017-06-06 11:06:27 +01001587 Node* instance_type =
1588 __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
Ben Murdochf91f0612016-11-29 16:50:11 +00001589 Node* check_oddball =
Ben Murdoch62ed6312017-06-06 11:06:27 +01001590 __ Word32Equal(instance_type, __ Int32Constant(ODDBALL_TYPE));
1591 __ DeoptimizeUnless(DeoptimizeReason::kNotANumberOrOddball, check_oddball,
1592 frame_state);
Ben Murdochf91f0612016-11-29 16:50:11 +00001593 STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
Ben Murdoch62ed6312017-06-06 11:06:27 +01001594 __ Goto(&check_done);
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001595
Ben Murdoch62ed6312017-06-06 11:06:27 +01001596 __ Bind(&check_done);
Ben Murdochf91f0612016-11-29 16:50:11 +00001597 break;
1598 }
1599 }
Ben Murdoch62ed6312017-06-06 11:06:27 +01001600 return __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001601}
1602
Ben Murdoch62ed6312017-06-06 11:06:27 +01001603Node* EffectControlLinearizer::LowerCheckedTaggedToFloat64(Node* node,
1604 Node* frame_state) {
Ben Murdochf91f0612016-11-29 16:50:11 +00001605 CheckTaggedInputMode mode = CheckTaggedInputModeOf(node->op());
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001606 Node* value = node->InputAt(0);
1607
Ben Murdoch62ed6312017-06-06 11:06:27 +01001608 auto if_smi = __ MakeLabel<1>();
1609 auto done = __ MakeLabel<2>(MachineRepresentation::kFloat64);
1610
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001611 Node* check = ObjectIsSmi(value);
Ben Murdoch62ed6312017-06-06 11:06:27 +01001612 __ GotoIf(check, &if_smi);
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001613
1614 // In the Smi case, just convert to int32 and then float64.
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001615 // Otherwise, check heap numberness and load the number.
Ben Murdoch62ed6312017-06-06 11:06:27 +01001616 Node* number =
1617 BuildCheckedHeapNumberOrOddballToFloat64(mode, value, frame_state);
1618 __ Goto(&done, number);
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001619
Ben Murdoch62ed6312017-06-06 11:06:27 +01001620 __ Bind(&if_smi);
1621 Node* from_smi = ChangeSmiToInt32(value);
1622 from_smi = __ ChangeInt32ToFloat64(from_smi);
1623 __ Goto(&done, from_smi);
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001624
Ben Murdoch62ed6312017-06-06 11:06:27 +01001625 __ Bind(&done);
1626 return done.PhiAt(0);
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001627}
1628
Ben Murdoch62ed6312017-06-06 11:06:27 +01001629Node* EffectControlLinearizer::LowerCheckedTaggedToTaggedSigned(
1630 Node* node, Node* frame_state) {
Ben Murdochf3b273f2017-01-17 12:11:28 +00001631 Node* value = node->InputAt(0);
1632
1633 Node* check = ObjectIsSmi(value);
Ben Murdoch62ed6312017-06-06 11:06:27 +01001634 __ DeoptimizeUnless(DeoptimizeReason::kNotASmi, check, frame_state);
Ben Murdochf3b273f2017-01-17 12:11:28 +00001635
Ben Murdoch62ed6312017-06-06 11:06:27 +01001636 return value;
Ben Murdochf3b273f2017-01-17 12:11:28 +00001637}
1638
Ben Murdoch62ed6312017-06-06 11:06:27 +01001639Node* EffectControlLinearizer::LowerCheckedTaggedToTaggedPointer(
1640 Node* node, Node* frame_state) {
Ben Murdochc8c1d9e2017-03-08 14:04:23 +00001641 Node* value = node->InputAt(0);
1642
1643 Node* check = ObjectIsSmi(value);
Ben Murdoch62ed6312017-06-06 11:06:27 +01001644 __ DeoptimizeIf(DeoptimizeReason::kSmi, check, frame_state);
1645 return value;
Ben Murdochc8c1d9e2017-03-08 14:04:23 +00001646}
1647
Ben Murdoch62ed6312017-06-06 11:06:27 +01001648Node* EffectControlLinearizer::LowerTruncateTaggedToWord32(Node* node) {
Ben Murdochbcf72ee2016-08-08 18:44:38 +01001649 Node* value = node->InputAt(0);
1650
Ben Murdoch62ed6312017-06-06 11:06:27 +01001651 auto if_not_smi = __ MakeDeferredLabel<1>();
1652 auto done = __ MakeLabel<2>(MachineRepresentation::kWord32);
1653
Ben Murdochbcf72ee2016-08-08 18:44:38 +01001654 Node* check = ObjectIsSmi(value);
Ben Murdoch62ed6312017-06-06 11:06:27 +01001655 __ GotoUnless(check, &if_not_smi);
1656 __ Goto(&done, ChangeSmiToInt32(value));
Ben Murdochbcf72ee2016-08-08 18:44:38 +01001657
Ben Murdoch62ed6312017-06-06 11:06:27 +01001658 __ Bind(&if_not_smi);
1659 STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
1660 Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
1661 vfalse = __ TruncateFloat64ToWord32(vfalse);
1662 __ Goto(&done, vfalse);
Ben Murdochbcf72ee2016-08-08 18:44:38 +01001663
Ben Murdoch62ed6312017-06-06 11:06:27 +01001664 __ Bind(&done);
1665 return done.PhiAt(0);
Ben Murdochbcf72ee2016-08-08 18:44:38 +01001666}
1667
Ben Murdoch62ed6312017-06-06 11:06:27 +01001668Node* EffectControlLinearizer::LowerCheckedTruncateTaggedToWord32(
1669 Node* node, Node* frame_state) {
Ben Murdochf91f0612016-11-29 16:50:11 +00001670 Node* value = node->InputAt(0);
1671
Ben Murdoch62ed6312017-06-06 11:06:27 +01001672 auto if_not_smi = __ MakeLabel<1>();
1673 auto done = __ MakeLabel<2>(MachineRepresentation::kWord32);
Ben Murdochf91f0612016-11-29 16:50:11 +00001674
Ben Murdoch62ed6312017-06-06 11:06:27 +01001675 Node* check = ObjectIsSmi(value);
1676 __ GotoUnless(check, &if_not_smi);
Ben Murdochf91f0612016-11-29 16:50:11 +00001677 // In the Smi case, just convert to int32.
Ben Murdoch62ed6312017-06-06 11:06:27 +01001678 __ Goto(&done, ChangeSmiToInt32(value));
Ben Murdochf91f0612016-11-29 16:50:11 +00001679
1680 // Otherwise, check that it's a heap number or oddball and truncate the value
1681 // to int32.
Ben Murdoch62ed6312017-06-06 11:06:27 +01001682 __ Bind(&if_not_smi);
1683 Node* number = BuildCheckedHeapNumberOrOddballToFloat64(
1684 CheckTaggedInputMode::kNumberOrOddball, value, frame_state);
1685 number = __ TruncateFloat64ToWord32(number);
1686 __ Goto(&done, number);
Ben Murdochf91f0612016-11-29 16:50:11 +00001687
Ben Murdoch62ed6312017-06-06 11:06:27 +01001688 __ Bind(&done);
1689 return done.PhiAt(0);
Ben Murdochf91f0612016-11-29 16:50:11 +00001690}
1691
Ben Murdoch62ed6312017-06-06 11:06:27 +01001692Node* EffectControlLinearizer::LowerObjectIsDetectableCallable(Node* node) {
Ben Murdochbcf72ee2016-08-08 18:44:38 +01001693 Node* value = node->InputAt(0);
1694
Ben Murdoch62ed6312017-06-06 11:06:27 +01001695 auto if_smi = __ MakeDeferredLabel<1>();
1696 auto done = __ MakeLabel<2>(MachineRepresentation::kBit);
1697
Ben Murdochbcf72ee2016-08-08 18:44:38 +01001698 Node* check = ObjectIsSmi(value);
Ben Murdoch62ed6312017-06-06 11:06:27 +01001699 __ GotoIf(check, &if_smi);
Ben Murdochbcf72ee2016-08-08 18:44:38 +01001700
Ben Murdoch62ed6312017-06-06 11:06:27 +01001701 Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
1702 Node* value_bit_field =
1703 __ LoadField(AccessBuilder::ForMapBitField(), value_map);
1704 Node* vfalse = __ Word32Equal(
1705 __ Int32Constant(1 << Map::kIsCallable),
1706 __ Word32And(value_bit_field,
1707 __ Int32Constant((1 << Map::kIsCallable) |
1708 (1 << Map::kIsUndetectable))));
1709 __ Goto(&done, vfalse);
Ben Murdochbcf72ee2016-08-08 18:44:38 +01001710
Ben Murdoch62ed6312017-06-06 11:06:27 +01001711 __ Bind(&if_smi);
1712 __ Goto(&done, __ Int32Constant(0));
Ben Murdochbcf72ee2016-08-08 18:44:38 +01001713
Ben Murdoch62ed6312017-06-06 11:06:27 +01001714 __ Bind(&done);
1715 return done.PhiAt(0);
Ben Murdochbcf72ee2016-08-08 18:44:38 +01001716}
1717
Ben Murdoch62ed6312017-06-06 11:06:27 +01001718Node* EffectControlLinearizer::LowerObjectIsNonCallable(Node* node) {
Ben Murdochbcf72ee2016-08-08 18:44:38 +01001719 Node* value = node->InputAt(0);
1720
Ben Murdoch62ed6312017-06-06 11:06:27 +01001721 auto if_primitive = __ MakeDeferredLabel<2>();
1722 auto done = __ MakeLabel<2>(MachineRepresentation::kBit);
1723
1724 Node* check0 = ObjectIsSmi(value);
1725 __ GotoIf(check0, &if_primitive);
1726
1727 Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
1728 Node* value_instance_type =
1729 __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
1730 STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
1731 Node* check1 = __ Uint32LessThanOrEqual(
1732 __ Uint32Constant(FIRST_JS_RECEIVER_TYPE), value_instance_type);
1733 __ GotoUnless(check1, &if_primitive);
1734
1735 Node* value_bit_field =
1736 __ LoadField(AccessBuilder::ForMapBitField(), value_map);
1737 Node* check2 = __ Word32Equal(
1738 __ Int32Constant(0),
1739 __ Word32And(value_bit_field, __ Int32Constant(1 << Map::kIsCallable)));
1740 __ Goto(&done, check2);
1741
1742 __ Bind(&if_primitive);
1743 __ Goto(&done, __ Int32Constant(0));
1744
1745 __ Bind(&done);
1746 return done.PhiAt(0);
1747}
1748
1749Node* EffectControlLinearizer::LowerObjectIsNumber(Node* node) {
1750 Node* value = node->InputAt(0);
1751
1752 auto if_smi = __ MakeLabel<1>();
1753 auto done = __ MakeLabel<2>(MachineRepresentation::kBit);
1754
1755 __ GotoIf(ObjectIsSmi(value), &if_smi);
1756 Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
1757 __ Goto(&done, __ WordEqual(value_map, __ HeapNumberMapConstant()));
1758
1759 __ Bind(&if_smi);
1760 __ Goto(&done, __ Int32Constant(1));
1761
1762 __ Bind(&done);
1763 return done.PhiAt(0);
1764}
1765
1766Node* EffectControlLinearizer::LowerObjectIsReceiver(Node* node) {
1767 Node* value = node->InputAt(0);
1768
1769 auto if_smi = __ MakeDeferredLabel<1>();
1770 auto done = __ MakeLabel<2>(MachineRepresentation::kBit);
1771
1772 __ GotoIf(ObjectIsSmi(value), &if_smi);
1773
1774 STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
1775 Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
1776 Node* value_instance_type =
1777 __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
1778 Node* result = __ Uint32LessThanOrEqual(
1779 __ Uint32Constant(FIRST_JS_RECEIVER_TYPE), value_instance_type);
1780 __ Goto(&done, result);
1781
1782 __ Bind(&if_smi);
1783 __ Goto(&done, __ Int32Constant(0));
1784
1785 __ Bind(&done);
1786 return done.PhiAt(0);
1787}
1788
1789Node* EffectControlLinearizer::LowerObjectIsSmi(Node* node) {
1790 Node* value = node->InputAt(0);
1791 return ObjectIsSmi(value);
1792}
1793
1794Node* EffectControlLinearizer::LowerObjectIsString(Node* node) {
1795 Node* value = node->InputAt(0);
1796
1797 auto if_smi = __ MakeDeferredLabel<1>();
1798 auto done = __ MakeLabel<2>(MachineRepresentation::kBit);
1799
Ben Murdochbcf72ee2016-08-08 18:44:38 +01001800 Node* check = ObjectIsSmi(value);
Ben Murdoch62ed6312017-06-06 11:06:27 +01001801 __ GotoIf(check, &if_smi);
1802 Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
1803 Node* value_instance_type =
1804 __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
1805 Node* vfalse = __ Uint32LessThan(value_instance_type,
1806 __ Uint32Constant(FIRST_NONSTRING_TYPE));
1807 __ Goto(&done, vfalse);
Ben Murdochbcf72ee2016-08-08 18:44:38 +01001808
Ben Murdoch62ed6312017-06-06 11:06:27 +01001809 __ Bind(&if_smi);
1810 __ Goto(&done, __ Int32Constant(0));
Ben Murdochbcf72ee2016-08-08 18:44:38 +01001811
Ben Murdoch62ed6312017-06-06 11:06:27 +01001812 __ Bind(&done);
1813 return done.PhiAt(0);
Ben Murdochbcf72ee2016-08-08 18:44:38 +01001814}
1815
Ben Murdoch62ed6312017-06-06 11:06:27 +01001816Node* EffectControlLinearizer::LowerObjectIsUndetectable(Node* node) {
Ben Murdochbcf72ee2016-08-08 18:44:38 +01001817 Node* value = node->InputAt(0);
1818
Ben Murdoch62ed6312017-06-06 11:06:27 +01001819 auto if_smi = __ MakeDeferredLabel<1>();
1820 auto done = __ MakeLabel<2>(MachineRepresentation::kBit);
1821
Ben Murdochbcf72ee2016-08-08 18:44:38 +01001822 Node* check = ObjectIsSmi(value);
Ben Murdoch62ed6312017-06-06 11:06:27 +01001823 __ GotoIf(check, &if_smi);
Ben Murdochbcf72ee2016-08-08 18:44:38 +01001824
Ben Murdoch62ed6312017-06-06 11:06:27 +01001825 Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
1826 Node* value_bit_field =
1827 __ LoadField(AccessBuilder::ForMapBitField(), value_map);
1828 Node* vfalse = __ Word32Equal(
1829 __ Word32Equal(__ Int32Constant(0),
1830 __ Word32And(value_bit_field,
1831 __ Int32Constant(1 << Map::kIsUndetectable))),
1832 __ Int32Constant(0));
1833 __ Goto(&done, vfalse);
Ben Murdochbcf72ee2016-08-08 18:44:38 +01001834
Ben Murdoch62ed6312017-06-06 11:06:27 +01001835 __ Bind(&if_smi);
1836 __ Goto(&done, __ Int32Constant(0));
Ben Murdochbcf72ee2016-08-08 18:44:38 +01001837
Ben Murdoch62ed6312017-06-06 11:06:27 +01001838 __ Bind(&done);
1839 return done.PhiAt(0);
Ben Murdochbcf72ee2016-08-08 18:44:38 +01001840}
1841
Ben Murdoch62ed6312017-06-06 11:06:27 +01001842Node* EffectControlLinearizer::LowerNewRestParameterElements(Node* node) {
1843 int const formal_parameter_count = ParameterCountOf(node->op());
1844
1845 Callable const callable = CodeFactory::NewRestParameterElements(isolate());
1846 Operator::Properties const properties = node->op()->properties();
1847 CallDescriptor::Flags const flags = CallDescriptor::kNoFlags;
1848 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
1849 isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties);
1850 return __ Call(desc, __ HeapConstant(callable.code()),
1851 __ IntPtrConstant(formal_parameter_count),
1852 __ NoContextConstant());
Ben Murdochbcf72ee2016-08-08 18:44:38 +01001853}
1854
Ben Murdoch62ed6312017-06-06 11:06:27 +01001855Node* EffectControlLinearizer::LowerNewUnmappedArgumentsElements(Node* node) {
1856 int const formal_parameter_count = ParameterCountOf(node->op());
1857
1858 Callable const callable =
1859 CodeFactory::NewUnmappedArgumentsElements(isolate());
1860 Operator::Properties const properties = node->op()->properties();
1861 CallDescriptor::Flags const flags = CallDescriptor::kNoFlags;
1862 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
1863 isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties);
1864 return __ Call(desc, __ HeapConstant(callable.code()),
1865 __ IntPtrConstant(formal_parameter_count),
1866 __ NoContextConstant());
1867}
1868
1869Node* EffectControlLinearizer::LowerArrayBufferWasNeutered(Node* node) {
Ben Murdochbcf72ee2016-08-08 18:44:38 +01001870 Node* value = node->InputAt(0);
1871
Ben Murdoch62ed6312017-06-06 11:06:27 +01001872 Node* value_bit_field =
1873 __ LoadField(AccessBuilder::ForJSArrayBufferBitField(), value);
1874 return __ Word32Equal(
1875 __ Word32Equal(
1876 __ Word32And(value_bit_field,
1877 __ Int32Constant(JSArrayBuffer::WasNeutered::kMask)),
1878 __ Int32Constant(0)),
1879 __ Int32Constant(0));
Ben Murdochbcf72ee2016-08-08 18:44:38 +01001880}
1881
Ben Murdoch62ed6312017-06-06 11:06:27 +01001882Node* EffectControlLinearizer::LowerStringCharAt(Node* node) {
1883 Node* receiver = node->InputAt(0);
1884 Node* position = node->InputAt(1);
1885
1886 Callable const callable = CodeFactory::StringCharAt(isolate());
1887 Operator::Properties properties = Operator::kNoThrow | Operator::kNoWrite;
1888 CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
1889 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
1890 isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties);
1891 return __ Call(desc, __ HeapConstant(callable.code()), receiver, position,
1892 __ NoContextConstant());
1893}
1894
1895Node* EffectControlLinearizer::LowerStringCharCodeAt(Node* node) {
1896 Node* receiver = node->InputAt(0);
1897 Node* position = node->InputAt(1);
1898
1899 Callable const callable = CodeFactory::StringCharCodeAt(isolate());
1900 Operator::Properties properties = Operator::kNoThrow | Operator::kNoWrite;
1901 CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
1902 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
1903 isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties,
1904 MachineType::TaggedSigned());
1905 return __ Call(desc, __ HeapConstant(callable.code()), receiver, position,
1906 __ NoContextConstant());
1907}
1908
1909Node* EffectControlLinearizer::LowerStringFromCharCode(Node* node) {
Ben Murdochbcf72ee2016-08-08 18:44:38 +01001910 Node* value = node->InputAt(0);
1911
Ben Murdoch62ed6312017-06-06 11:06:27 +01001912 auto runtime_call = __ MakeDeferredLabel<2>();
1913 auto if_undefined = __ MakeDeferredLabel<1>();
1914 auto done = __ MakeLabel<2>(MachineRepresentation::kTagged);
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001915
1916 // Compute the character code.
Ben Murdoch62ed6312017-06-06 11:06:27 +01001917 Node* code = __ Word32And(value, __ Int32Constant(String::kMaxUtf16CodeUnit));
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001918
1919 // Check if the {code} is a one-byte char code.
Ben Murdoch62ed6312017-06-06 11:06:27 +01001920 Node* check0 = __ Int32LessThanOrEqual(
1921 code, __ Int32Constant(String::kMaxOneByteCharCode));
1922 __ GotoUnless(check0, &runtime_call);
Ben Murdochc8c1d9e2017-03-08 14:04:23 +00001923
1924 // Load the isolate wide single character string cache.
Ben Murdoch62ed6312017-06-06 11:06:27 +01001925 Node* cache = __ HeapConstant(factory()->single_character_string_cache());
Ben Murdochc8c1d9e2017-03-08 14:04:23 +00001926
1927 // Compute the {cache} index for {code}.
Ben Murdoch62ed6312017-06-06 11:06:27 +01001928 Node* index = machine()->Is32() ? code : __ ChangeUint32ToUint64(code);
Ben Murdochc8c1d9e2017-03-08 14:04:23 +00001929
1930 // Check if we have an entry for the {code} in the single character string
1931 // cache already.
Ben Murdoch62ed6312017-06-06 11:06:27 +01001932 Node* entry =
1933 __ LoadElement(AccessBuilder::ForFixedArrayElement(), cache, index);
Ben Murdochc8c1d9e2017-03-08 14:04:23 +00001934
Ben Murdoch62ed6312017-06-06 11:06:27 +01001935 Node* check1 = __ WordEqual(entry, __ UndefinedConstant());
1936 __ GotoIf(check1, &runtime_call);
1937 __ Goto(&done, entry);
Ben Murdochc8c1d9e2017-03-08 14:04:23 +00001938
1939 // Let %StringFromCharCode handle this case.
1940 // TODO(turbofan): At some point we may consider adding a stub for this
1941 // deferred case, so that we don't need to call to C++ here.
Ben Murdoch62ed6312017-06-06 11:06:27 +01001942 __ Bind(&runtime_call);
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001943 {
Ben Murdochc8c1d9e2017-03-08 14:04:23 +00001944 Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow;
1945 Runtime::FunctionId id = Runtime::kStringCharFromCode;
1946 CallDescriptor const* desc = Linkage::GetRuntimeCallDescriptor(
1947 graph()->zone(), id, 1, properties, CallDescriptor::kNoFlags);
Ben Murdoch62ed6312017-06-06 11:06:27 +01001948 Node* vtrue1 =
1949 __ Call(desc, __ CEntryStubConstant(1), ChangeInt32ToSmi(code),
1950 __ ExternalConstant(ExternalReference(id, isolate())),
1951 __ Int32Constant(1), __ NoContextConstant());
1952 __ Goto(&done, vtrue1);
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001953 }
Ben Murdoch62ed6312017-06-06 11:06:27 +01001954 __ Bind(&done);
1955 return done.PhiAt(0);
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001956}
1957
Ben Murdoch62ed6312017-06-06 11:06:27 +01001958Node* EffectControlLinearizer::LowerStringFromCodePoint(Node* node) {
Ben Murdochf3b273f2017-01-17 12:11:28 +00001959 Node* value = node->InputAt(0);
1960 Node* code = value;
1961
Ben Murdoch62ed6312017-06-06 11:06:27 +01001962 auto if_not_single_code = __ MakeDeferredLabel<1>();
1963 auto if_not_one_byte = __ MakeDeferredLabel<1>();
1964 auto cache_miss = __ MakeDeferredLabel<1>();
1965 auto done = __ MakeLabel<4>(MachineRepresentation::kTagged);
Ben Murdochf3b273f2017-01-17 12:11:28 +00001966
1967 // Check if the {code} is a single code unit
Ben Murdoch62ed6312017-06-06 11:06:27 +01001968 Node* check0 = __ Uint32LessThanOrEqual(code, __ Uint32Constant(0xFFFF));
1969 __ GotoUnless(check0, &if_not_single_code);
Ben Murdochf3b273f2017-01-17 12:11:28 +00001970
Ben Murdochf3b273f2017-01-17 12:11:28 +00001971 {
1972 // Check if the {code} is a one byte character
Ben Murdoch62ed6312017-06-06 11:06:27 +01001973 Node* check1 = __ Uint32LessThanOrEqual(
1974 code, __ Uint32Constant(String::kMaxOneByteCharCode));
1975 __ GotoUnless(check1, &if_not_one_byte);
Ben Murdochf3b273f2017-01-17 12:11:28 +00001976 {
1977 // Load the isolate wide single character string cache.
Ben Murdoch62ed6312017-06-06 11:06:27 +01001978 Node* cache = __ HeapConstant(factory()->single_character_string_cache());
Ben Murdochf3b273f2017-01-17 12:11:28 +00001979
1980 // Compute the {cache} index for {code}.
Ben Murdoch62ed6312017-06-06 11:06:27 +01001981 Node* index = machine()->Is32() ? code : __ ChangeUint32ToUint64(code);
Ben Murdochf3b273f2017-01-17 12:11:28 +00001982
1983 // Check if we have an entry for the {code} in the single character string
1984 // cache already.
Ben Murdoch62ed6312017-06-06 11:06:27 +01001985 Node* entry =
1986 __ LoadElement(AccessBuilder::ForFixedArrayElement(), cache, index);
Ben Murdochf3b273f2017-01-17 12:11:28 +00001987
Ben Murdoch62ed6312017-06-06 11:06:27 +01001988 Node* check2 = __ WordEqual(entry, __ UndefinedConstant());
1989 __ GotoIf(check2, &cache_miss);
Ben Murdochf3b273f2017-01-17 12:11:28 +00001990
1991 // Use the {entry} from the {cache}.
Ben Murdoch62ed6312017-06-06 11:06:27 +01001992 __ Goto(&done, entry);
Ben Murdochf3b273f2017-01-17 12:11:28 +00001993
Ben Murdoch62ed6312017-06-06 11:06:27 +01001994 __ Bind(&cache_miss);
1995 {
1996 // Allocate a new SeqOneByteString for {code}.
1997 Node* vtrue2 = __ Allocate(
1998 NOT_TENURED, __ Int32Constant(SeqOneByteString::SizeFor(1)));
1999 __ StoreField(AccessBuilder::ForMap(), vtrue2,
2000 __ HeapConstant(factory()->one_byte_string_map()));
2001 __ StoreField(AccessBuilder::ForNameHashField(), vtrue2,
2002 __ IntPtrConstant(Name::kEmptyHashField));
2003 __ StoreField(AccessBuilder::ForStringLength(), vtrue2,
2004 __ SmiConstant(1));
2005 __ Store(
2006 StoreRepresentation(MachineRepresentation::kWord8, kNoWriteBarrier),
2007 vtrue2,
2008 __ IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag),
2009 code);
2010
2011 // Remember it in the {cache}.
2012 __ StoreElement(AccessBuilder::ForFixedArrayElement(), cache, index,
2013 vtrue2);
2014 __ Goto(&done, vtrue2);
2015 }
Ben Murdochf3b273f2017-01-17 12:11:28 +00002016 }
2017
Ben Murdoch62ed6312017-06-06 11:06:27 +01002018 __ Bind(&if_not_one_byte);
Ben Murdochf3b273f2017-01-17 12:11:28 +00002019 {
2020 // Allocate a new SeqTwoByteString for {code}.
Ben Murdoch62ed6312017-06-06 11:06:27 +01002021 Node* vfalse1 = __ Allocate(
2022 NOT_TENURED, __ Int32Constant(SeqTwoByteString::SizeFor(1)));
2023 __ StoreField(AccessBuilder::ForMap(), vfalse1,
2024 __ HeapConstant(factory()->string_map()));
2025 __ StoreField(AccessBuilder::ForNameHashField(), vfalse1,
2026 __ IntPtrConstant(Name::kEmptyHashField));
2027 __ StoreField(AccessBuilder::ForStringLength(), vfalse1,
2028 __ SmiConstant(1));
2029 __ Store(
2030 StoreRepresentation(MachineRepresentation::kWord16, kNoWriteBarrier),
2031 vfalse1,
2032 __ IntPtrConstant(SeqTwoByteString::kHeaderSize - kHeapObjectTag),
2033 code);
2034 __ Goto(&done, vfalse1);
Ben Murdochf3b273f2017-01-17 12:11:28 +00002035 }
Ben Murdochf3b273f2017-01-17 12:11:28 +00002036 }
2037
Ben Murdoch62ed6312017-06-06 11:06:27 +01002038 __ Bind(&if_not_single_code);
Ben Murdochf3b273f2017-01-17 12:11:28 +00002039 // Generate surrogate pair string
Ben Murdochf3b273f2017-01-17 12:11:28 +00002040 {
2041 switch (UnicodeEncodingOf(node->op())) {
2042 case UnicodeEncoding::UTF16:
2043 break;
2044
2045 case UnicodeEncoding::UTF32: {
2046 // Convert UTF32 to UTF16 code units, and store as a 32 bit word.
Ben Murdoch62ed6312017-06-06 11:06:27 +01002047 Node* lead_offset = __ Int32Constant(0xD800 - (0x10000 >> 10));
Ben Murdochf3b273f2017-01-17 12:11:28 +00002048
2049 // lead = (codepoint >> 10) + LEAD_OFFSET
2050 Node* lead =
Ben Murdoch62ed6312017-06-06 11:06:27 +01002051 __ Int32Add(__ Word32Shr(code, __ Int32Constant(10)), lead_offset);
Ben Murdochf3b273f2017-01-17 12:11:28 +00002052
2053 // trail = (codepoint & 0x3FF) + 0xDC00;
Ben Murdoch62ed6312017-06-06 11:06:27 +01002054 Node* trail = __ Int32Add(__ Word32And(code, __ Int32Constant(0x3FF)),
2055 __ Int32Constant(0xDC00));
Ben Murdochf3b273f2017-01-17 12:11:28 +00002056
2057 // codpoint = (trail << 16) | lead;
Ben Murdoch62ed6312017-06-06 11:06:27 +01002058 code = __ Word32Or(__ Word32Shl(trail, __ Int32Constant(16)), lead);
Ben Murdochf3b273f2017-01-17 12:11:28 +00002059 break;
2060 }
2061 }
2062
2063 // Allocate a new SeqTwoByteString for {code}.
Ben Murdoch62ed6312017-06-06 11:06:27 +01002064 Node* vfalse0 = __ Allocate(NOT_TENURED,
2065 __ Int32Constant(SeqTwoByteString::SizeFor(2)));
2066 __ StoreField(AccessBuilder::ForMap(), vfalse0,
2067 __ HeapConstant(factory()->string_map()));
2068 __ StoreField(AccessBuilder::ForNameHashField(), vfalse0,
2069 __ IntPtrConstant(Name::kEmptyHashField));
2070 __ StoreField(AccessBuilder::ForStringLength(), vfalse0, __ SmiConstant(2));
2071 __ Store(
2072 StoreRepresentation(MachineRepresentation::kWord32, kNoWriteBarrier),
2073 vfalse0,
2074 __ IntPtrConstant(SeqTwoByteString::kHeaderSize - kHeapObjectTag),
2075 code);
2076 __ Goto(&done, vfalse0);
Ben Murdochf3b273f2017-01-17 12:11:28 +00002077 }
2078
Ben Murdoch62ed6312017-06-06 11:06:27 +01002079 __ Bind(&done);
2080 return done.PhiAt(0);
Ben Murdochf3b273f2017-01-17 12:11:28 +00002081}
2082
Ben Murdoch62ed6312017-06-06 11:06:27 +01002083Node* EffectControlLinearizer::LowerStringIndexOf(Node* node) {
2084 Node* subject = node->InputAt(0);
2085 Node* search_string = node->InputAt(1);
2086 Node* position = node->InputAt(2);
2087
2088 Callable callable = CodeFactory::StringIndexOf(isolate());
Ben Murdochf3b273f2017-01-17 12:11:28 +00002089 Operator::Properties properties = Operator::kEliminatable;
2090 CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
2091 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
2092 isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties);
Ben Murdoch62ed6312017-06-06 11:06:27 +01002093 return __ Call(desc, __ HeapConstant(callable.code()), subject, search_string,
2094 position, __ NoContextConstant());
Ben Murdochf3b273f2017-01-17 12:11:28 +00002095}
2096
Ben Murdoch62ed6312017-06-06 11:06:27 +01002097Node* EffectControlLinearizer::LowerStringComparison(Callable const& callable,
2098 Node* node) {
2099 Node* lhs = node->InputAt(0);
2100 Node* rhs = node->InputAt(1);
2101
2102 Operator::Properties properties = Operator::kEliminatable;
2103 CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
2104 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
2105 isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties);
2106 return __ Call(desc, __ HeapConstant(callable.code()), lhs, rhs,
2107 __ NoContextConstant());
Ben Murdochf3b273f2017-01-17 12:11:28 +00002108}
2109
Ben Murdoch62ed6312017-06-06 11:06:27 +01002110Node* EffectControlLinearizer::LowerStringEqual(Node* node) {
2111 return LowerStringComparison(CodeFactory::StringEqual(isolate()), node);
Ben Murdochf3b273f2017-01-17 12:11:28 +00002112}
2113
Ben Murdoch62ed6312017-06-06 11:06:27 +01002114Node* EffectControlLinearizer::LowerStringLessThan(Node* node) {
2115 return LowerStringComparison(CodeFactory::StringLessThan(isolate()), node);
2116}
2117
2118Node* EffectControlLinearizer::LowerStringLessThanOrEqual(Node* node) {
Ben Murdochf3b273f2017-01-17 12:11:28 +00002119 return LowerStringComparison(CodeFactory::StringLessThanOrEqual(isolate()),
Ben Murdoch62ed6312017-06-06 11:06:27 +01002120 node);
Ben Murdochf3b273f2017-01-17 12:11:28 +00002121}
2122
Ben Murdoch62ed6312017-06-06 11:06:27 +01002123Node* EffectControlLinearizer::LowerCheckFloat64Hole(Node* node,
2124 Node* frame_state) {
Ben Murdoch13e2dad2016-09-16 13:49:30 +01002125 // If we reach this point w/o eliminating the {node} that's marked
2126 // with allow-return-hole, we cannot do anything, so just deoptimize
2127 // in case of the hole NaN (similar to Crankshaft).
2128 Node* value = node->InputAt(0);
Ben Murdoch62ed6312017-06-06 11:06:27 +01002129 Node* check = __ Word32Equal(__ Float64ExtractHighWord32(value),
2130 __ Int32Constant(kHoleNanUpper32));
2131 __ DeoptimizeIf(DeoptimizeReason::kHole, check, frame_state);
2132 return value;
Ben Murdoch13e2dad2016-09-16 13:49:30 +01002133}
2134
Ben Murdoch62ed6312017-06-06 11:06:27 +01002135Node* EffectControlLinearizer::LowerCheckTaggedHole(Node* node,
2136 Node* frame_state) {
Ben Murdoch13e2dad2016-09-16 13:49:30 +01002137 Node* value = node->InputAt(0);
Ben Murdoch62ed6312017-06-06 11:06:27 +01002138 Node* check = __ WordEqual(value, __ TheHoleConstant());
2139 __ DeoptimizeIf(DeoptimizeReason::kHole, check, frame_state);
2140 return value;
Ben Murdochf91f0612016-11-29 16:50:11 +00002141}
2142
Ben Murdoch62ed6312017-06-06 11:06:27 +01002143Node* EffectControlLinearizer::LowerConvertTaggedHoleToUndefined(Node* node) {
Ben Murdochf91f0612016-11-29 16:50:11 +00002144 Node* value = node->InputAt(0);
Ben Murdochf91f0612016-11-29 16:50:11 +00002145
Ben Murdoch62ed6312017-06-06 11:06:27 +01002146 auto if_is_hole = __ MakeDeferredLabel<1>();
2147 auto done = __ MakeLabel<2>(MachineRepresentation::kTagged);
Ben Murdochf91f0612016-11-29 16:50:11 +00002148
Ben Murdoch62ed6312017-06-06 11:06:27 +01002149 Node* check = __ WordEqual(value, __ TheHoleConstant());
2150 __ GotoIf(check, &if_is_hole);
2151 __ Goto(&done, value);
Ben Murdochf91f0612016-11-29 16:50:11 +00002152
Ben Murdoch62ed6312017-06-06 11:06:27 +01002153 __ Bind(&if_is_hole);
2154 __ Goto(&done, __ UndefinedConstant());
Ben Murdoch13e2dad2016-09-16 13:49:30 +01002155
Ben Murdoch62ed6312017-06-06 11:06:27 +01002156 __ Bind(&done);
2157 return done.PhiAt(0);
Ben Murdoch13e2dad2016-09-16 13:49:30 +01002158}
2159
Ben Murdoch62ed6312017-06-06 11:06:27 +01002160Node* EffectControlLinearizer::AllocateHeapNumberWithValue(Node* value) {
2161 Node* result = __ Allocate(NOT_TENURED, __ Int32Constant(HeapNumber::kSize));
2162 __ StoreField(AccessBuilder::ForMap(), result, __ HeapNumberMapConstant());
2163 __ StoreField(AccessBuilder::ForHeapNumberValue(), result, value);
2164 return result;
Ben Murdochbcf72ee2016-08-08 18:44:38 +01002165}
2166
2167Node* EffectControlLinearizer::ChangeInt32ToSmi(Node* value) {
2168 if (machine()->Is64()) {
Ben Murdoch62ed6312017-06-06 11:06:27 +01002169 value = __ ChangeInt32ToInt64(value);
Ben Murdochbcf72ee2016-08-08 18:44:38 +01002170 }
Ben Murdoch62ed6312017-06-06 11:06:27 +01002171 return __ WordShl(value, SmiShiftBitsConstant());
Ben Murdochbcf72ee2016-08-08 18:44:38 +01002172}
2173
2174Node* EffectControlLinearizer::ChangeUint32ToSmi(Node* value) {
2175 if (machine()->Is64()) {
Ben Murdoch62ed6312017-06-06 11:06:27 +01002176 value = __ ChangeUint32ToUint64(value);
Ben Murdochbcf72ee2016-08-08 18:44:38 +01002177 }
Ben Murdoch62ed6312017-06-06 11:06:27 +01002178 return __ WordShl(value, SmiShiftBitsConstant());
Ben Murdochbcf72ee2016-08-08 18:44:38 +01002179}
2180
2181Node* EffectControlLinearizer::ChangeSmiToInt32(Node* value) {
Ben Murdoch62ed6312017-06-06 11:06:27 +01002182 value = __ WordSar(value, SmiShiftBitsConstant());
Ben Murdochbcf72ee2016-08-08 18:44:38 +01002183 if (machine()->Is64()) {
Ben Murdoch62ed6312017-06-06 11:06:27 +01002184 value = __ TruncateInt64ToInt32(value);
Ben Murdochbcf72ee2016-08-08 18:44:38 +01002185 }
2186 return value;
2187}
Ben Murdoch62ed6312017-06-06 11:06:27 +01002188
Ben Murdochbcf72ee2016-08-08 18:44:38 +01002189Node* EffectControlLinearizer::ObjectIsSmi(Node* value) {
Ben Murdoch62ed6312017-06-06 11:06:27 +01002190 return __ WordEqual(__ WordAnd(value, __ IntPtrConstant(kSmiTagMask)),
2191 __ IntPtrConstant(kSmiTag));
Ben Murdochbcf72ee2016-08-08 18:44:38 +01002192}
2193
2194Node* EffectControlLinearizer::SmiMaxValueConstant() {
Ben Murdoch62ed6312017-06-06 11:06:27 +01002195 return __ Int32Constant(Smi::kMaxValue);
Ben Murdochbcf72ee2016-08-08 18:44:38 +01002196}
2197
2198Node* EffectControlLinearizer::SmiShiftBitsConstant() {
Ben Murdoch62ed6312017-06-06 11:06:27 +01002199 return __ IntPtrConstant(kSmiShiftSize + kSmiTagSize);
Ben Murdochbcf72ee2016-08-08 18:44:38 +01002200}
2201
Ben Murdoch62ed6312017-06-06 11:06:27 +01002202Node* EffectControlLinearizer::LowerPlainPrimitiveToNumber(Node* node) {
Ben Murdoch13e2dad2016-09-16 13:49:30 +01002203 Node* value = node->InputAt(0);
Ben Murdoch62ed6312017-06-06 11:06:27 +01002204 return __ ToNumber(value);
Ben Murdoch13e2dad2016-09-16 13:49:30 +01002205}
2206
Ben Murdoch62ed6312017-06-06 11:06:27 +01002207Node* EffectControlLinearizer::LowerPlainPrimitiveToWord32(Node* node) {
Ben Murdoch13e2dad2016-09-16 13:49:30 +01002208 Node* value = node->InputAt(0);
2209
Ben Murdoch62ed6312017-06-06 11:06:27 +01002210 auto if_not_smi = __ MakeDeferredLabel<1>();
2211 auto if_to_number_smi = __ MakeLabel<1>();
2212 auto done = __ MakeLabel<3>(MachineRepresentation::kWord32);
2213
Ben Murdoch13e2dad2016-09-16 13:49:30 +01002214 Node* check0 = ObjectIsSmi(value);
Ben Murdoch62ed6312017-06-06 11:06:27 +01002215 __ GotoUnless(check0, &if_not_smi);
2216 __ Goto(&done, ChangeSmiToInt32(value));
Ben Murdoch13e2dad2016-09-16 13:49:30 +01002217
Ben Murdoch62ed6312017-06-06 11:06:27 +01002218 __ Bind(&if_not_smi);
2219 Node* to_number = __ ToNumber(value);
Ben Murdoch13e2dad2016-09-16 13:49:30 +01002220
Ben Murdoch62ed6312017-06-06 11:06:27 +01002221 Node* check1 = ObjectIsSmi(to_number);
2222 __ GotoIf(check1, &if_to_number_smi);
2223 Node* number = __ LoadField(AccessBuilder::ForHeapNumberValue(), to_number);
2224 __ Goto(&done, __ TruncateFloat64ToWord32(number));
Ben Murdoch13e2dad2016-09-16 13:49:30 +01002225
Ben Murdoch62ed6312017-06-06 11:06:27 +01002226 __ Bind(&if_to_number_smi);
2227 __ Goto(&done, ChangeSmiToInt32(to_number));
Ben Murdoch13e2dad2016-09-16 13:49:30 +01002228
Ben Murdoch62ed6312017-06-06 11:06:27 +01002229 __ Bind(&done);
2230 return done.PhiAt(0);
Ben Murdoch13e2dad2016-09-16 13:49:30 +01002231}
2232
Ben Murdoch62ed6312017-06-06 11:06:27 +01002233Node* EffectControlLinearizer::LowerPlainPrimitiveToFloat64(Node* node) {
Ben Murdoch13e2dad2016-09-16 13:49:30 +01002234 Node* value = node->InputAt(0);
2235
Ben Murdoch62ed6312017-06-06 11:06:27 +01002236 auto if_not_smi = __ MakeDeferredLabel<1>();
2237 auto if_to_number_smi = __ MakeLabel<1>();
2238 auto done = __ MakeLabel<3>(MachineRepresentation::kFloat64);
2239
Ben Murdoch13e2dad2016-09-16 13:49:30 +01002240 Node* check0 = ObjectIsSmi(value);
Ben Murdoch62ed6312017-06-06 11:06:27 +01002241 __ GotoUnless(check0, &if_not_smi);
2242 Node* from_smi = ChangeSmiToInt32(value);
2243 __ Goto(&done, __ ChangeInt32ToFloat64(from_smi));
Ben Murdoch13e2dad2016-09-16 13:49:30 +01002244
Ben Murdoch62ed6312017-06-06 11:06:27 +01002245 __ Bind(&if_not_smi);
2246 Node* to_number = __ ToNumber(value);
2247 Node* check1 = ObjectIsSmi(to_number);
2248 __ GotoIf(check1, &if_to_number_smi);
Ben Murdoch13e2dad2016-09-16 13:49:30 +01002249
Ben Murdoch62ed6312017-06-06 11:06:27 +01002250 Node* number = __ LoadField(AccessBuilder::ForHeapNumberValue(), to_number);
2251 __ Goto(&done, number);
Ben Murdoch13e2dad2016-09-16 13:49:30 +01002252
Ben Murdoch62ed6312017-06-06 11:06:27 +01002253 __ Bind(&if_to_number_smi);
2254 Node* number_from_smi = ChangeSmiToInt32(to_number);
2255 number_from_smi = __ ChangeInt32ToFloat64(number_from_smi);
2256 __ Goto(&done, number_from_smi);
Ben Murdoch13e2dad2016-09-16 13:49:30 +01002257
Ben Murdoch62ed6312017-06-06 11:06:27 +01002258 __ Bind(&done);
2259 return done.PhiAt(0);
Ben Murdoch13e2dad2016-09-16 13:49:30 +01002260}
2261
Ben Murdoch62ed6312017-06-06 11:06:27 +01002262Node* EffectControlLinearizer::LowerEnsureWritableFastElements(Node* node) {
Ben Murdochf91f0612016-11-29 16:50:11 +00002263 Node* object = node->InputAt(0);
2264 Node* elements = node->InputAt(1);
2265
Ben Murdoch62ed6312017-06-06 11:06:27 +01002266 auto if_not_fixed_array = __ MakeDeferredLabel<1>();
2267 auto done = __ MakeLabel<2>(MachineRepresentation::kTagged);
2268
Ben Murdochf91f0612016-11-29 16:50:11 +00002269 // Load the current map of {elements}.
Ben Murdoch62ed6312017-06-06 11:06:27 +01002270 Node* elements_map = __ LoadField(AccessBuilder::ForMap(), elements);
Ben Murdochf91f0612016-11-29 16:50:11 +00002271
2272 // Check if {elements} is not a copy-on-write FixedArray.
Ben Murdoch62ed6312017-06-06 11:06:27 +01002273 Node* check = __ WordEqual(elements_map, __ FixedArrayMapConstant());
2274 __ GotoUnless(check, &if_not_fixed_array);
Ben Murdochf91f0612016-11-29 16:50:11 +00002275 // Nothing to do if the {elements} are not copy-on-write.
Ben Murdoch62ed6312017-06-06 11:06:27 +01002276 __ Goto(&done, elements);
Ben Murdochf91f0612016-11-29 16:50:11 +00002277
Ben Murdoch62ed6312017-06-06 11:06:27 +01002278 __ Bind(&if_not_fixed_array);
Ben Murdochf91f0612016-11-29 16:50:11 +00002279 // We need to take a copy of the {elements} and set them up for {object}.
Ben Murdoch62ed6312017-06-06 11:06:27 +01002280 Operator::Properties properties = Operator::kEliminatable;
2281 Callable callable = CodeFactory::CopyFastSmiOrObjectElements(isolate());
2282 CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
2283 CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
2284 isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties);
2285 Node* result = __ Call(desc, __ HeapConstant(callable.code()), object,
2286 __ NoContextConstant());
2287 __ Goto(&done, result);
Ben Murdochf91f0612016-11-29 16:50:11 +00002288
Ben Murdoch62ed6312017-06-06 11:06:27 +01002289 __ Bind(&done);
2290 return done.PhiAt(0);
Ben Murdochf91f0612016-11-29 16:50:11 +00002291}
2292
Ben Murdoch62ed6312017-06-06 11:06:27 +01002293Node* EffectControlLinearizer::LowerMaybeGrowFastElements(Node* node,
2294 Node* frame_state) {
Ben Murdochf91f0612016-11-29 16:50:11 +00002295 GrowFastElementsFlags flags = GrowFastElementsFlagsOf(node->op());
2296 Node* object = node->InputAt(0);
2297 Node* elements = node->InputAt(1);
2298 Node* index = node->InputAt(2);
2299 Node* length = node->InputAt(3);
2300
Ben Murdoch62ed6312017-06-06 11:06:27 +01002301 auto done = __ MakeLabel<2>(MachineRepresentation::kTagged);
2302 auto done_grow = __ MakeLabel<2>(MachineRepresentation::kTagged);
2303 auto if_grow = __ MakeDeferredLabel<1>();
2304 auto if_not_grow = __ MakeLabel<1>();
Ben Murdochf91f0612016-11-29 16:50:11 +00002305
Ben Murdoch62ed6312017-06-06 11:06:27 +01002306 Node* check0 = (flags & GrowFastElementsFlag::kHoleyElements)
2307 ? __ Uint32LessThanOrEqual(length, index)
2308 : __ Word32Equal(length, index);
2309 __ GotoUnless(check0, &if_not_grow);
Ben Murdochf91f0612016-11-29 16:50:11 +00002310 {
2311 // Load the length of the {elements} backing store.
Ben Murdoch62ed6312017-06-06 11:06:27 +01002312 Node* elements_length =
2313 __ LoadField(AccessBuilder::ForFixedArrayLength(), elements);
Ben Murdochf91f0612016-11-29 16:50:11 +00002314 elements_length = ChangeSmiToInt32(elements_length);
2315
2316 // Check if we need to grow the {elements} backing store.
Ben Murdoch62ed6312017-06-06 11:06:27 +01002317 Node* check1 = __ Uint32LessThan(index, elements_length);
2318 __ GotoUnless(check1, &if_grow);
2319 __ Goto(&done_grow, elements);
Ben Murdochf91f0612016-11-29 16:50:11 +00002320
Ben Murdoch62ed6312017-06-06 11:06:27 +01002321 __ Bind(&if_grow);
2322 // We need to grow the {elements} for {object}.
2323 Operator::Properties properties = Operator::kEliminatable;
2324 Callable callable =
2325 (flags & GrowFastElementsFlag::kDoubleElements)
2326 ? CodeFactory::GrowFastDoubleElements(isolate())
2327 : CodeFactory::GrowFastSmiOrObjectElements(isolate());
2328 CallDescriptor::Flags call_flags = CallDescriptor::kNoFlags;
2329 CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
2330 isolate(), graph()->zone(), callable.descriptor(), 0, call_flags,
2331 properties);
2332 Node* new_object = __ Call(desc, __ HeapConstant(callable.code()), object,
2333 ChangeInt32ToSmi(index), __ NoContextConstant());
Ben Murdochf91f0612016-11-29 16:50:11 +00002334
Ben Murdoch62ed6312017-06-06 11:06:27 +01002335 // Ensure that we were able to grow the {elements}.
2336 // TODO(turbofan): We use kSmi as reason here similar to Crankshaft,
2337 // but maybe we should just introduce a reason that makes sense.
2338 __ DeoptimizeIf(DeoptimizeReason::kSmi, ObjectIsSmi(new_object),
2339 frame_state);
2340 __ Goto(&done_grow, new_object);
Ben Murdochf91f0612016-11-29 16:50:11 +00002341
Ben Murdoch62ed6312017-06-06 11:06:27 +01002342 __ Bind(&done_grow);
Ben Murdochf91f0612016-11-29 16:50:11 +00002343
2344 // For JSArray {object}s we also need to update the "length".
2345 if (flags & GrowFastElementsFlag::kArrayObject) {
2346 // Compute the new {length}.
Ben Murdoch62ed6312017-06-06 11:06:27 +01002347 Node* object_length =
2348 ChangeInt32ToSmi(__ Int32Add(index, __ Int32Constant(1)));
Ben Murdochf91f0612016-11-29 16:50:11 +00002349
2350 // Update the "length" property of the {object}.
Ben Murdoch62ed6312017-06-06 11:06:27 +01002351 __ StoreField(AccessBuilder::ForJSArrayLength(FAST_ELEMENTS), object,
2352 object_length);
Ben Murdochf91f0612016-11-29 16:50:11 +00002353 }
Ben Murdoch62ed6312017-06-06 11:06:27 +01002354 __ Goto(&done, done_grow.PhiAt(0));
Ben Murdochf91f0612016-11-29 16:50:11 +00002355 }
2356
Ben Murdoch62ed6312017-06-06 11:06:27 +01002357 __ Bind(&if_not_grow);
Ben Murdochf91f0612016-11-29 16:50:11 +00002358 {
2359 // In case of non-holey {elements}, we need to verify that the {index} is
2360 // in-bounds, otherwise for holey {elements}, the check above already
2361 // guards the index (and the operator forces {index} to be unsigned).
2362 if (!(flags & GrowFastElementsFlag::kHoleyElements)) {
Ben Murdoch62ed6312017-06-06 11:06:27 +01002363 Node* check1 = __ Uint32LessThan(index, length);
2364 __ DeoptimizeUnless(DeoptimizeReason::kOutOfBounds, check1, frame_state);
Ben Murdochf91f0612016-11-29 16:50:11 +00002365 }
Ben Murdoch62ed6312017-06-06 11:06:27 +01002366 __ Goto(&done, elements);
Ben Murdochf91f0612016-11-29 16:50:11 +00002367 }
Ben Murdoch62ed6312017-06-06 11:06:27 +01002368 __ Bind(&done);
2369 return done.PhiAt(0);
Ben Murdochf91f0612016-11-29 16:50:11 +00002370}
2371
Ben Murdoch62ed6312017-06-06 11:06:27 +01002372void EffectControlLinearizer::LowerTransitionElementsKind(Node* node) {
Ben Murdochf91f0612016-11-29 16:50:11 +00002373 ElementsTransition const transition = ElementsTransitionOf(node->op());
2374 Node* object = node->InputAt(0);
Ben Murdoch62ed6312017-06-06 11:06:27 +01002375
2376 auto if_map_same = __ MakeDeferredLabel<1>();
2377 auto done = __ MakeLabel<2>();
2378
2379 Node* source_map = __ HeapConstant(transition.source());
2380 Node* target_map = __ HeapConstant(transition.target());
Ben Murdochf91f0612016-11-29 16:50:11 +00002381
2382 // Load the current map of {object}.
Ben Murdoch62ed6312017-06-06 11:06:27 +01002383 Node* object_map = __ LoadField(AccessBuilder::ForMap(), object);
Ben Murdochf91f0612016-11-29 16:50:11 +00002384
2385 // Check if {object_map} is the same as {source_map}.
Ben Murdoch62ed6312017-06-06 11:06:27 +01002386 Node* check = __ WordEqual(object_map, source_map);
2387 __ GotoIf(check, &if_map_same);
2388 __ Goto(&done);
Ben Murdochf91f0612016-11-29 16:50:11 +00002389
Ben Murdoch62ed6312017-06-06 11:06:27 +01002390 __ Bind(&if_map_same);
2391 switch (transition.mode()) {
2392 case ElementsTransition::kFastTransition:
2393 // In-place migration of {object}, just store the {target_map}.
2394 __ StoreField(AccessBuilder::ForMap(), object, target_map);
2395 break;
2396 case ElementsTransition::kSlowTransition: {
2397 // Instance migration, call out to the runtime for {object}.
2398 Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow;
2399 Runtime::FunctionId id = Runtime::kTransitionElementsKind;
2400 CallDescriptor const* desc = Linkage::GetRuntimeCallDescriptor(
2401 graph()->zone(), id, 2, properties, CallDescriptor::kNoFlags);
2402 __ Call(desc, __ CEntryStubConstant(1), object, target_map,
2403 __ ExternalConstant(ExternalReference(id, isolate())),
2404 __ Int32Constant(2), __ NoContextConstant());
2405 break;
Ben Murdochf91f0612016-11-29 16:50:11 +00002406 }
2407 }
Ben Murdoch62ed6312017-06-06 11:06:27 +01002408 __ Goto(&done);
Ben Murdochf91f0612016-11-29 16:50:11 +00002409
Ben Murdoch62ed6312017-06-06 11:06:27 +01002410 __ Bind(&done);
Ben Murdochf91f0612016-11-29 16:50:11 +00002411}
2412
Ben Murdoch62ed6312017-06-06 11:06:27 +01002413Node* EffectControlLinearizer::LowerLoadTypedElement(Node* node) {
Ben Murdochf91f0612016-11-29 16:50:11 +00002414 ExternalArrayType array_type = ExternalArrayTypeOf(node->op());
2415 Node* buffer = node->InputAt(0);
2416 Node* base = node->InputAt(1);
2417 Node* external = node->InputAt(2);
2418 Node* index = node->InputAt(3);
2419
2420 // We need to keep the {buffer} alive so that the GC will not release the
2421 // ArrayBuffer (if there's any) as long as we are still operating on it.
Ben Murdoch62ed6312017-06-06 11:06:27 +01002422 __ Retain(buffer);
Ben Murdochf91f0612016-11-29 16:50:11 +00002423
Ben Murdoch62ed6312017-06-06 11:06:27 +01002424 // Compute the effective storage pointer, handling the case where the
2425 // {external} pointer is the effective storage pointer (i.e. the {base}
2426 // is Smi zero).
2427 Node* storage = NumberMatcher(base).Is(0) ? external : __ UnsafePointerAdd(
2428 base, external);
Ben Murdochf91f0612016-11-29 16:50:11 +00002429
2430 // Perform the actual typed element access.
Ben Murdoch62ed6312017-06-06 11:06:27 +01002431 return __ LoadElement(AccessBuilder::ForTypedArrayElement(array_type, true),
2432 storage, index);
Ben Murdochf91f0612016-11-29 16:50:11 +00002433}
2434
Ben Murdoch62ed6312017-06-06 11:06:27 +01002435void EffectControlLinearizer::LowerStoreTypedElement(Node* node) {
Ben Murdochf91f0612016-11-29 16:50:11 +00002436 ExternalArrayType array_type = ExternalArrayTypeOf(node->op());
2437 Node* buffer = node->InputAt(0);
2438 Node* base = node->InputAt(1);
2439 Node* external = node->InputAt(2);
2440 Node* index = node->InputAt(3);
2441 Node* value = node->InputAt(4);
2442
2443 // We need to keep the {buffer} alive so that the GC will not release the
2444 // ArrayBuffer (if there's any) as long as we are still operating on it.
Ben Murdoch62ed6312017-06-06 11:06:27 +01002445 __ Retain(buffer);
Ben Murdochf91f0612016-11-29 16:50:11 +00002446
Ben Murdoch62ed6312017-06-06 11:06:27 +01002447 // Compute the effective storage pointer, handling the case where the
2448 // {external} pointer is the effective storage pointer (i.e. the {base}
2449 // is Smi zero).
2450 Node* storage = NumberMatcher(base).Is(0) ? external : __ UnsafePointerAdd(
2451 base, external);
Ben Murdochf91f0612016-11-29 16:50:11 +00002452
2453 // Perform the actual typed element access.
Ben Murdoch62ed6312017-06-06 11:06:27 +01002454 __ StoreElement(AccessBuilder::ForTypedArrayElement(array_type, true),
2455 storage, index, value);
Ben Murdochf91f0612016-11-29 16:50:11 +00002456}
2457
Ben Murdoch62ed6312017-06-06 11:06:27 +01002458Maybe<Node*> EffectControlLinearizer::LowerFloat64RoundUp(Node* node) {
Ben Murdochf91f0612016-11-29 16:50:11 +00002459 // Nothing to be done if a fast hardware instruction is available.
2460 if (machine()->Float64RoundUp().IsSupported()) {
Ben Murdoch62ed6312017-06-06 11:06:27 +01002461 return Nothing<Node*>();
Ben Murdochf91f0612016-11-29 16:50:11 +00002462 }
2463
Ben Murdochf91f0612016-11-29 16:50:11 +00002464 Node* const input = node->InputAt(0);
2465
2466 // General case for ceil.
2467 //
2468 // if 0.0 < input then
2469 // if 2^52 <= input then
2470 // input
2471 // else
2472 // let temp1 = (2^52 + input) - 2^52 in
2473 // if temp1 < input then
2474 // temp1 + 1
2475 // else
2476 // temp1
2477 // else
2478 // if input == 0 then
2479 // input
2480 // else
2481 // if input <= -2^52 then
2482 // input
2483 // else
2484 // let temp1 = -0 - input in
2485 // let temp2 = (2^52 + temp1) - 2^52 in
2486 // let temp3 = (if temp1 < temp2 then temp2 - 1 else temp2) in
2487 // -0 - temp3
Ben Murdoch62ed6312017-06-06 11:06:27 +01002488
2489 auto if_not_positive = __ MakeDeferredLabel<1>();
2490 auto if_greater_than_two_52 = __ MakeDeferredLabel<1>();
2491 auto if_less_than_minus_two_52 = __ MakeDeferredLabel<1>();
2492 auto if_zero = __ MakeDeferredLabel<1>();
2493 auto done_temp3 = __ MakeLabel<2>(MachineRepresentation::kFloat64);
2494 auto done = __ MakeLabel<6>(MachineRepresentation::kFloat64);
2495
2496 Node* const zero = __ Float64Constant(0.0);
2497 Node* const two_52 = __ Float64Constant(4503599627370496.0E0);
2498 Node* const one = __ Float64Constant(1.0);
2499
2500 Node* check0 = __ Float64LessThan(zero, input);
2501 __ GotoUnless(check0, &if_not_positive);
2502 {
2503 Node* check1 = __ Float64LessThanOrEqual(two_52, input);
2504 __ GotoIf(check1, &if_greater_than_two_52);
2505 {
2506 Node* temp1 = __ Float64Sub(__ Float64Add(two_52, input), two_52);
2507 __ GotoUnless(__ Float64LessThan(temp1, input), &done, temp1);
2508 __ Goto(&done, __ Float64Add(temp1, one));
2509 }
2510
2511 __ Bind(&if_greater_than_two_52);
2512 __ Goto(&done, input);
2513 }
2514
2515 __ Bind(&if_not_positive);
2516 {
2517 Node* check1 = __ Float64Equal(input, zero);
2518 __ GotoIf(check1, &if_zero);
2519
2520 Node* const minus_two_52 = __ Float64Constant(-4503599627370496.0E0);
2521 Node* check2 = __ Float64LessThanOrEqual(input, minus_two_52);
2522 __ GotoIf(check2, &if_less_than_minus_two_52);
2523
2524 {
2525 Node* const minus_zero = __ Float64Constant(-0.0);
2526 Node* temp1 = __ Float64Sub(minus_zero, input);
2527 Node* temp2 = __ Float64Sub(__ Float64Add(two_52, temp1), two_52);
2528 Node* check3 = __ Float64LessThan(temp1, temp2);
2529 __ GotoUnless(check3, &done_temp3, temp2);
2530 __ Goto(&done_temp3, __ Float64Sub(temp2, one));
2531
2532 __ Bind(&done_temp3);
2533 Node* temp3 = done_temp3.PhiAt(0);
2534 __ Goto(&done, __ Float64Sub(minus_zero, temp3));
2535 }
2536 __ Bind(&if_less_than_minus_two_52);
2537 __ Goto(&done, input);
2538
2539 __ Bind(&if_zero);
2540 __ Goto(&done, input);
2541 }
2542 __ Bind(&done);
2543 return Just(done.PhiAt(0));
2544}
2545
2546Node* EffectControlLinearizer::BuildFloat64RoundDown(Node* value) {
2547 Node* round_down = __ Float64RoundDown(value);
2548 if (round_down != nullptr) {
2549 return round_down;
2550 }
2551
2552 Node* const input = value;
2553
2554 // General case for floor.
Ben Murdochf91f0612016-11-29 16:50:11 +00002555 //
Ben Murdoch62ed6312017-06-06 11:06:27 +01002556 // if 0.0 < input then
2557 // if 2^52 <= input then
2558 // input
2559 // else
2560 // let temp1 = (2^52 + input) - 2^52 in
2561 // if input < temp1 then
2562 // temp1 - 1
2563 // else
2564 // temp1
2565 // else
2566 // if input == 0 then
2567 // input
2568 // else
2569 // if input <= -2^52 then
2570 // input
2571 // else
2572 // let temp1 = -0 - input in
2573 // let temp2 = (2^52 + temp1) - 2^52 in
2574 // if temp2 < temp1 then
2575 // -1 - temp2
2576 // else
2577 // -0 - temp2
Ben Murdochf91f0612016-11-29 16:50:11 +00002578
Ben Murdoch62ed6312017-06-06 11:06:27 +01002579 auto if_not_positive = __ MakeDeferredLabel<1>();
2580 auto if_greater_than_two_52 = __ MakeDeferredLabel<1>();
2581 auto if_less_than_minus_two_52 = __ MakeDeferredLabel<1>();
2582 auto if_temp2_lt_temp1 = __ MakeLabel<1>();
2583 auto if_zero = __ MakeDeferredLabel<1>();
2584 auto done = __ MakeLabel<7>(MachineRepresentation::kFloat64);
Ben Murdochf91f0612016-11-29 16:50:11 +00002585
Ben Murdoch62ed6312017-06-06 11:06:27 +01002586 Node* const zero = __ Float64Constant(0.0);
2587 Node* const two_52 = __ Float64Constant(4503599627370496.0E0);
2588
2589 Node* check0 = __ Float64LessThan(zero, input);
2590 __ GotoUnless(check0, &if_not_positive);
Ben Murdochf91f0612016-11-29 16:50:11 +00002591 {
Ben Murdoch62ed6312017-06-06 11:06:27 +01002592 Node* check1 = __ Float64LessThanOrEqual(two_52, input);
2593 __ GotoIf(check1, &if_greater_than_two_52);
Ben Murdochf91f0612016-11-29 16:50:11 +00002594 {
Ben Murdoch62ed6312017-06-06 11:06:27 +01002595 Node* const one = __ Float64Constant(1.0);
2596 Node* temp1 = __ Float64Sub(__ Float64Add(two_52, input), two_52);
2597 __ GotoUnless(__ Float64LessThan(input, temp1), &done, temp1);
2598 __ Goto(&done, __ Float64Sub(temp1, one));
Ben Murdochf91f0612016-11-29 16:50:11 +00002599 }
2600
Ben Murdoch62ed6312017-06-06 11:06:27 +01002601 __ Bind(&if_greater_than_two_52);
2602 __ Goto(&done, input);
Ben Murdochf91f0612016-11-29 16:50:11 +00002603 }
2604
Ben Murdoch62ed6312017-06-06 11:06:27 +01002605 __ Bind(&if_not_positive);
Ben Murdochf91f0612016-11-29 16:50:11 +00002606 {
Ben Murdoch62ed6312017-06-06 11:06:27 +01002607 Node* check1 = __ Float64Equal(input, zero);
2608 __ GotoIf(check1, &if_zero);
Ben Murdochf91f0612016-11-29 16:50:11 +00002609
Ben Murdoch62ed6312017-06-06 11:06:27 +01002610 Node* const minus_two_52 = __ Float64Constant(-4503599627370496.0E0);
2611 Node* check2 = __ Float64LessThanOrEqual(input, minus_two_52);
2612 __ GotoIf(check2, &if_less_than_minus_two_52);
Ben Murdochf91f0612016-11-29 16:50:11 +00002613
Ben Murdochf91f0612016-11-29 16:50:11 +00002614 {
Ben Murdoch62ed6312017-06-06 11:06:27 +01002615 Node* const minus_zero = __ Float64Constant(-0.0);
2616 Node* temp1 = __ Float64Sub(minus_zero, input);
2617 Node* temp2 = __ Float64Sub(__ Float64Add(two_52, temp1), two_52);
2618 Node* check3 = __ Float64LessThan(temp2, temp1);
2619 __ GotoIf(check3, &if_temp2_lt_temp1);
2620 __ Goto(&done, __ Float64Sub(minus_zero, temp2));
Ben Murdochf91f0612016-11-29 16:50:11 +00002621
Ben Murdoch62ed6312017-06-06 11:06:27 +01002622 __ Bind(&if_temp2_lt_temp1);
2623 __ Goto(&done, __ Float64Sub(__ Float64Constant(-1.0), temp2));
Ben Murdochf91f0612016-11-29 16:50:11 +00002624 }
Ben Murdoch62ed6312017-06-06 11:06:27 +01002625 __ Bind(&if_less_than_minus_two_52);
2626 __ Goto(&done, input);
Ben Murdochf91f0612016-11-29 16:50:11 +00002627
Ben Murdoch62ed6312017-06-06 11:06:27 +01002628 __ Bind(&if_zero);
2629 __ Goto(&done, input);
Ben Murdochf91f0612016-11-29 16:50:11 +00002630 }
Ben Murdoch62ed6312017-06-06 11:06:27 +01002631 __ Bind(&done);
2632 return done.PhiAt(0);
Ben Murdochf91f0612016-11-29 16:50:11 +00002633}
2634
Ben Murdoch62ed6312017-06-06 11:06:27 +01002635Maybe<Node*> EffectControlLinearizer::LowerFloat64RoundDown(Node* node) {
Ben Murdochf91f0612016-11-29 16:50:11 +00002636 // Nothing to be done if a fast hardware instruction is available.
2637 if (machine()->Float64RoundDown().IsSupported()) {
Ben Murdoch62ed6312017-06-06 11:06:27 +01002638 return Nothing<Node*>();
Ben Murdochf91f0612016-11-29 16:50:11 +00002639 }
2640
Ben Murdochc8c1d9e2017-03-08 14:04:23 +00002641 Node* const input = node->InputAt(0);
Ben Murdoch62ed6312017-06-06 11:06:27 +01002642 return Just(BuildFloat64RoundDown(input));
Ben Murdochc8c1d9e2017-03-08 14:04:23 +00002643}
2644
Ben Murdoch62ed6312017-06-06 11:06:27 +01002645Maybe<Node*> EffectControlLinearizer::LowerFloat64RoundTiesEven(Node* node) {
Ben Murdochc8c1d9e2017-03-08 14:04:23 +00002646 // Nothing to be done if a fast hardware instruction is available.
2647 if (machine()->Float64RoundTiesEven().IsSupported()) {
Ben Murdoch62ed6312017-06-06 11:06:27 +01002648 return Nothing<Node*>();
Ben Murdochc8c1d9e2017-03-08 14:04:23 +00002649 }
2650
Ben Murdochf91f0612016-11-29 16:50:11 +00002651 Node* const input = node->InputAt(0);
2652
Ben Murdochc8c1d9e2017-03-08 14:04:23 +00002653 // Generate case for round ties to even:
Ben Murdochf91f0612016-11-29 16:50:11 +00002654 //
Ben Murdochc8c1d9e2017-03-08 14:04:23 +00002655 // let value = floor(input) in
2656 // let temp1 = input - value in
2657 // if temp1 < 0.5 then
2658 // value
2659 // else if 0.5 < temp1 then
2660 // value + 1.0
Ben Murdochf91f0612016-11-29 16:50:11 +00002661 // else
Ben Murdochc8c1d9e2017-03-08 14:04:23 +00002662 // let temp2 = value % 2.0 in
2663 // if temp2 == 0.0 then
2664 // value
Ben Murdochf91f0612016-11-29 16:50:11 +00002665 // else
Ben Murdochc8c1d9e2017-03-08 14:04:23 +00002666 // value + 1.0
Ben Murdochf91f0612016-11-29 16:50:11 +00002667
Ben Murdoch62ed6312017-06-06 11:06:27 +01002668 auto if_is_half = __ MakeLabel<1>();
2669 auto done = __ MakeLabel<4>(MachineRepresentation::kFloat64);
Ben Murdochc8c1d9e2017-03-08 14:04:23 +00002670
Ben Murdoch62ed6312017-06-06 11:06:27 +01002671 Node* value = BuildFloat64RoundDown(input);
2672 Node* temp1 = __ Float64Sub(input, value);
Ben Murdochc8c1d9e2017-03-08 14:04:23 +00002673
Ben Murdoch62ed6312017-06-06 11:06:27 +01002674 Node* const half = __ Float64Constant(0.5);
2675 Node* check0 = __ Float64LessThan(temp1, half);
2676 __ GotoIf(check0, &done, value);
Ben Murdochf91f0612016-11-29 16:50:11 +00002677
Ben Murdoch62ed6312017-06-06 11:06:27 +01002678 Node* const one = __ Float64Constant(1.0);
2679 Node* check1 = __ Float64LessThan(half, temp1);
2680 __ GotoUnless(check1, &if_is_half);
2681 __ Goto(&done, __ Float64Add(value, one));
Ben Murdochf91f0612016-11-29 16:50:11 +00002682
Ben Murdoch62ed6312017-06-06 11:06:27 +01002683 __ Bind(&if_is_half);
2684 Node* temp2 = __ Float64Mod(value, __ Float64Constant(2.0));
2685 Node* check2 = __ Float64Equal(temp2, __ Float64Constant(0.0));
2686 __ GotoIf(check2, &done, value);
2687 __ Goto(&done, __ Float64Add(value, one));
Ben Murdochf91f0612016-11-29 16:50:11 +00002688
Ben Murdoch62ed6312017-06-06 11:06:27 +01002689 __ Bind(&done);
2690 return Just(done.PhiAt(0));
Ben Murdochf91f0612016-11-29 16:50:11 +00002691}
2692
Ben Murdoch62ed6312017-06-06 11:06:27 +01002693Maybe<Node*> EffectControlLinearizer::LowerFloat64RoundTruncate(Node* node) {
Ben Murdochf91f0612016-11-29 16:50:11 +00002694 // Nothing to be done if a fast hardware instruction is available.
2695 if (machine()->Float64RoundTruncate().IsSupported()) {
Ben Murdoch62ed6312017-06-06 11:06:27 +01002696 return Nothing<Node*>();
Ben Murdochf91f0612016-11-29 16:50:11 +00002697 }
2698
Ben Murdochf91f0612016-11-29 16:50:11 +00002699 Node* const input = node->InputAt(0);
2700
2701 // General case for trunc.
2702 //
2703 // if 0.0 < input then
2704 // if 2^52 <= input then
2705 // input
2706 // else
2707 // let temp1 = (2^52 + input) - 2^52 in
2708 // if input < temp1 then
2709 // temp1 - 1
2710 // else
2711 // temp1
2712 // else
2713 // if input == 0 then
2714 // input
2715 // else
2716 // if input <= -2^52 then
2717 // input
2718 // else
2719 // let temp1 = -0 - input in
2720 // let temp2 = (2^52 + temp1) - 2^52 in
2721 // let temp3 = (if temp1 < temp2 then temp2 - 1 else temp2) in
2722 // -0 - temp3
2723 //
2724 // Note: We do not use the Diamond helper class here, because it really hurts
2725 // readability with nested diamonds.
2726
Ben Murdoch62ed6312017-06-06 11:06:27 +01002727 auto if_not_positive = __ MakeDeferredLabel<1>();
2728 auto if_greater_than_two_52 = __ MakeDeferredLabel<1>();
2729 auto if_less_than_minus_two_52 = __ MakeDeferredLabel<1>();
2730 auto if_zero = __ MakeDeferredLabel<1>();
2731 auto done_temp3 = __ MakeLabel<2>(MachineRepresentation::kFloat64);
2732 auto done = __ MakeLabel<6>(MachineRepresentation::kFloat64);
Ben Murdochf91f0612016-11-29 16:50:11 +00002733
Ben Murdoch62ed6312017-06-06 11:06:27 +01002734 Node* const zero = __ Float64Constant(0.0);
2735 Node* const two_52 = __ Float64Constant(4503599627370496.0E0);
2736 Node* const one = __ Float64Constant(1.0);
2737
2738 Node* check0 = __ Float64LessThan(zero, input);
2739 __ GotoUnless(check0, &if_not_positive);
Ben Murdochf91f0612016-11-29 16:50:11 +00002740 {
Ben Murdoch62ed6312017-06-06 11:06:27 +01002741 Node* check1 = __ Float64LessThanOrEqual(two_52, input);
2742 __ GotoIf(check1, &if_greater_than_two_52);
Ben Murdochf91f0612016-11-29 16:50:11 +00002743 {
Ben Murdoch62ed6312017-06-06 11:06:27 +01002744 Node* temp1 = __ Float64Sub(__ Float64Add(two_52, input), two_52);
2745 __ GotoUnless(__ Float64LessThan(input, temp1), &done, temp1);
2746 __ Goto(&done, __ Float64Sub(temp1, one));
Ben Murdochf91f0612016-11-29 16:50:11 +00002747 }
2748
Ben Murdoch62ed6312017-06-06 11:06:27 +01002749 __ Bind(&if_greater_than_two_52);
2750 __ Goto(&done, input);
Ben Murdochf91f0612016-11-29 16:50:11 +00002751 }
2752
Ben Murdoch62ed6312017-06-06 11:06:27 +01002753 __ Bind(&if_not_positive);
Ben Murdochf91f0612016-11-29 16:50:11 +00002754 {
Ben Murdoch62ed6312017-06-06 11:06:27 +01002755 Node* check1 = __ Float64Equal(input, zero);
2756 __ GotoIf(check1, &if_zero);
Ben Murdochf91f0612016-11-29 16:50:11 +00002757
Ben Murdoch62ed6312017-06-06 11:06:27 +01002758 Node* const minus_two_52 = __ Float64Constant(-4503599627370496.0E0);
2759 Node* check2 = __ Float64LessThanOrEqual(input, minus_two_52);
2760 __ GotoIf(check2, &if_less_than_minus_two_52);
Ben Murdochf91f0612016-11-29 16:50:11 +00002761
Ben Murdochf91f0612016-11-29 16:50:11 +00002762 {
Ben Murdoch62ed6312017-06-06 11:06:27 +01002763 Node* const minus_zero = __ Float64Constant(-0.0);
2764 Node* temp1 = __ Float64Sub(minus_zero, input);
2765 Node* temp2 = __ Float64Sub(__ Float64Add(two_52, temp1), two_52);
2766 Node* check3 = __ Float64LessThan(temp1, temp2);
2767 __ GotoUnless(check3, &done_temp3, temp2);
2768 __ Goto(&done_temp3, __ Float64Sub(temp2, one));
Ben Murdochf91f0612016-11-29 16:50:11 +00002769
Ben Murdoch62ed6312017-06-06 11:06:27 +01002770 __ Bind(&done_temp3);
2771 Node* temp3 = done_temp3.PhiAt(0);
2772 __ Goto(&done, __ Float64Sub(minus_zero, temp3));
Ben Murdochf91f0612016-11-29 16:50:11 +00002773 }
Ben Murdoch62ed6312017-06-06 11:06:27 +01002774 __ Bind(&if_less_than_minus_two_52);
2775 __ Goto(&done, input);
Ben Murdochf91f0612016-11-29 16:50:11 +00002776
Ben Murdoch62ed6312017-06-06 11:06:27 +01002777 __ Bind(&if_zero);
2778 __ Goto(&done, input);
Ben Murdochf91f0612016-11-29 16:50:11 +00002779 }
Ben Murdoch62ed6312017-06-06 11:06:27 +01002780 __ Bind(&done);
2781 return Just(done.PhiAt(0));
Ben Murdochf91f0612016-11-29 16:50:11 +00002782}
2783
Ben Murdoch62ed6312017-06-06 11:06:27 +01002784#undef __
2785
Ben Murdoch13e2dad2016-09-16 13:49:30 +01002786Factory* EffectControlLinearizer::factory() const {
2787 return isolate()->factory();
2788}
2789
2790Isolate* EffectControlLinearizer::isolate() const {
2791 return jsgraph()->isolate();
2792}
2793
Ben Murdochbcf72ee2016-08-08 18:44:38 +01002794} // namespace compiler
2795} // namespace internal
2796} // namespace v8