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