Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 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 | 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/interpreter/bytecode-generator.h" | 5 #include "src/interpreter/bytecode-generator.h" |
| 6 | 6 |
| 7 #include "src/compiler.h" | 7 #include "src/compiler.h" |
| 8 #include "src/interpreter/control-flow-builders.h" | 8 #include "src/interpreter/control-flow-builders.h" |
| 9 #include "src/objects.h" | 9 #include "src/objects.h" |
| 10 #include "src/parser.h" | 10 #include "src/parser.h" |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 231 ExpressionResultScope* outer_; | 231 ExpressionResultScope* outer_; |
| 232 TemporaryRegisterScope allocator_; | 232 TemporaryRegisterScope allocator_; |
| 233 bool result_identified_; | 233 bool result_identified_; |
| 234 | 234 |
| 235 DISALLOW_COPY_AND_ASSIGN(ExpressionResultScope); | 235 DISALLOW_COPY_AND_ASSIGN(ExpressionResultScope); |
| 236 }; | 236 }; |
| 237 | 237 |
| 238 | 238 |
| 239 // Scoped class used when the result of the current expression is not | 239 // Scoped class used when the result of the current expression is not |
| 240 // expected to produce a result. | 240 // expected to produce a result. |
| 241 class BytecodeGenerator::EffectResultScope final | 241 class BytecodeGenerator::EffectResultScope : public ExpressionResultScope { |
| 242 : public ExpressionResultScope { | |
| 243 public: | 242 public: |
| 244 explicit EffectResultScope(BytecodeGenerator* generator) | 243 explicit EffectResultScope(BytecodeGenerator* generator) |
| 245 : ExpressionResultScope(generator, Expression::kEffect) { | 244 : ExpressionResultScope(generator, Expression::kEffect) { |
| 246 set_result_identified(); | 245 set_result_identified(); |
| 247 } | 246 } |
| 248 | 247 |
| 249 virtual void SetResultInAccumulator() {} | 248 virtual void SetResultInAccumulator() {} |
| 250 virtual void SetResultInRegister(Register reg) {} | 249 virtual void SetResultInRegister(Register reg) {} |
| 251 }; | 250 }; |
| 252 | 251 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 290 set_result_identified(); | 289 set_result_identified(); |
| 291 } | 290 } |
| 292 | 291 |
| 293 Register ResultRegister() const { return result_register_; } | 292 Register ResultRegister() const { return result_register_; } |
| 294 | 293 |
| 295 private: | 294 private: |
| 296 Register result_register_; | 295 Register result_register_; |
| 297 }; | 296 }; |
| 298 | 297 |
| 299 | 298 |
| 299 // Top-level result scope when evaluating expresions. It provides an | |
| 300 // outer scope for register allocations and also ensures that | |
| 301 // assignments in binary expressions produce the correct result by | |
| 302 // aliasing registers to temporaries when necessary. | |
| 303 class BytecodeGenerator::StatementResultScope : public EffectResultScope { | |
|
rmcilroy
2015/11/03 14:17:52
nit - final
oth
2015/11/04 10:03:36
Done.
| |
| 304 public: | |
| 305 explicit StatementResultScope(BytecodeGenerator* generator) | |
| 306 : EffectResultScope(generator), | |
| 307 alias_mappings_(generator->zone()), | |
| 308 aliased_locals_and_parameters_(generator->zone()), | |
| 309 hazard_depth_(0) { | |
| 310 DCHECK_NULL(generator->statement_execution_result()); | |
| 311 generator->set_statement_execution_result(this); | |
| 312 } | |
| 313 | |
| 314 ~StatementResultScope() { | |
| 315 DCHECK_EQ(this, generator()->statement_execution_result()); | |
| 316 DCHECK(hazard_depth_ == 0); | |
| 317 generator()->set_statement_execution_result(nullptr); | |
| 318 } | |
| 319 | |
| 320 Register LoadFromAliasedRegister(Register reg) { | |
|
rmcilroy
2015/11/03 14:17:52
Could you add a comment explaining what the return
oth
2015/11/04 10:03:36
Done.
| |
| 321 if (hazard_depth_ > 0) { | |
| 322 // Insert direct mapping if none exists as register is now of interest. | |
| 323 auto insert_result = alias_mappings_.insert(std::make_pair(reg, reg)); | |
| 324 auto iterator = insert_result.first; | |
|
rmcilroy
2015/11/03 14:17:52
nit - /s/iterator/previous_value
oth
2015/11/04 10:03:36
Renamed to 'mapping' as it's either the value just
| |
| 325 return iterator->second; | |
| 326 } else { | |
| 327 return reg; | |
| 328 } | |
| 329 } | |
| 330 | |
| 331 Register StoreToAliasedRegister(Register reg) { | |
| 332 if (hazard_depth_ == 0 || | |
| 333 alias_mappings_.find(reg) == alias_mappings_.end()) { | |
| 334 return reg; | |
| 335 } else { | |
| 336 Register alias = NewRegister(); | |
| 337 alias_mappings_[reg] = alias; | |
| 338 if (generator()->builder()->RegisterIsParameterOrLocal(reg)) { | |
| 339 aliased_locals_and_parameters_.insert(reg); | |
| 340 } | |
|
rmcilroy
2015/11/03 14:17:52
nit - a few comments here would be helpful
oth
2015/11/04 10:03:36
Done.
| |
| 341 return alias; | |
| 342 } | |
| 343 } | |
| 344 | |
| 345 void EnterAssignmentHazard() { hazard_depth_++; } | |
| 346 | |
| 347 void LeaveAssignmentHazard() { | |
| 348 if (--hazard_depth_ == 0) { | |
| 349 StopAliasingRegisters(); | |
| 350 } | |
| 351 } | |
| 352 | |
| 353 private: | |
| 354 void StopAliasingRegisters() { | |
|
rmcilroy
2015/11/03 14:17:52
nit - RestoreAliasedLocalsAndParameters?
oth
2015/11/04 10:03:36
Done. Definitely a better name.
| |
| 355 // Move temporary registers holding values for locals and | |
| 356 // parameters back into their local and parameter registers. | |
| 357 for (auto reg = aliased_locals_and_parameters_.begin(); | |
| 358 reg != aliased_locals_and_parameters_.end(); reg++) { | |
| 359 auto mapping = alias_mappings_.find(*reg); | |
| 360 if (mapping != alias_mappings_.end()) { | |
| 361 builder()->MoveRegister(mapping->second, *reg); | |
| 362 } | |
| 363 } | |
| 364 alias_mappings_.clear(); | |
| 365 aliased_locals_and_parameters_.clear(); | |
| 366 } | |
| 367 | |
| 368 ZoneMap<Register, Register> alias_mappings_; | |
| 369 ZoneSet<Register> aliased_locals_and_parameters_; | |
| 370 int hazard_depth_; | |
| 371 }; | |
| 372 | |
| 373 | |
| 300 BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone) | 374 BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone) |
| 301 : isolate_(isolate), | 375 : isolate_(isolate), |
| 302 zone_(zone), | 376 zone_(zone), |
| 303 builder_(isolate, zone), | 377 builder_(isolate, zone), |
| 304 info_(nullptr), | 378 info_(nullptr), |
| 305 scope_(nullptr), | 379 scope_(nullptr), |
| 306 globals_(0, zone), | 380 globals_(0, zone), |
| 307 execution_control_(nullptr), | 381 execution_control_(nullptr), |
| 308 execution_context_(nullptr), | 382 execution_context_(nullptr), |
| 309 execution_result_(nullptr), | 383 execution_result_(nullptr), |
| 310 binary_expression_depth_(0), | 384 statement_execution_result_(nullptr) { |
| 311 binary_expression_hazard_set_(zone) { | |
| 312 InitializeAstVisitor(isolate); | 385 InitializeAstVisitor(isolate); |
| 313 } | 386 } |
| 314 | 387 |
| 315 | 388 |
| 316 BytecodeGenerator::~BytecodeGenerator() {} | 389 BytecodeGenerator::~BytecodeGenerator() {} |
| 317 | 390 |
| 318 | 391 |
| 319 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) { | 392 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) { |
| 320 set_info(info); | 393 set_info(info); |
| 321 set_scope(info->scope()); | 394 set_scope(info->scope()); |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 501 builder()->LoadLiteral(Smi::FromInt(encoded_flags)); | 574 builder()->LoadLiteral(Smi::FromInt(encoded_flags)); |
| 502 builder()->StoreAccumulatorInRegister(flags); | 575 builder()->StoreAccumulatorInRegister(flags); |
| 503 DCHECK(flags.index() == pairs.index() + 1); | 576 DCHECK(flags.index() == pairs.index() + 1); |
| 504 | 577 |
| 505 builder()->CallRuntime(Runtime::kDeclareGlobals, pairs, 2); | 578 builder()->CallRuntime(Runtime::kDeclareGlobals, pairs, 2); |
| 506 globals()->clear(); | 579 globals()->clear(); |
| 507 } | 580 } |
| 508 | 581 |
| 509 | 582 |
| 510 void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { | 583 void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { |
| 511 // TODO(rmcilroy): Replace this with a StatementResultScope when it exists. | 584 StatementResultScope statement_result_scope(this); |
| 512 EffectResultScope effect_scope(this); | |
| 513 VisitForEffect(stmt->expression()); | 585 VisitForEffect(stmt->expression()); |
| 514 } | 586 } |
| 515 | 587 |
| 516 | 588 |
| 517 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { | 589 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { |
| 518 } | 590 } |
| 519 | 591 |
| 520 | 592 |
| 521 void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) { | 593 void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) { |
| 522 BytecodeLabel else_label, end_label; | 594 BytecodeLabel else_label, end_label; |
| 523 if (stmt->condition()->ToBooleanIsTrue()) { | 595 if (stmt->condition()->ToBooleanIsTrue()) { |
| 524 // Generate only then block. | 596 // Generate only then block. |
| 525 Visit(stmt->then_statement()); | 597 Visit(stmt->then_statement()); |
| 526 } else if (stmt->condition()->ToBooleanIsFalse()) { | 598 } else if (stmt->condition()->ToBooleanIsFalse()) { |
| 527 // Generate only else block if it exists. | 599 // Generate only else block if it exists. |
| 528 if (stmt->HasElseStatement()) { | 600 if (stmt->HasElseStatement()) { |
| 529 Visit(stmt->else_statement()); | 601 Visit(stmt->else_statement()); |
| 530 } | 602 } |
| 531 } else { | 603 } else { |
| 532 VisitForAccumulatorValue(stmt->condition()); | 604 VisitCondition(stmt->condition()); |
| 533 builder()->JumpIfFalse(&else_label); | 605 builder()->JumpIfFalse(&else_label); |
| 534 Visit(stmt->then_statement()); | 606 Visit(stmt->then_statement()); |
| 535 if (stmt->HasElseStatement()) { | 607 if (stmt->HasElseStatement()) { |
| 536 builder()->Jump(&end_label); | 608 builder()->Jump(&end_label); |
| 537 builder()->Bind(&else_label); | 609 builder()->Bind(&else_label); |
| 538 Visit(stmt->else_statement()); | 610 Visit(stmt->else_statement()); |
| 539 } else { | 611 } else { |
| 540 builder()->Bind(&else_label); | 612 builder()->Bind(&else_label); |
| 541 } | 613 } |
| 542 builder()->Bind(&end_label); | 614 builder()->Bind(&end_label); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 554 execution_control()->Continue(stmt->target()); | 626 execution_control()->Continue(stmt->target()); |
| 555 } | 627 } |
| 556 | 628 |
| 557 | 629 |
| 558 void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) { | 630 void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) { |
| 559 execution_control()->Break(stmt->target()); | 631 execution_control()->Break(stmt->target()); |
| 560 } | 632 } |
| 561 | 633 |
| 562 | 634 |
| 563 void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { | 635 void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { |
| 564 EffectResultScope effect_scope(this); | 636 StatementResultScope statement_result_scope(this); |
| 565 VisitForAccumulatorValue(stmt->expression()); | 637 VisitForAccumulatorValue(stmt->expression()); |
| 566 builder()->Return(); | 638 builder()->Return(); |
| 567 } | 639 } |
| 568 | 640 |
| 569 | 641 |
| 570 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) { | 642 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) { |
| 571 UNIMPLEMENTED(); | 643 UNIMPLEMENTED(); |
| 572 } | 644 } |
| 573 | 645 |
| 574 | 646 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 619 switch_builder.SetBreakTarget(done_label); | 691 switch_builder.SetBreakTarget(done_label); |
| 620 } | 692 } |
| 621 | 693 |
| 622 | 694 |
| 623 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) { | 695 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) { |
| 624 // Handled entirely in VisitSwitchStatement. | 696 // Handled entirely in VisitSwitchStatement. |
| 625 UNREACHABLE(); | 697 UNREACHABLE(); |
| 626 } | 698 } |
| 627 | 699 |
| 628 | 700 |
| 701 void BytecodeGenerator::VisitCondition(Expression* expr) { | |
| 702 StatementResultScope statement_result_scope(this); | |
| 703 VisitForAccumulatorValue(expr); | |
| 704 } | |
| 705 | |
| 706 | |
| 629 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { | 707 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { |
| 630 LoopBuilder loop_builder(builder()); | 708 LoopBuilder loop_builder(builder()); |
| 631 ControlScopeForIteration execution_control(this, stmt, &loop_builder); | 709 ControlScopeForIteration execution_control(this, stmt, &loop_builder); |
| 632 BytecodeLabel body_label, condition_label, done_label; | 710 BytecodeLabel body_label, condition_label, done_label; |
| 633 | |
| 634 if (stmt->cond()->ToBooleanIsFalse()) { | 711 if (stmt->cond()->ToBooleanIsFalse()) { |
| 635 Visit(stmt->body()); | 712 Visit(stmt->body()); |
| 636 // Bind condition_label and done_label for processing continue and break. | 713 // Bind condition_label and done_label for processing continue and break. |
| 637 builder()->Bind(&condition_label); | 714 builder()->Bind(&condition_label); |
| 638 builder()->Bind(&done_label); | 715 builder()->Bind(&done_label); |
| 639 } else { | 716 } else { |
| 640 builder()->Bind(&body_label); | 717 builder()->Bind(&body_label); |
| 641 Visit(stmt->body()); | 718 Visit(stmt->body()); |
| 642 | 719 |
| 643 builder()->Bind(&condition_label); | 720 builder()->Bind(&condition_label); |
| 644 if (stmt->cond()->ToBooleanIsTrue()) { | 721 if (stmt->cond()->ToBooleanIsTrue()) { |
| 645 builder()->Jump(&body_label); | 722 builder()->Jump(&body_label); |
| 646 } else { | 723 } else { |
| 647 VisitForAccumulatorValue(stmt->cond()); | 724 VisitCondition(stmt->cond()); |
| 648 builder()->JumpIfTrue(&body_label); | 725 builder()->JumpIfTrue(&body_label); |
| 649 } | 726 } |
| 650 builder()->Bind(&done_label); | 727 builder()->Bind(&done_label); |
| 651 } | 728 } |
| 652 loop_builder.SetBreakTarget(done_label); | 729 loop_builder.SetBreakTarget(done_label); |
| 653 loop_builder.SetContinueTarget(condition_label); | 730 loop_builder.SetContinueTarget(condition_label); |
| 654 } | 731 } |
| 655 | 732 |
| 656 | 733 |
| 657 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) { | 734 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) { |
| 658 LoopBuilder loop_builder(builder()); | 735 LoopBuilder loop_builder(builder()); |
| 659 ControlScopeForIteration execution_control(this, stmt, &loop_builder); | 736 ControlScopeForIteration execution_control(this, stmt, &loop_builder); |
| 660 | 737 |
| 661 BytecodeLabel body_label, condition_label, done_label; | 738 BytecodeLabel body_label, condition_label, done_label; |
| 662 if (stmt->cond()->ToBooleanIsFalse()) { | 739 if (stmt->cond()->ToBooleanIsFalse()) { |
| 663 // If the condition is false there is no need to generating the loop. | 740 // If the condition is false there is no need to generating the loop. |
| 664 return; | 741 return; |
| 665 } | 742 } |
| 666 | 743 |
| 667 if (!stmt->cond()->ToBooleanIsTrue()) { | 744 if (!stmt->cond()->ToBooleanIsTrue()) { |
| 668 builder()->Jump(&condition_label); | 745 builder()->Jump(&condition_label); |
| 669 } | 746 } |
| 670 builder()->Bind(&body_label); | 747 builder()->Bind(&body_label); |
| 671 Visit(stmt->body()); | 748 Visit(stmt->body()); |
| 672 | 749 |
| 673 builder()->Bind(&condition_label); | 750 builder()->Bind(&condition_label); |
| 674 if (stmt->cond()->ToBooleanIsTrue()) { | 751 if (stmt->cond()->ToBooleanIsTrue()) { |
| 675 builder()->Jump(&body_label); | 752 builder()->Jump(&body_label); |
| 676 } else { | 753 } else { |
| 677 VisitForAccumulatorValue(stmt->cond()); | 754 VisitCondition(stmt->cond()); |
| 678 builder()->JumpIfTrue(&body_label); | 755 builder()->JumpIfTrue(&body_label); |
| 679 } | 756 } |
| 680 builder()->Bind(&done_label); | 757 builder()->Bind(&done_label); |
| 681 | 758 |
| 682 loop_builder.SetBreakTarget(done_label); | 759 loop_builder.SetBreakTarget(done_label); |
| 683 loop_builder.SetContinueTarget(condition_label); | 760 loop_builder.SetContinueTarget(condition_label); |
| 684 } | 761 } |
| 685 | 762 |
| 686 | 763 |
| 687 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) { | 764 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) { |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 703 builder()->Jump(&condition_label); | 780 builder()->Jump(&condition_label); |
| 704 } | 781 } |
| 705 builder()->Bind(&body_label); | 782 builder()->Bind(&body_label); |
| 706 Visit(stmt->body()); | 783 Visit(stmt->body()); |
| 707 builder()->Bind(&next_label); | 784 builder()->Bind(&next_label); |
| 708 if (stmt->next() != nullptr) { | 785 if (stmt->next() != nullptr) { |
| 709 Visit(stmt->next()); | 786 Visit(stmt->next()); |
| 710 } | 787 } |
| 711 if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) { | 788 if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) { |
| 712 builder()->Bind(&condition_label); | 789 builder()->Bind(&condition_label); |
| 713 VisitForAccumulatorValue(stmt->cond()); | 790 VisitCondition(stmt->cond()); |
| 714 builder()->JumpIfTrue(&body_label); | 791 builder()->JumpIfTrue(&body_label); |
| 715 } else { | 792 } else { |
| 716 builder()->Jump(&body_label); | 793 builder()->Jump(&body_label); |
| 717 } | 794 } |
| 718 builder()->Bind(&done_label); | 795 builder()->Bind(&done_label); |
| 719 | 796 |
| 720 loop_builder.SetBreakTarget(done_label); | 797 loop_builder.SetBreakTarget(done_label); |
| 721 loop_builder.SetContinueTarget(next_label); | 798 loop_builder.SetContinueTarget(next_label); |
| 722 } | 799 } |
| 723 | 800 |
| (...skipping 469 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1193 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { | 1270 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { |
| 1194 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); | 1271 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); |
| 1195 } | 1272 } |
| 1196 | 1273 |
| 1197 | 1274 |
| 1198 void BytecodeGenerator::VisitVariableLoad(Variable* variable, | 1275 void BytecodeGenerator::VisitVariableLoad(Variable* variable, |
| 1199 FeedbackVectorSlot slot) { | 1276 FeedbackVectorSlot slot) { |
| 1200 switch (variable->location()) { | 1277 switch (variable->location()) { |
| 1201 case VariableLocation::LOCAL: { | 1278 case VariableLocation::LOCAL: { |
| 1202 Register source(Register(variable->index())); | 1279 Register source(Register(variable->index())); |
| 1280 if (statement_execution_result()) { | |
|
rmcilroy
2015/11/03 14:17:51
Should we not always have a statement_execution_re
oth
2015/11/04 10:03:36
Right, this bit is tricky. There are places we rea
| |
| 1281 source = statement_execution_result()->LoadFromAliasedRegister(source); | |
|
rmcilroy
2015/11/03 14:17:51
nit - RecordLoadFrom...
oth
2015/11/04 10:03:36
GetRegisterToLoadFrom?
GetRegisterToStoreTo?
| |
| 1282 } | |
| 1203 execution_result()->SetResultInRegister(source); | 1283 execution_result()->SetResultInRegister(source); |
| 1204 break; | 1284 break; |
| 1205 } | 1285 } |
| 1206 case VariableLocation::PARAMETER: { | 1286 case VariableLocation::PARAMETER: { |
| 1207 // The parameter indices are shifted by 1 (receiver is variable | 1287 // The parameter indices are shifted by 1 (receiver is variable |
| 1208 // index -1 but is parameter index 0 in BytecodeArrayBuilder). | 1288 // index -1 but is parameter index 0 in BytecodeArrayBuilder). |
| 1209 Register source = builder()->Parameter(variable->index() + 1); | 1289 Register source = builder()->Parameter(variable->index() + 1); |
| 1290 if (statement_execution_result()) { | |
| 1291 source = statement_execution_result()->LoadFromAliasedRegister(source); | |
| 1292 } | |
| 1210 execution_result()->SetResultInRegister(source); | 1293 execution_result()->SetResultInRegister(source); |
| 1211 break; | 1294 break; |
| 1212 } | 1295 } |
| 1213 case VariableLocation::GLOBAL: | 1296 case VariableLocation::GLOBAL: |
| 1214 case VariableLocation::UNALLOCATED: { | 1297 case VariableLocation::UNALLOCATED: { |
| 1215 size_t name_index = builder()->GetConstantPoolEntry(variable->name()); | 1298 size_t name_index = builder()->GetConstantPoolEntry(variable->name()); |
| 1216 builder()->LoadGlobal(name_index, feedback_index(slot), language_mode()); | 1299 builder()->LoadGlobal(name_index, feedback_index(slot), language_mode()); |
| 1217 execution_result()->SetResultInAccumulator(); | 1300 execution_result()->SetResultInAccumulator(); |
| 1218 break; | 1301 break; |
| 1219 } | 1302 } |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1263 return register_scope.ResultRegister(); | 1346 return register_scope.ResultRegister(); |
| 1264 } | 1347 } |
| 1265 | 1348 |
| 1266 | 1349 |
| 1267 void BytecodeGenerator::VisitVariableAssignment(Variable* variable, | 1350 void BytecodeGenerator::VisitVariableAssignment(Variable* variable, |
| 1268 FeedbackVectorSlot slot) { | 1351 FeedbackVectorSlot slot) { |
| 1269 switch (variable->location()) { | 1352 switch (variable->location()) { |
| 1270 case VariableLocation::LOCAL: { | 1353 case VariableLocation::LOCAL: { |
| 1271 // TODO(rmcilroy): support const mode initialization. | 1354 // TODO(rmcilroy): support const mode initialization. |
| 1272 Register destination(variable->index()); | 1355 Register destination(variable->index()); |
| 1356 if (statement_execution_result()) { | |
|
rmcilroy
2015/11/03 14:17:51
Ditto with assignments?
oth
2015/11/04 10:03:36
Changed to assignment_hazard_scope, but have to ch
| |
| 1357 destination = | |
| 1358 statement_execution_result()->StoreToAliasedRegister(destination); | |
|
rmcilroy
2015/11/03 14:17:52
nit - RecordStoreTo...
oth
2015/11/04 10:03:36
GetRegisterForStore okay?
| |
| 1359 } | |
| 1273 builder()->StoreAccumulatorInRegister(destination); | 1360 builder()->StoreAccumulatorInRegister(destination); |
| 1274 RecordStoreToRegister(destination); | |
| 1275 break; | 1361 break; |
| 1276 } | 1362 } |
| 1277 case VariableLocation::PARAMETER: { | 1363 case VariableLocation::PARAMETER: { |
| 1278 // The parameter indices are shifted by 1 (receiver is variable | 1364 // The parameter indices are shifted by 1 (receiver is variable |
| 1279 // index -1 but is parameter index 0 in BytecodeArrayBuilder). | 1365 // index -1 but is parameter index 0 in BytecodeArrayBuilder). |
| 1280 Register destination(builder()->Parameter(variable->index() + 1)); | 1366 Register destination(builder()->Parameter(variable->index() + 1)); |
| 1367 if (statement_execution_result()) { | |
| 1368 destination = | |
| 1369 statement_execution_result()->StoreToAliasedRegister(destination); | |
| 1370 } | |
| 1281 builder()->StoreAccumulatorInRegister(destination); | 1371 builder()->StoreAccumulatorInRegister(destination); |
| 1282 RecordStoreToRegister(destination); | |
| 1283 break; | 1372 break; |
| 1284 } | 1373 } |
| 1285 case VariableLocation::GLOBAL: | 1374 case VariableLocation::GLOBAL: |
| 1286 case VariableLocation::UNALLOCATED: { | 1375 case VariableLocation::UNALLOCATED: { |
| 1287 size_t name_index = builder()->GetConstantPoolEntry(variable->name()); | 1376 size_t name_index = builder()->GetConstantPoolEntry(variable->name()); |
| 1288 builder()->StoreGlobal(name_index, feedback_index(slot), language_mode()); | 1377 builder()->StoreGlobal(name_index, feedback_index(slot), language_mode()); |
| 1289 break; | 1378 break; |
| 1290 } | 1379 } |
| 1291 case VariableLocation::CONTEXT: { | 1380 case VariableLocation::CONTEXT: { |
| 1292 // TODO(rmcilroy): support const mode initialization. | 1381 // TODO(rmcilroy): support const mode initialization. |
| (...skipping 525 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1818 VisitLogicalAndExpression(binop); | 1907 VisitLogicalAndExpression(binop); |
| 1819 break; | 1908 break; |
| 1820 default: | 1909 default: |
| 1821 VisitArithmeticExpression(binop); | 1910 VisitArithmeticExpression(binop); |
| 1822 break; | 1911 break; |
| 1823 } | 1912 } |
| 1824 } | 1913 } |
| 1825 | 1914 |
| 1826 | 1915 |
| 1827 void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) { | 1916 void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) { |
| 1828 // TODO(oth): Remove PrepareForBinaryExpression/CompleteBinaryExpression | 1917 // The evaluation of binary comparison expressions has an assignment |
| 1829 // once we have StatementScope that tracks hazardous loads/stores. | 1918 // hazard because the lhs may be a variable that evaluates to a |
| 1830 PrepareForBinaryExpression(); | 1919 // local or parameter and the rhs may modify that, e.g. y = x + (x = 1) |
| 1920 // To get a correct result the generator treats the inner assigment | |
| 1921 // as being made to a temporary x' that is spilled on exit of the | |
| 1922 // assignment hazard. | |
| 1923 statement_execution_result()->EnterAssignmentHazard(); | |
| 1831 Register lhs = VisitForRegisterValue(expr->left()); | 1924 Register lhs = VisitForRegisterValue(expr->left()); |
| 1832 if (builder()->RegisterIsParameterOrLocal(lhs)) { | |
| 1833 // Result was returned in an existing local or parameter. See if | |
| 1834 // it needs to be moved to a temporary. | |
| 1835 // TODO(oth) LoadFromAliasedRegister call into VisitVariableLoad(). | |
| 1836 lhs = LoadFromAliasedRegister(lhs); | |
| 1837 } | |
| 1838 VisitForAccumulatorValue(expr->right()); | 1925 VisitForAccumulatorValue(expr->right()); |
| 1839 builder()->CompareOperation(expr->op(), lhs, language_mode_strength()); | 1926 builder()->CompareOperation(expr->op(), lhs, language_mode_strength()); |
| 1840 CompleteBinaryExpression(); | |
| 1841 execution_result()->SetResultInAccumulator(); | 1927 execution_result()->SetResultInAccumulator(); |
| 1928 statement_execution_result()->LeaveAssignmentHazard(); | |
| 1842 } | 1929 } |
| 1843 | 1930 |
| 1844 | 1931 |
| 1845 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) { | 1932 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) { |
| 1846 // TODO(oth): Remove PrepareForBinaryExpression/CompleteBinaryExpression | 1933 // The evaluation of binary arithmetic expressions has an assignment |
| 1847 // once we have StatementScope that tracks hazardous loads/stores. | 1934 // hazard because the lhs may be a variable that evaluates to a |
| 1848 PrepareForBinaryExpression(); | 1935 // local or parameter and the rhs may modify that, e.g. y = x + (x = 1) |
| 1936 // To get a correct result the generator treats the inner assigment | |
| 1937 // as being made to a temporary x' that is spilled on exit of the | |
| 1938 // assignment hazard. | |
| 1939 statement_execution_result()->EnterAssignmentHazard(); | |
|
rmcilroy
2015/11/03 14:17:52
Could we do this as a scoped class (AssignmentHaza
oth
2015/11/04 10:03:36
Done.
| |
| 1849 Register lhs = VisitForRegisterValue(expr->left()); | 1940 Register lhs = VisitForRegisterValue(expr->left()); |
| 1850 if (builder()->RegisterIsParameterOrLocal(lhs)) { | |
| 1851 // Result was returned in an existing local or parameter. See if | |
| 1852 // it needs to be moved to a temporary. | |
| 1853 // TODO(oth) LoadFromAliasedRegister call into VisitVariableLoad(). | |
| 1854 lhs = LoadFromAliasedRegister(lhs); | |
| 1855 } | |
| 1856 VisitForAccumulatorValue(expr->right()); | 1941 VisitForAccumulatorValue(expr->right()); |
| 1857 builder()->BinaryOperation(expr->op(), lhs, language_mode_strength()); | 1942 builder()->BinaryOperation(expr->op(), lhs, language_mode_strength()); |
| 1858 CompleteBinaryExpression(); | |
| 1859 execution_result()->SetResultInAccumulator(); | 1943 execution_result()->SetResultInAccumulator(); |
| 1944 statement_execution_result()->LeaveAssignmentHazard(); | |
| 1860 } | 1945 } |
| 1861 | 1946 |
| 1862 | 1947 |
| 1863 void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); } | 1948 void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); } |
| 1864 | 1949 |
| 1865 | 1950 |
| 1866 void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) { | 1951 void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) { |
| 1867 UNREACHABLE(); | 1952 UNREACHABLE(); |
| 1868 } | 1953 } |
| 1869 | 1954 |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2069 // Pass a SMI sentinel and let the runtime look up the empty function. | 2154 // Pass a SMI sentinel and let the runtime look up the empty function. |
| 2070 builder()->LoadLiteral(Smi::FromInt(0)); | 2155 builder()->LoadLiteral(Smi::FromInt(0)); |
| 2071 } else { | 2156 } else { |
| 2072 DCHECK(closure_scope->is_function_scope()); | 2157 DCHECK(closure_scope->is_function_scope()); |
| 2073 builder()->LoadAccumulatorWithRegister(Register::function_closure()); | 2158 builder()->LoadAccumulatorWithRegister(Register::function_closure()); |
| 2074 } | 2159 } |
| 2075 execution_result()->SetResultInAccumulator(); | 2160 execution_result()->SetResultInAccumulator(); |
| 2076 } | 2161 } |
| 2077 | 2162 |
| 2078 | 2163 |
| 2079 void BytecodeGenerator::PrepareForBinaryExpression() { | |
| 2080 if (binary_expression_depth_++ == 0) { | |
| 2081 binary_expression_hazard_set_.clear(); | |
| 2082 } | |
| 2083 } | |
| 2084 | |
| 2085 | |
| 2086 // Visits the expression |expr| and places the result in the accumulator. | 2164 // Visits the expression |expr| and places the result in the accumulator. |
| 2087 void BytecodeGenerator::VisitForAccumulatorValue(Expression* expr) { | 2165 void BytecodeGenerator::VisitForAccumulatorValue(Expression* expr) { |
| 2088 AccumulatorResultScope accumulator_scope(this); | 2166 AccumulatorResultScope accumulator_scope(this); |
| 2089 Visit(expr); | 2167 Visit(expr); |
| 2090 } | 2168 } |
| 2091 | 2169 |
| 2092 | 2170 |
| 2093 // Visits the expression |expr| and discards the result. | 2171 // Visits the expression |expr| and discards the result. |
| 2094 void BytecodeGenerator::VisitForEffect(Expression* expr) { | 2172 void BytecodeGenerator::VisitForEffect(Expression* expr) { |
| 2095 EffectResultScope effect_scope(this); | 2173 EffectResultScope effect_scope(this); |
| 2096 Visit(expr); | 2174 Visit(expr); |
| 2097 } | 2175 } |
| 2098 | 2176 |
| 2099 | 2177 |
| 2100 // Visits the expression |expr| and returns the register containing | 2178 // Visits the expression |expr| and returns the register containing |
| 2101 // the expression result. | 2179 // the expression result. |
| 2102 Register BytecodeGenerator::VisitForRegisterValue(Expression* expr) { | 2180 Register BytecodeGenerator::VisitForRegisterValue(Expression* expr) { |
| 2103 RegisterResultScope register_scope(this); | 2181 RegisterResultScope register_scope(this); |
| 2104 Visit(expr); | 2182 Visit(expr); |
| 2105 return register_scope.ResultRegister(); | 2183 return register_scope.ResultRegister(); |
| 2106 } | 2184 } |
| 2107 | 2185 |
| 2108 | 2186 |
| 2109 Register BytecodeGenerator::LoadFromAliasedRegister(Register reg) { | |
| 2110 // TODO(oth): Follow on CL to load from re-map here. | |
| 2111 DCHECK(builder()->RegisterIsParameterOrLocal(reg)); | |
| 2112 if (binary_expression_depth_ > 0) { | |
| 2113 binary_expression_hazard_set_.insert(reg.index()); | |
| 2114 } | |
| 2115 return reg; | |
| 2116 } | |
| 2117 | |
| 2118 | |
| 2119 void BytecodeGenerator::RecordStoreToRegister(Register reg) { | |
| 2120 DCHECK(builder()->RegisterIsParameterOrLocal(reg)); | |
| 2121 if (binary_expression_depth_ > 0) { | |
| 2122 // TODO(oth): a store to a register that's be loaded needs to be | |
| 2123 // remapped. | |
| 2124 DCHECK(binary_expression_hazard_set_.find(reg.index()) == | |
| 2125 binary_expression_hazard_set_.end()); | |
| 2126 } | |
| 2127 } | |
| 2128 | |
| 2129 | |
| 2130 void BytecodeGenerator::CompleteBinaryExpression() { | |
| 2131 DCHECK(binary_expression_depth_ > 0); | |
| 2132 binary_expression_depth_ -= 1; | |
| 2133 // TODO(oth): spill remapped registers into origins. | |
| 2134 // TODO(oth): make statement/top-level. | |
| 2135 } | |
| 2136 | |
| 2137 | |
| 2138 Register BytecodeGenerator::NextContextRegister() const { | 2187 Register BytecodeGenerator::NextContextRegister() const { |
| 2139 if (execution_context() == nullptr) { | 2188 if (execution_context() == nullptr) { |
| 2140 // Return the incoming function context for the outermost execution context. | 2189 // Return the incoming function context for the outermost execution context. |
| 2141 return Register::function_context(); | 2190 return Register::function_context(); |
| 2142 } | 2191 } |
| 2143 Register previous = execution_context()->reg(); | 2192 Register previous = execution_context()->reg(); |
| 2144 if (previous == Register::function_context()) { | 2193 if (previous == Register::function_context()) { |
| 2145 // If the previous context was the incoming function context, then the next | 2194 // If the previous context was the incoming function context, then the next |
| 2146 // context register is the first local context register. | 2195 // context register is the first local context register. |
| 2147 return builder_.first_context_register(); | 2196 return builder_.first_context_register(); |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 2163 } | 2212 } |
| 2164 | 2213 |
| 2165 | 2214 |
| 2166 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 2215 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
| 2167 return info()->feedback_vector()->GetIndex(slot); | 2216 return info()->feedback_vector()->GetIndex(slot); |
| 2168 } | 2217 } |
| 2169 | 2218 |
| 2170 } // namespace interpreter | 2219 } // namespace interpreter |
| 2171 } // namespace internal | 2220 } // namespace internal |
| 2172 } // namespace v8 | 2221 } // namespace v8 |
| OLD | NEW |