Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(61)

Side by Side Diff: src/interpreter/bytecode-generator.cc

Issue 1412683011: [Interpreter] Enable assignments in expressions. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Additional tests for conditional expressions. Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698