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 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
290 set_result_identified(); | 290 set_result_identified(); |
291 } | 291 } |
292 | 292 |
293 Register ResultRegister() const { return result_register_; } | 293 Register ResultRegister() const { return result_register_; } |
294 | 294 |
295 private: | 295 private: |
296 Register result_register_; | 296 Register result_register_; |
297 }; | 297 }; |
298 | 298 |
299 | 299 |
| 300 BytecodeGenerator::AssignmentHazardHelper::AssignmentHazardHelper( |
| 301 BytecodeGenerator* generator) |
| 302 : generator_(generator), |
| 303 alias_mappings_(generator->zone()), |
| 304 aliased_locals_and_parameters_(generator->zone()), |
| 305 execution_result_(nullptr), |
| 306 scope_depth_(0) {} |
| 307 |
| 308 |
| 309 void BytecodeGenerator::AssignmentHazardHelper::EnterScope() { |
| 310 DCHECK_GE(scope_depth_, 0); |
| 311 if (scope_depth_++ == 0) { |
| 312 execution_result_ = generator_->execution_result(); |
| 313 } |
| 314 } |
| 315 |
| 316 |
| 317 void BytecodeGenerator::AssignmentHazardHelper::LeaveScope() { |
| 318 DCHECK_GT(scope_depth_, 0); |
| 319 if (--scope_depth_ == 0) { |
| 320 DCHECK_EQ(execution_result_, generator_->execution_result()); |
| 321 RestoreAliasedLocalsAndParameters(); |
| 322 } |
| 323 } |
| 324 |
| 325 |
| 326 // Returns a register that a load instruction should use when |
| 327 // loading from |reg|. This allows an alias for a modified version |
| 328 // of |reg| to be used within a hazard regions. |
| 329 MUST_USE_RESULT Register |
| 330 BytecodeGenerator::AssignmentHazardHelper::GetRegisterForLoad(Register reg) { |
| 331 if (scope_depth_ == 0) { |
| 332 return reg; |
| 333 } else { |
| 334 // A load from |reg| is to be issued. The register is placed in |
| 335 // the mappings table initially mapping to itself. Future stores |
| 336 // will update the mapping with temporaries thus preserving the |
| 337 // original register's value. |
| 338 // |
| 339 // NB This insert only updates the table if no mapping exists |
| 340 // already (std::map::insert semantics). |
| 341 auto insert_result = |
| 342 alias_mappings_.insert(std::make_pair(reg.index(), reg.index())); |
| 343 auto mapping = insert_result.first; |
| 344 // Return the current alias for reg. |
| 345 return Register(mapping->second); |
| 346 } |
| 347 } |
| 348 |
| 349 |
| 350 // Returns a register that a store instruction should use when |
| 351 // loading from |reg|. This allows an alias for a modified version |
| 352 // of |reg| to be used within hazard regions. |
| 353 MUST_USE_RESULT Register |
| 354 BytecodeGenerator::AssignmentHazardHelper::GetRegisterForStore(Register reg) { |
| 355 if (scope_depth_ == 0 || |
| 356 alias_mappings_.find(reg.index()) == alias_mappings_.end()) { |
| 357 // If not in a hazard region or a load for this register has not |
| 358 // occurred no mapping is necessary. |
| 359 return reg; |
| 360 } else { |
| 361 // Storing to a register with 1 or more loads issued. The |
| 362 // register is mapped to a temporary alias so we don't overwrite |
| 363 // the lhs value, e.g. y = x + (x = 1); has a register for x on |
| 364 // the lhs and needs a new register x' for the upcoming store on |
| 365 // the rhs as the original x is an input to the add operation. |
| 366 Register alias = execution_result_->NewRegister(); |
| 367 alias_mappings_[reg.index()] = alias.index(); |
| 368 if (generator_->builder()->RegisterIsParameterOrLocal(reg)) { |
| 369 // Keep track of registers that need to be restored on exit |
| 370 // from the assignment hazard region. |
| 371 aliased_locals_and_parameters_.insert(reg.index()); |
| 372 } |
| 373 return alias; |
| 374 } |
| 375 } |
| 376 |
| 377 |
| 378 void BytecodeGenerator::AssignmentHazardHelper:: |
| 379 RestoreAliasedLocalsAndParameters() { |
| 380 DCHECK(scope_depth_ == 0); |
| 381 // Move temporary registers holding values for locals and |
| 382 // parameters back into their local and parameter registers. |
| 383 for (auto reg = aliased_locals_and_parameters_.begin(); |
| 384 reg != aliased_locals_and_parameters_.end(); reg++) { |
| 385 auto mapping = alias_mappings_.find(*reg); |
| 386 if (mapping != alias_mappings_.end()) { |
| 387 generator_->builder()->MoveRegister(Register(mapping->second), |
| 388 Register(*reg)); |
| 389 } |
| 390 } |
| 391 alias_mappings_.clear(); |
| 392 aliased_locals_and_parameters_.clear(); |
| 393 } |
| 394 |
| 395 |
| 396 class BytecodeGenerator::AssignmentHazardScope final { |
| 397 public: |
| 398 explicit AssignmentHazardScope(BytecodeGenerator* generator) |
| 399 : generator_(generator) { |
| 400 generator_->assignment_hazard_helper()->EnterScope(); |
| 401 } |
| 402 |
| 403 ~AssignmentHazardScope() { |
| 404 generator_->assignment_hazard_helper()->LeaveScope(); |
| 405 } |
| 406 |
| 407 private: |
| 408 BytecodeGenerator* generator_; |
| 409 |
| 410 DISALLOW_COPY_AND_ASSIGN(AssignmentHazardScope); |
| 411 }; |
| 412 |
| 413 |
300 BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone) | 414 BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone) |
301 : isolate_(isolate), | 415 : isolate_(isolate), |
302 zone_(zone), | 416 zone_(zone), |
303 builder_(isolate, zone), | 417 builder_(isolate, zone), |
304 info_(nullptr), | 418 info_(nullptr), |
305 scope_(nullptr), | 419 scope_(nullptr), |
306 globals_(0, zone), | 420 globals_(0, zone), |
307 execution_control_(nullptr), | 421 execution_control_(nullptr), |
308 execution_context_(nullptr), | 422 execution_context_(nullptr), |
309 execution_result_(nullptr), | 423 execution_result_(nullptr), |
310 binary_expression_depth_(0), | 424 assignment_hazard_helper_(this) { |
311 binary_expression_hazard_set_(zone) { | |
312 InitializeAstVisitor(isolate); | 425 InitializeAstVisitor(isolate); |
313 } | 426 } |
314 | 427 |
315 | 428 |
316 BytecodeGenerator::~BytecodeGenerator() {} | |
317 | |
318 | |
319 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) { | 429 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) { |
320 set_info(info); | 430 set_info(info); |
321 set_scope(info->scope()); | 431 set_scope(info->scope()); |
322 | 432 |
323 // Initialize the incoming context. | 433 // Initialize the incoming context. |
324 ContextScope incoming_context(this, scope(), false); | 434 ContextScope incoming_context(this, scope(), false); |
325 | 435 |
326 builder()->set_parameter_count(info->num_parameters_including_this()); | 436 builder()->set_parameter_count(info->num_parameters_including_this()); |
327 builder()->set_locals_count(scope()->num_stack_slots()); | 437 builder()->set_locals_count(scope()->num_stack_slots()); |
328 builder()->set_context_count(scope()->MaxNestedContextChainLength()); | 438 builder()->set_context_count(scope()->MaxNestedContextChainLength()); |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
499 builder()->LoadLiteral(Smi::FromInt(encoded_flags)); | 609 builder()->LoadLiteral(Smi::FromInt(encoded_flags)); |
500 builder()->StoreAccumulatorInRegister(flags); | 610 builder()->StoreAccumulatorInRegister(flags); |
501 DCHECK(flags.index() == pairs.index() + 1); | 611 DCHECK(flags.index() == pairs.index() + 1); |
502 | 612 |
503 builder()->CallRuntime(Runtime::kDeclareGlobals, pairs, 2); | 613 builder()->CallRuntime(Runtime::kDeclareGlobals, pairs, 2); |
504 globals()->clear(); | 614 globals()->clear(); |
505 } | 615 } |
506 | 616 |
507 | 617 |
508 void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { | 618 void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { |
509 // TODO(rmcilroy): Replace this with a StatementResultScope when it exists. | 619 EffectResultScope statement_result_scope(this); |
510 EffectResultScope effect_scope(this); | |
511 VisitForEffect(stmt->expression()); | 620 VisitForEffect(stmt->expression()); |
512 } | 621 } |
513 | 622 |
514 | 623 |
515 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { | 624 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { |
516 } | 625 } |
517 | 626 |
518 | 627 |
519 void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) { | 628 void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) { |
520 BytecodeLabel else_label, end_label; | 629 BytecodeLabel else_label, end_label; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
552 execution_control()->Continue(stmt->target()); | 661 execution_control()->Continue(stmt->target()); |
553 } | 662 } |
554 | 663 |
555 | 664 |
556 void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) { | 665 void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) { |
557 execution_control()->Break(stmt->target()); | 666 execution_control()->Break(stmt->target()); |
558 } | 667 } |
559 | 668 |
560 | 669 |
561 void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { | 670 void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { |
562 EffectResultScope effect_scope(this); | 671 EffectResultScope statement_result_scope(this); |
563 VisitForAccumulatorValue(stmt->expression()); | 672 VisitForAccumulatorValue(stmt->expression()); |
564 builder()->Return(); | 673 builder()->Return(); |
565 } | 674 } |
566 | 675 |
567 | 676 |
568 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) { | 677 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) { |
569 UNIMPLEMENTED(); | 678 UNIMPLEMENTED(); |
570 } | 679 } |
571 | 680 |
572 | 681 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
621 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) { | 730 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) { |
622 // Handled entirely in VisitSwitchStatement. | 731 // Handled entirely in VisitSwitchStatement. |
623 UNREACHABLE(); | 732 UNREACHABLE(); |
624 } | 733 } |
625 | 734 |
626 | 735 |
627 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { | 736 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { |
628 LoopBuilder loop_builder(builder()); | 737 LoopBuilder loop_builder(builder()); |
629 ControlScopeForIteration execution_control(this, stmt, &loop_builder); | 738 ControlScopeForIteration execution_control(this, stmt, &loop_builder); |
630 BytecodeLabel body_label, condition_label, done_label; | 739 BytecodeLabel body_label, condition_label, done_label; |
631 | |
632 if (stmt->cond()->ToBooleanIsFalse()) { | 740 if (stmt->cond()->ToBooleanIsFalse()) { |
633 Visit(stmt->body()); | 741 Visit(stmt->body()); |
634 // Bind condition_label and done_label for processing continue and break. | 742 // Bind condition_label and done_label for processing continue and break. |
635 builder()->Bind(&condition_label); | 743 builder()->Bind(&condition_label); |
636 builder()->Bind(&done_label); | 744 builder()->Bind(&done_label); |
637 } else { | 745 } else { |
638 builder()->Bind(&body_label); | 746 builder()->Bind(&body_label); |
639 Visit(stmt->body()); | 747 Visit(stmt->body()); |
640 | 748 |
641 builder()->Bind(&condition_label); | 749 builder()->Bind(&condition_label); |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
757 break; | 865 break; |
758 } | 866 } |
759 case NAMED_SUPER_PROPERTY: | 867 case NAMED_SUPER_PROPERTY: |
760 case KEYED_SUPER_PROPERTY: | 868 case KEYED_SUPER_PROPERTY: |
761 UNIMPLEMENTED(); | 869 UNIMPLEMENTED(); |
762 } | 870 } |
763 } | 871 } |
764 | 872 |
765 | 873 |
766 void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) { | 874 void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) { |
767 // TODO(oth): For now we need a parent scope for paths that end up | 875 EffectResultScope statement_result_scope(this); |
768 // in VisitLiteral which can allocate in the parent scope. A future | |
769 // CL in preparation will add a StatementResultScope that will | |
770 // remove the need for this EffectResultScope. | |
771 EffectResultScope result_scope(this); | |
772 | 876 |
773 if (stmt->subject()->IsNullLiteral() || | 877 if (stmt->subject()->IsNullLiteral() || |
774 stmt->subject()->IsUndefinedLiteral(isolate())) { | 878 stmt->subject()->IsUndefinedLiteral(isolate())) { |
775 // ForIn generates lots of code, skip if it wouldn't produce any effects. | 879 // ForIn generates lots of code, skip if it wouldn't produce any effects. |
776 return; | 880 return; |
777 } | 881 } |
778 | 882 |
779 LoopBuilder loop_builder(builder()); | 883 LoopBuilder loop_builder(builder()); |
780 ControlScopeForIteration control_scope(this, stmt, &loop_builder); | 884 ControlScopeForIteration control_scope(this, stmt, &loop_builder); |
781 | 885 |
(...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1191 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); | 1295 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); |
1192 } | 1296 } |
1193 | 1297 |
1194 | 1298 |
1195 void BytecodeGenerator::VisitVariableLoad(Variable* variable, | 1299 void BytecodeGenerator::VisitVariableLoad(Variable* variable, |
1196 FeedbackVectorSlot slot, | 1300 FeedbackVectorSlot slot, |
1197 TypeofMode typeof_mode) { | 1301 TypeofMode typeof_mode) { |
1198 switch (variable->location()) { | 1302 switch (variable->location()) { |
1199 case VariableLocation::LOCAL: { | 1303 case VariableLocation::LOCAL: { |
1200 Register source(Register(variable->index())); | 1304 Register source(Register(variable->index())); |
| 1305 source = assignment_hazard_helper()->GetRegisterForLoad(source); |
1201 execution_result()->SetResultInRegister(source); | 1306 execution_result()->SetResultInRegister(source); |
1202 break; | 1307 break; |
1203 } | 1308 } |
1204 case VariableLocation::PARAMETER: { | 1309 case VariableLocation::PARAMETER: { |
1205 // The parameter indices are shifted by 1 (receiver is variable | 1310 // The parameter indices are shifted by 1 (receiver is variable |
1206 // index -1 but is parameter index 0 in BytecodeArrayBuilder). | 1311 // index -1 but is parameter index 0 in BytecodeArrayBuilder). |
1207 Register source = builder()->Parameter(variable->index() + 1); | 1312 Register source = builder()->Parameter(variable->index() + 1); |
| 1313 source = assignment_hazard_helper()->GetRegisterForLoad(source); |
1208 execution_result()->SetResultInRegister(source); | 1314 execution_result()->SetResultInRegister(source); |
1209 break; | 1315 break; |
1210 } | 1316 } |
1211 case VariableLocation::GLOBAL: | 1317 case VariableLocation::GLOBAL: |
1212 case VariableLocation::UNALLOCATED: { | 1318 case VariableLocation::UNALLOCATED: { |
1213 size_t name_index = builder()->GetConstantPoolEntry(variable->name()); | 1319 size_t name_index = builder()->GetConstantPoolEntry(variable->name()); |
1214 builder()->LoadGlobal(name_index, feedback_index(slot), language_mode(), | 1320 builder()->LoadGlobal(name_index, feedback_index(slot), language_mode(), |
1215 typeof_mode); | 1321 typeof_mode); |
1216 execution_result()->SetResultInAccumulator(); | 1322 execution_result()->SetResultInAccumulator(); |
1217 break; | 1323 break; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1262 return register_scope.ResultRegister(); | 1368 return register_scope.ResultRegister(); |
1263 } | 1369 } |
1264 | 1370 |
1265 | 1371 |
1266 void BytecodeGenerator::VisitVariableAssignment(Variable* variable, | 1372 void BytecodeGenerator::VisitVariableAssignment(Variable* variable, |
1267 FeedbackVectorSlot slot) { | 1373 FeedbackVectorSlot slot) { |
1268 switch (variable->location()) { | 1374 switch (variable->location()) { |
1269 case VariableLocation::LOCAL: { | 1375 case VariableLocation::LOCAL: { |
1270 // TODO(rmcilroy): support const mode initialization. | 1376 // TODO(rmcilroy): support const mode initialization. |
1271 Register destination(variable->index()); | 1377 Register destination(variable->index()); |
| 1378 destination = |
| 1379 assignment_hazard_helper()->GetRegisterForStore(destination); |
1272 builder()->StoreAccumulatorInRegister(destination); | 1380 builder()->StoreAccumulatorInRegister(destination); |
1273 RecordStoreToRegister(destination); | |
1274 break; | 1381 break; |
1275 } | 1382 } |
1276 case VariableLocation::PARAMETER: { | 1383 case VariableLocation::PARAMETER: { |
1277 // The parameter indices are shifted by 1 (receiver is variable | 1384 // The parameter indices are shifted by 1 (receiver is variable |
1278 // index -1 but is parameter index 0 in BytecodeArrayBuilder). | 1385 // index -1 but is parameter index 0 in BytecodeArrayBuilder). |
1279 Register destination(builder()->Parameter(variable->index() + 1)); | 1386 Register destination(builder()->Parameter(variable->index() + 1)); |
| 1387 destination = |
| 1388 assignment_hazard_helper()->GetRegisterForStore(destination); |
| 1389 |
1280 builder()->StoreAccumulatorInRegister(destination); | 1390 builder()->StoreAccumulatorInRegister(destination); |
1281 RecordStoreToRegister(destination); | |
1282 break; | 1391 break; |
1283 } | 1392 } |
1284 case VariableLocation::GLOBAL: | 1393 case VariableLocation::GLOBAL: |
1285 case VariableLocation::UNALLOCATED: { | 1394 case VariableLocation::UNALLOCATED: { |
1286 size_t name_index = builder()->GetConstantPoolEntry(variable->name()); | 1395 size_t name_index = builder()->GetConstantPoolEntry(variable->name()); |
1287 builder()->StoreGlobal(name_index, feedback_index(slot), language_mode()); | 1396 builder()->StoreGlobal(name_index, feedback_index(slot), language_mode()); |
1288 break; | 1397 break; |
1289 } | 1398 } |
1290 case VariableLocation::CONTEXT: { | 1399 case VariableLocation::CONTEXT: { |
1291 // TODO(rmcilroy): support const mode initialization. | 1400 // TODO(rmcilroy): support const mode initialization. |
(...skipping 527 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1819 VisitLogicalAndExpression(binop); | 1928 VisitLogicalAndExpression(binop); |
1820 break; | 1929 break; |
1821 default: | 1930 default: |
1822 VisitArithmeticExpression(binop); | 1931 VisitArithmeticExpression(binop); |
1823 break; | 1932 break; |
1824 } | 1933 } |
1825 } | 1934 } |
1826 | 1935 |
1827 | 1936 |
1828 void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) { | 1937 void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) { |
1829 // TODO(oth): Remove PrepareForBinaryExpression/CompleteBinaryExpression | 1938 // The evaluation of binary comparison expressions has an assignment |
1830 // once we have StatementScope that tracks hazardous loads/stores. | 1939 // hazard because the lhs may be a variable that evaluates to a |
1831 PrepareForBinaryExpression(); | 1940 // local or parameter and the rhs may modify that, e.g. y = x + (x = 1) |
| 1941 // To get a correct result the generator treats the inner assigment |
| 1942 // as being made to a temporary x' that is spilled on exit of the |
| 1943 // assignment hazard. |
| 1944 AssignmentHazardScope assignment_hazard_scope(this); |
| 1945 |
1832 Register lhs = VisitForRegisterValue(expr->left()); | 1946 Register lhs = VisitForRegisterValue(expr->left()); |
1833 if (builder()->RegisterIsParameterOrLocal(lhs)) { | |
1834 // Result was returned in an existing local or parameter. See if | |
1835 // it needs to be moved to a temporary. | |
1836 // TODO(oth) LoadFromAliasedRegister call into VisitVariableLoad(). | |
1837 lhs = LoadFromAliasedRegister(lhs); | |
1838 } | |
1839 VisitForAccumulatorValue(expr->right()); | 1947 VisitForAccumulatorValue(expr->right()); |
1840 builder()->CompareOperation(expr->op(), lhs, language_mode_strength()); | 1948 builder()->CompareOperation(expr->op(), lhs, language_mode_strength()); |
1841 CompleteBinaryExpression(); | |
1842 execution_result()->SetResultInAccumulator(); | 1949 execution_result()->SetResultInAccumulator(); |
1843 } | 1950 } |
1844 | 1951 |
1845 | 1952 |
1846 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) { | 1953 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) { |
1847 // TODO(oth): Remove PrepareForBinaryExpression/CompleteBinaryExpression | 1954 // The evaluation of binary arithmetic expressions has an assignment |
1848 // once we have StatementScope that tracks hazardous loads/stores. | 1955 // hazard because the lhs may be a variable that evaluates to a |
1849 PrepareForBinaryExpression(); | 1956 // local or parameter and the rhs may modify that, e.g. y = x + (x = 1) |
| 1957 // To get a correct result the generator treats the inner assigment |
| 1958 // as being made to a temporary x' that is spilled on exit of the |
| 1959 // assignment hazard. |
| 1960 AssignmentHazardScope assignment_hazard_scope(this); |
| 1961 |
1850 Register lhs = VisitForRegisterValue(expr->left()); | 1962 Register lhs = VisitForRegisterValue(expr->left()); |
1851 if (builder()->RegisterIsParameterOrLocal(lhs)) { | |
1852 // Result was returned in an existing local or parameter. See if | |
1853 // it needs to be moved to a temporary. | |
1854 // TODO(oth) LoadFromAliasedRegister call into VisitVariableLoad(). | |
1855 lhs = LoadFromAliasedRegister(lhs); | |
1856 } | |
1857 VisitForAccumulatorValue(expr->right()); | 1963 VisitForAccumulatorValue(expr->right()); |
1858 builder()->BinaryOperation(expr->op(), lhs, language_mode_strength()); | 1964 builder()->BinaryOperation(expr->op(), lhs, language_mode_strength()); |
1859 CompleteBinaryExpression(); | |
1860 execution_result()->SetResultInAccumulator(); | 1965 execution_result()->SetResultInAccumulator(); |
1861 } | 1966 } |
1862 | 1967 |
1863 | 1968 |
1864 void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); } | 1969 void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); } |
1865 | 1970 |
1866 | 1971 |
1867 void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) { | 1972 void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) { |
1868 UNREACHABLE(); | 1973 UNREACHABLE(); |
1869 } | 1974 } |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2067 // Pass a SMI sentinel and let the runtime look up the empty function. | 2172 // Pass a SMI sentinel and let the runtime look up the empty function. |
2068 builder()->LoadLiteral(Smi::FromInt(0)); | 2173 builder()->LoadLiteral(Smi::FromInt(0)); |
2069 } else { | 2174 } else { |
2070 DCHECK(closure_scope->is_function_scope()); | 2175 DCHECK(closure_scope->is_function_scope()); |
2071 builder()->LoadAccumulatorWithRegister(Register::function_closure()); | 2176 builder()->LoadAccumulatorWithRegister(Register::function_closure()); |
2072 } | 2177 } |
2073 execution_result()->SetResultInAccumulator(); | 2178 execution_result()->SetResultInAccumulator(); |
2074 } | 2179 } |
2075 | 2180 |
2076 | 2181 |
2077 void BytecodeGenerator::PrepareForBinaryExpression() { | |
2078 if (binary_expression_depth_++ == 0) { | |
2079 binary_expression_hazard_set_.clear(); | |
2080 } | |
2081 } | |
2082 | |
2083 | |
2084 // Visits the expression |expr| and places the result in the accumulator. | 2182 // Visits the expression |expr| and places the result in the accumulator. |
2085 void BytecodeGenerator::VisitForAccumulatorValue(Expression* expr) { | 2183 void BytecodeGenerator::VisitForAccumulatorValue(Expression* expr) { |
2086 AccumulatorResultScope accumulator_scope(this); | 2184 AccumulatorResultScope accumulator_scope(this); |
2087 Visit(expr); | 2185 Visit(expr); |
2088 } | 2186 } |
2089 | 2187 |
2090 | 2188 |
2091 // Visits the expression |expr| and discards the result. | 2189 // Visits the expression |expr| and discards the result. |
2092 void BytecodeGenerator::VisitForEffect(Expression* expr) { | 2190 void BytecodeGenerator::VisitForEffect(Expression* expr) { |
2093 EffectResultScope effect_scope(this); | 2191 EffectResultScope effect_scope(this); |
2094 Visit(expr); | 2192 Visit(expr); |
2095 } | 2193 } |
2096 | 2194 |
2097 | 2195 |
2098 // Visits the expression |expr| and returns the register containing | 2196 // Visits the expression |expr| and returns the register containing |
2099 // the expression result. | 2197 // the expression result. |
2100 Register BytecodeGenerator::VisitForRegisterValue(Expression* expr) { | 2198 Register BytecodeGenerator::VisitForRegisterValue(Expression* expr) { |
2101 RegisterResultScope register_scope(this); | 2199 RegisterResultScope register_scope(this); |
2102 Visit(expr); | 2200 Visit(expr); |
2103 return register_scope.ResultRegister(); | 2201 return register_scope.ResultRegister(); |
2104 } | 2202 } |
2105 | 2203 |
2106 | 2204 |
2107 Register BytecodeGenerator::LoadFromAliasedRegister(Register reg) { | |
2108 // TODO(oth): Follow on CL to load from re-map here. | |
2109 DCHECK(builder()->RegisterIsParameterOrLocal(reg)); | |
2110 if (binary_expression_depth_ > 0) { | |
2111 binary_expression_hazard_set_.insert(reg.index()); | |
2112 } | |
2113 return reg; | |
2114 } | |
2115 | |
2116 | |
2117 void BytecodeGenerator::RecordStoreToRegister(Register reg) { | |
2118 DCHECK(builder()->RegisterIsParameterOrLocal(reg)); | |
2119 if (binary_expression_depth_ > 0) { | |
2120 // TODO(oth): a store to a register that's be loaded needs to be | |
2121 // remapped. | |
2122 DCHECK(binary_expression_hazard_set_.find(reg.index()) == | |
2123 binary_expression_hazard_set_.end()); | |
2124 } | |
2125 } | |
2126 | |
2127 | |
2128 void BytecodeGenerator::CompleteBinaryExpression() { | |
2129 DCHECK(binary_expression_depth_ > 0); | |
2130 binary_expression_depth_ -= 1; | |
2131 // TODO(oth): spill remapped registers into origins. | |
2132 // TODO(oth): make statement/top-level. | |
2133 } | |
2134 | |
2135 | |
2136 Register BytecodeGenerator::NextContextRegister() const { | 2205 Register BytecodeGenerator::NextContextRegister() const { |
2137 if (execution_context() == nullptr) { | 2206 if (execution_context() == nullptr) { |
2138 // Return the incoming function context for the outermost execution context. | 2207 // Return the incoming function context for the outermost execution context. |
2139 return Register::function_context(); | 2208 return Register::function_context(); |
2140 } | 2209 } |
2141 Register previous = execution_context()->reg(); | 2210 Register previous = execution_context()->reg(); |
2142 if (previous == Register::function_context()) { | 2211 if (previous == Register::function_context()) { |
2143 // If the previous context was the incoming function context, then the next | 2212 // If the previous context was the incoming function context, then the next |
2144 // context register is the first local context register. | 2213 // context register is the first local context register. |
2145 return builder_.first_context_register(); | 2214 return builder_.first_context_register(); |
(...skipping 15 matching lines...) Expand all Loading... |
2161 } | 2230 } |
2162 | 2231 |
2163 | 2232 |
2164 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 2233 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
2165 return info()->feedback_vector()->GetIndex(slot); | 2234 return info()->feedback_vector()->GetIndex(slot); |
2166 } | 2235 } |
2167 | 2236 |
2168 } // namespace interpreter | 2237 } // namespace interpreter |
2169 } // namespace internal | 2238 } // namespace internal |
2170 } // namespace v8 | 2239 } // namespace v8 |
OLD | NEW |