| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 1 | // Copyright 2015 the V8 project authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "src/compiler/effect-control-linearizer.h" |
| 6 | |
| 7 | #include "src/code-factory.h" |
| 8 | #include "src/compiler/access-builder.h" |
| Ben Murdoch | c8c1d9e | 2017-03-08 14:04:23 +0000 | [diff] [blame] | 9 | #include "src/compiler/compiler-source-position-table.h" |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 10 | #include "src/compiler/js-graph.h" |
| 11 | #include "src/compiler/linkage.h" |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 12 | #include "src/compiler/node-matchers.h" |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 13 | #include "src/compiler/node-properties.h" |
| 14 | #include "src/compiler/node.h" |
| 15 | #include "src/compiler/schedule.h" |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 16 | #include "src/objects-inl.h" |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 17 | |
| 18 | namespace v8 { |
| 19 | namespace internal { |
| 20 | namespace compiler { |
| 21 | |
| Ben Murdoch | c8c1d9e | 2017-03-08 14:04:23 +0000 | [diff] [blame] | 22 | EffectControlLinearizer::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 Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 28 | source_positions_(source_positions), |
| 29 | graph_assembler_(js_graph, nullptr, nullptr, temp_zone) {} |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 30 | |
| 31 | Graph* EffectControlLinearizer::graph() const { return js_graph_->graph(); } |
| 32 | CommonOperatorBuilder* EffectControlLinearizer::common() const { |
| 33 | return js_graph_->common(); |
| 34 | } |
| 35 | SimplifiedOperatorBuilder* EffectControlLinearizer::simplified() const { |
| 36 | return js_graph_->simplified(); |
| 37 | } |
| 38 | MachineOperatorBuilder* EffectControlLinearizer::machine() const { |
| 39 | return js_graph_->machine(); |
| 40 | } |
| 41 | |
| 42 | namespace { |
| 43 | |
| 44 | struct BlockEffectControlData { |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 45 | Node* current_effect = nullptr; // New effect. |
| 46 | Node* current_control = nullptr; // New control. |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 47 | Node* current_frame_state = nullptr; // New frame state. |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 48 | }; |
| 49 | |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 50 | class 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 Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 69 | // Effect phis that need to be updated after the first pass. |
| 70 | struct 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 | |
| 78 | void UpdateEffectPhi(Node* node, BasicBlock* block, |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 79 | BlockEffectControlMap* block_effects) { |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 80 | // 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 Murdoch | c8c1d9e | 2017-03-08 14:04:23 +0000 | [diff] [blame] | 83 | DCHECK_EQ(static_cast<size_t>(node->op()->EffectInputCount()), |
| 84 | block->PredecessorCount()); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 85 | 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 88 | 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 Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 92 | } |
| 93 | } |
| 94 | } |
| 95 | |
| 96 | void UpdateBlockControl(BasicBlock* block, |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 97 | BlockEffectControlMap* block_effects) { |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 98 | 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 105 | DCHECK(control->opcode() == IrOpcode::kMerge || |
| Ben Murdoch | c8c1d9e | 2017-03-08 14:04:23 +0000 | [diff] [blame] | 106 | static_cast<size_t>(control->op()->ControlInputCount()) == |
| 107 | block->PredecessorCount()); |
| 108 | if (static_cast<size_t>(control->op()->ControlInputCount()) != |
| 109 | block->PredecessorCount()) { |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 110 | return; // We already re-wired the control inputs of this node. |
| 111 | } |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 112 | 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 115 | 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 Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 120 | } |
| 121 | } |
| 122 | } |
| 123 | |
| 124 | bool 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 | |
| 133 | void 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 151 | void TryCloneBranch(Node* node, BasicBlock* block, Graph* graph, |
| 152 | CommonOperatorBuilder* common, |
| Ben Murdoch | c8c1d9e | 2017-03-08 14:04:23 +0000 | [diff] [blame] | 153 | BlockEffectControlMap* block_effects, |
| 154 | SourcePositionTable* source_positions) { |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 155 | 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 Murdoch | c8c1d9e | 2017-03-08 14:04:23 +0000 | [diff] [blame] | 206 | SourcePositionTable::Scope scope(source_positions, |
| 207 | source_positions->GetSourcePosition(node)); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 208 | 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 Murdoch | c8c1d9e | 2017-03-08 14:04:23 +0000 | [diff] [blame] | 261 | DCHECK_EQ(2u, block->SuccessorCount()); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 262 | 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 280 | } 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 Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 305 | } // namespace |
| 306 | |
| 307 | void EffectControlLinearizer::Run() { |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 308 | BlockEffectControlMap block_effects(temp_zone()); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 309 | ZoneVector<PendingEffectPhi> pending_effect_phis(temp_zone()); |
| 310 | ZoneVector<BasicBlock*> pending_block_controls(temp_zone()); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 311 | 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 376 | // 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 Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 383 | 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 392 | inputs_buffer.resize(block->PredecessorCount(), jsgraph()->Dead()); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 393 | 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 397 | // 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 Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 403 | } 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 Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 417 | // 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 426 | frame_state = |
| 427 | block_effects.For(block->PredecessorAt(0), block).current_frame_state; |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 428 | for (size_t i = 1; i < block->PredecessorCount(); i++) { |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 429 | if (block_effects.For(block->PredecessorAt(i), block) |
| 430 | .current_frame_state != frame_state) { |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 431 | frame_state = nullptr; |
| 432 | break; |
| 433 | } |
| 434 | } |
| 435 | } |
| 436 | |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 437 | // Process the ordinary instructions. |
| 438 | for (; instr < block->NodeCount(); instr++) { |
| 439 | Node* node = block->NodeAt(instr); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 440 | ProcessNode(node, &frame_state, &effect, &control); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 441 | } |
| 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 Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 450 | case BasicBlock::kSwitch: |
| 451 | case BasicBlock::kReturn: |
| 452 | case BasicBlock::kDeoptimize: |
| 453 | case BasicBlock::kThrow: |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 454 | ProcessNode(block->control_input(), &frame_state, &effect, &control); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 455 | break; |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 456 | |
| 457 | case BasicBlock::kBranch: |
| 458 | ProcessNode(block->control_input(), &frame_state, &effect, &control); |
| 459 | TryCloneBranch(block->control_input(), block, graph(), common(), |
| Ben Murdoch | c8c1d9e | 2017-03-08 14:04:23 +0000 | [diff] [blame] | 460 | &block_effects, source_positions_); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 461 | break; |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 462 | } |
| 463 | |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 464 | // 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 Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 475 | } |
| 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 | |
| 488 | namespace { |
| 489 | |
| 490 | void 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 Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 504 | void EffectControlLinearizer::ProcessNode(Node* node, Node** frame_state, |
| 505 | Node** effect, Node** control) { |
| Ben Murdoch | c8c1d9e | 2017-03-08 14:04:23 +0000 | [diff] [blame] | 506 | SourcePositionTable::Scope scope(source_positions_, |
| 507 | source_positions_->GetSourcePosition(node)); |
| 508 | |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 509 | // If the node needs to be wired into the effect/control chain, do this |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 510 | // here. Pass current frame state for lowering to eager deoptimization. |
| 511 | if (TryWireInStateEffect(node, *frame_state, effect, control)) { |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 512 | return; |
| 513 | } |
| 514 | |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 515 | // 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 Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 523 | // Remove the end markers of 'atomic' allocation region because the |
| 524 | // region should be wired-in now. |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 525 | 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 Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 538 | // 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 Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 543 | // Special treatment for checkpoint nodes. |
| 544 | if (node->opcode() == IrOpcode::kCheckpoint) { |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 545 | // Unlink the check point; effect uses will be updated to the incoming |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 546 | // effect that is passed. The frame state is preserved for lowering. |
| 547 | DCHECK_EQ(RegionObservability::kObservable, region_observability_); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 548 | *frame_state = NodeProperties::GetFrameStateInput(node); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 549 | 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 Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 597 | bool EffectControlLinearizer::TryWireInStateEffect(Node* node, |
| 598 | Node* frame_state, |
| 599 | Node** effect, |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 600 | Node** control) { |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 601 | gasm()->Reset(*effect, *control); |
| 602 | Node* result = nullptr; |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 603 | switch (node->opcode()) { |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 604 | case IrOpcode::kChangeBitToTagged: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 605 | result = LowerChangeBitToTagged(node); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 606 | break; |
| 607 | case IrOpcode::kChangeInt31ToTaggedSigned: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 608 | result = LowerChangeInt31ToTaggedSigned(node); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 609 | break; |
| 610 | case IrOpcode::kChangeInt32ToTagged: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 611 | result = LowerChangeInt32ToTagged(node); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 612 | break; |
| 613 | case IrOpcode::kChangeUint32ToTagged: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 614 | result = LowerChangeUint32ToTagged(node); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 615 | break; |
| 616 | case IrOpcode::kChangeFloat64ToTagged: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 617 | result = LowerChangeFloat64ToTagged(node); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 618 | break; |
| Ben Murdoch | c8c1d9e | 2017-03-08 14:04:23 +0000 | [diff] [blame] | 619 | case IrOpcode::kChangeFloat64ToTaggedPointer: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 620 | result = LowerChangeFloat64ToTaggedPointer(node); |
| Ben Murdoch | c8c1d9e | 2017-03-08 14:04:23 +0000 | [diff] [blame] | 621 | break; |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 622 | case IrOpcode::kChangeTaggedSignedToInt32: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 623 | result = LowerChangeTaggedSignedToInt32(node); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 624 | break; |
| 625 | case IrOpcode::kChangeTaggedToBit: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 626 | result = LowerChangeTaggedToBit(node); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 627 | break; |
| 628 | case IrOpcode::kChangeTaggedToInt32: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 629 | result = LowerChangeTaggedToInt32(node); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 630 | break; |
| 631 | case IrOpcode::kChangeTaggedToUint32: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 632 | result = LowerChangeTaggedToUint32(node); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 633 | break; |
| 634 | case IrOpcode::kChangeTaggedToFloat64: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 635 | result = LowerChangeTaggedToFloat64(node); |
| 636 | break; |
| 637 | case IrOpcode::kChangeTaggedToTaggedSigned: |
| 638 | result = LowerChangeTaggedToTaggedSigned(node); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 639 | break; |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 640 | case IrOpcode::kTruncateTaggedToBit: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 641 | result = LowerTruncateTaggedToBit(node); |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 642 | break; |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 643 | case IrOpcode::kTruncateTaggedToFloat64: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 644 | result = LowerTruncateTaggedToFloat64(node); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 645 | break; |
| 646 | case IrOpcode::kCheckBounds: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 647 | result = LowerCheckBounds(node, frame_state); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 648 | break; |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 649 | case IrOpcode::kCheckMaps: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 650 | result = LowerCheckMaps(node, frame_state); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 651 | break; |
| 652 | case IrOpcode::kCheckNumber: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 653 | result = LowerCheckNumber(node, frame_state); |
| 654 | break; |
| 655 | case IrOpcode::kCheckReceiver: |
| 656 | result = LowerCheckReceiver(node, frame_state); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 657 | break; |
| 658 | case IrOpcode::kCheckString: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 659 | result = LowerCheckString(node, frame_state); |
| 660 | break; |
| 661 | case IrOpcode::kCheckInternalizedString: |
| 662 | result = LowerCheckInternalizedString(node, frame_state); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 663 | break; |
| 664 | case IrOpcode::kCheckIf: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 665 | result = LowerCheckIf(node, frame_state); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 666 | break; |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 667 | case IrOpcode::kCheckedInt32Add: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 668 | result = LowerCheckedInt32Add(node, frame_state); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 669 | break; |
| 670 | case IrOpcode::kCheckedInt32Sub: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 671 | result = LowerCheckedInt32Sub(node, frame_state); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 672 | break; |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 673 | case IrOpcode::kCheckedInt32Div: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 674 | result = LowerCheckedInt32Div(node, frame_state); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 675 | break; |
| 676 | case IrOpcode::kCheckedInt32Mod: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 677 | result = LowerCheckedInt32Mod(node, frame_state); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 678 | break; |
| 679 | case IrOpcode::kCheckedUint32Div: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 680 | result = LowerCheckedUint32Div(node, frame_state); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 681 | break; |
| 682 | case IrOpcode::kCheckedUint32Mod: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 683 | result = LowerCheckedUint32Mod(node, frame_state); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 684 | break; |
| 685 | case IrOpcode::kCheckedInt32Mul: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 686 | result = LowerCheckedInt32Mul(node, frame_state); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 687 | break; |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 688 | case IrOpcode::kCheckedInt32ToTaggedSigned: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 689 | result = LowerCheckedInt32ToTaggedSigned(node, frame_state); |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 690 | break; |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 691 | case IrOpcode::kCheckedUint32ToInt32: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 692 | result = LowerCheckedUint32ToInt32(node, frame_state); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 693 | break; |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 694 | case IrOpcode::kCheckedUint32ToTaggedSigned: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 695 | result = LowerCheckedUint32ToTaggedSigned(node, frame_state); |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 696 | break; |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 697 | case IrOpcode::kCheckedFloat64ToInt32: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 698 | result = LowerCheckedFloat64ToInt32(node, frame_state); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 699 | break; |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 700 | case IrOpcode::kCheckedTaggedSignedToInt32: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 701 | result = LowerCheckedTaggedSignedToInt32(node, frame_state); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 702 | break; |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 703 | case IrOpcode::kCheckedTaggedToInt32: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 704 | result = LowerCheckedTaggedToInt32(node, frame_state); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 705 | break; |
| 706 | case IrOpcode::kCheckedTaggedToFloat64: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 707 | result = LowerCheckedTaggedToFloat64(node, frame_state); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 708 | break; |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 709 | case IrOpcode::kCheckedTaggedToTaggedSigned: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 710 | result = LowerCheckedTaggedToTaggedSigned(node, frame_state); |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 711 | break; |
| Ben Murdoch | c8c1d9e | 2017-03-08 14:04:23 +0000 | [diff] [blame] | 712 | case IrOpcode::kCheckedTaggedToTaggedPointer: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 713 | result = LowerCheckedTaggedToTaggedPointer(node, frame_state); |
| Ben Murdoch | c8c1d9e | 2017-03-08 14:04:23 +0000 | [diff] [blame] | 714 | break; |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 715 | case IrOpcode::kTruncateTaggedToWord32: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 716 | result = LowerTruncateTaggedToWord32(node); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 717 | break; |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 718 | case IrOpcode::kCheckedTruncateTaggedToWord32: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 719 | result = LowerCheckedTruncateTaggedToWord32(node, frame_state); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 720 | break; |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 721 | case IrOpcode::kObjectIsDetectableCallable: |
| 722 | result = LowerObjectIsDetectableCallable(node); |
| 723 | break; |
| 724 | case IrOpcode::kObjectIsNonCallable: |
| 725 | result = LowerObjectIsNonCallable(node); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 726 | break; |
| 727 | case IrOpcode::kObjectIsNumber: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 728 | result = LowerObjectIsNumber(node); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 729 | break; |
| 730 | case IrOpcode::kObjectIsReceiver: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 731 | result = LowerObjectIsReceiver(node); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 732 | break; |
| 733 | case IrOpcode::kObjectIsSmi: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 734 | result = LowerObjectIsSmi(node); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 735 | break; |
| 736 | case IrOpcode::kObjectIsString: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 737 | result = LowerObjectIsString(node); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 738 | break; |
| 739 | case IrOpcode::kObjectIsUndetectable: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 740 | result = LowerObjectIsUndetectable(node); |
| 741 | break; |
| 742 | case IrOpcode::kNewRestParameterElements: |
| 743 | result = LowerNewRestParameterElements(node); |
| 744 | break; |
| 745 | case IrOpcode::kNewUnmappedArgumentsElements: |
| 746 | result = LowerNewUnmappedArgumentsElements(node); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 747 | break; |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 748 | case IrOpcode::kArrayBufferWasNeutered: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 749 | result = LowerArrayBufferWasNeutered(node); |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 750 | break; |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 751 | case IrOpcode::kStringFromCharCode: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 752 | result = LowerStringFromCharCode(node); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 753 | break; |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 754 | case IrOpcode::kStringFromCodePoint: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 755 | result = LowerStringFromCodePoint(node); |
| 756 | break; |
| 757 | case IrOpcode::kStringIndexOf: |
| 758 | result = LowerStringIndexOf(node); |
| 759 | break; |
| 760 | case IrOpcode::kStringCharAt: |
| 761 | result = LowerStringCharAt(node); |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 762 | break; |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 763 | case IrOpcode::kStringCharCodeAt: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 764 | result = LowerStringCharCodeAt(node); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 765 | break; |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 766 | case IrOpcode::kStringEqual: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 767 | result = LowerStringEqual(node); |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 768 | break; |
| 769 | case IrOpcode::kStringLessThan: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 770 | result = LowerStringLessThan(node); |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 771 | break; |
| 772 | case IrOpcode::kStringLessThanOrEqual: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 773 | result = LowerStringLessThanOrEqual(node); |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 774 | break; |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 775 | case IrOpcode::kCheckFloat64Hole: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 776 | result = LowerCheckFloat64Hole(node, frame_state); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 777 | break; |
| 778 | case IrOpcode::kCheckTaggedHole: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 779 | result = LowerCheckTaggedHole(node, frame_state); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 780 | break; |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 781 | case IrOpcode::kConvertTaggedHoleToUndefined: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 782 | result = LowerConvertTaggedHoleToUndefined(node); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 783 | break; |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 784 | case IrOpcode::kPlainPrimitiveToNumber: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 785 | result = LowerPlainPrimitiveToNumber(node); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 786 | break; |
| 787 | case IrOpcode::kPlainPrimitiveToWord32: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 788 | result = LowerPlainPrimitiveToWord32(node); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 789 | break; |
| 790 | case IrOpcode::kPlainPrimitiveToFloat64: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 791 | result = LowerPlainPrimitiveToFloat64(node); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 792 | break; |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 793 | case IrOpcode::kEnsureWritableFastElements: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 794 | result = LowerEnsureWritableFastElements(node); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 795 | break; |
| 796 | case IrOpcode::kMaybeGrowFastElements: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 797 | result = LowerMaybeGrowFastElements(node, frame_state); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 798 | break; |
| 799 | case IrOpcode::kTransitionElementsKind: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 800 | LowerTransitionElementsKind(node); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 801 | break; |
| 802 | case IrOpcode::kLoadTypedElement: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 803 | result = LowerLoadTypedElement(node); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 804 | break; |
| 805 | case IrOpcode::kStoreTypedElement: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 806 | LowerStoreTypedElement(node); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 807 | break; |
| 808 | case IrOpcode::kFloat64RoundUp: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 809 | if (!LowerFloat64RoundUp(node).To(&result)) { |
| 810 | return false; |
| 811 | } |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 812 | break; |
| 813 | case IrOpcode::kFloat64RoundDown: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 814 | if (!LowerFloat64RoundDown(node).To(&result)) { |
| 815 | return false; |
| 816 | } |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 817 | break; |
| 818 | case IrOpcode::kFloat64RoundTruncate: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 819 | if (!LowerFloat64RoundTruncate(node).To(&result)) { |
| 820 | return false; |
| 821 | } |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 822 | break; |
| Ben Murdoch | c8c1d9e | 2017-03-08 14:04:23 +0000 | [diff] [blame] | 823 | case IrOpcode::kFloat64RoundTiesEven: |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 824 | if (!LowerFloat64RoundTiesEven(node).To(&result)) { |
| 825 | return false; |
| 826 | } |
| Ben Murdoch | c8c1d9e | 2017-03-08 14:04:23 +0000 | [diff] [blame] | 827 | break; |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 828 | default: |
| 829 | return false; |
| 830 | } |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 831 | *effect = gasm()->ExtractCurrentEffect(); |
| 832 | *control = gasm()->ExtractCurrentControl(); |
| 833 | NodeProperties::ReplaceUses(node, result, *effect, *control); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 834 | return true; |
| 835 | } |
| 836 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 837 | #define __ gasm()-> |
| 838 | |
| 839 | Node* EffectControlLinearizer::LowerChangeFloat64ToTagged(Node* node) { |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 840 | Node* value = node->InputAt(0); |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 841 | return AllocateHeapNumberWithValue(value); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 842 | } |
| 843 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 844 | Node* EffectControlLinearizer::LowerChangeFloat64ToTaggedPointer(Node* node) { |
| Ben Murdoch | c8c1d9e | 2017-03-08 14:04:23 +0000 | [diff] [blame] | 845 | Node* value = node->InputAt(0); |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 846 | return AllocateHeapNumberWithValue(value); |
| Ben Murdoch | c8c1d9e | 2017-03-08 14:04:23 +0000 | [diff] [blame] | 847 | } |
| 848 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 849 | Node* EffectControlLinearizer::LowerChangeBitToTagged(Node* node) { |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 850 | Node* value = node->InputAt(0); |
| 851 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 852 | auto if_true = __ MakeLabel<1>(); |
| 853 | auto done = __ MakeLabel<2>(MachineRepresentation::kTagged); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 854 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 855 | __ GotoIf(value, &if_true); |
| 856 | __ Goto(&done, __ FalseConstant()); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 857 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 858 | __ Bind(&if_true); |
| 859 | __ Goto(&done, __ TrueConstant()); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 860 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 861 | __ Bind(&done); |
| 862 | return done.PhiAt(0); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 863 | } |
| 864 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 865 | Node* EffectControlLinearizer::LowerChangeInt31ToTaggedSigned(Node* node) { |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 866 | Node* value = node->InputAt(0); |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 867 | return ChangeInt32ToSmi(value); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 868 | } |
| 869 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 870 | Node* EffectControlLinearizer::LowerChangeInt32ToTagged(Node* node) { |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 871 | Node* value = node->InputAt(0); |
| 872 | |
| 873 | if (machine()->Is64()) { |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 874 | return ChangeInt32ToSmi(value); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 875 | } |
| 876 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 877 | auto if_overflow = __ MakeDeferredLabel<1>(); |
| 878 | auto done = __ MakeLabel<2>(MachineRepresentation::kTagged); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 879 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 880 | Node* add = __ Int32AddWithOverflow(value, value); |
| 881 | Node* ovf = __ Projection(1, add); |
| 882 | __ GotoIf(ovf, &if_overflow); |
| 883 | __ Goto(&done, __ Projection(0, add)); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 884 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 885 | __ Bind(&if_overflow); |
| 886 | Node* number = AllocateHeapNumberWithValue(__ ChangeInt32ToFloat64(value)); |
| 887 | __ Goto(&done, number); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 888 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 889 | __ Bind(&done); |
| 890 | return done.PhiAt(0); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 891 | } |
| 892 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 893 | Node* EffectControlLinearizer::LowerChangeUint32ToTagged(Node* node) { |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 894 | Node* value = node->InputAt(0); |
| 895 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 896 | auto if_not_in_smi_range = __ MakeDeferredLabel<1>(); |
| 897 | auto done = __ MakeLabel<2>(MachineRepresentation::kTagged); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 898 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 899 | Node* check = __ Uint32LessThanOrEqual(value, SmiMaxValueConstant()); |
| 900 | __ GotoUnless(check, &if_not_in_smi_range); |
| 901 | __ Goto(&done, ChangeUint32ToSmi(value)); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 902 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 903 | __ Bind(&if_not_in_smi_range); |
| 904 | Node* number = AllocateHeapNumberWithValue(__ ChangeUint32ToFloat64(value)); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 905 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 906 | __ Goto(&done, number); |
| 907 | __ Bind(&done); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 908 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 909 | return done.PhiAt(0); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 910 | } |
| 911 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 912 | Node* EffectControlLinearizer::LowerChangeTaggedSignedToInt32(Node* node) { |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 913 | Node* value = node->InputAt(0); |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 914 | return ChangeSmiToInt32(value); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 915 | } |
| 916 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 917 | Node* EffectControlLinearizer::LowerChangeTaggedToBit(Node* node) { |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 918 | Node* value = node->InputAt(0); |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 919 | return __ WordEqual(value, __ TrueConstant()); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 920 | } |
| 921 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 922 | Node* EffectControlLinearizer::LowerTruncateTaggedToBit(Node* node) { |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 923 | Node* value = node->InputAt(0); |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 924 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 925 | 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 Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 934 | |
| 935 | // Check if {value} is a Smi. |
| 936 | Node* check_smi = ObjectIsSmi(value); |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 937 | __ GotoIf(check_smi, &if_smi); |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 938 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 939 | // Check if {value} is the empty string. |
| 940 | __ GotoIf(__ WordEqual(value, __ EmptyStringConstant()), &done, zero); |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 941 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 942 | // Load the map of {value}. |
| 943 | Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 944 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 945 | // 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 Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 953 | |
| 954 | // Check if {value} is a HeapNumber. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 955 | __ GotoIf(__ WordEqual(value_map, __ HeapNumberMapConstant()), |
| 956 | &if_heapnumber); |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 957 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 958 | // All other values that reach here are true. |
| 959 | __ Goto(&done, __ Int32Constant(1)); |
| 960 | |
| 961 | __ Bind(&if_heapnumber); |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 962 | { |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 963 | // 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 Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 968 | } |
| 969 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 970 | __ 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 Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 976 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 977 | __ Bind(&done); |
| 978 | return done.PhiAt(0); |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 979 | } |
| 980 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 981 | Node* EffectControlLinearizer::LowerChangeTaggedToInt32(Node* node) { |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 982 | Node* value = node->InputAt(0); |
| 983 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 984 | auto if_not_smi = __ MakeDeferredLabel<1>(); |
| 985 | auto done = __ MakeLabel<2>(MachineRepresentation::kWord32); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 986 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 987 | 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 | |
| 1001 | Node* 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 | |
| 1021 | Node* EffectControlLinearizer::LowerChangeTaggedToFloat64(Node* node) { |
| 1022 | return LowerTruncateTaggedToFloat64(node); |
| 1023 | } |
| 1024 | |
| 1025 | Node* 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 | |
| 1046 | Node* 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 Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 1054 | Node* vtrue = ChangeSmiToInt32(value); |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1055 | vtrue = __ ChangeInt32ToFloat64(vtrue); |
| 1056 | __ Goto(&done, vtrue); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 1057 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1058 | __ Bind(&if_not_smi); |
| 1059 | STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset); |
| 1060 | Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value); |
| 1061 | __ Goto(&done, vfalse); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 1062 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1063 | __ Bind(&done); |
| 1064 | return done.PhiAt(0); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 1065 | } |
| 1066 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1067 | Node* EffectControlLinearizer::LowerCheckBounds(Node* node, Node* frame_state) { |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 1068 | Node* index = node->InputAt(0); |
| 1069 | Node* limit = node->InputAt(1); |
| 1070 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1071 | Node* check = __ Uint32LessThan(index, limit); |
| 1072 | __ DeoptimizeUnless(DeoptimizeReason::kOutOfBounds, check, frame_state); |
| 1073 | return index; |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 1074 | } |
| 1075 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1076 | Node* EffectControlLinearizer::LowerCheckMaps(Node* node, Node* frame_state) { |
| 1077 | CheckMapsParameters const& p = CheckMapsParametersOf(node->op()); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1078 | Node* value = node->InputAt(0); |
| 1079 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1080 | ZoneHandleSet<Map> const& maps = p.maps(); |
| 1081 | size_t const map_count = maps.size(); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1082 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1083 | if (p.flags() & CheckMapsFlag::kTryMigrateInstance) { |
| 1084 | auto done = |
| 1085 | __ MakeLabelFor(GraphAssemblerLabelType::kNonDeferred, map_count * 2); |
| 1086 | auto migrate = __ MakeDeferredLabel<1>(); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1087 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1088 | // Load the current map of the {value}. |
| 1089 | Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1090 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1091 | // 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1101 | } |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1102 | |
| 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1162 | } |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1163 | return value; |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1164 | } |
| 1165 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1166 | Node* EffectControlLinearizer::LowerCheckNumber(Node* node, Node* frame_state) { |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1167 | Node* value = node->InputAt(0); |
| 1168 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1169 | auto if_not_smi = __ MakeDeferredLabel<1>(); |
| 1170 | auto done = __ MakeLabel<2>(); |
| 1171 | |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1172 | Node* check0 = ObjectIsSmi(value); |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1173 | __ GotoUnless(check0, &if_not_smi); |
| 1174 | __ Goto(&done); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1175 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1176 | __ 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1181 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1182 | __ Bind(&done); |
| 1183 | return value; |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1184 | } |
| 1185 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1186 | Node* EffectControlLinearizer::LowerCheckReceiver(Node* node, |
| 1187 | Node* frame_state) { |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1188 | Node* value = node->InputAt(0); |
| 1189 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1190 | Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); |
| 1191 | Node* value_instance_type = |
| 1192 | __ LoadField(AccessBuilder::ForMapInstanceType(), value_map); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1193 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1194 | 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1200 | } |
| 1201 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1202 | Node* EffectControlLinearizer::LowerCheckString(Node* node, Node* frame_state) { |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1203 | Node* value = node->InputAt(0); |
| 1204 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1205 | Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); |
| 1206 | Node* value_instance_type = |
| 1207 | __ LoadField(AccessBuilder::ForMapInstanceType(), value_map); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1208 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1209 | Node* check = __ Uint32LessThan(value_instance_type, |
| 1210 | __ Uint32Constant(FIRST_NONSTRING_TYPE)); |
| 1211 | __ DeoptimizeUnless(DeoptimizeReason::kWrongInstanceType, check, frame_state); |
| 1212 | return value; |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1213 | } |
| 1214 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1215 | Node* 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 | |
| 1232 | Node* 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 | |
| 1239 | Node* EffectControlLinearizer::LowerCheckedInt32Add(Node* node, |
| 1240 | Node* frame_state) { |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 1241 | Node* lhs = node->InputAt(0); |
| 1242 | Node* rhs = node->InputAt(1); |
| 1243 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1244 | Node* value = __ Int32AddWithOverflow(lhs, rhs); |
| 1245 | Node* check = __ Projection(1, value); |
| 1246 | __ DeoptimizeIf(DeoptimizeReason::kOverflow, check, frame_state); |
| 1247 | return __ Projection(0, value); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 1248 | } |
| 1249 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1250 | Node* EffectControlLinearizer::LowerCheckedInt32Sub(Node* node, |
| 1251 | Node* frame_state) { |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 1252 | Node* lhs = node->InputAt(0); |
| 1253 | Node* rhs = node->InputAt(1); |
| 1254 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1255 | Node* value = __ Int32SubWithOverflow(lhs, rhs); |
| 1256 | Node* check = __ Projection(1, value); |
| 1257 | __ DeoptimizeIf(DeoptimizeReason::kOverflow, check, frame_state); |
| 1258 | return __ Projection(0, value); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1259 | } |
| 1260 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1261 | Node* EffectControlLinearizer::LowerCheckedInt32Div(Node* node, |
| 1262 | Node* frame_state) { |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1263 | Node* lhs = node->InputAt(0); |
| 1264 | Node* rhs = node->InputAt(1); |
| 1265 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1266 | 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1273 | // Check if {rhs} is positive (and not zero). |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1274 | Node* check0 = __ Int32LessThan(zero, rhs); |
| 1275 | __ GotoUnless(check0, &if_not_positive); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1276 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1277 | // Fast case, no additional checking required. |
| 1278 | __ Goto(&done, __ Int32Div(lhs, rhs)); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1279 | |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1280 | { |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1281 | __ Bind(&if_not_positive); |
| 1282 | |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1283 | // Check if {rhs} is zero. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1284 | Node* check = __ Word32Equal(rhs, zero); |
| 1285 | __ DeoptimizeIf(DeoptimizeReason::kDivisionByZero, check, frame_state); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1286 | |
| 1287 | // Check if {lhs} is zero, as that would produce minus zero. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1288 | check = __ Word32Equal(lhs, zero); |
| 1289 | __ DeoptimizeIf(DeoptimizeReason::kMinusZero, check, frame_state); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1290 | |
| 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 Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1293 | Node* minint = __ Int32Constant(std::numeric_limits<int32_t>::min()); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1294 | Node* check1 = graph()->NewNode(machine()->Word32Equal(), lhs, minint); |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1295 | __ GotoIf(check1, &if_is_minint); |
| 1296 | __ Goto(&minint_check_done); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1297 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1298 | __ 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1304 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1305 | __ Bind(&minint_check_done); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1306 | // Perform the actual integer division. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1307 | __ Goto(&done, __ Int32Div(lhs, rhs)); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1308 | } |
| 1309 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1310 | __ Bind(&done); |
| 1311 | Node* value = done.PhiAt(0); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1312 | |
| 1313 | // Check if the remainder is non-zero. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1314 | Node* check = __ Word32Equal(lhs, __ Int32Mul(rhs, value)); |
| 1315 | __ DeoptimizeUnless(DeoptimizeReason::kLostPrecision, check, frame_state); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1316 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1317 | return value; |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1318 | } |
| 1319 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1320 | Node* EffectControlLinearizer::LowerCheckedInt32Mod(Node* node, |
| 1321 | Node* frame_state) { |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1322 | // 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 Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1342 | 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1347 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1348 | 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1356 | { |
| 1357 | // Negate {rhs}, might still produce a negative result in case of |
| 1358 | // -2^31, but that is handled safely below. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1359 | Node* vtrue0 = __ Int32Sub(zero, rhs); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1360 | |
| 1361 | // Ensure that {rhs} is not zero, otherwise we'd have to return NaN. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1362 | Node* check = __ Word32Equal(vtrue0, zero); |
| 1363 | __ DeoptimizeIf(DeoptimizeReason::kDivisionByZero, check, frame_state); |
| 1364 | __ Goto(&rhs_checked, vtrue0); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1365 | } |
| 1366 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1367 | __ Bind(&rhs_checked); |
| 1368 | rhs = rhs_checked.PhiAt(0); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1369 | |
| 1370 | // Check if {lhs} is negative. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1371 | Node* check1 = __ Int32LessThan(lhs, zero); |
| 1372 | __ GotoIf(check1, &if_lhs_negative); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1373 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1374 | // {lhs} non-negative. |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1375 | { |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1376 | Node* one = __ Int32Constant(1); |
| 1377 | Node* msk = __ Int32Sub(rhs, one); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1378 | |
| 1379 | // Check if {rhs} minus one is a valid mask. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1380 | Node* check2 = __ Word32Equal(__ Word32And(rhs, msk), zero); |
| 1381 | __ GotoIf(check2, &if_power_of_two); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1382 | // Compute the remainder using the generic {lhs % rhs}. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1383 | __ Goto(&done, __ Int32Mod(lhs, rhs)); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1384 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1385 | __ Bind(&if_power_of_two); |
| 1386 | // Compute the remainder using {lhs & msk}. |
| 1387 | __ Goto(&done, __ Word32And(lhs, msk)); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1388 | } |
| 1389 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1390 | __ Bind(&if_lhs_negative); |
| 1391 | { |
| 1392 | // Compute the remainder using {lhs % msk}. |
| 1393 | Node* vtrue1 = __ Int32Mod(lhs, rhs); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1394 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1395 | // 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1403 | } |
| 1404 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1405 | Node* EffectControlLinearizer::LowerCheckedUint32Div(Node* node, |
| 1406 | Node* frame_state) { |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1407 | Node* lhs = node->InputAt(0); |
| 1408 | Node* rhs = node->InputAt(1); |
| 1409 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1410 | Node* zero = __ Int32Constant(0); |
| 1411 | |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1412 | // Ensure that {rhs} is not zero, otherwise we'd have to return NaN. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1413 | Node* check = __ Word32Equal(rhs, zero); |
| 1414 | __ DeoptimizeIf(DeoptimizeReason::kDivisionByZero, check, frame_state); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1415 | |
| 1416 | // Perform the actual unsigned integer division. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1417 | Node* value = __ Uint32Div(lhs, rhs); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1418 | |
| 1419 | // Check if the remainder is non-zero. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1420 | check = __ Word32Equal(lhs, __ Int32Mul(rhs, value)); |
| 1421 | __ DeoptimizeUnless(DeoptimizeReason::kLostPrecision, check, frame_state); |
| 1422 | return value; |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1423 | } |
| 1424 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1425 | Node* EffectControlLinearizer::LowerCheckedUint32Mod(Node* node, |
| 1426 | Node* frame_state) { |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1427 | Node* lhs = node->InputAt(0); |
| 1428 | Node* rhs = node->InputAt(1); |
| 1429 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1430 | Node* zero = __ Int32Constant(0); |
| 1431 | |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1432 | // Ensure that {rhs} is not zero, otherwise we'd have to return NaN. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1433 | Node* check = __ Word32Equal(rhs, zero); |
| 1434 | __ DeoptimizeIf(DeoptimizeReason::kDivisionByZero, check, frame_state); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1435 | |
| 1436 | // Perform the actual unsigned integer modulus. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1437 | return __ Uint32Mod(lhs, rhs); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1438 | } |
| 1439 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1440 | Node* EffectControlLinearizer::LowerCheckedInt32Mul(Node* node, |
| 1441 | Node* frame_state) { |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1442 | CheckForMinusZeroMode mode = CheckMinusZeroModeOf(node->op()); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1443 | Node* lhs = node->InputAt(0); |
| 1444 | Node* rhs = node->InputAt(1); |
| 1445 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1446 | Node* projection = __ Int32MulWithOverflow(lhs, rhs); |
| 1447 | Node* check = __ Projection(1, projection); |
| 1448 | __ DeoptimizeIf(DeoptimizeReason::kOverflow, check, frame_state); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1449 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1450 | Node* value = __ Projection(0, projection); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1451 | |
| 1452 | if (mode == CheckForMinusZeroMode::kCheckForMinusZero) { |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1453 | 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1459 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1460 | __ 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1465 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1466 | __ Bind(&check_done); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1467 | } |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 1468 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1469 | return value; |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 1470 | } |
| 1471 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1472 | Node* EffectControlLinearizer::LowerCheckedInt32ToTaggedSigned( |
| 1473 | Node* node, Node* frame_state) { |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 1474 | DCHECK(SmiValuesAre31Bits()); |
| 1475 | Node* value = node->InputAt(0); |
| 1476 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1477 | Node* add = __ Int32AddWithOverflow(value, value); |
| 1478 | Node* check = __ Projection(1, add); |
| 1479 | __ DeoptimizeIf(DeoptimizeReason::kOverflow, check, frame_state); |
| 1480 | return __ Projection(0, add); |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 1481 | } |
| 1482 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1483 | Node* EffectControlLinearizer::LowerCheckedUint32ToInt32(Node* node, |
| 1484 | Node* frame_state) { |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 1485 | Node* value = node->InputAt(0); |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1486 | 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 Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 1490 | } |
| 1491 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1492 | Node* EffectControlLinearizer::LowerCheckedUint32ToTaggedSigned( |
| 1493 | Node* node, Node* frame_state) { |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 1494 | Node* value = node->InputAt(0); |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1495 | Node* check = __ Uint32LessThanOrEqual(value, SmiMaxValueConstant()); |
| 1496 | __ DeoptimizeUnless(DeoptimizeReason::kLostPrecision, check, frame_state); |
| 1497 | return ChangeUint32ToSmi(value); |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 1498 | } |
| 1499 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1500 | Node* 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 Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 1506 | |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1507 | if (mode == CheckForMinusZeroMode::kCheckForMinusZero) { |
| 1508 | // Check if {value} is -0. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1509 | auto if_zero = __ MakeDeferredLabel<1>(); |
| 1510 | auto check_done = __ MakeLabel<2>(); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 1511 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1512 | Node* check_zero = __ Word32Equal(value32, __ Int32Constant(0)); |
| 1513 | __ GotoIf(check_zero, &if_zero); |
| 1514 | __ Goto(&check_done); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 1515 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1516 | __ Bind(&if_zero); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1517 | // In case of 0, we need to check the high bits for the IEEE -0 pattern. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1518 | Node* check_negative = __ Int32LessThan(__ Float64ExtractHighWord32(value), |
| 1519 | __ Int32Constant(0)); |
| 1520 | __ DeoptimizeIf(DeoptimizeReason::kMinusZero, check_negative, frame_state); |
| 1521 | __ Goto(&check_done); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 1522 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1523 | __ Bind(&check_done); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1524 | } |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1525 | return value32; |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 1526 | } |
| 1527 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1528 | Node* 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 | |
| 1535 | Node* 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 | |
| 1543 | Node* EffectControlLinearizer::LowerCheckedTaggedToInt32(Node* node, |
| 1544 | Node* frame_state) { |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1545 | CheckForMinusZeroMode mode = CheckMinusZeroModeOf(node->op()); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 1546 | Node* value = node->InputAt(0); |
| 1547 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1548 | auto if_not_smi = __ MakeDeferredLabel<1>(); |
| 1549 | auto done = __ MakeLabel<2>(MachineRepresentation::kWord32); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1550 | |
| 1551 | Node* check = ObjectIsSmi(value); |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1552 | __ GotoUnless(check, &if_not_smi); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 1553 | // In the Smi case, just convert to int32. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1554 | __ Goto(&done, ChangeSmiToInt32(value)); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 1555 | |
| 1556 | // In the non-Smi case, check the heap numberness, load the number and convert |
| 1557 | // to int32. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1558 | __ 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 Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 1566 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1567 | __ Bind(&done); |
| 1568 | return done.PhiAt(0); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 1569 | } |
| 1570 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1571 | Node* 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1575 | switch (mode) { |
| 1576 | case CheckTaggedInputMode::kNumber: { |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1577 | __ DeoptimizeUnless(DeoptimizeReason::kNotAHeapNumber, check_number, |
| 1578 | frame_state); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1579 | break; |
| 1580 | } |
| 1581 | case CheckTaggedInputMode::kNumberOrOddball: { |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1582 | auto check_done = __ MakeLabel<2>(); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 1583 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1584 | __ GotoIf(check_number, &check_done); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1585 | // For oddballs also contain the numeric value, let us just check that |
| 1586 | // we have an oddball here. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1587 | Node* instance_type = |
| 1588 | __ LoadField(AccessBuilder::ForMapInstanceType(), value_map); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1589 | Node* check_oddball = |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1590 | __ Word32Equal(instance_type, __ Int32Constant(ODDBALL_TYPE)); |
| 1591 | __ DeoptimizeUnless(DeoptimizeReason::kNotANumberOrOddball, check_oddball, |
| 1592 | frame_state); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1593 | STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset); |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1594 | __ Goto(&check_done); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 1595 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1596 | __ Bind(&check_done); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1597 | break; |
| 1598 | } |
| 1599 | } |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1600 | return __ LoadField(AccessBuilder::ForHeapNumberValue(), value); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 1601 | } |
| 1602 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1603 | Node* EffectControlLinearizer::LowerCheckedTaggedToFloat64(Node* node, |
| 1604 | Node* frame_state) { |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1605 | CheckTaggedInputMode mode = CheckTaggedInputModeOf(node->op()); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 1606 | Node* value = node->InputAt(0); |
| 1607 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1608 | auto if_smi = __ MakeLabel<1>(); |
| 1609 | auto done = __ MakeLabel<2>(MachineRepresentation::kFloat64); |
| 1610 | |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 1611 | Node* check = ObjectIsSmi(value); |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1612 | __ GotoIf(check, &if_smi); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 1613 | |
| 1614 | // In the Smi case, just convert to int32 and then float64. |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 1615 | // Otherwise, check heap numberness and load the number. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1616 | Node* number = |
| 1617 | BuildCheckedHeapNumberOrOddballToFloat64(mode, value, frame_state); |
| 1618 | __ Goto(&done, number); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 1619 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1620 | __ Bind(&if_smi); |
| 1621 | Node* from_smi = ChangeSmiToInt32(value); |
| 1622 | from_smi = __ ChangeInt32ToFloat64(from_smi); |
| 1623 | __ Goto(&done, from_smi); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 1624 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1625 | __ Bind(&done); |
| 1626 | return done.PhiAt(0); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 1627 | } |
| 1628 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1629 | Node* EffectControlLinearizer::LowerCheckedTaggedToTaggedSigned( |
| 1630 | Node* node, Node* frame_state) { |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 1631 | Node* value = node->InputAt(0); |
| 1632 | |
| 1633 | Node* check = ObjectIsSmi(value); |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1634 | __ DeoptimizeUnless(DeoptimizeReason::kNotASmi, check, frame_state); |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 1635 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1636 | return value; |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 1637 | } |
| 1638 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1639 | Node* EffectControlLinearizer::LowerCheckedTaggedToTaggedPointer( |
| 1640 | Node* node, Node* frame_state) { |
| Ben Murdoch | c8c1d9e | 2017-03-08 14:04:23 +0000 | [diff] [blame] | 1641 | Node* value = node->InputAt(0); |
| 1642 | |
| 1643 | Node* check = ObjectIsSmi(value); |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1644 | __ DeoptimizeIf(DeoptimizeReason::kSmi, check, frame_state); |
| 1645 | return value; |
| Ben Murdoch | c8c1d9e | 2017-03-08 14:04:23 +0000 | [diff] [blame] | 1646 | } |
| 1647 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1648 | Node* EffectControlLinearizer::LowerTruncateTaggedToWord32(Node* node) { |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 1649 | Node* value = node->InputAt(0); |
| 1650 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1651 | auto if_not_smi = __ MakeDeferredLabel<1>(); |
| 1652 | auto done = __ MakeLabel<2>(MachineRepresentation::kWord32); |
| 1653 | |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 1654 | Node* check = ObjectIsSmi(value); |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1655 | __ GotoUnless(check, &if_not_smi); |
| 1656 | __ Goto(&done, ChangeSmiToInt32(value)); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 1657 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1658 | __ 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 Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 1663 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1664 | __ Bind(&done); |
| 1665 | return done.PhiAt(0); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 1666 | } |
| 1667 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1668 | Node* EffectControlLinearizer::LowerCheckedTruncateTaggedToWord32( |
| 1669 | Node* node, Node* frame_state) { |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1670 | Node* value = node->InputAt(0); |
| 1671 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1672 | auto if_not_smi = __ MakeLabel<1>(); |
| 1673 | auto done = __ MakeLabel<2>(MachineRepresentation::kWord32); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1674 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1675 | Node* check = ObjectIsSmi(value); |
| 1676 | __ GotoUnless(check, &if_not_smi); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1677 | // In the Smi case, just convert to int32. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1678 | __ Goto(&done, ChangeSmiToInt32(value)); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1679 | |
| 1680 | // Otherwise, check that it's a heap number or oddball and truncate the value |
| 1681 | // to int32. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1682 | __ Bind(&if_not_smi); |
| 1683 | Node* number = BuildCheckedHeapNumberOrOddballToFloat64( |
| 1684 | CheckTaggedInputMode::kNumberOrOddball, value, frame_state); |
| 1685 | number = __ TruncateFloat64ToWord32(number); |
| 1686 | __ Goto(&done, number); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1687 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1688 | __ Bind(&done); |
| 1689 | return done.PhiAt(0); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 1690 | } |
| 1691 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1692 | Node* EffectControlLinearizer::LowerObjectIsDetectableCallable(Node* node) { |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 1693 | Node* value = node->InputAt(0); |
| 1694 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1695 | auto if_smi = __ MakeDeferredLabel<1>(); |
| 1696 | auto done = __ MakeLabel<2>(MachineRepresentation::kBit); |
| 1697 | |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 1698 | Node* check = ObjectIsSmi(value); |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1699 | __ GotoIf(check, &if_smi); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 1700 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1701 | 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 Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 1710 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1711 | __ Bind(&if_smi); |
| 1712 | __ Goto(&done, __ Int32Constant(0)); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 1713 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1714 | __ Bind(&done); |
| 1715 | return done.PhiAt(0); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 1716 | } |
| 1717 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1718 | Node* EffectControlLinearizer::LowerObjectIsNonCallable(Node* node) { |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 1719 | Node* value = node->InputAt(0); |
| 1720 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1721 | 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 | |
| 1749 | Node* 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 | |
| 1766 | Node* 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 | |
| 1789 | Node* EffectControlLinearizer::LowerObjectIsSmi(Node* node) { |
| 1790 | Node* value = node->InputAt(0); |
| 1791 | return ObjectIsSmi(value); |
| 1792 | } |
| 1793 | |
| 1794 | Node* 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 Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 1800 | Node* check = ObjectIsSmi(value); |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1801 | __ 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 Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 1808 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1809 | __ Bind(&if_smi); |
| 1810 | __ Goto(&done, __ Int32Constant(0)); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 1811 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1812 | __ Bind(&done); |
| 1813 | return done.PhiAt(0); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 1814 | } |
| 1815 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1816 | Node* EffectControlLinearizer::LowerObjectIsUndetectable(Node* node) { |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 1817 | Node* value = node->InputAt(0); |
| 1818 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1819 | auto if_smi = __ MakeDeferredLabel<1>(); |
| 1820 | auto done = __ MakeLabel<2>(MachineRepresentation::kBit); |
| 1821 | |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 1822 | Node* check = ObjectIsSmi(value); |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1823 | __ GotoIf(check, &if_smi); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 1824 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1825 | 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 Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 1834 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1835 | __ Bind(&if_smi); |
| 1836 | __ Goto(&done, __ Int32Constant(0)); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 1837 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1838 | __ Bind(&done); |
| 1839 | return done.PhiAt(0); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 1840 | } |
| 1841 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1842 | Node* 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 Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 1853 | } |
| 1854 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1855 | Node* 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 | |
| 1869 | Node* EffectControlLinearizer::LowerArrayBufferWasNeutered(Node* node) { |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 1870 | Node* value = node->InputAt(0); |
| 1871 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1872 | 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 Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 1880 | } |
| 1881 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1882 | Node* 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 | |
| 1895 | Node* 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 | |
| 1909 | Node* EffectControlLinearizer::LowerStringFromCharCode(Node* node) { |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 1910 | Node* value = node->InputAt(0); |
| 1911 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1912 | auto runtime_call = __ MakeDeferredLabel<2>(); |
| 1913 | auto if_undefined = __ MakeDeferredLabel<1>(); |
| 1914 | auto done = __ MakeLabel<2>(MachineRepresentation::kTagged); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 1915 | |
| 1916 | // Compute the character code. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1917 | Node* code = __ Word32And(value, __ Int32Constant(String::kMaxUtf16CodeUnit)); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 1918 | |
| 1919 | // Check if the {code} is a one-byte char code. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1920 | Node* check0 = __ Int32LessThanOrEqual( |
| 1921 | code, __ Int32Constant(String::kMaxOneByteCharCode)); |
| 1922 | __ GotoUnless(check0, &runtime_call); |
| Ben Murdoch | c8c1d9e | 2017-03-08 14:04:23 +0000 | [diff] [blame] | 1923 | |
| 1924 | // Load the isolate wide single character string cache. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1925 | Node* cache = __ HeapConstant(factory()->single_character_string_cache()); |
| Ben Murdoch | c8c1d9e | 2017-03-08 14:04:23 +0000 | [diff] [blame] | 1926 | |
| 1927 | // Compute the {cache} index for {code}. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1928 | Node* index = machine()->Is32() ? code : __ ChangeUint32ToUint64(code); |
| Ben Murdoch | c8c1d9e | 2017-03-08 14:04:23 +0000 | [diff] [blame] | 1929 | |
| 1930 | // Check if we have an entry for the {code} in the single character string |
| 1931 | // cache already. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1932 | Node* entry = |
| 1933 | __ LoadElement(AccessBuilder::ForFixedArrayElement(), cache, index); |
| Ben Murdoch | c8c1d9e | 2017-03-08 14:04:23 +0000 | [diff] [blame] | 1934 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1935 | Node* check1 = __ WordEqual(entry, __ UndefinedConstant()); |
| 1936 | __ GotoIf(check1, &runtime_call); |
| 1937 | __ Goto(&done, entry); |
| Ben Murdoch | c8c1d9e | 2017-03-08 14:04:23 +0000 | [diff] [blame] | 1938 | |
| 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 Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1942 | __ Bind(&runtime_call); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 1943 | { |
| Ben Murdoch | c8c1d9e | 2017-03-08 14:04:23 +0000 | [diff] [blame] | 1944 | 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 Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1948 | Node* vtrue1 = |
| 1949 | __ Call(desc, __ CEntryStubConstant(1), ChangeInt32ToSmi(code), |
| 1950 | __ ExternalConstant(ExternalReference(id, isolate())), |
| 1951 | __ Int32Constant(1), __ NoContextConstant()); |
| 1952 | __ Goto(&done, vtrue1); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 1953 | } |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1954 | __ Bind(&done); |
| 1955 | return done.PhiAt(0); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 1956 | } |
| 1957 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1958 | Node* EffectControlLinearizer::LowerStringFromCodePoint(Node* node) { |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 1959 | Node* value = node->InputAt(0); |
| 1960 | Node* code = value; |
| 1961 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1962 | 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 Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 1966 | |
| 1967 | // Check if the {code} is a single code unit |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1968 | Node* check0 = __ Uint32LessThanOrEqual(code, __ Uint32Constant(0xFFFF)); |
| 1969 | __ GotoUnless(check0, &if_not_single_code); |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 1970 | |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 1971 | { |
| 1972 | // Check if the {code} is a one byte character |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1973 | Node* check1 = __ Uint32LessThanOrEqual( |
| 1974 | code, __ Uint32Constant(String::kMaxOneByteCharCode)); |
| 1975 | __ GotoUnless(check1, &if_not_one_byte); |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 1976 | { |
| 1977 | // Load the isolate wide single character string cache. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1978 | Node* cache = __ HeapConstant(factory()->single_character_string_cache()); |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 1979 | |
| 1980 | // Compute the {cache} index for {code}. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1981 | Node* index = machine()->Is32() ? code : __ ChangeUint32ToUint64(code); |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 1982 | |
| 1983 | // Check if we have an entry for the {code} in the single character string |
| 1984 | // cache already. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1985 | Node* entry = |
| 1986 | __ LoadElement(AccessBuilder::ForFixedArrayElement(), cache, index); |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 1987 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1988 | Node* check2 = __ WordEqual(entry, __ UndefinedConstant()); |
| 1989 | __ GotoIf(check2, &cache_miss); |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 1990 | |
| 1991 | // Use the {entry} from the {cache}. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1992 | __ Goto(&done, entry); |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 1993 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 1994 | __ 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 Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 2016 | } |
| 2017 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2018 | __ Bind(&if_not_one_byte); |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 2019 | { |
| 2020 | // Allocate a new SeqTwoByteString for {code}. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2021 | 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 Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 2035 | } |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 2036 | } |
| 2037 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2038 | __ Bind(&if_not_single_code); |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 2039 | // Generate surrogate pair string |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 2040 | { |
| 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 Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2047 | Node* lead_offset = __ Int32Constant(0xD800 - (0x10000 >> 10)); |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 2048 | |
| 2049 | // lead = (codepoint >> 10) + LEAD_OFFSET |
| 2050 | Node* lead = |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2051 | __ Int32Add(__ Word32Shr(code, __ Int32Constant(10)), lead_offset); |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 2052 | |
| 2053 | // trail = (codepoint & 0x3FF) + 0xDC00; |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2054 | Node* trail = __ Int32Add(__ Word32And(code, __ Int32Constant(0x3FF)), |
| 2055 | __ Int32Constant(0xDC00)); |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 2056 | |
| 2057 | // codpoint = (trail << 16) | lead; |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2058 | code = __ Word32Or(__ Word32Shl(trail, __ Int32Constant(16)), lead); |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 2059 | break; |
| 2060 | } |
| 2061 | } |
| 2062 | |
| 2063 | // Allocate a new SeqTwoByteString for {code}. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2064 | 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 Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 2077 | } |
| 2078 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2079 | __ Bind(&done); |
| 2080 | return done.PhiAt(0); |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 2081 | } |
| 2082 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2083 | Node* 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 Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 2089 | 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 Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2093 | return __ Call(desc, __ HeapConstant(callable.code()), subject, search_string, |
| 2094 | position, __ NoContextConstant()); |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 2095 | } |
| 2096 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2097 | Node* 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 Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 2108 | } |
| 2109 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2110 | Node* EffectControlLinearizer::LowerStringEqual(Node* node) { |
| 2111 | return LowerStringComparison(CodeFactory::StringEqual(isolate()), node); |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 2112 | } |
| 2113 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2114 | Node* EffectControlLinearizer::LowerStringLessThan(Node* node) { |
| 2115 | return LowerStringComparison(CodeFactory::StringLessThan(isolate()), node); |
| 2116 | } |
| 2117 | |
| 2118 | Node* EffectControlLinearizer::LowerStringLessThanOrEqual(Node* node) { |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 2119 | return LowerStringComparison(CodeFactory::StringLessThanOrEqual(isolate()), |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2120 | node); |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 2121 | } |
| 2122 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2123 | Node* EffectControlLinearizer::LowerCheckFloat64Hole(Node* node, |
| 2124 | Node* frame_state) { |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 2125 | // 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 Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2129 | Node* check = __ Word32Equal(__ Float64ExtractHighWord32(value), |
| 2130 | __ Int32Constant(kHoleNanUpper32)); |
| 2131 | __ DeoptimizeIf(DeoptimizeReason::kHole, check, frame_state); |
| 2132 | return value; |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 2133 | } |
| 2134 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2135 | Node* EffectControlLinearizer::LowerCheckTaggedHole(Node* node, |
| 2136 | Node* frame_state) { |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 2137 | Node* value = node->InputAt(0); |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2138 | Node* check = __ WordEqual(value, __ TheHoleConstant()); |
| 2139 | __ DeoptimizeIf(DeoptimizeReason::kHole, check, frame_state); |
| 2140 | return value; |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2141 | } |
| 2142 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2143 | Node* EffectControlLinearizer::LowerConvertTaggedHoleToUndefined(Node* node) { |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2144 | Node* value = node->InputAt(0); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2145 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2146 | auto if_is_hole = __ MakeDeferredLabel<1>(); |
| 2147 | auto done = __ MakeLabel<2>(MachineRepresentation::kTagged); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2148 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2149 | Node* check = __ WordEqual(value, __ TheHoleConstant()); |
| 2150 | __ GotoIf(check, &if_is_hole); |
| 2151 | __ Goto(&done, value); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2152 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2153 | __ Bind(&if_is_hole); |
| 2154 | __ Goto(&done, __ UndefinedConstant()); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 2155 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2156 | __ Bind(&done); |
| 2157 | return done.PhiAt(0); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 2158 | } |
| 2159 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2160 | Node* 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 Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 2165 | } |
| 2166 | |
| 2167 | Node* EffectControlLinearizer::ChangeInt32ToSmi(Node* value) { |
| 2168 | if (machine()->Is64()) { |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2169 | value = __ ChangeInt32ToInt64(value); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 2170 | } |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2171 | return __ WordShl(value, SmiShiftBitsConstant()); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 2172 | } |
| 2173 | |
| 2174 | Node* EffectControlLinearizer::ChangeUint32ToSmi(Node* value) { |
| 2175 | if (machine()->Is64()) { |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2176 | value = __ ChangeUint32ToUint64(value); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 2177 | } |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2178 | return __ WordShl(value, SmiShiftBitsConstant()); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 2179 | } |
| 2180 | |
| 2181 | Node* EffectControlLinearizer::ChangeSmiToInt32(Node* value) { |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2182 | value = __ WordSar(value, SmiShiftBitsConstant()); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 2183 | if (machine()->Is64()) { |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2184 | value = __ TruncateInt64ToInt32(value); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 2185 | } |
| 2186 | return value; |
| 2187 | } |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2188 | |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 2189 | Node* EffectControlLinearizer::ObjectIsSmi(Node* value) { |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2190 | return __ WordEqual(__ WordAnd(value, __ IntPtrConstant(kSmiTagMask)), |
| 2191 | __ IntPtrConstant(kSmiTag)); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 2192 | } |
| 2193 | |
| 2194 | Node* EffectControlLinearizer::SmiMaxValueConstant() { |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2195 | return __ Int32Constant(Smi::kMaxValue); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 2196 | } |
| 2197 | |
| 2198 | Node* EffectControlLinearizer::SmiShiftBitsConstant() { |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2199 | return __ IntPtrConstant(kSmiShiftSize + kSmiTagSize); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 2200 | } |
| 2201 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2202 | Node* EffectControlLinearizer::LowerPlainPrimitiveToNumber(Node* node) { |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 2203 | Node* value = node->InputAt(0); |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2204 | return __ ToNumber(value); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 2205 | } |
| 2206 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2207 | Node* EffectControlLinearizer::LowerPlainPrimitiveToWord32(Node* node) { |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 2208 | Node* value = node->InputAt(0); |
| 2209 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2210 | auto if_not_smi = __ MakeDeferredLabel<1>(); |
| 2211 | auto if_to_number_smi = __ MakeLabel<1>(); |
| 2212 | auto done = __ MakeLabel<3>(MachineRepresentation::kWord32); |
| 2213 | |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 2214 | Node* check0 = ObjectIsSmi(value); |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2215 | __ GotoUnless(check0, &if_not_smi); |
| 2216 | __ Goto(&done, ChangeSmiToInt32(value)); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 2217 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2218 | __ Bind(&if_not_smi); |
| 2219 | Node* to_number = __ ToNumber(value); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 2220 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2221 | 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 Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 2225 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2226 | __ Bind(&if_to_number_smi); |
| 2227 | __ Goto(&done, ChangeSmiToInt32(to_number)); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 2228 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2229 | __ Bind(&done); |
| 2230 | return done.PhiAt(0); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 2231 | } |
| 2232 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2233 | Node* EffectControlLinearizer::LowerPlainPrimitiveToFloat64(Node* node) { |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 2234 | Node* value = node->InputAt(0); |
| 2235 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2236 | auto if_not_smi = __ MakeDeferredLabel<1>(); |
| 2237 | auto if_to_number_smi = __ MakeLabel<1>(); |
| 2238 | auto done = __ MakeLabel<3>(MachineRepresentation::kFloat64); |
| 2239 | |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 2240 | Node* check0 = ObjectIsSmi(value); |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2241 | __ GotoUnless(check0, &if_not_smi); |
| 2242 | Node* from_smi = ChangeSmiToInt32(value); |
| 2243 | __ Goto(&done, __ ChangeInt32ToFloat64(from_smi)); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 2244 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2245 | __ Bind(&if_not_smi); |
| 2246 | Node* to_number = __ ToNumber(value); |
| 2247 | Node* check1 = ObjectIsSmi(to_number); |
| 2248 | __ GotoIf(check1, &if_to_number_smi); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 2249 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2250 | Node* number = __ LoadField(AccessBuilder::ForHeapNumberValue(), to_number); |
| 2251 | __ Goto(&done, number); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 2252 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2253 | __ 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 Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 2257 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2258 | __ Bind(&done); |
| 2259 | return done.PhiAt(0); |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 2260 | } |
| 2261 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2262 | Node* EffectControlLinearizer::LowerEnsureWritableFastElements(Node* node) { |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2263 | Node* object = node->InputAt(0); |
| 2264 | Node* elements = node->InputAt(1); |
| 2265 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2266 | auto if_not_fixed_array = __ MakeDeferredLabel<1>(); |
| 2267 | auto done = __ MakeLabel<2>(MachineRepresentation::kTagged); |
| 2268 | |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2269 | // Load the current map of {elements}. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2270 | Node* elements_map = __ LoadField(AccessBuilder::ForMap(), elements); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2271 | |
| 2272 | // Check if {elements} is not a copy-on-write FixedArray. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2273 | Node* check = __ WordEqual(elements_map, __ FixedArrayMapConstant()); |
| 2274 | __ GotoUnless(check, &if_not_fixed_array); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2275 | // Nothing to do if the {elements} are not copy-on-write. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2276 | __ Goto(&done, elements); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2277 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2278 | __ Bind(&if_not_fixed_array); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2279 | // We need to take a copy of the {elements} and set them up for {object}. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2280 | 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2288 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2289 | __ Bind(&done); |
| 2290 | return done.PhiAt(0); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2291 | } |
| 2292 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2293 | Node* EffectControlLinearizer::LowerMaybeGrowFastElements(Node* node, |
| 2294 | Node* frame_state) { |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2295 | 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 Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2301 | 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2305 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2306 | Node* check0 = (flags & GrowFastElementsFlag::kHoleyElements) |
| 2307 | ? __ Uint32LessThanOrEqual(length, index) |
| 2308 | : __ Word32Equal(length, index); |
| 2309 | __ GotoUnless(check0, &if_not_grow); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2310 | { |
| 2311 | // Load the length of the {elements} backing store. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2312 | Node* elements_length = |
| 2313 | __ LoadField(AccessBuilder::ForFixedArrayLength(), elements); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2314 | elements_length = ChangeSmiToInt32(elements_length); |
| 2315 | |
| 2316 | // Check if we need to grow the {elements} backing store. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2317 | Node* check1 = __ Uint32LessThan(index, elements_length); |
| 2318 | __ GotoUnless(check1, &if_grow); |
| 2319 | __ Goto(&done_grow, elements); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2320 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2321 | __ 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2334 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2335 | // 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2341 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2342 | __ Bind(&done_grow); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2343 | |
| 2344 | // For JSArray {object}s we also need to update the "length". |
| 2345 | if (flags & GrowFastElementsFlag::kArrayObject) { |
| 2346 | // Compute the new {length}. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2347 | Node* object_length = |
| 2348 | ChangeInt32ToSmi(__ Int32Add(index, __ Int32Constant(1))); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2349 | |
| 2350 | // Update the "length" property of the {object}. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2351 | __ StoreField(AccessBuilder::ForJSArrayLength(FAST_ELEMENTS), object, |
| 2352 | object_length); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2353 | } |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2354 | __ Goto(&done, done_grow.PhiAt(0)); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2355 | } |
| 2356 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2357 | __ Bind(&if_not_grow); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2358 | { |
| 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 Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2363 | Node* check1 = __ Uint32LessThan(index, length); |
| 2364 | __ DeoptimizeUnless(DeoptimizeReason::kOutOfBounds, check1, frame_state); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2365 | } |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2366 | __ Goto(&done, elements); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2367 | } |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2368 | __ Bind(&done); |
| 2369 | return done.PhiAt(0); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2370 | } |
| 2371 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2372 | void EffectControlLinearizer::LowerTransitionElementsKind(Node* node) { |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2373 | ElementsTransition const transition = ElementsTransitionOf(node->op()); |
| 2374 | Node* object = node->InputAt(0); |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2375 | |
| 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2381 | |
| 2382 | // Load the current map of {object}. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2383 | Node* object_map = __ LoadField(AccessBuilder::ForMap(), object); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2384 | |
| 2385 | // Check if {object_map} is the same as {source_map}. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2386 | Node* check = __ WordEqual(object_map, source_map); |
| 2387 | __ GotoIf(check, &if_map_same); |
| 2388 | __ Goto(&done); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2389 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2390 | __ 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2406 | } |
| 2407 | } |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2408 | __ Goto(&done); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2409 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2410 | __ Bind(&done); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2411 | } |
| 2412 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2413 | Node* EffectControlLinearizer::LowerLoadTypedElement(Node* node) { |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2414 | 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 Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2422 | __ Retain(buffer); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2423 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2424 | // 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2429 | |
| 2430 | // Perform the actual typed element access. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2431 | return __ LoadElement(AccessBuilder::ForTypedArrayElement(array_type, true), |
| 2432 | storage, index); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2433 | } |
| 2434 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2435 | void EffectControlLinearizer::LowerStoreTypedElement(Node* node) { |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2436 | 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 Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2445 | __ Retain(buffer); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2446 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2447 | // 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2452 | |
| 2453 | // Perform the actual typed element access. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2454 | __ StoreElement(AccessBuilder::ForTypedArrayElement(array_type, true), |
| 2455 | storage, index, value); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2456 | } |
| 2457 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2458 | Maybe<Node*> EffectControlLinearizer::LowerFloat64RoundUp(Node* node) { |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2459 | // Nothing to be done if a fast hardware instruction is available. |
| 2460 | if (machine()->Float64RoundUp().IsSupported()) { |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2461 | return Nothing<Node*>(); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2462 | } |
| 2463 | |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2464 | 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 Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2488 | |
| 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 | |
| 2546 | Node* 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2555 | // |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2556 | // 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2578 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2579 | 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2585 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2586 | 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2591 | { |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2592 | Node* check1 = __ Float64LessThanOrEqual(two_52, input); |
| 2593 | __ GotoIf(check1, &if_greater_than_two_52); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2594 | { |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2595 | 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2599 | } |
| 2600 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2601 | __ Bind(&if_greater_than_two_52); |
| 2602 | __ Goto(&done, input); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2603 | } |
| 2604 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2605 | __ Bind(&if_not_positive); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2606 | { |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2607 | Node* check1 = __ Float64Equal(input, zero); |
| 2608 | __ GotoIf(check1, &if_zero); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2609 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2610 | 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2613 | |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2614 | { |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2615 | 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2621 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2622 | __ Bind(&if_temp2_lt_temp1); |
| 2623 | __ Goto(&done, __ Float64Sub(__ Float64Constant(-1.0), temp2)); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2624 | } |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2625 | __ Bind(&if_less_than_minus_two_52); |
| 2626 | __ Goto(&done, input); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2627 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2628 | __ Bind(&if_zero); |
| 2629 | __ Goto(&done, input); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2630 | } |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2631 | __ Bind(&done); |
| 2632 | return done.PhiAt(0); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2633 | } |
| 2634 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2635 | Maybe<Node*> EffectControlLinearizer::LowerFloat64RoundDown(Node* node) { |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2636 | // Nothing to be done if a fast hardware instruction is available. |
| 2637 | if (machine()->Float64RoundDown().IsSupported()) { |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2638 | return Nothing<Node*>(); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2639 | } |
| 2640 | |
| Ben Murdoch | c8c1d9e | 2017-03-08 14:04:23 +0000 | [diff] [blame] | 2641 | Node* const input = node->InputAt(0); |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2642 | return Just(BuildFloat64RoundDown(input)); |
| Ben Murdoch | c8c1d9e | 2017-03-08 14:04:23 +0000 | [diff] [blame] | 2643 | } |
| 2644 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2645 | Maybe<Node*> EffectControlLinearizer::LowerFloat64RoundTiesEven(Node* node) { |
| Ben Murdoch | c8c1d9e | 2017-03-08 14:04:23 +0000 | [diff] [blame] | 2646 | // Nothing to be done if a fast hardware instruction is available. |
| 2647 | if (machine()->Float64RoundTiesEven().IsSupported()) { |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2648 | return Nothing<Node*>(); |
| Ben Murdoch | c8c1d9e | 2017-03-08 14:04:23 +0000 | [diff] [blame] | 2649 | } |
| 2650 | |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2651 | Node* const input = node->InputAt(0); |
| 2652 | |
| Ben Murdoch | c8c1d9e | 2017-03-08 14:04:23 +0000 | [diff] [blame] | 2653 | // Generate case for round ties to even: |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2654 | // |
| Ben Murdoch | c8c1d9e | 2017-03-08 14:04:23 +0000 | [diff] [blame] | 2655 | // 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2661 | // else |
| Ben Murdoch | c8c1d9e | 2017-03-08 14:04:23 +0000 | [diff] [blame] | 2662 | // let temp2 = value % 2.0 in |
| 2663 | // if temp2 == 0.0 then |
| 2664 | // value |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2665 | // else |
| Ben Murdoch | c8c1d9e | 2017-03-08 14:04:23 +0000 | [diff] [blame] | 2666 | // value + 1.0 |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2667 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2668 | auto if_is_half = __ MakeLabel<1>(); |
| 2669 | auto done = __ MakeLabel<4>(MachineRepresentation::kFloat64); |
| Ben Murdoch | c8c1d9e | 2017-03-08 14:04:23 +0000 | [diff] [blame] | 2670 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2671 | Node* value = BuildFloat64RoundDown(input); |
| 2672 | Node* temp1 = __ Float64Sub(input, value); |
| Ben Murdoch | c8c1d9e | 2017-03-08 14:04:23 +0000 | [diff] [blame] | 2673 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2674 | Node* const half = __ Float64Constant(0.5); |
| 2675 | Node* check0 = __ Float64LessThan(temp1, half); |
| 2676 | __ GotoIf(check0, &done, value); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2677 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2678 | 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2682 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2683 | __ 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2688 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2689 | __ Bind(&done); |
| 2690 | return Just(done.PhiAt(0)); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2691 | } |
| 2692 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2693 | Maybe<Node*> EffectControlLinearizer::LowerFloat64RoundTruncate(Node* node) { |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2694 | // Nothing to be done if a fast hardware instruction is available. |
| 2695 | if (machine()->Float64RoundTruncate().IsSupported()) { |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2696 | return Nothing<Node*>(); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2697 | } |
| 2698 | |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2699 | 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 Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2727 | 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2733 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2734 | 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2740 | { |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2741 | Node* check1 = __ Float64LessThanOrEqual(two_52, input); |
| 2742 | __ GotoIf(check1, &if_greater_than_two_52); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2743 | { |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2744 | Node* temp1 = __ Float64Sub(__ Float64Add(two_52, input), two_52); |
| 2745 | __ GotoUnless(__ Float64LessThan(input, temp1), &done, temp1); |
| 2746 | __ Goto(&done, __ Float64Sub(temp1, one)); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2747 | } |
| 2748 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2749 | __ Bind(&if_greater_than_two_52); |
| 2750 | __ Goto(&done, input); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2751 | } |
| 2752 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2753 | __ Bind(&if_not_positive); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2754 | { |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2755 | Node* check1 = __ Float64Equal(input, zero); |
| 2756 | __ GotoIf(check1, &if_zero); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2757 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2758 | 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2761 | |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2762 | { |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2763 | 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 Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2769 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2770 | __ Bind(&done_temp3); |
| 2771 | Node* temp3 = done_temp3.PhiAt(0); |
| 2772 | __ Goto(&done, __ Float64Sub(minus_zero, temp3)); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2773 | } |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2774 | __ Bind(&if_less_than_minus_two_52); |
| 2775 | __ Goto(&done, input); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2776 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2777 | __ Bind(&if_zero); |
| 2778 | __ Goto(&done, input); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2779 | } |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2780 | __ Bind(&done); |
| 2781 | return Just(done.PhiAt(0)); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 2782 | } |
| 2783 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame] | 2784 | #undef __ |
| 2785 | |
| Ben Murdoch | 13e2dad | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 2786 | Factory* EffectControlLinearizer::factory() const { |
| 2787 | return isolate()->factory(); |
| 2788 | } |
| 2789 | |
| 2790 | Isolate* EffectControlLinearizer::isolate() const { |
| 2791 | return jsgraph()->isolate(); |
| 2792 | } |
| 2793 | |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 2794 | } // namespace compiler |
| 2795 | } // namespace internal |
| 2796 | } // namespace v8 |