| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/compiler/simplified-lowering.h" | 5 #include "src/compiler/simplified-lowering.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 | 8 |
| 9 #include "src/address-map.h" | 9 #include "src/address-map.h" |
| 10 #include "src/base/bits.h" | 10 #include "src/base/bits.h" |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 44 // 1.) PROPAGATE: Traverse the graph from the end, pushing usage information | 44 // 1.) PROPAGATE: Traverse the graph from the end, pushing usage information |
| 45 // backwards from uses to definitions, around cycles in phis, according | 45 // backwards from uses to definitions, around cycles in phis, according |
| 46 // to local rules for each operator. | 46 // to local rules for each operator. |
| 47 // During this phase, the usage information for a node determines the best | 47 // During this phase, the usage information for a node determines the best |
| 48 // possible lowering for each operator so far, and that in turn determines | 48 // possible lowering for each operator so far, and that in turn determines |
| 49 // the output representation. | 49 // the output representation. |
| 50 // Therefore, to be correct, this phase must iterate to a fixpoint before | 50 // Therefore, to be correct, this phase must iterate to a fixpoint before |
| 51 // the next phase can begin. | 51 // the next phase can begin. |
| 52 PROPAGATE, | 52 PROPAGATE, |
| 53 | 53 |
| 54 // 2.) LOWER: perform lowering for all {Simplified} nodes by replacing some | 54 // 2.) RETYPE: Propagate types from type feedback forwards. |
| 55 RETYPE, |
| 56 |
| 57 // 3.) LOWER: perform lowering for all {Simplified} nodes by replacing some |
| 55 // operators for some nodes, expanding some nodes to multiple nodes, or | 58 // operators for some nodes, expanding some nodes to multiple nodes, or |
| 56 // removing some (redundant) nodes. | 59 // removing some (redundant) nodes. |
| 57 // During this phase, use the {RepresentationChanger} to insert | 60 // During this phase, use the {RepresentationChanger} to insert |
| 58 // representation changes between uses that demand a particular | 61 // representation changes between uses that demand a particular |
| 59 // representation and nodes that produce a different representation. | 62 // representation and nodes that produce a different representation. |
| 60 LOWER | 63 LOWER |
| 61 }; | 64 }; |
| 62 | 65 |
| 63 | |
| 64 namespace { | 66 namespace { |
| 65 | 67 |
| 66 | 68 |
| 67 UseInfo TruncatingUseInfoFromRepresentation(MachineRepresentation rep) { | 69 UseInfo TruncatingUseInfoFromRepresentation(MachineRepresentation rep) { |
| 68 switch (rep) { | 70 switch (rep) { |
| 69 case MachineRepresentation::kTagged: | 71 case MachineRepresentation::kTagged: |
| 70 return UseInfo::AnyTagged(); | 72 return UseInfo::AnyTagged(); |
| 71 case MachineRepresentation::kFloat64: | 73 case MachineRepresentation::kFloat64: |
| 72 return UseInfo::TruncatingFloat64(); | 74 return UseInfo::TruncatingFloat64(); |
| 73 case MachineRepresentation::kFloat32: | 75 case MachineRepresentation::kFloat32: |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 239 changer_(changer), | 241 changer_(changer), |
| 240 queue_(zone), | 242 queue_(zone), |
| 241 typing_stack_(zone), | 243 typing_stack_(zone), |
| 242 source_positions_(source_positions), | 244 source_positions_(source_positions), |
| 243 type_cache_(TypeCache::Get()), | 245 type_cache_(TypeCache::Get()), |
| 244 op_typer_(jsgraph->isolate(), graph_zone()) { | 246 op_typer_(jsgraph->isolate(), graph_zone()) { |
| 245 } | 247 } |
| 246 | 248 |
| 247 // Forward propagation of types from type feedback. | 249 // Forward propagation of types from type feedback. |
| 248 void RunTypePropagationPhase() { | 250 void RunTypePropagationPhase() { |
| 251 // Run type propagation. |
| 252 TRACE("--{Type propagation phase}--\n"); |
| 253 phase_ = RETYPE; |
| 254 ResetNodeInfoState(); |
| 255 |
| 249 DCHECK(typing_stack_.empty()); | 256 DCHECK(typing_stack_.empty()); |
| 250 | |
| 251 typing_stack_.push({graph()->end(), 0}); | 257 typing_stack_.push({graph()->end(), 0}); |
| 252 GetInfo(graph()->end())->set_pushed(); | 258 GetInfo(graph()->end())->set_pushed(); |
| 253 while (!typing_stack_.empty()) { | 259 while (!typing_stack_.empty()) { |
| 254 NodeState& current = typing_stack_.top(); | 260 NodeState& current = typing_stack_.top(); |
| 255 | 261 |
| 256 // If there is an unvisited input, push it and continue. | 262 // If there is an unvisited input, push it and continue. |
| 257 bool pushed_unvisited = false; | 263 bool pushed_unvisited = false; |
| 258 while (current.input_index < current.node->InputCount()) { | 264 while (current.input_index < current.node->InputCount()) { |
| 259 Node* input = current.node->InputAt(current.input_index); | 265 Node* input = current.node->InputAt(current.input_index); |
| 260 NodeInfo* input_info = GetInfo(input); | 266 NodeInfo* input_info = GetInfo(input); |
| 261 current.input_index++; | 267 current.input_index++; |
| 262 if (input_info->unvisited()) { | 268 if (input_info->unvisited()) { |
| 263 input_info->set_pushed(); | 269 input_info->set_pushed(); |
| 264 typing_stack_.push({input, 0}); | 270 typing_stack_.push({input, 0}); |
| 265 pushed_unvisited = true; | 271 pushed_unvisited = true; |
| 266 break; | 272 break; |
| 267 } | 273 } |
| 268 } | 274 } |
| 269 if (pushed_unvisited) continue; | 275 if (pushed_unvisited) continue; |
| 270 | 276 |
| 271 // Process the top of the stack. | 277 // Process the top of the stack. |
| 272 Node* node = current.node; | 278 Node* node = current.node; |
| 273 typing_stack_.pop(); | 279 typing_stack_.pop(); |
| 274 NodeInfo* info = GetInfo(node); | 280 NodeInfo* info = GetInfo(node); |
| 275 info->set_visited(); | 281 info->set_visited(); |
| 276 bool updated = UpdateFeedbackType(node); | 282 bool updated = UpdateFeedbackType(node); |
| 283 TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic()); |
| 284 VisitNode(node, info->truncation(), nullptr); |
| 277 if (updated) { | 285 if (updated) { |
| 278 for (Node* const user : node->uses()) { | 286 for (Node* const user : node->uses()) { |
| 279 if (GetInfo(user)->visited()) { | 287 if (GetInfo(user)->visited()) { |
| 280 GetInfo(user)->set_queued(); | 288 GetInfo(user)->set_queued(); |
| 281 queue_.push(user); | 289 queue_.push(user); |
| 282 } | 290 } |
| 283 } | 291 } |
| 284 } | 292 } |
| 285 } | 293 } |
| 286 | 294 |
| 287 // Process the revisit queue. | 295 // Process the revisit queue. |
| 288 while (!queue_.empty()) { | 296 while (!queue_.empty()) { |
| 289 Node* node = queue_.front(); | 297 Node* node = queue_.front(); |
| 290 queue_.pop(); | 298 queue_.pop(); |
| 291 NodeInfo* info = GetInfo(node); | 299 NodeInfo* info = GetInfo(node); |
| 292 info->set_visited(); | 300 info->set_visited(); |
| 293 bool updated = UpdateFeedbackType(node); | 301 bool updated = UpdateFeedbackType(node); |
| 302 TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic()); |
| 303 VisitNode(node, info->truncation(), nullptr); |
| 294 if (updated) { | 304 if (updated) { |
| 295 for (Node* const user : node->uses()) { | 305 for (Node* const user : node->uses()) { |
| 296 if (GetInfo(user)->visited()) { | 306 if (GetInfo(user)->visited()) { |
| 297 GetInfo(user)->set_queued(); | 307 GetInfo(user)->set_queued(); |
| 298 queue_.push(user); | 308 queue_.push(user); |
| 299 } | 309 } |
| 300 } | 310 } |
| 301 } | 311 } |
| 302 } | 312 } |
| 303 } | 313 } |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 369 } | 379 } |
| 370 | 380 |
| 371 switch (node->opcode()) { | 381 switch (node->opcode()) { |
| 372 case IrOpcode::kSpeculativeNumberAdd: { | 382 case IrOpcode::kSpeculativeNumberAdd: { |
| 373 // TODO(jarin) The ToNumber conversion is too conservative here, | 383 // TODO(jarin) The ToNumber conversion is too conservative here, |
| 374 // e.g. it will treat true as 1 even though the number check will | 384 // e.g. it will treat true as 1 even though the number check will |
| 375 // fail on a boolean. OperationTyper should have a function that | 385 // fail on a boolean. OperationTyper should have a function that |
| 376 // computes a more precise type. | 386 // computes a more precise type. |
| 377 Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); | 387 Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); |
| 378 Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); | 388 Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); |
| 379 Type* static_type = op_typer_.NumericAdd(lhs, rhs); | 389 Type* static_type = op_typer_.NumberAdd(lhs, rhs); |
| 380 if (info->type_check() == TypeCheckKind::kNone) { | 390 if (info->type_check() == TypeCheckKind::kNone) { |
| 381 new_type = static_type; | 391 new_type = static_type; |
| 382 } else { | 392 } else { |
| 383 Type* feedback_type = TypeOfSpeculativeOp(info->type_check()); | 393 Type* feedback_type = TypeOfSpeculativeOp(info->type_check()); |
| 384 new_type = Type::Intersect(static_type, feedback_type, graph_zone()); | 394 new_type = Type::Intersect(static_type, feedback_type, graph_zone()); |
| 385 } | 395 } |
| 386 break; | 396 break; |
| 387 } | 397 } |
| 388 | 398 |
| 389 case IrOpcode::kSpeculativeNumberSubtract: { | 399 case IrOpcode::kSpeculativeNumberSubtract: { |
| 390 // TODO(jarin) The ToNumber conversion is too conservative here, | 400 // TODO(jarin) The ToNumber conversion is too conservative here, |
| 391 // e.g. it will treat true as 1 even though the number check will | 401 // e.g. it will treat true as 1 even though the number check will |
| 392 // fail on a boolean. OperationTyper should have a function that | 402 // fail on a boolean. OperationTyper should have a function that |
| 393 // computes a more precise type. | 403 // computes a more precise type. |
| 394 Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); | 404 Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); |
| 395 Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); | 405 Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); |
| 396 Type* static_type = op_typer_.NumericSubtract(lhs, rhs); | 406 Type* static_type = op_typer_.NumberSubtract(lhs, rhs); |
| 397 if (info->type_check() == TypeCheckKind::kNone) { | 407 if (info->type_check() == TypeCheckKind::kNone) { |
| 398 new_type = static_type; | 408 new_type = static_type; |
| 399 } else { | 409 } else { |
| 400 Type* feedback_type = TypeOfSpeculativeOp(info->type_check()); | 410 Type* feedback_type = TypeOfSpeculativeOp(info->type_check()); |
| 401 new_type = Type::Intersect(static_type, feedback_type, graph_zone()); | 411 new_type = Type::Intersect(static_type, feedback_type, graph_zone()); |
| 402 } | 412 } |
| 403 break; | 413 break; |
| 404 } | 414 } |
| 405 | 415 |
| 406 case IrOpcode::kSpeculativeNumberMultiply: { | 416 case IrOpcode::kSpeculativeNumberMultiply: { |
| 407 // TODO(jarin) The ToNumber conversion is too conservative here, | 417 // TODO(jarin) The ToNumber conversion is too conservative here, |
| 408 // e.g. it will treat true as 1 even though the number check will | 418 // e.g. it will treat true as 1 even though the number check will |
| 409 // fail on a boolean. OperationTyper should have a function that | 419 // fail on a boolean. OperationTyper should have a function that |
| 410 // computes a more precise type. | 420 // computes a more precise type. |
| 411 Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); | 421 Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); |
| 412 Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); | 422 Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); |
| 413 Type* static_type = op_typer_.NumericMultiply(lhs, rhs); | 423 Type* static_type = op_typer_.NumberMultiply(lhs, rhs); |
| 414 if (info->type_check() == TypeCheckKind::kNone) { | 424 if (info->type_check() == TypeCheckKind::kNone) { |
| 415 new_type = static_type; | 425 new_type = static_type; |
| 416 } else { | 426 } else { |
| 417 Type* feedback_type = TypeOfSpeculativeOp(info->type_check()); | 427 Type* feedback_type = TypeOfSpeculativeOp(info->type_check()); |
| 418 new_type = Type::Intersect(static_type, feedback_type, graph_zone()); | 428 new_type = Type::Intersect(static_type, feedback_type, graph_zone()); |
| 419 } | 429 } |
| 420 break; | 430 break; |
| 421 } | 431 } |
| 422 | 432 |
| 423 case IrOpcode::kSpeculativeNumberDivide: { | 433 case IrOpcode::kSpeculativeNumberDivide: { |
| 424 // TODO(jarin) The ToNumber conversion is too conservative here, | 434 // TODO(jarin) The ToNumber conversion is too conservative here, |
| 425 // e.g. it will treat true as 1 even though the number check will | 435 // e.g. it will treat true as 1 even though the number check will |
| 426 // fail on a boolean. OperationTyper should have a function that | 436 // fail on a boolean. OperationTyper should have a function that |
| 427 // computes a more precise type. | 437 // computes a more precise type. |
| 428 Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); | 438 Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); |
| 429 Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); | 439 Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); |
| 430 Type* static_type = op_typer_.NumericDivide(lhs, rhs); | 440 Type* static_type = op_typer_.NumberDivide(lhs, rhs); |
| 431 if (info->type_check() == TypeCheckKind::kNone) { | 441 if (info->type_check() == TypeCheckKind::kNone) { |
| 432 new_type = static_type; | 442 new_type = static_type; |
| 433 } else { | 443 } else { |
| 434 Type* feedback_type = TypeOfSpeculativeOp(info->type_check()); | 444 Type* feedback_type = TypeOfSpeculativeOp(info->type_check()); |
| 435 new_type = Type::Intersect(static_type, feedback_type, graph_zone()); | 445 new_type = Type::Intersect(static_type, feedback_type, graph_zone()); |
| 436 } | 446 } |
| 437 break; | 447 break; |
| 438 } | 448 } |
| 439 | 449 |
| 440 case IrOpcode::kSpeculativeNumberModulus: { | 450 case IrOpcode::kSpeculativeNumberModulus: { |
| 441 // TODO(jarin) The ToNumber conversion is too conservative here, | 451 // TODO(jarin) The ToNumber conversion is too conservative here, |
| 442 // e.g. it will treat true as 1 even though the number check will | 452 // e.g. it will treat true as 1 even though the number check will |
| 443 // fail on a boolean. OperationTyper should have a function that | 453 // fail on a boolean. OperationTyper should have a function that |
| 444 // computes a more precise type. | 454 // computes a more precise type. |
| 445 Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); | 455 Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); |
| 446 Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); | 456 Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); |
| 447 Type* static_type = op_typer_.NumericModulus(lhs, rhs); | 457 Type* static_type = op_typer_.NumberModulus(lhs, rhs); |
| 448 if (info->type_check() == TypeCheckKind::kNone) { | 458 if (info->type_check() == TypeCheckKind::kNone) { |
| 449 new_type = static_type; | 459 new_type = static_type; |
| 450 } else { | 460 } else { |
| 451 Type* feedback_type = TypeOfSpeculativeOp(info->type_check()); | 461 Type* feedback_type = TypeOfSpeculativeOp(info->type_check()); |
| 452 new_type = Type::Intersect(static_type, feedback_type, graph_zone()); | 462 new_type = Type::Intersect(static_type, feedback_type, graph_zone()); |
| 453 } | 463 } |
| 454 break; | 464 break; |
| 455 } | 465 } |
| 456 | 466 |
| 467 case IrOpcode::kNumberAbs: { |
| 468 new_type = op_typer_.NumberAbs(FeedbackTypeOf(node->InputAt(0))); |
| 469 break; |
| 470 } |
| 471 |
| 457 case IrOpcode::kPhi: { | 472 case IrOpcode::kPhi: { |
| 458 new_type = TypePhi(node); | 473 new_type = TypePhi(node); |
| 459 if (type != nullptr) { | 474 if (type != nullptr) { |
| 460 new_type = Weaken(node, type, new_type); | 475 new_type = Weaken(node, type, new_type); |
| 461 } | 476 } |
| 462 // Recompute the phi representation based on the new type. | |
| 463 MachineRepresentation output = | |
| 464 GetOutputInfoForPhi(node, GetInfo(node)->truncation(), new_type); | |
| 465 ResetOutput(node, output); | |
| 466 break; | 477 break; |
| 467 } | 478 } |
| 468 | 479 |
| 469 case IrOpcode::kSelect: { | 480 case IrOpcode::kSelect: { |
| 470 new_type = TypeSelect(node); | 481 new_type = TypeSelect(node); |
| 471 // Recompute representation based on the new type. | |
| 472 MachineRepresentation output = | |
| 473 GetOutputInfoForPhi(node, GetInfo(node)->truncation(), new_type); | |
| 474 ResetOutput(node, output); | |
| 475 break; | 482 break; |
| 476 } | 483 } |
| 477 | 484 |
| 478 default: | 485 default: |
| 479 // Shortcut for operations that we do not handle. | 486 // Shortcut for operations that we do not handle. |
| 480 if (type == nullptr) { | 487 if (type == nullptr) { |
| 481 GetInfo(node)->set_feedback_type(NodeProperties::GetType(node)); | 488 GetInfo(node)->set_feedback_type(NodeProperties::GetType(node)); |
| 482 return true; | 489 return true; |
| 483 } | 490 } |
| 484 return false; | 491 return false; |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 562 VisitNode(node, info->truncation(), nullptr); | 569 VisitNode(node, info->truncation(), nullptr); |
| 563 TRACE(" ==> output "); | 570 TRACE(" ==> output "); |
| 564 PrintOutputInfo(info); | 571 PrintOutputInfo(info); |
| 565 TRACE("\n"); | 572 TRACE("\n"); |
| 566 } | 573 } |
| 567 } | 574 } |
| 568 | 575 |
| 569 void Run(SimplifiedLowering* lowering) { | 576 void Run(SimplifiedLowering* lowering) { |
| 570 RunTruncationPropagationPhase(); | 577 RunTruncationPropagationPhase(); |
| 571 | 578 |
| 572 // Run type propagation. | |
| 573 ResetNodeInfoState(); | |
| 574 RunTypePropagationPhase(); | 579 RunTypePropagationPhase(); |
| 575 | 580 |
| 576 // Run lowering and change insertion phase. | 581 // Run lowering and change insertion phase. |
| 577 TRACE("--{Simplified lowering phase}--\n"); | 582 TRACE("--{Simplified lowering phase}--\n"); |
| 578 phase_ = LOWER; | 583 phase_ = LOWER; |
| 579 // Process nodes from the collected {nodes_} vector. | 584 // Process nodes from the collected {nodes_} vector. |
| 580 for (NodeVector::iterator i = nodes_.begin(); i != nodes_.end(); ++i) { | 585 for (NodeVector::iterator i = nodes_.begin(); i != nodes_.end(); ++i) { |
| 581 Node* node = *i; | 586 Node* node = *i; |
| 582 NodeInfo* info = GetInfo(node); | 587 NodeInfo* info = GetInfo(node); |
| 583 TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic()); | 588 TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic()); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 640 queue_.push(node); | 645 queue_.push(node); |
| 641 info->set_queued(); | 646 info->set_queued(); |
| 642 TRACE(" added: "); | 647 TRACE(" added: "); |
| 643 } else { | 648 } else { |
| 644 TRACE(" inqueue: "); | 649 TRACE(" inqueue: "); |
| 645 } | 650 } |
| 646 PrintTruncation(info->truncation()); | 651 PrintTruncation(info->truncation()); |
| 647 } | 652 } |
| 648 } | 653 } |
| 649 | 654 |
| 650 bool lower() { return phase_ == LOWER; } | 655 bool lower() const { return phase_ == LOWER; } |
| 651 bool propagate() { return phase_ == PROPAGATE; } | 656 bool retype() const { return phase_ == RETYPE; } |
| 657 bool propagate() const { return phase_ == PROPAGATE; } |
| 652 | 658 |
| 653 void SetOutput(Node* node, MachineRepresentation representation, | 659 void SetOutput(Node* node, MachineRepresentation representation, |
| 654 TypeCheckKind type_check = TypeCheckKind::kNone) { | 660 TypeCheckKind type_check = TypeCheckKind::kNone) { |
| 655 DCHECK(MachineRepresentationIsSubtype(GetInfo(node)->representation(), | 661 NodeInfo* const info = GetInfo(node); |
| 656 representation)); | 662 switch (phase_) { |
| 657 ResetOutput(node, representation, type_check); | 663 case PROPAGATE: |
| 664 info->set_type_check(type_check); |
| 665 break; |
| 666 case RETYPE: |
| 667 DCHECK_EQ(info->type_check(), type_check); |
| 668 info->set_output(representation); |
| 669 break; |
| 670 case LOWER: |
| 671 DCHECK_EQ(info->type_check(), type_check); |
| 672 DCHECK_EQ(info->representation(), representation); |
| 673 break; |
| 674 } |
| 658 } | 675 } |
| 659 | 676 |
| 660 void ResetOutput(Node* node, MachineRepresentation representation, | 677 void ResetOutput(Node* node, MachineRepresentation representation, |
| 661 TypeCheckKind type_check = TypeCheckKind::kNone) { | 678 TypeCheckKind type_check = TypeCheckKind::kNone) { |
| 662 NodeInfo* info = GetInfo(node); | 679 NodeInfo* info = GetInfo(node); |
| 663 info->set_output(representation); | 680 info->set_output(representation); |
| 664 info->set_type_check(type_check); | 681 info->set_type_check(type_check); |
| 665 } | 682 } |
| 666 | 683 |
| 667 Type* GetUpperBound(Node* node) { return NodeProperties::GetType(node); } | 684 Type* GetUpperBound(Node* node) { return NodeProperties::GetType(node); } |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 708 TRACE(" to "); | 725 TRACE(" to "); |
| 709 PrintUseInfo(use); | 726 PrintUseInfo(use); |
| 710 TRACE("\n"); | 727 TRACE("\n"); |
| 711 Node* n = changer_->GetRepresentationFor( | 728 Node* n = changer_->GetRepresentationFor( |
| 712 input, input_info->representation(), TypeOf(input), node, use); | 729 input, input_info->representation(), TypeOf(input), node, use); |
| 713 node->ReplaceInput(index, n); | 730 node->ReplaceInput(index, n); |
| 714 } | 731 } |
| 715 } | 732 } |
| 716 | 733 |
| 717 void ProcessInput(Node* node, int index, UseInfo use) { | 734 void ProcessInput(Node* node, int index, UseInfo use) { |
| 718 if (phase_ == PROPAGATE) { | 735 switch (phase_) { |
| 719 EnqueueInput(node, index, use); | 736 case PROPAGATE: |
| 720 } else { | 737 EnqueueInput(node, index, use); |
| 721 ConvertInput(node, index, use); | 738 break; |
| 739 case RETYPE: |
| 740 break; |
| 741 case LOWER: |
| 742 ConvertInput(node, index, use); |
| 743 break; |
| 722 } | 744 } |
| 723 } | 745 } |
| 724 | 746 |
| 725 void ProcessRemainingInputs(Node* node, int index) { | 747 void ProcessRemainingInputs(Node* node, int index) { |
| 726 DCHECK_GE(index, NodeProperties::PastValueIndex(node)); | 748 DCHECK_GE(index, NodeProperties::PastValueIndex(node)); |
| 727 DCHECK_GE(index, NodeProperties::PastContextIndex(node)); | 749 DCHECK_GE(index, NodeProperties::PastContextIndex(node)); |
| 728 for (int i = std::max(index, NodeProperties::FirstEffectIndex(node)); | 750 for (int i = std::max(index, NodeProperties::FirstEffectIndex(node)); |
| 729 i < NodeProperties::PastEffectIndex(node); ++i) { | 751 i < NodeProperties::PastEffectIndex(node); ++i) { |
| 730 EnqueueInput(node, i); // Effect inputs: just visit | 752 EnqueueInput(node, i); // Effect inputs: just visit |
| 731 } | 753 } |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 820 VisitBinop(node, UseInfo::TruncatingWord32(), MachineRepresentation::kBit); | 842 VisitBinop(node, UseInfo::TruncatingWord32(), MachineRepresentation::kBit); |
| 821 } | 843 } |
| 822 void VisitInt64Cmp(Node* node) { | 844 void VisitInt64Cmp(Node* node) { |
| 823 VisitBinop(node, UseInfo::TruncatingWord64(), MachineRepresentation::kBit); | 845 VisitBinop(node, UseInfo::TruncatingWord64(), MachineRepresentation::kBit); |
| 824 } | 846 } |
| 825 void VisitUint64Cmp(Node* node) { | 847 void VisitUint64Cmp(Node* node) { |
| 826 VisitBinop(node, UseInfo::TruncatingWord64(), MachineRepresentation::kBit); | 848 VisitBinop(node, UseInfo::TruncatingWord64(), MachineRepresentation::kBit); |
| 827 } | 849 } |
| 828 | 850 |
| 829 // Infer representation for phi-like nodes. | 851 // Infer representation for phi-like nodes. |
| 830 MachineRepresentation GetOutputInfoForPhi(Node* node, Truncation use, | 852 MachineRepresentation GetOutputInfoForPhi(Node* node, Truncation use) { |
| 831 Type* type = nullptr) { | |
| 832 // Compute the representation. | 853 // Compute the representation. |
| 833 if (type == nullptr) { | 854 Type* type = TypeOf(node); |
| 834 type = TypeOf(node); | |
| 835 } | |
| 836 if (type->Is(Type::None())) { | 855 if (type->Is(Type::None())) { |
| 837 return MachineRepresentation::kNone; | 856 return MachineRepresentation::kNone; |
| 838 } else if (type->Is(Type::Signed32()) || type->Is(Type::Unsigned32())) { | 857 } else if (type->Is(Type::Signed32()) || type->Is(Type::Unsigned32())) { |
| 839 return MachineRepresentation::kWord32; | 858 return MachineRepresentation::kWord32; |
| 840 } else if (use.TruncatesToWord32()) { | 859 } else if (use.TruncatesToWord32()) { |
| 841 return MachineRepresentation::kWord32; | 860 return MachineRepresentation::kWord32; |
| 842 } else if (type->Is(Type::Boolean())) { | 861 } else if (type->Is(Type::Boolean())) { |
| 843 return MachineRepresentation::kBit; | 862 return MachineRepresentation::kBit; |
| 844 } else if (type->Is(Type::Number())) { | 863 } else if (type->Is(Type::Number())) { |
| 845 return MachineRepresentation::kFloat64; | 864 return MachineRepresentation::kFloat64; |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 942 if (type->Is(Type::Signed32())) { | 961 if (type->Is(Type::Signed32())) { |
| 943 return MachineSemantic::kInt32; | 962 return MachineSemantic::kInt32; |
| 944 } else if (type->Is(Type::Unsigned32())) { | 963 } else if (type->Is(Type::Unsigned32())) { |
| 945 return MachineSemantic::kUint32; | 964 return MachineSemantic::kUint32; |
| 946 } else { | 965 } else { |
| 947 return MachineSemantic::kAny; | 966 return MachineSemantic::kAny; |
| 948 } | 967 } |
| 949 } | 968 } |
| 950 | 969 |
| 951 void VisitStateValues(Node* node) { | 970 void VisitStateValues(Node* node) { |
| 952 if (phase_ == PROPAGATE) { | 971 if (propagate()) { |
| 953 for (int i = 0; i < node->InputCount(); i++) { | 972 for (int i = 0; i < node->InputCount(); i++) { |
| 954 EnqueueInput(node, i, UseInfo::Any()); | 973 EnqueueInput(node, i, UseInfo::Any()); |
| 955 } | 974 } |
| 956 } else { | 975 } else if (lower()) { |
| 957 Zone* zone = jsgraph_->zone(); | 976 Zone* zone = jsgraph_->zone(); |
| 958 ZoneVector<MachineType>* types = | 977 ZoneVector<MachineType>* types = |
| 959 new (zone->New(sizeof(ZoneVector<MachineType>))) | 978 new (zone->New(sizeof(ZoneVector<MachineType>))) |
| 960 ZoneVector<MachineType>(node->InputCount(), zone); | 979 ZoneVector<MachineType>(node->InputCount(), zone); |
| 961 for (int i = 0; i < node->InputCount(); i++) { | 980 for (int i = 0; i < node->InputCount(); i++) { |
| 962 Node* input = node->InputAt(i); | 981 Node* input = node->InputAt(i); |
| 963 NodeInfo* input_info = GetInfo(input); | 982 NodeInfo* input_info = GetInfo(input); |
| 964 MachineType machine_type(input_info->representation(), | 983 MachineType machine_type(input_info->representation(), |
| 965 DeoptValueSemanticOf(TypeOf(input))); | 984 DeoptValueSemanticOf(TypeOf(input))); |
| 966 DCHECK(machine_type.representation() != | 985 DCHECK(machine_type.representation() != |
| (...skipping 622 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1589 case IrOpcode::kNumberShiftRightLogical: { | 1608 case IrOpcode::kNumberShiftRightLogical: { |
| 1590 Type* rhs_type = GetUpperBound(node->InputAt(1)); | 1609 Type* rhs_type = GetUpperBound(node->InputAt(1)); |
| 1591 VisitBinop(node, UseInfo::TruncatingWord32(), | 1610 VisitBinop(node, UseInfo::TruncatingWord32(), |
| 1592 UseInfo::TruncatingWord32(), MachineRepresentation::kWord32); | 1611 UseInfo::TruncatingWord32(), MachineRepresentation::kWord32); |
| 1593 if (lower()) { | 1612 if (lower()) { |
| 1594 lowering->DoShift(node, lowering->machine()->Word32Shr(), rhs_type); | 1613 lowering->DoShift(node, lowering->machine()->Word32Shr(), rhs_type); |
| 1595 } | 1614 } |
| 1596 return; | 1615 return; |
| 1597 } | 1616 } |
| 1598 case IrOpcode::kNumberAbs: { | 1617 case IrOpcode::kNumberAbs: { |
| 1599 if (InputIs(node, Type::Unsigned32())) { | 1618 if (TypeOf(node->InputAt(0))->Is(Type::Unsigned32())) { |
| 1600 VisitUnop(node, UseInfo::TruncatingWord32(), | 1619 VisitUnop(node, UseInfo::TruncatingWord32(), |
| 1601 MachineRepresentation::kWord32); | 1620 MachineRepresentation::kWord32); |
| 1602 if (lower()) DeferReplacement(node, node->InputAt(0)); | 1621 if (lower()) DeferReplacement(node, node->InputAt(0)); |
| 1603 } else if (InputIs(node, Type::Signed32())) { | 1622 } else if (TypeOf(node->InputAt(0))->Is(Type::Signed32())) { |
| 1604 VisitUnop(node, UseInfo::TruncatingWord32(), | 1623 VisitUnop(node, UseInfo::TruncatingWord32(), |
| 1605 MachineRepresentation::kWord32); | 1624 MachineRepresentation::kWord32); |
| 1606 if (lower()) DeferReplacement(node, lowering->Int32Abs(node)); | 1625 if (lower()) DeferReplacement(node, lowering->Int32Abs(node)); |
| 1607 } else if (InputIs(node, | 1626 } else if (TypeOf(node->InputAt(0)) |
| 1608 type_cache_.kPositiveIntegerOrMinusZeroOrNaN)) { | 1627 ->Is(type_cache_.kPositiveIntegerOrMinusZeroOrNaN)) { |
| 1609 VisitUnop(node, UseInfo::TruncatingFloat64(), | 1628 VisitUnop(node, UseInfo::TruncatingFloat64(), |
| 1610 MachineRepresentation::kFloat64); | 1629 MachineRepresentation::kFloat64); |
| 1611 if (lower()) DeferReplacement(node, node->InputAt(0)); | 1630 if (lower()) DeferReplacement(node, node->InputAt(0)); |
| 1612 } else { | 1631 } else { |
| 1613 VisitUnop(node, UseInfo::TruncatingFloat64(), | 1632 VisitUnop(node, UseInfo::TruncatingFloat64(), |
| 1614 MachineRepresentation::kFloat64); | 1633 MachineRepresentation::kFloat64); |
| 1615 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); | 1634 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); |
| 1616 } | 1635 } |
| 1617 return; | 1636 return; |
| 1618 } | 1637 } |
| (...skipping 1667 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3286 isolate(), graph()->zone(), callable.descriptor(), 0, flags, | 3305 isolate(), graph()->zone(), callable.descriptor(), 0, flags, |
| 3287 Operator::kNoProperties); | 3306 Operator::kNoProperties); |
| 3288 to_number_operator_.set(common()->Call(desc)); | 3307 to_number_operator_.set(common()->Call(desc)); |
| 3289 } | 3308 } |
| 3290 return to_number_operator_.get(); | 3309 return to_number_operator_.get(); |
| 3291 } | 3310 } |
| 3292 | 3311 |
| 3293 } // namespace compiler | 3312 } // namespace compiler |
| 3294 } // namespace internal | 3313 } // namespace internal |
| 3295 } // namespace v8 | 3314 } // namespace v8 |
| OLD | NEW |