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