| 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/ast/compile-time-value.h" | 7 #include "src/ast/compile-time-value.h" |
| 8 #include "src/ast/scopes.h" | 8 #include "src/ast/scopes.h" |
| 9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
| 10 #include "src/compilation-info.h" | 10 #include "src/compilation-info.h" |
| (...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 367 generator()->builder()->PopContext(current->context()->reg()); | 367 generator()->builder()->PopContext(current->context()->reg()); |
| 368 } | 368 } |
| 369 } while (current != nullptr); | 369 } while (current != nullptr); |
| 370 UNREACHABLE(); | 370 UNREACHABLE(); |
| 371 } | 371 } |
| 372 | 372 |
| 373 class BytecodeGenerator::RegisterAllocationScope { | 373 class BytecodeGenerator::RegisterAllocationScope { |
| 374 public: | 374 public: |
| 375 explicit RegisterAllocationScope(BytecodeGenerator* generator) | 375 explicit RegisterAllocationScope(BytecodeGenerator* generator) |
| 376 : generator_(generator), | 376 : generator_(generator), |
| 377 outer_(generator->register_allocator()), | 377 outer_next_register_index_( |
| 378 allocator_(builder()->zone(), | 378 generator->register_allocator()->next_register_index()) {} |
| 379 builder()->temporary_register_allocator()) { | 379 |
| 380 generator_->set_register_allocator(this); | 380 virtual ~RegisterAllocationScope() { |
| 381 generator_->register_allocator()->ReleaseRegisters( |
| 382 outer_next_register_index_); |
| 381 } | 383 } |
| 382 | 384 |
| 383 virtual ~RegisterAllocationScope() { | |
| 384 generator_->set_register_allocator(outer_); | |
| 385 } | |
| 386 | |
| 387 Register NewRegister() { | |
| 388 RegisterAllocationScope* current_scope = generator()->register_allocator(); | |
| 389 if ((current_scope == this) || | |
| 390 (current_scope->outer() == this && | |
| 391 !current_scope->allocator_.HasConsecutiveAllocations())) { | |
| 392 // Regular case - Allocating registers in current or outer context. | |
| 393 // VisitForRegisterValue allocates register in outer context. | |
| 394 return allocator_.NewRegister(); | |
| 395 } else { | |
| 396 // If it is required to allocate a register other than current or outer | |
| 397 // scopes, allocate a new temporary register. It might be expensive to | |
| 398 // walk the full context chain and compute the list of consecutive | |
| 399 // reservations in the innerscopes. | |
| 400 UNIMPLEMENTED(); | |
| 401 return Register::invalid_value(); | |
| 402 } | |
| 403 } | |
| 404 | |
| 405 void PrepareForConsecutiveAllocations(int count) { | |
| 406 allocator_.PrepareForConsecutiveAllocations(count); | |
| 407 } | |
| 408 | |
| 409 Register NextConsecutiveRegister() { | |
| 410 return allocator_.NextConsecutiveRegister(); | |
| 411 } | |
| 412 | |
| 413 bool RegisterIsAllocatedInThisScope(Register reg) const { | |
| 414 return allocator_.RegisterIsAllocatedInThisScope(reg); | |
| 415 } | |
| 416 | |
| 417 RegisterAllocationScope* outer() const { return outer_; } | |
| 418 | |
| 419 private: | 385 private: |
| 420 BytecodeGenerator* generator() const { return generator_; } | |
| 421 BytecodeArrayBuilder* builder() const { return generator_->builder(); } | |
| 422 | |
| 423 BytecodeGenerator* generator_; | 386 BytecodeGenerator* generator_; |
| 424 RegisterAllocationScope* outer_; | 387 int outer_next_register_index_; |
| 425 BytecodeRegisterAllocator allocator_; | |
| 426 | 388 |
| 427 DISALLOW_COPY_AND_ASSIGN(RegisterAllocationScope); | 389 DISALLOW_COPY_AND_ASSIGN(RegisterAllocationScope); |
| 428 }; | 390 }; |
| 429 | 391 |
| 430 // Scoped base class for determining where the result of an expression | 392 // Scoped base class for determining how the result of an expression will be |
| 431 // is stored. | 393 // used. |
| 432 class BytecodeGenerator::ExpressionResultScope { | 394 class BytecodeGenerator::ExpressionResultScope { |
| 433 public: | 395 public: |
| 434 ExpressionResultScope(BytecodeGenerator* generator, Expression::Context kind) | 396 ExpressionResultScope(BytecodeGenerator* generator, Expression::Context kind) |
| 435 : generator_(generator), | 397 : generator_(generator), |
| 436 kind_(kind), | 398 kind_(kind), |
| 437 outer_(generator->execution_result()), | 399 outer_(generator->execution_result()), |
| 438 allocator_(generator), | 400 allocator_(generator) { |
| 439 result_identified_(false) { | |
| 440 generator_->set_execution_result(this); | 401 generator_->set_execution_result(this); |
| 441 } | 402 } |
| 442 | 403 |
| 443 virtual ~ExpressionResultScope() { | 404 virtual ~ExpressionResultScope() { |
| 444 generator_->set_execution_result(outer_); | 405 generator_->set_execution_result(outer_); |
| 445 DCHECK(result_identified() || generator_->HasStackOverflow()); | |
| 446 } | 406 } |
| 447 | 407 |
| 448 bool IsEffect() const { return kind_ == Expression::kEffect; } | 408 bool IsEffect() const { return kind_ == Expression::kEffect; } |
| 449 bool IsValue() const { return kind_ == Expression::kValue; } | 409 bool IsValue() const { return kind_ == Expression::kValue; } |
| 450 bool IsTest() const { return kind_ == Expression::kTest; } | 410 bool IsTest() const { return kind_ == Expression::kTest; } |
| 451 | 411 |
| 452 TestResultScope* AsTest() { | 412 TestResultScope* AsTest() { |
| 453 DCHECK(IsTest()); | 413 DCHECK(IsTest()); |
| 454 return reinterpret_cast<TestResultScope*>(this); | 414 return reinterpret_cast<TestResultScope*>(this); |
| 455 } | 415 } |
| 456 | 416 |
| 457 virtual void SetResultInAccumulator() = 0; | |
| 458 virtual void SetResultInRegister(Register reg) = 0; | |
| 459 | |
| 460 protected: | |
| 461 ExpressionResultScope* outer() const { return outer_; } | |
| 462 BytecodeArrayBuilder* builder() const { return generator_->builder(); } | |
| 463 BytecodeGenerator* generator() const { return generator_; } | |
| 464 const RegisterAllocationScope* allocator() const { return &allocator_; } | |
| 465 | |
| 466 void set_result_identified() { | |
| 467 DCHECK(!result_identified()); | |
| 468 result_identified_ = true; | |
| 469 } | |
| 470 | |
| 471 bool result_identified() const { return result_identified_; } | |
| 472 | |
| 473 private: | 417 private: |
| 474 BytecodeGenerator* generator_; | 418 BytecodeGenerator* generator_; |
| 475 Expression::Context kind_; | 419 Expression::Context kind_; |
| 476 ExpressionResultScope* outer_; | 420 ExpressionResultScope* outer_; |
| 477 RegisterAllocationScope allocator_; | 421 RegisterAllocationScope allocator_; |
| 478 bool result_identified_; | |
| 479 | 422 |
| 480 DISALLOW_COPY_AND_ASSIGN(ExpressionResultScope); | 423 DISALLOW_COPY_AND_ASSIGN(ExpressionResultScope); |
| 481 }; | 424 }; |
| 482 | 425 |
| 483 // Scoped class used when the result of the current expression is not | 426 // Scoped class used when the result of the current expression is not |
| 484 // expected to produce a result. | 427 // expected to produce a result. |
| 485 class BytecodeGenerator::EffectResultScope final | 428 class BytecodeGenerator::EffectResultScope final |
| 486 : public ExpressionResultScope { | 429 : public ExpressionResultScope { |
| 487 public: | 430 public: |
| 488 explicit EffectResultScope(BytecodeGenerator* generator) | 431 explicit EffectResultScope(BytecodeGenerator* generator) |
| 489 : ExpressionResultScope(generator, Expression::kEffect) { | 432 : ExpressionResultScope(generator, Expression::kEffect) {} |
| 490 set_result_identified(); | |
| 491 } | |
| 492 | |
| 493 virtual void SetResultInAccumulator() {} | |
| 494 virtual void SetResultInRegister(Register reg) {} | |
| 495 }; | 433 }; |
| 496 | 434 |
| 497 // Scoped class used when the result of the current expression to be | 435 // Scoped class used when the result of the current expression to be |
| 498 // evaluated should go into the interpreter's accumulator register. | 436 // evaluated should go into the interpreter's accumulator. |
| 499 class BytecodeGenerator::AccumulatorResultScope final | 437 class BytecodeGenerator::ValueResultScope final : public ExpressionResultScope { |
| 500 : public ExpressionResultScope { | |
| 501 public: | 438 public: |
| 502 explicit AccumulatorResultScope(BytecodeGenerator* generator) | 439 explicit ValueResultScope(BytecodeGenerator* generator) |
| 503 : ExpressionResultScope(generator, Expression::kValue) {} | 440 : ExpressionResultScope(generator, Expression::kValue) {} |
| 504 | |
| 505 virtual void SetResultInAccumulator() { set_result_identified(); } | |
| 506 | |
| 507 virtual void SetResultInRegister(Register reg) { | |
| 508 builder()->LoadAccumulatorWithRegister(reg); | |
| 509 set_result_identified(); | |
| 510 } | |
| 511 }; | 441 }; |
| 512 | 442 |
| 513 // Scoped class used when the result of the current expression to be | 443 // Scoped class used when the result of the current expression to be |
| 514 // evaluated should go into an interpreter register. | |
| 515 class BytecodeGenerator::RegisterResultScope final | |
| 516 : public ExpressionResultScope { | |
| 517 public: | |
| 518 explicit RegisterResultScope(BytecodeGenerator* generator) | |
| 519 : ExpressionResultScope(generator, Expression::kValue) {} | |
| 520 | |
| 521 virtual void SetResultInAccumulator() { | |
| 522 result_register_ = allocator()->outer()->NewRegister(); | |
| 523 builder()->StoreAccumulatorInRegister(result_register_); | |
| 524 set_result_identified(); | |
| 525 } | |
| 526 | |
| 527 virtual void SetResultInRegister(Register reg) { | |
| 528 DCHECK(builder()->RegisterIsParameterOrLocal(reg) || | |
| 529 (builder()->TemporaryRegisterIsLive(reg) && | |
| 530 !allocator()->RegisterIsAllocatedInThisScope(reg))); | |
| 531 result_register_ = reg; | |
| 532 set_result_identified(); | |
| 533 } | |
| 534 | |
| 535 Register ResultRegister() { | |
| 536 if (generator()->HasStackOverflow() && !result_identified()) { | |
| 537 SetResultInAccumulator(); | |
| 538 } | |
| 539 return result_register_; | |
| 540 } | |
| 541 | |
| 542 private: | |
| 543 Register result_register_; | |
| 544 }; | |
| 545 | |
| 546 // Scoped class used when the result of the current expression to be | |
| 547 // evaluated is only tested with jumps to two branches. | 444 // evaluated is only tested with jumps to two branches. |
| 548 class BytecodeGenerator::TestResultScope final : public ExpressionResultScope { | 445 class BytecodeGenerator::TestResultScope final : public ExpressionResultScope { |
| 549 public: | 446 public: |
| 550 TestResultScope(BytecodeGenerator* generator, BytecodeLabels* then_labels, | 447 TestResultScope(BytecodeGenerator* generator, BytecodeLabels* then_labels, |
| 551 BytecodeLabels* else_labels, TestFallthrough fallthrough) | 448 BytecodeLabels* else_labels, TestFallthrough fallthrough) |
| 552 : ExpressionResultScope(generator, Expression::kTest), | 449 : ExpressionResultScope(generator, Expression::kTest), |
| 553 then_labels_(then_labels), | 450 then_labels_(then_labels), |
| 554 else_labels_(else_labels), | 451 else_labels_(else_labels), |
| 555 fallthrough_(fallthrough), | 452 fallthrough_(fallthrough), |
| 556 result_consumed_by_test_(false) {} | 453 result_consumed_by_test_(false) {} |
| 557 | 454 |
| 558 virtual void SetResultInAccumulator() { set_result_identified(); } | |
| 559 | |
| 560 virtual void SetResultInRegister(Register reg) { | |
| 561 builder()->LoadAccumulatorWithRegister(reg); | |
| 562 set_result_identified(); | |
| 563 } | |
| 564 | |
| 565 // Used when code special cases for TestResultScope and consumes any | 455 // Used when code special cases for TestResultScope and consumes any |
| 566 // possible value by testing and jumping to a then/else label. | 456 // possible value by testing and jumping to a then/else label. |
| 567 void SetResultConsumedByTest() { | 457 void SetResultConsumedByTest() { |
| 568 result_consumed_by_test_ = true; | 458 result_consumed_by_test_ = true; |
| 569 set_result_identified(); | |
| 570 } | 459 } |
| 571 | 460 |
| 572 bool ResultConsumedByTest() { return result_consumed_by_test_; } | 461 bool ResultConsumedByTest() { return result_consumed_by_test_; } |
| 573 | 462 |
| 574 BytecodeLabel* NewThenLabel() { return then_labels_->New(); } | 463 BytecodeLabel* NewThenLabel() { return then_labels_->New(); } |
| 575 BytecodeLabel* NewElseLabel() { return else_labels_->New(); } | 464 BytecodeLabel* NewElseLabel() { return else_labels_->New(); } |
| 576 | 465 |
| 577 BytecodeLabels* then_labels() const { return then_labels_; } | 466 BytecodeLabels* then_labels() const { return then_labels_; } |
| 578 BytecodeLabels* else_labels() const { return else_labels_; } | 467 BytecodeLabels* else_labels() const { return else_labels_; } |
| 579 | 468 |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 671 info->SourcePositionRecordingMode())), | 560 info->SourcePositionRecordingMode())), |
| 672 info_(info), | 561 info_(info), |
| 673 scope_(info->scope()), | 562 scope_(info->scope()), |
| 674 globals_builder_(new (zone()) GlobalDeclarationsBuilder(info->zone())), | 563 globals_builder_(new (zone()) GlobalDeclarationsBuilder(info->zone())), |
| 675 global_declarations_(0, info->zone()), | 564 global_declarations_(0, info->zone()), |
| 676 function_literals_(0, info->zone()), | 565 function_literals_(0, info->zone()), |
| 677 native_function_literals_(0, info->zone()), | 566 native_function_literals_(0, info->zone()), |
| 678 execution_control_(nullptr), | 567 execution_control_(nullptr), |
| 679 execution_context_(nullptr), | 568 execution_context_(nullptr), |
| 680 execution_result_(nullptr), | 569 execution_result_(nullptr), |
| 681 register_allocator_(nullptr), | |
| 682 generator_resume_points_(info->literal()->yield_count(), info->zone()), | 570 generator_resume_points_(info->literal()->yield_count(), info->zone()), |
| 683 generator_state_(), | 571 generator_state_(), |
| 684 loop_depth_(0), | 572 loop_depth_(0), |
| 685 home_object_symbol_(info->isolate()->factory()->home_object_symbol()), | 573 home_object_symbol_(info->isolate()->factory()->home_object_symbol()), |
| 686 prototype_string_(info->isolate()->factory()->prototype_string()) { | 574 prototype_string_(info->isolate()->factory()->prototype_string()) { |
| 687 } | 575 } |
| 688 | 576 |
| 689 Handle<BytecodeArray> BytecodeGenerator::FinalizeBytecode(Isolate* isolate) { | 577 Handle<BytecodeArray> BytecodeGenerator::FinalizeBytecode(Isolate* isolate) { |
| 690 AllocateDeferredConstants(); | 578 AllocateDeferredConstants(); |
| 691 if (HasStackOverflow()) return Handle<BytecodeArray>(); | 579 if (HasStackOverflow()) return Handle<BytecodeArray>(); |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 921 break; | 809 break; |
| 922 case VariableLocation::LOOKUP: { | 810 case VariableLocation::LOOKUP: { |
| 923 DCHECK_EQ(VAR, variable->mode()); | 811 DCHECK_EQ(VAR, variable->mode()); |
| 924 DCHECK(!variable->binding_needs_init()); | 812 DCHECK(!variable->binding_needs_init()); |
| 925 | 813 |
| 926 Register name = register_allocator()->NewRegister(); | 814 Register name = register_allocator()->NewRegister(); |
| 927 | 815 |
| 928 builder() | 816 builder() |
| 929 ->LoadLiteral(variable->name()) | 817 ->LoadLiteral(variable->name()) |
| 930 .StoreAccumulatorInRegister(name) | 818 .StoreAccumulatorInRegister(name) |
| 931 .CallRuntime(Runtime::kDeclareEvalVar, name, 1); | 819 .CallRuntime(Runtime::kDeclareEvalVar, name); |
| 932 break; | 820 break; |
| 933 } | 821 } |
| 934 case VariableLocation::MODULE: | 822 case VariableLocation::MODULE: |
| 935 if (variable->IsExport() && variable->binding_needs_init()) { | 823 if (variable->IsExport() && variable->binding_needs_init()) { |
| 936 builder()->LoadTheHole(); | 824 builder()->LoadTheHole(); |
| 937 VisitVariableAssignment(variable, Token::INIT, | 825 VisitVariableAssignment(variable, Token::INIT, |
| 938 FeedbackVectorSlot::Invalid()); | 826 FeedbackVectorSlot::Invalid()); |
| 939 } | 827 } |
| 940 // Nothing to do for imports. | 828 // Nothing to do for imports. |
| 941 break; | 829 break; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 959 break; | 847 break; |
| 960 } | 848 } |
| 961 case VariableLocation::CONTEXT: { | 849 case VariableLocation::CONTEXT: { |
| 962 DCHECK_EQ(0, execution_context()->ContextChainDepth(variable->scope())); | 850 DCHECK_EQ(0, execution_context()->ContextChainDepth(variable->scope())); |
| 963 VisitForAccumulatorValue(decl->fun()); | 851 VisitForAccumulatorValue(decl->fun()); |
| 964 builder()->StoreContextSlot(execution_context()->reg(), variable->index(), | 852 builder()->StoreContextSlot(execution_context()->reg(), variable->index(), |
| 965 0); | 853 0); |
| 966 break; | 854 break; |
| 967 } | 855 } |
| 968 case VariableLocation::LOOKUP: { | 856 case VariableLocation::LOOKUP: { |
| 969 register_allocator()->PrepareForConsecutiveAllocations(2); | 857 RegisterList args = register_allocator()->NewRegisterList(2); |
| 970 Register name = register_allocator()->NextConsecutiveRegister(); | 858 builder() |
| 971 Register literal = register_allocator()->NextConsecutiveRegister(); | 859 ->LoadLiteral(variable->name()) |
| 972 builder()->LoadLiteral(variable->name()).StoreAccumulatorInRegister(name); | 860 .StoreAccumulatorInRegister(args[0]); |
| 973 | |
| 974 VisitForAccumulatorValue(decl->fun()); | 861 VisitForAccumulatorValue(decl->fun()); |
| 975 builder()->StoreAccumulatorInRegister(literal).CallRuntime( | 862 builder()->StoreAccumulatorInRegister(args[1]).CallRuntime( |
| 976 Runtime::kDeclareEvalFunction, name, 2); | 863 Runtime::kDeclareEvalFunction, args); |
| 977 break; | 864 break; |
| 978 } | 865 } |
| 979 case VariableLocation::MODULE: | 866 case VariableLocation::MODULE: |
| 980 DCHECK_EQ(variable->mode(), LET); | 867 DCHECK_EQ(variable->mode(), LET); |
| 981 DCHECK(variable->IsExport()); | 868 DCHECK(variable->IsExport()); |
| 982 VisitForAccumulatorValue(decl->fun()); | 869 VisitForAccumulatorValue(decl->fun()); |
| 983 VisitVariableAssignment(variable, Token::INIT, | 870 VisitVariableAssignment(variable, Token::INIT, |
| 984 FeedbackVectorSlot::Invalid()); | 871 FeedbackVectorSlot::Invalid()); |
| 985 break; | 872 break; |
| 986 } | 873 } |
| 987 } | 874 } |
| 988 | 875 |
| 989 void BytecodeGenerator::VisitDeclarations( | 876 void BytecodeGenerator::VisitDeclarations( |
| 990 ZoneList<Declaration*>* declarations) { | 877 ZoneList<Declaration*>* declarations) { |
| 991 RegisterAllocationScope register_scope(this); | 878 RegisterAllocationScope register_scope(this); |
| 992 DCHECK(globals_builder()->empty()); | 879 DCHECK(globals_builder()->empty()); |
| 993 for (int i = 0; i < declarations->length(); i++) { | 880 for (int i = 0; i < declarations->length(); i++) { |
| 994 RegisterAllocationScope register_scope(this); | 881 RegisterAllocationScope register_scope(this); |
| 995 Visit(declarations->at(i)); | 882 Visit(declarations->at(i)); |
| 996 } | 883 } |
| 997 if (globals_builder()->empty()) return; | 884 if (globals_builder()->empty()) return; |
| 998 | 885 |
| 999 globals_builder()->set_constant_pool_entry( | 886 globals_builder()->set_constant_pool_entry( |
| 1000 builder()->AllocateConstantPoolEntry()); | 887 builder()->AllocateConstantPoolEntry()); |
| 1001 int encoded_flags = info()->GetDeclareGlobalsFlags(); | 888 int encoded_flags = info()->GetDeclareGlobalsFlags(); |
| 1002 | 889 |
| 1003 register_allocator()->PrepareForConsecutiveAllocations(3); | |
| 1004 | |
| 1005 Register pairs = register_allocator()->NextConsecutiveRegister(); | |
| 1006 Register flags = register_allocator()->NextConsecutiveRegister(); | |
| 1007 Register function = register_allocator()->NextConsecutiveRegister(); | |
| 1008 | |
| 1009 // Emit code to declare globals. | 890 // Emit code to declare globals. |
| 891 RegisterList args = register_allocator()->NewRegisterList(3); |
| 1010 builder() | 892 builder() |
| 1011 ->LoadConstantPoolEntry(globals_builder()->constant_pool_entry()) | 893 ->LoadConstantPoolEntry(globals_builder()->constant_pool_entry()) |
| 1012 .StoreAccumulatorInRegister(pairs) | 894 .StoreAccumulatorInRegister(args[0]) |
| 1013 .LoadLiteral(Smi::FromInt(encoded_flags)) | 895 .LoadLiteral(Smi::FromInt(encoded_flags)) |
| 1014 .StoreAccumulatorInRegister(flags) | 896 .StoreAccumulatorInRegister(args[1]) |
| 1015 .MoveRegister(Register::function_closure(), function) | 897 .MoveRegister(Register::function_closure(), args[2]) |
| 1016 .CallRuntime(Runtime::kDeclareGlobalsForInterpreter, pairs, 3); | 898 .CallRuntime(Runtime::kDeclareGlobalsForInterpreter, args); |
| 1017 | 899 |
| 1018 // Push and reset globals builder. | 900 // Push and reset globals builder. |
| 1019 global_declarations_.push_back(globals_builder()); | 901 global_declarations_.push_back(globals_builder()); |
| 1020 globals_builder_ = new (zone()) GlobalDeclarationsBuilder(zone()); | 902 globals_builder_ = new (zone()) GlobalDeclarationsBuilder(zone()); |
| 1021 } | 903 } |
| 1022 | 904 |
| 1023 void BytecodeGenerator::VisitStatements(ZoneList<Statement*>* statements) { | 905 void BytecodeGenerator::VisitStatements(ZoneList<Statement*>* statements) { |
| 1024 for (int i = 0; i < statements->length(); i++) { | 906 for (int i = 0; i < statements->length(); i++) { |
| 1025 // Allocate an outer register allocations scope for the statement. | 907 // Allocate an outer register allocations scope for the statement. |
| 1026 RegisterAllocationScope allocation_scope(this); | 908 RegisterAllocationScope allocation_scope(this); |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1261 builder()->StoreAccumulatorInRegister(value); | 1143 builder()->StoreAccumulatorInRegister(value); |
| 1262 Register object = VisitForRegisterValue(property->obj()); | 1144 Register object = VisitForRegisterValue(property->obj()); |
| 1263 Register key = VisitForRegisterValue(property->key()); | 1145 Register key = VisitForRegisterValue(property->key()); |
| 1264 builder()->LoadAccumulatorWithRegister(value); | 1146 builder()->LoadAccumulatorWithRegister(value); |
| 1265 builder()->StoreKeyedProperty(object, key, feedback_index(slot), | 1147 builder()->StoreKeyedProperty(object, key, feedback_index(slot), |
| 1266 language_mode()); | 1148 language_mode()); |
| 1267 break; | 1149 break; |
| 1268 } | 1150 } |
| 1269 case NAMED_SUPER_PROPERTY: { | 1151 case NAMED_SUPER_PROPERTY: { |
| 1270 RegisterAllocationScope register_scope(this); | 1152 RegisterAllocationScope register_scope(this); |
| 1271 register_allocator()->PrepareForConsecutiveAllocations(4); | 1153 RegisterList args = register_allocator()->NewRegisterList(4); |
| 1272 Register receiver = register_allocator()->NextConsecutiveRegister(); | 1154 builder()->StoreAccumulatorInRegister(args[3]); |
| 1273 Register home_object = register_allocator()->NextConsecutiveRegister(); | |
| 1274 Register name = register_allocator()->NextConsecutiveRegister(); | |
| 1275 Register value = register_allocator()->NextConsecutiveRegister(); | |
| 1276 builder()->StoreAccumulatorInRegister(value); | |
| 1277 SuperPropertyReference* super_property = | 1155 SuperPropertyReference* super_property = |
| 1278 property->obj()->AsSuperPropertyReference(); | 1156 property->obj()->AsSuperPropertyReference(); |
| 1279 VisitForRegisterValue(super_property->this_var(), receiver); | 1157 VisitForRegisterValue(super_property->this_var(), args[0]); |
| 1280 VisitForRegisterValue(super_property->home_object(), home_object); | 1158 VisitForRegisterValue(super_property->home_object(), args[1]); |
| 1281 builder() | 1159 builder() |
| 1282 ->LoadLiteral(property->key()->AsLiteral()->AsPropertyName()) | 1160 ->LoadLiteral(property->key()->AsLiteral()->AsPropertyName()) |
| 1283 .StoreAccumulatorInRegister(name); | 1161 .StoreAccumulatorInRegister(args[2]) |
| 1284 BuildNamedSuperPropertyStore(receiver, home_object, name, value); | 1162 .CallRuntime(StoreToSuperRuntimeId(), args); |
| 1285 break; | 1163 break; |
| 1286 } | 1164 } |
| 1287 case KEYED_SUPER_PROPERTY: { | 1165 case KEYED_SUPER_PROPERTY: { |
| 1288 RegisterAllocationScope register_scope(this); | 1166 RegisterAllocationScope register_scope(this); |
| 1289 register_allocator()->PrepareForConsecutiveAllocations(4); | 1167 RegisterList args = register_allocator()->NewRegisterList(4); |
| 1290 Register receiver = register_allocator()->NextConsecutiveRegister(); | 1168 builder()->StoreAccumulatorInRegister(args[3]); |
| 1291 Register home_object = register_allocator()->NextConsecutiveRegister(); | |
| 1292 Register key = register_allocator()->NextConsecutiveRegister(); | |
| 1293 Register value = register_allocator()->NextConsecutiveRegister(); | |
| 1294 builder()->StoreAccumulatorInRegister(value); | |
| 1295 SuperPropertyReference* super_property = | 1169 SuperPropertyReference* super_property = |
| 1296 property->obj()->AsSuperPropertyReference(); | 1170 property->obj()->AsSuperPropertyReference(); |
| 1297 VisitForRegisterValue(super_property->this_var(), receiver); | 1171 VisitForRegisterValue(super_property->this_var(), args[0]); |
| 1298 VisitForRegisterValue(super_property->home_object(), home_object); | 1172 VisitForRegisterValue(super_property->home_object(), args[1]); |
| 1299 VisitForRegisterValue(property->key(), key); | 1173 VisitForRegisterValue(property->key(), args[2]); |
| 1300 BuildKeyedSuperPropertyStore(receiver, home_object, key, value); | 1174 builder()->CallRuntime(StoreKeyedToSuperRuntimeId(), args); |
| 1301 break; | 1175 break; |
| 1302 } | 1176 } |
| 1303 } | 1177 } |
| 1304 } | 1178 } |
| 1305 | 1179 |
| 1306 void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) { | 1180 void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) { |
| 1307 if (stmt->subject()->IsNullLiteral() || | 1181 if (stmt->subject()->IsNullLiteral() || |
| 1308 stmt->subject()->IsUndefinedLiteral()) { | 1182 stmt->subject()->IsUndefinedLiteral()) { |
| 1309 // ForIn generates lots of code, skip if it wouldn't produce any effects. | 1183 // ForIn generates lots of code, skip if it wouldn't produce any effects. |
| 1310 return; | 1184 return; |
| 1311 } | 1185 } |
| 1312 | 1186 |
| 1313 LoopBuilder loop_builder(builder()); | 1187 LoopBuilder loop_builder(builder()); |
| 1314 BytecodeLabel subject_null_label, subject_undefined_label; | 1188 BytecodeLabel subject_null_label, subject_undefined_label; |
| 1315 | 1189 |
| 1316 // Prepare the state for executing ForIn. | 1190 // Prepare the state for executing ForIn. |
| 1317 builder()->SetExpressionAsStatementPosition(stmt->subject()); | 1191 builder()->SetExpressionAsStatementPosition(stmt->subject()); |
| 1318 VisitForAccumulatorValue(stmt->subject()); | 1192 VisitForAccumulatorValue(stmt->subject()); |
| 1319 builder()->JumpIfUndefined(&subject_undefined_label); | 1193 builder()->JumpIfUndefined(&subject_undefined_label); |
| 1320 builder()->JumpIfNull(&subject_null_label); | 1194 builder()->JumpIfNull(&subject_null_label); |
| 1321 Register receiver = register_allocator()->NewRegister(); | 1195 Register receiver = register_allocator()->NewRegister(); |
| 1322 builder()->ConvertAccumulatorToObject(receiver); | 1196 builder()->ConvertAccumulatorToObject(receiver); |
| 1323 | 1197 |
| 1324 register_allocator()->PrepareForConsecutiveAllocations(3); | |
| 1325 Register cache_type = register_allocator()->NextConsecutiveRegister(); | |
| 1326 Register cache_array = register_allocator()->NextConsecutiveRegister(); | |
| 1327 Register cache_length = register_allocator()->NextConsecutiveRegister(); | |
| 1328 // Used as kRegTriple and kRegPair in ForInPrepare and ForInNext. | 1198 // Used as kRegTriple and kRegPair in ForInPrepare and ForInNext. |
| 1329 USE(cache_array); | 1199 RegisterList triple = register_allocator()->NewRegisterList(3); |
| 1330 builder()->ForInPrepare(receiver, cache_type); | 1200 Register cache_length = triple[2]; |
| 1201 builder()->ForInPrepare(receiver, triple.first_register()); |
| 1331 | 1202 |
| 1332 // Set up loop counter | 1203 // Set up loop counter |
| 1333 Register index = register_allocator()->NewRegister(); | 1204 Register index = register_allocator()->NewRegister(); |
| 1334 builder()->LoadLiteral(Smi::FromInt(0)); | 1205 builder()->LoadLiteral(Smi::FromInt(0)); |
| 1335 builder()->StoreAccumulatorInRegister(index); | 1206 builder()->StoreAccumulatorInRegister(index); |
| 1336 | 1207 |
| 1337 // The loop | 1208 // The loop |
| 1338 VisitIterationHeader(stmt, &loop_builder); | 1209 VisitIterationHeader(stmt, &loop_builder); |
| 1339 builder()->SetExpressionAsStatementPosition(stmt->each()); | 1210 builder()->SetExpressionAsStatementPosition(stmt->each()); |
| 1340 builder()->ForInContinue(index, cache_length); | 1211 builder()->ForInContinue(index, cache_length); |
| 1341 loop_builder.BreakIfFalse(); | 1212 loop_builder.BreakIfFalse(); |
| 1342 DCHECK(Register::AreContiguous(cache_type, cache_array)); | |
| 1343 FeedbackVectorSlot slot = stmt->ForInFeedbackSlot(); | 1213 FeedbackVectorSlot slot = stmt->ForInFeedbackSlot(); |
| 1344 builder()->ForInNext(receiver, index, cache_type, feedback_index(slot)); | 1214 builder()->ForInNext(receiver, index, triple.first_register(), |
| 1215 feedback_index(slot)); |
| 1345 loop_builder.ContinueIfUndefined(); | 1216 loop_builder.ContinueIfUndefined(); |
| 1346 VisitForInAssignment(stmt->each(), stmt->EachFeedbackSlot()); | 1217 VisitForInAssignment(stmt->each(), stmt->EachFeedbackSlot()); |
| 1347 VisitIterationBody(stmt, &loop_builder); | 1218 VisitIterationBody(stmt, &loop_builder); |
| 1348 builder()->ForInStep(index); | 1219 builder()->ForInStep(index); |
| 1349 builder()->StoreAccumulatorInRegister(index); | 1220 builder()->StoreAccumulatorInRegister(index); |
| 1350 loop_builder.JumpToHeader(loop_depth_); | 1221 loop_builder.JumpToHeader(loop_depth_); |
| 1351 loop_builder.EndLoop(); | 1222 loop_builder.EndLoop(); |
| 1352 builder()->Bind(&subject_null_label); | 1223 builder()->Bind(&subject_null_label); |
| 1353 builder()->Bind(&subject_undefined_label); | 1224 builder()->Bind(&subject_undefined_label); |
| 1354 } | 1225 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1366 loop_builder.BreakIfTrue(); | 1237 loop_builder.BreakIfTrue(); |
| 1367 | 1238 |
| 1368 VisitForEffect(stmt->assign_each()); | 1239 VisitForEffect(stmt->assign_each()); |
| 1369 VisitIterationBody(stmt, &loop_builder); | 1240 VisitIterationBody(stmt, &loop_builder); |
| 1370 loop_builder.JumpToHeader(loop_depth_); | 1241 loop_builder.JumpToHeader(loop_depth_); |
| 1371 loop_builder.EndLoop(); | 1242 loop_builder.EndLoop(); |
| 1372 } | 1243 } |
| 1373 | 1244 |
| 1374 void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { | 1245 void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { |
| 1375 TryCatchBuilder try_control_builder(builder(), stmt->catch_prediction()); | 1246 TryCatchBuilder try_control_builder(builder(), stmt->catch_prediction()); |
| 1376 Register no_reg; | |
| 1377 | 1247 |
| 1378 // Preserve the context in a dedicated register, so that it can be restored | 1248 // Preserve the context in a dedicated register, so that it can be restored |
| 1379 // when the handler is entered by the stack-unwinding machinery. | 1249 // when the handler is entered by the stack-unwinding machinery. |
| 1380 // TODO(mstarzinger): Be smarter about register allocation. | 1250 // TODO(mstarzinger): Be smarter about register allocation. |
| 1381 Register context = register_allocator()->NewRegister(); | 1251 Register context = register_allocator()->NewRegister(); |
| 1382 builder()->MoveRegister(Register::current_context(), context); | 1252 builder()->MoveRegister(Register::current_context(), context); |
| 1383 | 1253 |
| 1384 // Evaluate the try-block inside a control scope. This simulates a handler | 1254 // Evaluate the try-block inside a control scope. This simulates a handler |
| 1385 // that is intercepting 'throw' control commands. | 1255 // that is intercepting 'throw' control commands. |
| 1386 try_control_builder.BeginTry(context); | 1256 try_control_builder.BeginTry(context); |
| 1387 { | 1257 { |
| 1388 ControlScopeForTryCatch scope(this, &try_control_builder); | 1258 ControlScopeForTryCatch scope(this, &try_control_builder); |
| 1389 Visit(stmt->try_block()); | 1259 Visit(stmt->try_block()); |
| 1390 } | 1260 } |
| 1391 try_control_builder.EndTry(); | 1261 try_control_builder.EndTry(); |
| 1392 | 1262 |
| 1393 // Create a catch scope that binds the exception. | 1263 // Create a catch scope that binds the exception. |
| 1394 BuildNewLocalCatchContext(stmt->variable(), stmt->scope()); | 1264 BuildNewLocalCatchContext(stmt->variable(), stmt->scope()); |
| 1395 builder()->StoreAccumulatorInRegister(context); | 1265 builder()->StoreAccumulatorInRegister(context); |
| 1396 | 1266 |
| 1397 // If requested, clear message object as we enter the catch block. | 1267 // If requested, clear message object as we enter the catch block. |
| 1398 if (stmt->clear_pending_message()) { | 1268 if (stmt->clear_pending_message()) { |
| 1399 builder()->CallRuntime(Runtime::kInterpreterClearPendingMessage, no_reg, 0); | 1269 builder()->CallRuntime(Runtime::kInterpreterClearPendingMessage); |
| 1400 } | 1270 } |
| 1401 | 1271 |
| 1402 // Load the catch context into the accumulator. | 1272 // Load the catch context into the accumulator. |
| 1403 builder()->LoadAccumulatorWithRegister(context); | 1273 builder()->LoadAccumulatorWithRegister(context); |
| 1404 | 1274 |
| 1405 // Evaluate the catch-block. | 1275 // Evaluate the catch-block. |
| 1406 VisitInScope(stmt->catch_block(), stmt->scope()); | 1276 VisitInScope(stmt->catch_block(), stmt->scope()); |
| 1407 try_control_builder.EndCatch(); | 1277 try_control_builder.EndCatch(); |
| 1408 } | 1278 } |
| 1409 | 1279 |
| 1410 void BytecodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) { | 1280 void BytecodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) { |
| 1411 TryFinallyBuilder try_control_builder(builder(), stmt->catch_prediction()); | 1281 TryFinallyBuilder try_control_builder(builder(), stmt->catch_prediction()); |
| 1412 Register no_reg; | |
| 1413 | 1282 |
| 1414 // We keep a record of all paths that enter the finally-block to be able to | 1283 // We keep a record of all paths that enter the finally-block to be able to |
| 1415 // dispatch to the correct continuation point after the statements in the | 1284 // dispatch to the correct continuation point after the statements in the |
| 1416 // finally-block have been evaluated. | 1285 // finally-block have been evaluated. |
| 1417 // | 1286 // |
| 1418 // The try-finally construct can enter the finally-block in three ways: | 1287 // The try-finally construct can enter the finally-block in three ways: |
| 1419 // 1. By exiting the try-block normally, falling through at the end. | 1288 // 1. By exiting the try-block normally, falling through at the end. |
| 1420 // 2. By exiting the try-block with a function-local control flow transfer | 1289 // 2. By exiting the try-block with a function-local control flow transfer |
| 1421 // (i.e. through break/continue/return statements). | 1290 // (i.e. through break/continue/return statements). |
| 1422 // 3. By exiting the try-block with a thrown exception. | 1291 // 3. By exiting the try-block with a thrown exception. |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1450 try_control_builder.LeaveTry(); | 1319 try_control_builder.LeaveTry(); |
| 1451 try_control_builder.BeginHandler(); | 1320 try_control_builder.BeginHandler(); |
| 1452 commands.RecordHandlerReThrowPath(); | 1321 commands.RecordHandlerReThrowPath(); |
| 1453 | 1322 |
| 1454 // Pending message object is saved on entry. | 1323 // Pending message object is saved on entry. |
| 1455 try_control_builder.BeginFinally(); | 1324 try_control_builder.BeginFinally(); |
| 1456 Register message = context; // Reuse register. | 1325 Register message = context; // Reuse register. |
| 1457 | 1326 |
| 1458 // Clear message object as we enter the finally block. | 1327 // Clear message object as we enter the finally block. |
| 1459 builder() | 1328 builder() |
| 1460 ->CallRuntime(Runtime::kInterpreterClearPendingMessage, no_reg, 0) | 1329 ->CallRuntime(Runtime::kInterpreterClearPendingMessage) |
| 1461 .StoreAccumulatorInRegister(message); | 1330 .StoreAccumulatorInRegister(message); |
| 1462 | 1331 |
| 1463 // Evaluate the finally-block. | 1332 // Evaluate the finally-block. |
| 1464 Visit(stmt->finally_block()); | 1333 Visit(stmt->finally_block()); |
| 1465 try_control_builder.EndFinally(); | 1334 try_control_builder.EndFinally(); |
| 1466 | 1335 |
| 1467 // Pending message object is restored on exit. | 1336 // Pending message object is restored on exit. |
| 1468 builder()->CallRuntime(Runtime::kInterpreterSetPendingMessage, message, 1); | 1337 builder()->CallRuntime(Runtime::kInterpreterSetPendingMessage, message); |
| 1469 | 1338 |
| 1470 // Dynamic dispatch after the finally-block. | 1339 // Dynamic dispatch after the finally-block. |
| 1471 commands.ApplyDeferredCommands(); | 1340 commands.ApplyDeferredCommands(); |
| 1472 } | 1341 } |
| 1473 | 1342 |
| 1474 void BytecodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) { | 1343 void BytecodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) { |
| 1475 builder()->SetStatementPosition(stmt); | 1344 builder()->SetStatementPosition(stmt); |
| 1476 builder()->Debugger(); | 1345 builder()->Debugger(); |
| 1477 } | 1346 } |
| 1478 | 1347 |
| 1479 void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { | 1348 void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { |
| 1480 uint8_t flags = CreateClosureFlags::Encode(expr->pretenure(), | 1349 uint8_t flags = CreateClosureFlags::Encode(expr->pretenure(), |
| 1481 scope()->is_function_scope()); | 1350 scope()->is_function_scope()); |
| 1482 size_t entry = builder()->AllocateConstantPoolEntry(); | 1351 size_t entry = builder()->AllocateConstantPoolEntry(); |
| 1483 builder()->CreateClosure(entry, flags); | 1352 builder()->CreateClosure(entry, flags); |
| 1484 function_literals_.push_back(std::make_pair(expr, entry)); | 1353 function_literals_.push_back(std::make_pair(expr, entry)); |
| 1485 execution_result()->SetResultInAccumulator(); | |
| 1486 } | 1354 } |
| 1487 | 1355 |
| 1488 void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) { | 1356 void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) { |
| 1489 VisitClassLiteralForRuntimeDefinition(expr); | 1357 VisitClassLiteralForRuntimeDefinition(expr); |
| 1490 | 1358 |
| 1491 // Load the "prototype" from the constructor. | 1359 // Load the "prototype" from the constructor. |
| 1492 register_allocator()->PrepareForConsecutiveAllocations(2); | 1360 RegisterList args = register_allocator()->NewRegisterList(2); |
| 1493 Register literal = register_allocator()->NextConsecutiveRegister(); | 1361 Register literal = args[0]; |
| 1494 Register prototype = register_allocator()->NextConsecutiveRegister(); | 1362 Register prototype = args[1]; |
| 1495 FeedbackVectorSlot slot = expr->PrototypeSlot(); | 1363 FeedbackVectorSlot slot = expr->PrototypeSlot(); |
| 1496 builder() | 1364 builder() |
| 1497 ->StoreAccumulatorInRegister(literal) | 1365 ->StoreAccumulatorInRegister(literal) |
| 1498 .LoadNamedProperty(literal, prototype_string(), feedback_index(slot)) | 1366 .LoadNamedProperty(literal, prototype_string(), feedback_index(slot)) |
| 1499 .StoreAccumulatorInRegister(prototype); | 1367 .StoreAccumulatorInRegister(prototype); |
| 1500 | 1368 |
| 1501 VisitClassLiteralProperties(expr, literal, prototype); | 1369 VisitClassLiteralProperties(expr, literal, prototype); |
| 1502 builder()->CallRuntime(Runtime::kToFastProperties, literal, 1); | 1370 builder()->CallRuntime(Runtime::kToFastProperties, literal); |
| 1503 // Assign to class variable. | 1371 // Assign to class variable. |
| 1504 if (expr->class_variable_proxy() != nullptr) { | 1372 if (expr->class_variable_proxy() != nullptr) { |
| 1505 Variable* var = expr->class_variable_proxy()->var(); | 1373 Variable* var = expr->class_variable_proxy()->var(); |
| 1506 FeedbackVectorSlot slot = expr->NeedsProxySlot() | 1374 FeedbackVectorSlot slot = expr->NeedsProxySlot() |
| 1507 ? expr->ProxySlot() | 1375 ? expr->ProxySlot() |
| 1508 : FeedbackVectorSlot::Invalid(); | 1376 : FeedbackVectorSlot::Invalid(); |
| 1509 VisitVariableAssignment(var, Token::INIT, slot); | 1377 VisitVariableAssignment(var, Token::INIT, slot); |
| 1510 } | 1378 } |
| 1511 execution_result()->SetResultInAccumulator(); | |
| 1512 } | 1379 } |
| 1513 | 1380 |
| 1514 void BytecodeGenerator::VisitClassLiteralForRuntimeDefinition( | 1381 void BytecodeGenerator::VisitClassLiteralForRuntimeDefinition( |
| 1515 ClassLiteral* expr) { | 1382 ClassLiteral* expr) { |
| 1516 AccumulatorResultScope result_scope(this); | 1383 RegisterAllocationScope register_scope(this); |
| 1517 register_allocator()->PrepareForConsecutiveAllocations(4); | 1384 RegisterList args = register_allocator()->NewRegisterList(4); |
| 1518 Register extends = register_allocator()->NextConsecutiveRegister(); | |
| 1519 Register constructor = register_allocator()->NextConsecutiveRegister(); | |
| 1520 Register start_position = register_allocator()->NextConsecutiveRegister(); | |
| 1521 Register end_position = register_allocator()->NextConsecutiveRegister(); | |
| 1522 | |
| 1523 VisitForAccumulatorValueOrTheHole(expr->extends()); | 1385 VisitForAccumulatorValueOrTheHole(expr->extends()); |
| 1524 builder()->StoreAccumulatorInRegister(extends); | 1386 builder()->StoreAccumulatorInRegister(args[0]); |
| 1525 | 1387 VisitForRegisterValue(expr->constructor(), args[1]); |
| 1526 VisitForAccumulatorValue(expr->constructor()); | |
| 1527 builder() | 1388 builder() |
| 1528 ->StoreAccumulatorInRegister(constructor) | 1389 ->LoadLiteral(Smi::FromInt(expr->start_position())) |
| 1529 .LoadLiteral(Smi::FromInt(expr->start_position())) | 1390 .StoreAccumulatorInRegister(args[2]) |
| 1530 .StoreAccumulatorInRegister(start_position) | |
| 1531 .LoadLiteral(Smi::FromInt(expr->end_position())) | 1391 .LoadLiteral(Smi::FromInt(expr->end_position())) |
| 1532 .StoreAccumulatorInRegister(end_position) | 1392 .StoreAccumulatorInRegister(args[3]) |
| 1533 .CallRuntime(Runtime::kDefineClass, extends, 4); | 1393 .CallRuntime(Runtime::kDefineClass, args); |
| 1534 result_scope.SetResultInAccumulator(); | |
| 1535 } | 1394 } |
| 1536 | 1395 |
| 1537 void BytecodeGenerator::VisitClassLiteralProperties(ClassLiteral* expr, | 1396 void BytecodeGenerator::VisitClassLiteralProperties(ClassLiteral* expr, |
| 1538 Register literal, | 1397 Register literal, |
| 1539 Register prototype) { | 1398 Register prototype) { |
| 1540 RegisterAllocationScope register_scope(this); | 1399 RegisterAllocationScope register_scope(this); |
| 1541 register_allocator()->PrepareForConsecutiveAllocations(5); | 1400 RegisterList args = register_allocator()->NewRegisterList(5); |
| 1542 Register receiver = register_allocator()->NextConsecutiveRegister(); | 1401 Register receiver = args[0], key = args[1], value = args[2], attr = args[3], |
| 1543 Register key = register_allocator()->NextConsecutiveRegister(); | 1402 set_function_name = args[4]; |
| 1544 Register value = register_allocator()->NextConsecutiveRegister(); | |
| 1545 Register attr = register_allocator()->NextConsecutiveRegister(); | |
| 1546 Register set_function_name = register_allocator()->NextConsecutiveRegister(); | |
| 1547 | 1403 |
| 1548 bool attr_assigned = false; | 1404 bool attr_assigned = false; |
| 1549 Register old_receiver = Register::invalid_value(); | 1405 Register old_receiver = Register::invalid_value(); |
| 1550 | 1406 |
| 1551 // Create nodes to store method values into the literal. | 1407 // Create nodes to store method values into the literal. |
| 1552 for (int i = 0; i < expr->properties()->length(); i++) { | 1408 for (int i = 0; i < expr->properties()->length(); i++) { |
| 1553 ClassLiteral::Property* property = expr->properties()->at(i); | 1409 ClassLiteral::Property* property = expr->properties()->at(i); |
| 1554 | 1410 |
| 1555 // Set-up receiver. | 1411 // Set-up receiver. |
| 1556 Register new_receiver = property->is_static() ? literal : prototype; | 1412 Register new_receiver = property->is_static() ? literal : prototype; |
| 1557 if (new_receiver != old_receiver) { | 1413 if (new_receiver != old_receiver) { |
| 1558 builder()->MoveRegister(new_receiver, receiver); | 1414 builder()->MoveRegister(new_receiver, receiver); |
| 1559 old_receiver = new_receiver; | 1415 old_receiver = new_receiver; |
| 1560 } | 1416 } |
| 1561 | 1417 |
| 1562 VisitForAccumulatorValue(property->key()); | 1418 VisitForAccumulatorValue(property->key()); |
| 1563 builder()->ConvertAccumulatorToName(key); | 1419 builder()->ConvertAccumulatorToName(key); |
| 1564 // The static prototype property is read only. We handle the non computed | 1420 |
| 1565 // property name case in the parser. Since this is the only case where we | |
| 1566 // need to check for an own read only property we special case this so we do | |
| 1567 // not need to do this for every property. | |
| 1568 if (property->is_static() && property->is_computed_name()) { | 1421 if (property->is_static() && property->is_computed_name()) { |
| 1569 VisitClassLiteralStaticPrototypeWithComputedName(key); | 1422 // The static prototype property is read only. We handle the non computed |
| 1423 // property name case in the parser. Since this is the only case where we |
| 1424 // need to check for an own read only property we special case this so we |
| 1425 // do not need to do this for every property. |
| 1426 BytecodeLabel done; |
| 1427 builder() |
| 1428 ->LoadLiteral(prototype_string()) |
| 1429 .CompareOperation(Token::Value::EQ_STRICT, key) |
| 1430 .JumpIfFalse(&done) |
| 1431 .CallRuntime(Runtime::kThrowStaticPrototypeError) |
| 1432 .Bind(&done); |
| 1570 } | 1433 } |
| 1571 VisitForAccumulatorValue(property->value()); | |
| 1572 builder()->StoreAccumulatorInRegister(value); | |
| 1573 | 1434 |
| 1435 VisitForRegisterValue(property->value(), value); |
| 1574 VisitSetHomeObject(value, receiver, property); | 1436 VisitSetHomeObject(value, receiver, property); |
| 1575 | 1437 |
| 1576 if (!attr_assigned) { | 1438 if (!attr_assigned) { |
| 1577 builder() | 1439 builder() |
| 1578 ->LoadLiteral(Smi::FromInt(DONT_ENUM)) | 1440 ->LoadLiteral(Smi::FromInt(DONT_ENUM)) |
| 1579 .StoreAccumulatorInRegister(attr); | 1441 .StoreAccumulatorInRegister(attr); |
| 1580 attr_assigned = true; | 1442 attr_assigned = true; |
| 1581 } | 1443 } |
| 1582 | 1444 |
| 1583 switch (property->kind()) { | 1445 switch (property->kind()) { |
| 1584 case ClassLiteral::Property::METHOD: { | 1446 case ClassLiteral::Property::METHOD: { |
| 1585 builder() | 1447 builder() |
| 1586 ->LoadLiteral(Smi::FromInt(property->NeedsSetFunctionName())) | 1448 ->LoadLiteral(Smi::FromInt(property->NeedsSetFunctionName())) |
| 1587 .StoreAccumulatorInRegister(set_function_name); | 1449 .StoreAccumulatorInRegister(set_function_name) |
| 1588 builder()->CallRuntime(Runtime::kDefineDataPropertyInLiteral, receiver, | 1450 .CallRuntime(Runtime::kDefineDataPropertyInLiteral, args); |
| 1589 5); | |
| 1590 break; | 1451 break; |
| 1591 } | 1452 } |
| 1592 case ClassLiteral::Property::GETTER: { | 1453 case ClassLiteral::Property::GETTER: { |
| 1593 builder()->CallRuntime(Runtime::kDefineGetterPropertyUnchecked, | 1454 builder()->CallRuntime(Runtime::kDefineGetterPropertyUnchecked, |
| 1594 receiver, 4); | 1455 args.Truncate(4)); |
| 1595 break; | 1456 break; |
| 1596 } | 1457 } |
| 1597 case ClassLiteral::Property::SETTER: { | 1458 case ClassLiteral::Property::SETTER: { |
| 1598 builder()->CallRuntime(Runtime::kDefineSetterPropertyUnchecked, | 1459 builder()->CallRuntime(Runtime::kDefineSetterPropertyUnchecked, |
| 1599 receiver, 4); | 1460 args.Truncate(4)); |
| 1600 break; | 1461 break; |
| 1601 } | 1462 } |
| 1602 case ClassLiteral::Property::FIELD: { | 1463 case ClassLiteral::Property::FIELD: { |
| 1603 UNREACHABLE(); | 1464 UNREACHABLE(); |
| 1604 break; | 1465 break; |
| 1605 } | 1466 } |
| 1606 } | 1467 } |
| 1607 } | 1468 } |
| 1608 } | 1469 } |
| 1609 | 1470 |
| 1610 void BytecodeGenerator::VisitClassLiteralStaticPrototypeWithComputedName( | |
| 1611 Register key) { | |
| 1612 BytecodeLabel done; | |
| 1613 builder() | |
| 1614 ->LoadLiteral(prototype_string()) | |
| 1615 .CompareOperation(Token::Value::EQ_STRICT, key) | |
| 1616 .JumpIfFalse(&done) | |
| 1617 .CallRuntime(Runtime::kThrowStaticPrototypeError, Register(0), 0) | |
| 1618 .Bind(&done); | |
| 1619 } | |
| 1620 | |
| 1621 void BytecodeGenerator::VisitNativeFunctionLiteral( | 1471 void BytecodeGenerator::VisitNativeFunctionLiteral( |
| 1622 NativeFunctionLiteral* expr) { | 1472 NativeFunctionLiteral* expr) { |
| 1623 size_t entry = builder()->AllocateConstantPoolEntry(); | 1473 size_t entry = builder()->AllocateConstantPoolEntry(); |
| 1624 builder()->CreateClosure(entry, NOT_TENURED); | 1474 builder()->CreateClosure(entry, NOT_TENURED); |
| 1625 native_function_literals_.push_back(std::make_pair(expr, entry)); | 1475 native_function_literals_.push_back(std::make_pair(expr, entry)); |
| 1626 execution_result()->SetResultInAccumulator(); | |
| 1627 } | 1476 } |
| 1628 | 1477 |
| 1629 void BytecodeGenerator::VisitDoExpression(DoExpression* expr) { | 1478 void BytecodeGenerator::VisitDoExpression(DoExpression* expr) { |
| 1630 VisitBlock(expr->block()); | 1479 VisitBlock(expr->block()); |
| 1631 VisitVariableProxy(expr->result()); | 1480 VisitVariableProxy(expr->result()); |
| 1632 } | 1481 } |
| 1633 | 1482 |
| 1634 void BytecodeGenerator::VisitConditional(Conditional* expr) { | 1483 void BytecodeGenerator::VisitConditional(Conditional* expr) { |
| 1635 if (expr->condition()->ToBooleanIsTrue()) { | 1484 if (expr->condition()->ToBooleanIsTrue()) { |
| 1636 // Generate then block unconditionally as always true. | 1485 // Generate then block unconditionally as always true. |
| 1637 VisitForAccumulatorValue(expr->then_expression()); | 1486 VisitForAccumulatorValue(expr->then_expression()); |
| 1638 } else if (expr->condition()->ToBooleanIsFalse()) { | 1487 } else if (expr->condition()->ToBooleanIsFalse()) { |
| 1639 // Generate else block unconditionally if it exists. | 1488 // Generate else block unconditionally if it exists. |
| 1640 VisitForAccumulatorValue(expr->else_expression()); | 1489 VisitForAccumulatorValue(expr->else_expression()); |
| 1641 } else { | 1490 } else { |
| 1642 BytecodeLabel end_label; | 1491 BytecodeLabel end_label; |
| 1643 BytecodeLabels then_labels(zone()), else_labels(zone()); | 1492 BytecodeLabels then_labels(zone()), else_labels(zone()); |
| 1644 | 1493 |
| 1645 VisitForTest(expr->condition(), &then_labels, &else_labels, | 1494 VisitForTest(expr->condition(), &then_labels, &else_labels, |
| 1646 TestFallthrough::kThen); | 1495 TestFallthrough::kThen); |
| 1647 | 1496 |
| 1648 then_labels.Bind(builder()); | 1497 then_labels.Bind(builder()); |
| 1649 VisitForAccumulatorValue(expr->then_expression()); | 1498 VisitForAccumulatorValue(expr->then_expression()); |
| 1650 builder()->Jump(&end_label); | 1499 builder()->Jump(&end_label); |
| 1651 | 1500 |
| 1652 else_labels.Bind(builder()); | 1501 else_labels.Bind(builder()); |
| 1653 VisitForAccumulatorValue(expr->else_expression()); | 1502 VisitForAccumulatorValue(expr->else_expression()); |
| 1654 builder()->Bind(&end_label); | 1503 builder()->Bind(&end_label); |
| 1655 } | 1504 } |
| 1656 | |
| 1657 execution_result()->SetResultInAccumulator(); | |
| 1658 } | 1505 } |
| 1659 | 1506 |
| 1660 void BytecodeGenerator::VisitLiteral(Literal* expr) { | 1507 void BytecodeGenerator::VisitLiteral(Literal* expr) { |
| 1661 if (!execution_result()->IsEffect()) { | 1508 if (!execution_result()->IsEffect()) { |
| 1662 const AstValue* raw_value = expr->raw_value(); | 1509 const AstValue* raw_value = expr->raw_value(); |
| 1663 if (raw_value->IsSmi()) { | 1510 if (raw_value->IsSmi()) { |
| 1664 builder()->LoadLiteral(raw_value->AsSmi()); | 1511 builder()->LoadLiteral(raw_value->AsSmi()); |
| 1665 } else if (raw_value->IsUndefined()) { | 1512 } else if (raw_value->IsUndefined()) { |
| 1666 builder()->LoadUndefined(); | 1513 builder()->LoadUndefined(); |
| 1667 } else if (raw_value->IsTrue()) { | 1514 } else if (raw_value->IsTrue()) { |
| 1668 builder()->LoadTrue(); | 1515 builder()->LoadTrue(); |
| 1669 } else if (raw_value->IsFalse()) { | 1516 } else if (raw_value->IsFalse()) { |
| 1670 builder()->LoadFalse(); | 1517 builder()->LoadFalse(); |
| 1671 } else if (raw_value->IsNull()) { | 1518 } else if (raw_value->IsNull()) { |
| 1672 builder()->LoadNull(); | 1519 builder()->LoadNull(); |
| 1673 } else if (raw_value->IsTheHole()) { | 1520 } else if (raw_value->IsTheHole()) { |
| 1674 builder()->LoadTheHole(); | 1521 builder()->LoadTheHole(); |
| 1675 } else { | 1522 } else { |
| 1676 builder()->LoadLiteral(raw_value->value()); | 1523 builder()->LoadLiteral(raw_value->value()); |
| 1677 } | 1524 } |
| 1678 execution_result()->SetResultInAccumulator(); | |
| 1679 } | 1525 } |
| 1680 } | 1526 } |
| 1681 | 1527 |
| 1682 void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 1528 void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 1683 // Materialize a regular expression literal. | 1529 // Materialize a regular expression literal. |
| 1684 builder()->CreateRegExpLiteral(expr->pattern(), expr->literal_index(), | 1530 builder()->CreateRegExpLiteral(expr->pattern(), expr->literal_index(), |
| 1685 expr->flags()); | 1531 expr->flags()); |
| 1686 execution_result()->SetResultInAccumulator(); | |
| 1687 } | 1532 } |
| 1688 | 1533 |
| 1689 void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { | 1534 void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
| 1690 // Copy the literal boilerplate. | 1535 // Copy the literal boilerplate. |
| 1691 uint8_t flags = CreateObjectLiteralFlags::Encode( | 1536 uint8_t flags = CreateObjectLiteralFlags::Encode( |
| 1692 FastCloneShallowObjectStub::IsSupported(expr), | 1537 FastCloneShallowObjectStub::IsSupported(expr), |
| 1693 FastCloneShallowObjectStub::PropertiesCount(expr->properties_count()), | 1538 FastCloneShallowObjectStub::PropertiesCount(expr->properties_count()), |
| 1694 expr->ComputeFlags()); | 1539 expr->ComputeFlags()); |
| 1695 // Allocate in the outer scope since this register is used to return the | 1540 // Allocate in the outer scope since this register is used to return the |
| 1696 // expression's results to the caller. | 1541 // expression's results to the caller. |
| 1697 Register literal = register_allocator()->outer()->NewRegister(); | 1542 Register literal = register_allocator()->NewRegister(); |
| 1698 builder()->CreateObjectLiteral(expr->constant_properties(), | 1543 builder()->CreateObjectLiteral(expr->constant_properties(), |
| 1699 expr->literal_index(), flags, literal); | 1544 expr->literal_index(), flags, literal); |
| 1700 | 1545 |
| 1701 // Store computed values into the literal. | 1546 // Store computed values into the literal. |
| 1702 int property_index = 0; | 1547 int property_index = 0; |
| 1703 AccessorTable accessor_table(zone()); | 1548 AccessorTable accessor_table(zone()); |
| 1704 for (; property_index < expr->properties()->length(); property_index++) { | 1549 for (; property_index < expr->properties()->length(); property_index++) { |
| 1705 ObjectLiteral::Property* property = expr->properties()->at(property_index); | 1550 ObjectLiteral::Property* property = expr->properties()->at(property_index); |
| 1706 if (property->is_computed_name()) break; | 1551 if (property->is_computed_name()) break; |
| 1707 if (property->IsCompileTimeValue()) continue; | 1552 if (property->IsCompileTimeValue()) continue; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1731 VisitSetHomeObject(value, literal, property, 1); | 1576 VisitSetHomeObject(value, literal, property, 1); |
| 1732 } else { | 1577 } else { |
| 1733 builder()->StoreNamedProperty( | 1578 builder()->StoreNamedProperty( |
| 1734 literal, key->AsPropertyName(), | 1579 literal, key->AsPropertyName(), |
| 1735 feedback_index(property->GetSlot(0)), language_mode()); | 1580 feedback_index(property->GetSlot(0)), language_mode()); |
| 1736 } | 1581 } |
| 1737 } else { | 1582 } else { |
| 1738 VisitForEffect(property->value()); | 1583 VisitForEffect(property->value()); |
| 1739 } | 1584 } |
| 1740 } else { | 1585 } else { |
| 1741 register_allocator()->PrepareForConsecutiveAllocations(4); | 1586 RegisterList args = register_allocator()->NewRegisterList(4); |
| 1742 Register literal_argument = | |
| 1743 register_allocator()->NextConsecutiveRegister(); | |
| 1744 Register key = register_allocator()->NextConsecutiveRegister(); | |
| 1745 Register value = register_allocator()->NextConsecutiveRegister(); | |
| 1746 Register language = register_allocator()->NextConsecutiveRegister(); | |
| 1747 | 1587 |
| 1748 builder()->MoveRegister(literal, literal_argument); | 1588 builder()->MoveRegister(literal, args[0]); |
| 1749 VisitForAccumulatorValue(property->key()); | 1589 VisitForRegisterValue(property->key(), args[1]); |
| 1750 builder()->StoreAccumulatorInRegister(key); | 1590 VisitForRegisterValue(property->value(), args[2]); |
| 1751 VisitForAccumulatorValue(property->value()); | |
| 1752 builder()->StoreAccumulatorInRegister(value); | |
| 1753 if (property->emit_store()) { | 1591 if (property->emit_store()) { |
| 1754 builder() | 1592 builder() |
| 1755 ->LoadLiteral(Smi::FromInt(SLOPPY)) | 1593 ->LoadLiteral(Smi::FromInt(SLOPPY)) |
| 1756 .StoreAccumulatorInRegister(language) | 1594 .StoreAccumulatorInRegister(args[3]) |
| 1757 .CallRuntime(Runtime::kSetProperty, literal_argument, 4); | 1595 .CallRuntime(Runtime::kSetProperty, args); |
| 1596 Register value = args[2]; |
| 1758 VisitSetHomeObject(value, literal, property); | 1597 VisitSetHomeObject(value, literal, property); |
| 1759 } | 1598 } |
| 1760 } | 1599 } |
| 1761 break; | 1600 break; |
| 1762 } | 1601 } |
| 1763 case ObjectLiteral::Property::PROTOTYPE: { | 1602 case ObjectLiteral::Property::PROTOTYPE: { |
| 1764 DCHECK(property->emit_store()); | 1603 DCHECK(property->emit_store()); |
| 1765 register_allocator()->PrepareForConsecutiveAllocations(2); | 1604 RegisterList args = register_allocator()->NewRegisterList(2); |
| 1766 Register literal_argument = | 1605 builder()->MoveRegister(literal, args[0]); |
| 1767 register_allocator()->NextConsecutiveRegister(); | 1606 VisitForRegisterValue(property->value(), args[1]); |
| 1768 Register value = register_allocator()->NextConsecutiveRegister(); | 1607 builder()->CallRuntime(Runtime::kInternalSetPrototype, args); |
| 1769 | |
| 1770 builder()->MoveRegister(literal, literal_argument); | |
| 1771 VisitForAccumulatorValue(property->value()); | |
| 1772 builder()->StoreAccumulatorInRegister(value).CallRuntime( | |
| 1773 Runtime::kInternalSetPrototype, literal_argument, 2); | |
| 1774 break; | 1608 break; |
| 1775 } | 1609 } |
| 1776 case ObjectLiteral::Property::GETTER: | 1610 case ObjectLiteral::Property::GETTER: |
| 1777 if (property->emit_store()) { | 1611 if (property->emit_store()) { |
| 1778 accessor_table.lookup(key)->second->getter = property; | 1612 accessor_table.lookup(key)->second->getter = property; |
| 1779 } | 1613 } |
| 1780 break; | 1614 break; |
| 1781 case ObjectLiteral::Property::SETTER: | 1615 case ObjectLiteral::Property::SETTER: |
| 1782 if (property->emit_store()) { | 1616 if (property->emit_store()) { |
| 1783 accessor_table.lookup(key)->second->setter = property; | 1617 accessor_table.lookup(key)->second->setter = property; |
| 1784 } | 1618 } |
| 1785 break; | 1619 break; |
| 1786 } | 1620 } |
| 1787 } | 1621 } |
| 1788 | 1622 |
| 1789 // Define accessors, using only a single call to the runtime for each pair of | 1623 // Define accessors, using only a single call to the runtime for each pair of |
| 1790 // corresponding getters and setters. | 1624 // corresponding getters and setters. |
| 1791 for (AccessorTable::Iterator it = accessor_table.begin(); | 1625 for (AccessorTable::Iterator it = accessor_table.begin(); |
| 1792 it != accessor_table.end(); ++it) { | 1626 it != accessor_table.end(); ++it) { |
| 1793 RegisterAllocationScope inner_register_scope(this); | 1627 RegisterAllocationScope inner_register_scope(this); |
| 1794 register_allocator()->PrepareForConsecutiveAllocations(5); | 1628 RegisterList args = register_allocator()->NewRegisterList(5); |
| 1795 Register literal_argument = register_allocator()->NextConsecutiveRegister(); | 1629 builder()->MoveRegister(literal, args[0]); |
| 1796 Register name = register_allocator()->NextConsecutiveRegister(); | 1630 VisitForRegisterValue(it->first, args[1]); |
| 1797 Register getter = register_allocator()->NextConsecutiveRegister(); | 1631 VisitObjectLiteralAccessor(literal, it->second->getter, args[2]); |
| 1798 Register setter = register_allocator()->NextConsecutiveRegister(); | 1632 VisitObjectLiteralAccessor(literal, it->second->setter, args[3]); |
| 1799 Register attr = register_allocator()->NextConsecutiveRegister(); | |
| 1800 | |
| 1801 builder()->MoveRegister(literal, literal_argument); | |
| 1802 VisitForAccumulatorValue(it->first); | |
| 1803 builder()->StoreAccumulatorInRegister(name); | |
| 1804 VisitObjectLiteralAccessor(literal, it->second->getter, getter); | |
| 1805 VisitObjectLiteralAccessor(literal, it->second->setter, setter); | |
| 1806 builder() | 1633 builder() |
| 1807 ->LoadLiteral(Smi::FromInt(NONE)) | 1634 ->LoadLiteral(Smi::FromInt(NONE)) |
| 1808 .StoreAccumulatorInRegister(attr) | 1635 .StoreAccumulatorInRegister(args[4]) |
| 1809 .CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, | 1636 .CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, args); |
| 1810 literal_argument, 5); | |
| 1811 } | 1637 } |
| 1812 | 1638 |
| 1813 // Object literals have two parts. The "static" part on the left contains no | 1639 // Object literals have two parts. The "static" part on the left contains no |
| 1814 // computed property names, and so we can compute its map ahead of time; see | 1640 // computed property names, and so we can compute its map ahead of time; see |
| 1815 // Runtime_CreateObjectLiteralBoilerplate. The second "dynamic" part starts | 1641 // Runtime_CreateObjectLiteralBoilerplate. The second "dynamic" part starts |
| 1816 // with the first computed property name and continues with all properties to | 1642 // with the first computed property name and continues with all properties to |
| 1817 // its right. All the code from above initializes the static component of the | 1643 // its right. All the code from above initializes the static component of the |
| 1818 // object literal, and arranges for the map of the result to reflect the | 1644 // object literal, and arranges for the map of the result to reflect the |
| 1819 // static order in which the keys appear. For the dynamic properties, we | 1645 // static order in which the keys appear. For the dynamic properties, we |
| 1820 // compile them into a series of "SetOwnProperty" runtime calls. This will | 1646 // compile them into a series of "SetOwnProperty" runtime calls. This will |
| 1821 // preserve insertion order. | 1647 // preserve insertion order. |
| 1822 for (; property_index < expr->properties()->length(); property_index++) { | 1648 for (; property_index < expr->properties()->length(); property_index++) { |
| 1823 ObjectLiteral::Property* property = expr->properties()->at(property_index); | 1649 ObjectLiteral::Property* property = expr->properties()->at(property_index); |
| 1824 RegisterAllocationScope inner_register_scope(this); | 1650 RegisterAllocationScope inner_register_scope(this); |
| 1825 | 1651 |
| 1826 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) { | 1652 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) { |
| 1827 DCHECK(property->emit_store()); | 1653 DCHECK(property->emit_store()); |
| 1828 register_allocator()->PrepareForConsecutiveAllocations(2); | 1654 RegisterList args = register_allocator()->NewRegisterList(2); |
| 1829 Register literal_argument = | 1655 builder()->MoveRegister(literal, args[0]); |
| 1830 register_allocator()->NextConsecutiveRegister(); | 1656 VisitForRegisterValue(property->value(), args[1]); |
| 1831 Register value = register_allocator()->NextConsecutiveRegister(); | 1657 builder()->CallRuntime(Runtime::kInternalSetPrototype, args); |
| 1832 | |
| 1833 builder()->MoveRegister(literal, literal_argument); | |
| 1834 VisitForAccumulatorValue(property->value()); | |
| 1835 builder()->StoreAccumulatorInRegister(value).CallRuntime( | |
| 1836 Runtime::kInternalSetPrototype, literal_argument, 2); | |
| 1837 continue; | 1658 continue; |
| 1838 } | 1659 } |
| 1839 | 1660 |
| 1840 register_allocator()->PrepareForConsecutiveAllocations(5); | |
| 1841 Register literal_argument = register_allocator()->NextConsecutiveRegister(); | |
| 1842 Register key = register_allocator()->NextConsecutiveRegister(); | |
| 1843 Register value = register_allocator()->NextConsecutiveRegister(); | |
| 1844 Register attr = register_allocator()->NextConsecutiveRegister(); | |
| 1845 DCHECK(Register::AreContiguous(literal_argument, key, value, attr)); | |
| 1846 Register set_function_name = | |
| 1847 register_allocator()->NextConsecutiveRegister(); | |
| 1848 | |
| 1849 builder()->MoveRegister(literal, literal_argument); | |
| 1850 VisitForAccumulatorValue(property->key()); | |
| 1851 builder()->ConvertAccumulatorToName(key); | |
| 1852 VisitForAccumulatorValue(property->value()); | |
| 1853 builder()->StoreAccumulatorInRegister(value); | |
| 1854 VisitSetHomeObject(value, literal, property); | |
| 1855 builder()->LoadLiteral(Smi::FromInt(NONE)).StoreAccumulatorInRegister(attr); | |
| 1856 switch (property->kind()) { | 1661 switch (property->kind()) { |
| 1857 case ObjectLiteral::Property::CONSTANT: | 1662 case ObjectLiteral::Property::CONSTANT: |
| 1858 case ObjectLiteral::Property::COMPUTED: | 1663 case ObjectLiteral::Property::COMPUTED: |
| 1859 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1664 case ObjectLiteral::Property::MATERIALIZED_LITERAL: { |
| 1665 RegisterList args = register_allocator()->NewRegisterList(5); |
| 1666 builder()->MoveRegister(literal, args[0]); |
| 1667 VisitForAccumulatorValue(property->key()); |
| 1668 builder()->ConvertAccumulatorToName(args[1]); |
| 1669 VisitForRegisterValue(property->value(), args[2]); |
| 1670 VisitSetHomeObject(args[2], literal, property); |
| 1860 builder() | 1671 builder() |
| 1861 ->LoadLiteral(Smi::FromInt(property->NeedsSetFunctionName())) | 1672 ->LoadLiteral(Smi::FromInt(NONE)) |
| 1862 .StoreAccumulatorInRegister(set_function_name); | 1673 .StoreAccumulatorInRegister(args[3]) |
| 1863 builder()->CallRuntime(Runtime::kDefineDataPropertyInLiteral, | 1674 .LoadLiteral(Smi::FromInt(property->NeedsSetFunctionName())) |
| 1864 literal_argument, 5); | 1675 .StoreAccumulatorInRegister(args[4]); |
| 1676 builder()->CallRuntime(Runtime::kDefineDataPropertyInLiteral, args); |
| 1865 break; | 1677 break; |
| 1678 } |
| 1679 case ObjectLiteral::Property::GETTER: |
| 1680 case ObjectLiteral::Property::SETTER: { |
| 1681 RegisterList args = register_allocator()->NewRegisterList(4); |
| 1682 builder()->MoveRegister(literal, args[0]); |
| 1683 VisitForAccumulatorValue(property->key()); |
| 1684 builder()->ConvertAccumulatorToName(args[1]); |
| 1685 VisitForRegisterValue(property->value(), args[2]); |
| 1686 VisitSetHomeObject(args[2], literal, property); |
| 1687 builder() |
| 1688 ->LoadLiteral(Smi::FromInt(NONE)) |
| 1689 .StoreAccumulatorInRegister(args[3]); |
| 1690 Runtime::FunctionId function_id = |
| 1691 property->kind() == ObjectLiteral::Property::GETTER |
| 1692 ? Runtime::kDefineGetterPropertyUnchecked |
| 1693 : Runtime::kDefineSetterPropertyUnchecked; |
| 1694 builder()->CallRuntime(function_id, args); |
| 1695 break; |
| 1696 } |
| 1866 case ObjectLiteral::Property::PROTOTYPE: | 1697 case ObjectLiteral::Property::PROTOTYPE: |
| 1867 UNREACHABLE(); // Handled specially above. | 1698 UNREACHABLE(); // Handled specially above. |
| 1868 break; | 1699 break; |
| 1869 case ObjectLiteral::Property::GETTER: | |
| 1870 builder()->CallRuntime(Runtime::kDefineGetterPropertyUnchecked, | |
| 1871 literal_argument, 4); | |
| 1872 break; | |
| 1873 case ObjectLiteral::Property::SETTER: | |
| 1874 builder()->CallRuntime(Runtime::kDefineSetterPropertyUnchecked, | |
| 1875 literal_argument, 4); | |
| 1876 break; | |
| 1877 } | 1700 } |
| 1878 } | 1701 } |
| 1879 | 1702 |
| 1880 execution_result()->SetResultInRegister(literal); | 1703 builder()->LoadAccumulatorWithRegister(literal); |
| 1881 } | 1704 } |
| 1882 | 1705 |
| 1883 void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 1706 void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
| 1884 // Deep-copy the literal boilerplate. | 1707 // Deep-copy the literal boilerplate. |
| 1885 int runtime_flags = expr->ComputeFlags(); | 1708 int runtime_flags = expr->ComputeFlags(); |
| 1886 bool use_fast_shallow_clone = | 1709 bool use_fast_shallow_clone = |
| 1887 (runtime_flags & ArrayLiteral::kShallowElements) != 0 && | 1710 (runtime_flags & ArrayLiteral::kShallowElements) != 0 && |
| 1888 expr->values()->length() <= JSArray::kInitialMaxFastElementArray; | 1711 expr->values()->length() <= JSArray::kInitialMaxFastElementArray; |
| 1889 uint8_t flags = | 1712 uint8_t flags = |
| 1890 CreateArrayLiteralFlags::Encode(use_fast_shallow_clone, runtime_flags); | 1713 CreateArrayLiteralFlags::Encode(use_fast_shallow_clone, runtime_flags); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1914 .StoreAccumulatorInRegister(index); | 1737 .StoreAccumulatorInRegister(index); |
| 1915 VisitForAccumulatorValue(subexpr); | 1738 VisitForAccumulatorValue(subexpr); |
| 1916 builder()->StoreKeyedProperty(literal, index, feedback_index(slot), | 1739 builder()->StoreKeyedProperty(literal, index, feedback_index(slot), |
| 1917 language_mode()); | 1740 language_mode()); |
| 1918 } | 1741 } |
| 1919 | 1742 |
| 1920 if (!literal_in_accumulator) { | 1743 if (!literal_in_accumulator) { |
| 1921 // Restore literal array into accumulator. | 1744 // Restore literal array into accumulator. |
| 1922 builder()->LoadAccumulatorWithRegister(literal); | 1745 builder()->LoadAccumulatorWithRegister(literal); |
| 1923 } | 1746 } |
| 1924 execution_result()->SetResultInAccumulator(); | |
| 1925 } | 1747 } |
| 1926 | 1748 |
| 1927 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { | 1749 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { |
| 1928 builder()->SetExpressionPosition(proxy); | 1750 builder()->SetExpressionPosition(proxy); |
| 1929 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); | 1751 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); |
| 1930 } | 1752 } |
| 1931 | 1753 |
| 1932 void BytecodeGenerator::BuildHoleCheckForVariableLoad(Variable* variable) { | 1754 void BytecodeGenerator::BuildHoleCheckForVariableLoad(Variable* variable) { |
| 1933 if (variable->binding_needs_init()) { | 1755 if (variable->binding_needs_init()) { |
| 1934 BuildThrowIfHole(variable->name()); | 1756 BuildThrowIfHole(variable->name()); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2002 } | 1824 } |
| 2003 case VariableLocation::MODULE: { | 1825 case VariableLocation::MODULE: { |
| 2004 ModuleDescriptor* descriptor = scope()->GetModuleScope()->module(); | 1826 ModuleDescriptor* descriptor = scope()->GetModuleScope()->module(); |
| 2005 if (variable->IsExport()) { | 1827 if (variable->IsExport()) { |
| 2006 auto it = descriptor->regular_exports().find(variable->raw_name()); | 1828 auto it = descriptor->regular_exports().find(variable->raw_name()); |
| 2007 DCHECK(it != descriptor->regular_exports().end()); | 1829 DCHECK(it != descriptor->regular_exports().end()); |
| 2008 Register export_name = register_allocator()->NewRegister(); | 1830 Register export_name = register_allocator()->NewRegister(); |
| 2009 builder() | 1831 builder() |
| 2010 ->LoadLiteral(it->second->export_name->string()) | 1832 ->LoadLiteral(it->second->export_name->string()) |
| 2011 .StoreAccumulatorInRegister(export_name) | 1833 .StoreAccumulatorInRegister(export_name) |
| 2012 .CallRuntime(Runtime::kLoadModuleExport, export_name, 1); | 1834 .CallRuntime(Runtime::kLoadModuleExport, export_name); |
| 2013 } else { | 1835 } else { |
| 2014 auto it = descriptor->regular_imports().find(variable->raw_name()); | 1836 auto it = descriptor->regular_imports().find(variable->raw_name()); |
| 2015 DCHECK(it != descriptor->regular_imports().end()); | 1837 DCHECK(it != descriptor->regular_imports().end()); |
| 2016 register_allocator()->PrepareForConsecutiveAllocations(2); | 1838 RegisterList args = register_allocator()->NewRegisterList(2); |
| 2017 Register import_name = register_allocator()->NextConsecutiveRegister(); | |
| 2018 Register module_request = | |
| 2019 register_allocator()->NextConsecutiveRegister(); | |
| 2020 builder() | 1839 builder() |
| 2021 ->LoadLiteral(it->second->import_name->string()) | 1840 ->LoadLiteral(it->second->import_name->string()) |
| 2022 .StoreAccumulatorInRegister(import_name) | 1841 .StoreAccumulatorInRegister(args[0]) |
| 2023 .LoadLiteral(Smi::FromInt(it->second->module_request)) | 1842 .LoadLiteral(Smi::FromInt(it->second->module_request)) |
| 2024 .StoreAccumulatorInRegister(module_request) | 1843 .StoreAccumulatorInRegister(args[1]) |
| 2025 .CallRuntime(Runtime::kLoadModuleImport, import_name, 2); | 1844 .CallRuntime(Runtime::kLoadModuleImport, args); |
| 2026 } | 1845 } |
| 2027 BuildHoleCheckForVariableLoad(variable); | 1846 BuildHoleCheckForVariableLoad(variable); |
| 2028 break; | 1847 break; |
| 2029 } | 1848 } |
| 2030 } | 1849 } |
| 2031 execution_result()->SetResultInAccumulator(); | |
| 2032 } | 1850 } |
| 2033 | 1851 |
| 2034 void BytecodeGenerator::VisitVariableLoadForAccumulatorValue( | 1852 void BytecodeGenerator::VisitVariableLoadForAccumulatorValue( |
| 2035 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) { | 1853 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) { |
| 2036 AccumulatorResultScope accumulator_result(this); | 1854 ValueResultScope accumulator_result(this); |
| 2037 VisitVariableLoad(variable, slot, typeof_mode); | 1855 VisitVariableLoad(variable, slot, typeof_mode); |
| 2038 } | 1856 } |
| 2039 | 1857 |
| 2040 Register BytecodeGenerator::VisitVariableLoadForRegisterValue( | |
| 2041 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) { | |
| 2042 RegisterResultScope register_scope(this); | |
| 2043 VisitVariableLoad(variable, slot, typeof_mode); | |
| 2044 return register_scope.ResultRegister(); | |
| 2045 } | |
| 2046 | |
| 2047 void BytecodeGenerator::BuildNamedSuperPropertyLoad(Register receiver, | |
| 2048 Register home_object, | |
| 2049 Register name) { | |
| 2050 DCHECK(Register::AreContiguous(receiver, home_object, name)); | |
| 2051 builder()->CallRuntime(Runtime::kLoadFromSuper, receiver, 3); | |
| 2052 } | |
| 2053 | |
| 2054 void BytecodeGenerator::BuildKeyedSuperPropertyLoad(Register receiver, | |
| 2055 Register home_object, | |
| 2056 Register key) { | |
| 2057 DCHECK(Register::AreContiguous(receiver, home_object, key)); | |
| 2058 builder()->CallRuntime(Runtime::kLoadKeyedFromSuper, receiver, 3); | |
| 2059 } | |
| 2060 | |
| 2061 void BytecodeGenerator::BuildNamedSuperPropertyStore(Register receiver, | |
| 2062 Register home_object, | |
| 2063 Register name, | |
| 2064 Register value) { | |
| 2065 DCHECK(Register::AreContiguous(receiver, home_object, name, value)); | |
| 2066 Runtime::FunctionId function_id = is_strict(language_mode()) | |
| 2067 ? Runtime::kStoreToSuper_Strict | |
| 2068 : Runtime::kStoreToSuper_Sloppy; | |
| 2069 builder()->CallRuntime(function_id, receiver, 4); | |
| 2070 } | |
| 2071 | |
| 2072 void BytecodeGenerator::BuildKeyedSuperPropertyStore(Register receiver, | |
| 2073 Register home_object, | |
| 2074 Register key, | |
| 2075 Register value) { | |
| 2076 DCHECK(Register::AreContiguous(receiver, home_object, key, value)); | |
| 2077 Runtime::FunctionId function_id = is_strict(language_mode()) | |
| 2078 ? Runtime::kStoreKeyedToSuper_Strict | |
| 2079 : Runtime::kStoreKeyedToSuper_Sloppy; | |
| 2080 builder()->CallRuntime(function_id, receiver, 4); | |
| 2081 } | |
| 2082 | |
| 2083 void BytecodeGenerator::BuildAbort(BailoutReason bailout_reason) { | 1858 void BytecodeGenerator::BuildAbort(BailoutReason bailout_reason) { |
| 2084 RegisterAllocationScope register_scope(this); | 1859 RegisterAllocationScope register_scope(this); |
| 2085 Register reason = register_allocator()->NewRegister(); | 1860 Register reason = register_allocator()->NewRegister(); |
| 2086 builder() | 1861 builder() |
| 2087 ->LoadLiteral(Smi::FromInt(static_cast<int>(bailout_reason))) | 1862 ->LoadLiteral(Smi::FromInt(static_cast<int>(bailout_reason))) |
| 2088 .StoreAccumulatorInRegister(reason) | 1863 .StoreAccumulatorInRegister(reason) |
| 2089 .CallRuntime(Runtime::kAbort, reason, 1); | 1864 .CallRuntime(Runtime::kAbort, reason); |
| 2090 } | 1865 } |
| 2091 | 1866 |
| 2092 void BytecodeGenerator::BuildThrowReferenceError(Handle<String> name) { | 1867 void BytecodeGenerator::BuildThrowReferenceError(Handle<String> name) { |
| 2093 RegisterAllocationScope register_scope(this); | 1868 RegisterAllocationScope register_scope(this); |
| 2094 Register name_reg = register_allocator()->NewRegister(); | 1869 Register name_reg = register_allocator()->NewRegister(); |
| 2095 builder()->LoadLiteral(name).StoreAccumulatorInRegister(name_reg).CallRuntime( | 1870 builder()->LoadLiteral(name).StoreAccumulatorInRegister(name_reg).CallRuntime( |
| 2096 Runtime::kThrowReferenceError, name_reg, 1); | 1871 Runtime::kThrowReferenceError, name_reg); |
| 2097 } | 1872 } |
| 2098 | 1873 |
| 2099 void BytecodeGenerator::BuildThrowIfHole(Handle<String> name) { | 1874 void BytecodeGenerator::BuildThrowIfHole(Handle<String> name) { |
| 2100 // TODO(interpreter): Can the parser reduce the number of checks | 1875 // TODO(interpreter): Can the parser reduce the number of checks |
| 2101 // performed? Or should there be a ThrowIfHole bytecode. | 1876 // performed? Or should there be a ThrowIfHole bytecode. |
| 2102 BytecodeLabel no_reference_error; | 1877 BytecodeLabel no_reference_error; |
| 2103 builder()->JumpIfNotHole(&no_reference_error); | 1878 builder()->JumpIfNotHole(&no_reference_error); |
| 2104 BuildThrowReferenceError(name); | 1879 BuildThrowReferenceError(name); |
| 2105 builder()->Bind(&no_reference_error); | 1880 builder()->Bind(&no_reference_error); |
| 2106 } | 1881 } |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2159 ->StoreAccumulatorInRegister(value_temp) | 1934 ->StoreAccumulatorInRegister(value_temp) |
| 2160 .LoadAccumulatorWithRegister(destination); | 1935 .LoadAccumulatorWithRegister(destination); |
| 2161 | 1936 |
| 2162 BuildHoleCheckForVariableAssignment(variable, op); | 1937 BuildHoleCheckForVariableAssignment(variable, op); |
| 2163 builder()->LoadAccumulatorWithRegister(value_temp); | 1938 builder()->LoadAccumulatorWithRegister(value_temp); |
| 2164 } | 1939 } |
| 2165 | 1940 |
| 2166 if (mode != CONST || op == Token::INIT) { | 1941 if (mode != CONST || op == Token::INIT) { |
| 2167 builder()->StoreAccumulatorInRegister(destination); | 1942 builder()->StoreAccumulatorInRegister(destination); |
| 2168 } else if (variable->throw_on_const_assignment(language_mode())) { | 1943 } else if (variable->throw_on_const_assignment(language_mode())) { |
| 2169 builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(), 0); | 1944 builder()->CallRuntime(Runtime::kThrowConstAssignError); |
| 2170 } | 1945 } |
| 2171 break; | 1946 break; |
| 2172 } | 1947 } |
| 2173 case VariableLocation::UNALLOCATED: { | 1948 case VariableLocation::UNALLOCATED: { |
| 2174 builder()->StoreGlobal(variable->name(), feedback_index(slot), | 1949 builder()->StoreGlobal(variable->name(), feedback_index(slot), |
| 2175 language_mode()); | 1950 language_mode()); |
| 2176 break; | 1951 break; |
| 2177 } | 1952 } |
| 2178 case VariableLocation::CONTEXT: { | 1953 case VariableLocation::CONTEXT: { |
| 2179 int depth = execution_context()->ContextChainDepth(variable->scope()); | 1954 int depth = execution_context()->ContextChainDepth(variable->scope()); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2194 ->StoreAccumulatorInRegister(value_temp) | 1969 ->StoreAccumulatorInRegister(value_temp) |
| 2195 .LoadContextSlot(context_reg, variable->index(), depth); | 1970 .LoadContextSlot(context_reg, variable->index(), depth); |
| 2196 | 1971 |
| 2197 BuildHoleCheckForVariableAssignment(variable, op); | 1972 BuildHoleCheckForVariableAssignment(variable, op); |
| 2198 builder()->LoadAccumulatorWithRegister(value_temp); | 1973 builder()->LoadAccumulatorWithRegister(value_temp); |
| 2199 } | 1974 } |
| 2200 | 1975 |
| 2201 if (mode != CONST || op == Token::INIT) { | 1976 if (mode != CONST || op == Token::INIT) { |
| 2202 builder()->StoreContextSlot(context_reg, variable->index(), depth); | 1977 builder()->StoreContextSlot(context_reg, variable->index(), depth); |
| 2203 } else if (variable->throw_on_const_assignment(language_mode())) { | 1978 } else if (variable->throw_on_const_assignment(language_mode())) { |
| 2204 builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(), 0); | 1979 builder()->CallRuntime(Runtime::kThrowConstAssignError); |
| 2205 } | 1980 } |
| 2206 break; | 1981 break; |
| 2207 } | 1982 } |
| 2208 case VariableLocation::LOOKUP: { | 1983 case VariableLocation::LOOKUP: { |
| 2209 builder()->StoreLookupSlot(variable->name(), language_mode()); | 1984 builder()->StoreLookupSlot(variable->name(), language_mode()); |
| 2210 break; | 1985 break; |
| 2211 } | 1986 } |
| 2212 case VariableLocation::MODULE: { | 1987 case VariableLocation::MODULE: { |
| 2213 DCHECK(IsDeclaredVariableMode(mode)); | 1988 DCHECK(IsDeclaredVariableMode(mode)); |
| 2214 | 1989 |
| 2215 if (mode == CONST && op != Token::INIT) { | 1990 if (mode == CONST && op != Token::INIT) { |
| 2216 builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(), 0); | 1991 builder()->CallRuntime(Runtime::kThrowConstAssignError); |
| 2217 break; | 1992 break; |
| 2218 } | 1993 } |
| 2219 | 1994 |
| 2220 // If we don't throw above, we know that we're dealing with an | 1995 // If we don't throw above, we know that we're dealing with an |
| 2221 // export because imports are const and we do not generate initializing | 1996 // export because imports are const and we do not generate initializing |
| 2222 // assignments for them. | 1997 // assignments for them. |
| 2223 DCHECK(variable->IsExport()); | 1998 DCHECK(variable->IsExport()); |
| 2224 | 1999 |
| 2225 ModuleDescriptor* mod = scope()->GetModuleScope()->module(); | 2000 ModuleDescriptor* mod = scope()->GetModuleScope()->module(); |
| 2226 // There may be several export names for this local name, but it doesn't | 2001 // There may be several export names for this local name, but it doesn't |
| 2227 // matter which one we pick, as they all map to the same cell. | 2002 // matter which one we pick, as they all map to the same cell. |
| 2228 auto it = mod->regular_exports().find(variable->raw_name()); | 2003 auto it = mod->regular_exports().find(variable->raw_name()); |
| 2229 DCHECK(it != mod->regular_exports().end()); | 2004 DCHECK(it != mod->regular_exports().end()); |
| 2230 | 2005 |
| 2231 register_allocator()->PrepareForConsecutiveAllocations(2); | 2006 RegisterList args = register_allocator()->NewRegisterList(2); |
| 2232 Register export_name = register_allocator()->NextConsecutiveRegister(); | |
| 2233 Register value = register_allocator()->NextConsecutiveRegister(); | |
| 2234 builder() | 2007 builder() |
| 2235 ->StoreAccumulatorInRegister(value) | 2008 ->StoreAccumulatorInRegister(args[1]) |
| 2236 .LoadLiteral(it->second->export_name->string()) | 2009 .LoadLiteral(it->second->export_name->string()) |
| 2237 .StoreAccumulatorInRegister(export_name) | 2010 .StoreAccumulatorInRegister(args[0]) |
| 2238 .CallRuntime(Runtime::kStoreModuleExport, export_name, 2); | 2011 .CallRuntime(Runtime::kStoreModuleExport, args); |
| 2239 break; | 2012 break; |
| 2240 } | 2013 } |
| 2241 } | 2014 } |
| 2242 } | 2015 } |
| 2243 | 2016 |
| 2244 void BytecodeGenerator::VisitAssignment(Assignment* expr) { | 2017 void BytecodeGenerator::VisitAssignment(Assignment* expr) { |
| 2245 DCHECK(expr->target()->IsValidReferenceExpressionOrThis()); | 2018 DCHECK(expr->target()->IsValidReferenceExpressionOrThis()); |
| 2246 Register object, key, home_object, value; | 2019 Register object, key; |
| 2020 RegisterList super_property_args; |
| 2247 Handle<String> name; | 2021 Handle<String> name; |
| 2248 | 2022 |
| 2249 // Left-hand side can only be a property, a global or a variable slot. | 2023 // Left-hand side can only be a property, a global or a variable slot. |
| 2250 Property* property = expr->target()->AsProperty(); | 2024 Property* property = expr->target()->AsProperty(); |
| 2251 LhsKind assign_type = Property::GetAssignType(property); | 2025 LhsKind assign_type = Property::GetAssignType(property); |
| 2252 | 2026 |
| 2253 // Evaluate LHS expression. | 2027 // Evaluate LHS expression. |
| 2254 switch (assign_type) { | 2028 switch (assign_type) { |
| 2255 case VARIABLE: | 2029 case VARIABLE: |
| 2256 // Nothing to do to evaluate variable assignment LHS. | 2030 // Nothing to do to evaluate variable assignment LHS. |
| 2257 break; | 2031 break; |
| 2258 case NAMED_PROPERTY: { | 2032 case NAMED_PROPERTY: { |
| 2259 object = VisitForRegisterValue(property->obj()); | 2033 object = VisitForRegisterValue(property->obj()); |
| 2260 name = property->key()->AsLiteral()->AsPropertyName(); | 2034 name = property->key()->AsLiteral()->AsPropertyName(); |
| 2261 break; | 2035 break; |
| 2262 } | 2036 } |
| 2263 case KEYED_PROPERTY: { | 2037 case KEYED_PROPERTY: { |
| 2264 object = VisitForRegisterValue(property->obj()); | 2038 object = VisitForRegisterValue(property->obj()); |
| 2265 if (expr->is_compound()) { | 2039 key = VisitForRegisterValue(property->key()); |
| 2266 // Use VisitForAccumulator and store to register so that the key is | |
| 2267 // still in the accumulator for loading the old value below. | |
| 2268 key = register_allocator()->NewRegister(); | |
| 2269 VisitForAccumulatorValue(property->key()); | |
| 2270 builder()->StoreAccumulatorInRegister(key); | |
| 2271 } else { | |
| 2272 key = VisitForRegisterValue(property->key()); | |
| 2273 } | |
| 2274 break; | 2040 break; |
| 2275 } | 2041 } |
| 2276 case NAMED_SUPER_PROPERTY: { | 2042 case NAMED_SUPER_PROPERTY: { |
| 2277 register_allocator()->PrepareForConsecutiveAllocations(4); | 2043 super_property_args = register_allocator()->NewRegisterList(4); |
| 2278 object = register_allocator()->NextConsecutiveRegister(); | |
| 2279 home_object = register_allocator()->NextConsecutiveRegister(); | |
| 2280 key = register_allocator()->NextConsecutiveRegister(); | |
| 2281 value = register_allocator()->NextConsecutiveRegister(); | |
| 2282 SuperPropertyReference* super_property = | 2044 SuperPropertyReference* super_property = |
| 2283 property->obj()->AsSuperPropertyReference(); | 2045 property->obj()->AsSuperPropertyReference(); |
| 2284 VisitForRegisterValue(super_property->this_var(), object); | 2046 VisitForRegisterValue(super_property->this_var(), super_property_args[0]); |
| 2285 VisitForRegisterValue(super_property->home_object(), home_object); | 2047 VisitForRegisterValue(super_property->home_object(), |
| 2048 super_property_args[1]); |
| 2286 builder() | 2049 builder() |
| 2287 ->LoadLiteral(property->key()->AsLiteral()->AsPropertyName()) | 2050 ->LoadLiteral(property->key()->AsLiteral()->AsPropertyName()) |
| 2288 .StoreAccumulatorInRegister(key); | 2051 .StoreAccumulatorInRegister(super_property_args[2]); |
| 2289 break; | 2052 break; |
| 2290 } | 2053 } |
| 2291 case KEYED_SUPER_PROPERTY: { | 2054 case KEYED_SUPER_PROPERTY: { |
| 2292 register_allocator()->PrepareForConsecutiveAllocations(4); | 2055 super_property_args = register_allocator()->NewRegisterList(4); |
| 2293 object = register_allocator()->NextConsecutiveRegister(); | |
| 2294 home_object = register_allocator()->NextConsecutiveRegister(); | |
| 2295 key = register_allocator()->NextConsecutiveRegister(); | |
| 2296 value = register_allocator()->NextConsecutiveRegister(); | |
| 2297 builder()->StoreAccumulatorInRegister(value); | |
| 2298 SuperPropertyReference* super_property = | 2056 SuperPropertyReference* super_property = |
| 2299 property->obj()->AsSuperPropertyReference(); | 2057 property->obj()->AsSuperPropertyReference(); |
| 2300 VisitForRegisterValue(super_property->this_var(), object); | 2058 VisitForRegisterValue(super_property->this_var(), super_property_args[0]); |
| 2301 VisitForRegisterValue(super_property->home_object(), home_object); | 2059 VisitForRegisterValue(super_property->home_object(), |
| 2302 VisitForRegisterValue(property->key(), key); | 2060 super_property_args[1]); |
| 2061 VisitForRegisterValue(property->key(), super_property_args[2]); |
| 2303 break; | 2062 break; |
| 2304 } | 2063 } |
| 2305 } | 2064 } |
| 2306 | 2065 |
| 2307 // Evaluate the value and potentially handle compound assignments by loading | 2066 // Evaluate the value and potentially handle compound assignments by loading |
| 2308 // the left-hand side value and performing a binary operation. | 2067 // the left-hand side value and performing a binary operation. |
| 2309 if (expr->is_compound()) { | 2068 if (expr->is_compound()) { |
| 2310 Register old_value; | 2069 Register old_value = register_allocator()->NewRegister(); |
| 2311 switch (assign_type) { | 2070 switch (assign_type) { |
| 2312 case VARIABLE: { | 2071 case VARIABLE: { |
| 2313 VariableProxy* proxy = expr->target()->AsVariableProxy(); | 2072 VariableProxy* proxy = expr->target()->AsVariableProxy(); |
| 2314 old_value = VisitVariableLoadForRegisterValue( | 2073 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); |
| 2315 proxy->var(), proxy->VariableFeedbackSlot()); | 2074 builder()->StoreAccumulatorInRegister(old_value); |
| 2316 break; | 2075 break; |
| 2317 } | 2076 } |
| 2318 case NAMED_PROPERTY: { | 2077 case NAMED_PROPERTY: { |
| 2319 FeedbackVectorSlot slot = property->PropertyFeedbackSlot(); | 2078 FeedbackVectorSlot slot = property->PropertyFeedbackSlot(); |
| 2320 old_value = register_allocator()->NewRegister(); | |
| 2321 builder() | 2079 builder() |
| 2322 ->LoadNamedProperty(object, name, feedback_index(slot)) | 2080 ->LoadNamedProperty(object, name, feedback_index(slot)) |
| 2323 .StoreAccumulatorInRegister(old_value); | 2081 .StoreAccumulatorInRegister(old_value); |
| 2324 break; | 2082 break; |
| 2325 } | 2083 } |
| 2326 case KEYED_PROPERTY: { | 2084 case KEYED_PROPERTY: { |
| 2327 // Key is already in accumulator at this point due to evaluating the | 2085 // Key is already in accumulator at this point due to evaluating the |
| 2328 // LHS above. | 2086 // LHS above. |
| 2329 FeedbackVectorSlot slot = property->PropertyFeedbackSlot(); | 2087 FeedbackVectorSlot slot = property->PropertyFeedbackSlot(); |
| 2330 old_value = register_allocator()->NewRegister(); | |
| 2331 builder() | 2088 builder() |
| 2332 ->LoadKeyedProperty(object, feedback_index(slot)) | 2089 ->LoadKeyedProperty(object, feedback_index(slot)) |
| 2333 .StoreAccumulatorInRegister(old_value); | 2090 .StoreAccumulatorInRegister(old_value); |
| 2334 break; | 2091 break; |
| 2335 } | 2092 } |
| 2336 case NAMED_SUPER_PROPERTY: { | 2093 case NAMED_SUPER_PROPERTY: { |
| 2337 old_value = register_allocator()->NewRegister(); | 2094 builder() |
| 2338 BuildNamedSuperPropertyLoad(object, home_object, key); | 2095 ->CallRuntime(Runtime::kLoadFromSuper, |
| 2339 builder()->StoreAccumulatorInRegister(old_value); | 2096 super_property_args.Truncate(3)) |
| 2097 .StoreAccumulatorInRegister(old_value); |
| 2340 break; | 2098 break; |
| 2341 } | 2099 } |
| 2342 case KEYED_SUPER_PROPERTY: { | 2100 case KEYED_SUPER_PROPERTY: { |
| 2343 old_value = register_allocator()->NewRegister(); | 2101 builder() |
| 2344 BuildKeyedSuperPropertyLoad(object, home_object, key); | 2102 ->CallRuntime(Runtime::kLoadKeyedFromSuper, |
| 2345 builder()->StoreAccumulatorInRegister(old_value); | 2103 super_property_args.Truncate(3)) |
| 2104 .StoreAccumulatorInRegister(old_value); |
| 2346 break; | 2105 break; |
| 2347 } | 2106 } |
| 2348 } | 2107 } |
| 2349 VisitForAccumulatorValue(expr->value()); | 2108 VisitForAccumulatorValue(expr->value()); |
| 2350 FeedbackVectorSlot slot = | 2109 FeedbackVectorSlot slot = |
| 2351 expr->binary_operation()->BinaryOperationFeedbackSlot(); | 2110 expr->binary_operation()->BinaryOperationFeedbackSlot(); |
| 2352 builder()->BinaryOperation(expr->binary_op(), old_value, | 2111 builder()->BinaryOperation(expr->binary_op(), old_value, |
| 2353 feedback_index(slot)); | 2112 feedback_index(slot)); |
| 2354 } else { | 2113 } else { |
| 2355 VisitForAccumulatorValue(expr->value()); | 2114 VisitForAccumulatorValue(expr->value()); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2368 } | 2127 } |
| 2369 case NAMED_PROPERTY: | 2128 case NAMED_PROPERTY: |
| 2370 builder()->StoreNamedProperty(object, name, feedback_index(slot), | 2129 builder()->StoreNamedProperty(object, name, feedback_index(slot), |
| 2371 language_mode()); | 2130 language_mode()); |
| 2372 break; | 2131 break; |
| 2373 case KEYED_PROPERTY: | 2132 case KEYED_PROPERTY: |
| 2374 builder()->StoreKeyedProperty(object, key, feedback_index(slot), | 2133 builder()->StoreKeyedProperty(object, key, feedback_index(slot), |
| 2375 language_mode()); | 2134 language_mode()); |
| 2376 break; | 2135 break; |
| 2377 case NAMED_SUPER_PROPERTY: { | 2136 case NAMED_SUPER_PROPERTY: { |
| 2378 builder()->StoreAccumulatorInRegister(value); | 2137 builder() |
| 2379 BuildNamedSuperPropertyStore(object, home_object, key, value); | 2138 ->StoreAccumulatorInRegister(super_property_args[3]) |
| 2139 .CallRuntime(StoreToSuperRuntimeId(), super_property_args); |
| 2380 break; | 2140 break; |
| 2381 } | 2141 } |
| 2382 case KEYED_SUPER_PROPERTY: { | 2142 case KEYED_SUPER_PROPERTY: { |
| 2383 builder()->StoreAccumulatorInRegister(value); | 2143 builder() |
| 2384 BuildKeyedSuperPropertyStore(object, home_object, key, value); | 2144 ->StoreAccumulatorInRegister(super_property_args[3]) |
| 2145 .CallRuntime(StoreKeyedToSuperRuntimeId(), super_property_args); |
| 2385 break; | 2146 break; |
| 2386 } | 2147 } |
| 2387 } | 2148 } |
| 2388 execution_result()->SetResultInAccumulator(); | |
| 2389 } | 2149 } |
| 2390 | 2150 |
| 2391 void BytecodeGenerator::VisitYield(Yield* expr) { | 2151 void BytecodeGenerator::VisitYield(Yield* expr) { |
| 2392 builder()->SetExpressionPosition(expr); | 2152 builder()->SetExpressionPosition(expr); |
| 2393 Register value = VisitForRegisterValue(expr->expression()); | 2153 Register value = VisitForRegisterValue(expr->expression()); |
| 2394 | 2154 |
| 2395 Register generator = VisitForRegisterValue(expr->generator_object()); | 2155 Register generator = VisitForRegisterValue(expr->generator_object()); |
| 2396 | 2156 |
| 2397 // Save context, registers, and state. Then return. | 2157 // Save context, registers, and state. Then return. |
| 2398 builder() | 2158 builder() |
| 2399 ->LoadLiteral(Smi::FromInt(expr->yield_id())) | 2159 ->LoadLiteral(Smi::FromInt(expr->yield_id())) |
| 2400 .SuspendGenerator(generator) | 2160 .SuspendGenerator(generator) |
| 2401 .LoadAccumulatorWithRegister(value) | 2161 .LoadAccumulatorWithRegister(value) |
| 2402 .Return(); // Hard return (ignore any finally blocks). | 2162 .Return(); // Hard return (ignore any finally blocks). |
| 2403 | 2163 |
| 2404 builder()->Bind(&(generator_resume_points_[expr->yield_id()])); | 2164 builder()->Bind(&(generator_resume_points_[expr->yield_id()])); |
| 2405 // Upon resume, we continue here. | 2165 // Upon resume, we continue here. |
| 2406 | 2166 |
| 2407 { | 2167 { |
| 2408 RegisterAllocationScope register_scope(this); | 2168 RegisterAllocationScope register_scope(this); |
| 2409 | 2169 |
| 2410 // Update state to indicate that we have finished resuming. Loop headers | 2170 // Update state to indicate that we have finished resuming. Loop headers |
| 2411 // rely on this. | 2171 // rely on this. |
| 2412 builder() | 2172 builder() |
| 2413 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)) | 2173 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)) |
| 2414 .StoreAccumulatorInRegister(generator_state_); | 2174 .StoreAccumulatorInRegister(generator_state_); |
| 2415 | 2175 |
| 2416 Register input = register_allocator()->NewRegister(); | 2176 Register input = register_allocator()->NewRegister(); |
| 2417 builder() | 2177 builder() |
| 2418 ->CallRuntime(Runtime::kInlineGeneratorGetInputOrDebugPos, generator, 1) | 2178 ->CallRuntime(Runtime::kInlineGeneratorGetInputOrDebugPos, generator) |
| 2419 .StoreAccumulatorInRegister(input); | 2179 .StoreAccumulatorInRegister(input); |
| 2420 | 2180 |
| 2421 Register resume_mode = register_allocator()->NewRegister(); | 2181 Register resume_mode = register_allocator()->NewRegister(); |
| 2422 builder() | 2182 builder() |
| 2423 ->CallRuntime(Runtime::kInlineGeneratorGetResumeMode, generator, 1) | 2183 ->CallRuntime(Runtime::kInlineGeneratorGetResumeMode, generator) |
| 2424 .StoreAccumulatorInRegister(resume_mode); | 2184 .StoreAccumulatorInRegister(resume_mode); |
| 2425 | 2185 |
| 2426 // Now dispatch on resume mode. | 2186 // Now dispatch on resume mode. |
| 2427 | 2187 |
| 2428 BytecodeLabel resume_with_next; | 2188 BytecodeLabel resume_with_next; |
| 2429 BytecodeLabel resume_with_return; | 2189 BytecodeLabel resume_with_return; |
| 2430 BytecodeLabel resume_with_throw; | 2190 BytecodeLabel resume_with_throw; |
| 2431 | 2191 |
| 2432 builder() | 2192 builder() |
| 2433 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kNext)) | 2193 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kNext)) |
| 2434 .CompareOperation(Token::EQ_STRICT, resume_mode) | 2194 .CompareOperation(Token::EQ_STRICT, resume_mode) |
| 2435 .JumpIfTrue(&resume_with_next) | 2195 .JumpIfTrue(&resume_with_next) |
| 2436 .LoadLiteral(Smi::FromInt(JSGeneratorObject::kThrow)) | 2196 .LoadLiteral(Smi::FromInt(JSGeneratorObject::kThrow)) |
| 2437 .CompareOperation(Token::EQ_STRICT, resume_mode) | 2197 .CompareOperation(Token::EQ_STRICT, resume_mode) |
| 2438 .JumpIfTrue(&resume_with_throw) | 2198 .JumpIfTrue(&resume_with_throw) |
| 2439 .Jump(&resume_with_return); | 2199 .Jump(&resume_with_return); |
| 2440 | 2200 |
| 2441 builder()->Bind(&resume_with_return); | 2201 builder()->Bind(&resume_with_return); |
| 2442 { | 2202 { |
| 2443 register_allocator()->PrepareForConsecutiveAllocations(2); | 2203 RegisterList args = register_allocator()->NewRegisterList(2); |
| 2444 Register value = register_allocator()->NextConsecutiveRegister(); | |
| 2445 Register done = register_allocator()->NextConsecutiveRegister(); | |
| 2446 builder() | 2204 builder() |
| 2447 ->MoveRegister(input, value) | 2205 ->MoveRegister(input, args[0]) |
| 2448 .LoadTrue() | 2206 .LoadTrue() |
| 2449 .StoreAccumulatorInRegister(done) | 2207 .StoreAccumulatorInRegister(args[1]) |
| 2450 .CallRuntime(Runtime::kInlineCreateIterResultObject, value, 2); | 2208 .CallRuntime(Runtime::kInlineCreateIterResultObject, args); |
| 2451 execution_control()->ReturnAccumulator(); | 2209 execution_control()->ReturnAccumulator(); |
| 2452 } | 2210 } |
| 2453 | 2211 |
| 2454 builder()->Bind(&resume_with_throw); | 2212 builder()->Bind(&resume_with_throw); |
| 2455 builder()->SetExpressionPosition(expr); | 2213 builder()->SetExpressionPosition(expr); |
| 2456 builder()->LoadAccumulatorWithRegister(input); | 2214 builder()->LoadAccumulatorWithRegister(input); |
| 2457 if (expr->rethrow_on_exception()) { | 2215 if (expr->rethrow_on_exception()) { |
| 2458 builder()->ReThrow(); | 2216 builder()->ReThrow(); |
| 2459 } else { | 2217 } else { |
| 2460 builder()->Throw(); | 2218 builder()->Throw(); |
| 2461 } | 2219 } |
| 2462 | 2220 |
| 2463 builder()->Bind(&resume_with_next); | 2221 builder()->Bind(&resume_with_next); |
| 2464 builder()->LoadAccumulatorWithRegister(input); | 2222 builder()->LoadAccumulatorWithRegister(input); |
| 2465 } | 2223 } |
| 2466 execution_result()->SetResultInAccumulator(); | |
| 2467 } | 2224 } |
| 2468 | 2225 |
| 2469 void BytecodeGenerator::VisitThrow(Throw* expr) { | 2226 void BytecodeGenerator::VisitThrow(Throw* expr) { |
| 2470 VisitForAccumulatorValue(expr->exception()); | 2227 VisitForAccumulatorValue(expr->exception()); |
| 2471 builder()->SetExpressionPosition(expr); | 2228 builder()->SetExpressionPosition(expr); |
| 2472 builder()->Throw(); | 2229 builder()->Throw(); |
| 2473 // Throw statements are modeled as expressions instead of statements. These | |
| 2474 // are converted from assignment statements in Rewriter::ReWrite pass. An | |
| 2475 // assignment statement expects a value in the accumulator. This is a hack to | |
| 2476 // avoid DCHECK fails assert accumulator has been set. | |
| 2477 execution_result()->SetResultInAccumulator(); | |
| 2478 } | 2230 } |
| 2479 | 2231 |
| 2480 void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* expr) { | 2232 void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* expr) { |
| 2481 LhsKind property_kind = Property::GetAssignType(expr); | 2233 LhsKind property_kind = Property::GetAssignType(expr); |
| 2482 FeedbackVectorSlot slot = expr->PropertyFeedbackSlot(); | 2234 FeedbackVectorSlot slot = expr->PropertyFeedbackSlot(); |
| 2483 builder()->SetExpressionPosition(expr); | 2235 builder()->SetExpressionPosition(expr); |
| 2484 switch (property_kind) { | 2236 switch (property_kind) { |
| 2485 case VARIABLE: | 2237 case VARIABLE: |
| 2486 UNREACHABLE(); | 2238 UNREACHABLE(); |
| 2487 case NAMED_PROPERTY: { | 2239 case NAMED_PROPERTY: { |
| 2488 builder()->LoadNamedProperty(obj, | 2240 builder()->LoadNamedProperty(obj, |
| 2489 expr->key()->AsLiteral()->AsPropertyName(), | 2241 expr->key()->AsLiteral()->AsPropertyName(), |
| 2490 feedback_index(slot)); | 2242 feedback_index(slot)); |
| 2491 break; | 2243 break; |
| 2492 } | 2244 } |
| 2493 case KEYED_PROPERTY: { | 2245 case KEYED_PROPERTY: { |
| 2494 VisitForAccumulatorValue(expr->key()); | 2246 VisitForAccumulatorValue(expr->key()); |
| 2495 builder()->LoadKeyedProperty(obj, feedback_index(slot)); | 2247 builder()->LoadKeyedProperty(obj, feedback_index(slot)); |
| 2496 break; | 2248 break; |
| 2497 } | 2249 } |
| 2498 case NAMED_SUPER_PROPERTY: | 2250 case NAMED_SUPER_PROPERTY: |
| 2499 VisitNamedSuperPropertyLoad(expr, Register::invalid_value()); | 2251 VisitNamedSuperPropertyLoad(expr, Register::invalid_value()); |
| 2500 break; | 2252 break; |
| 2501 case KEYED_SUPER_PROPERTY: | 2253 case KEYED_SUPER_PROPERTY: |
| 2502 VisitKeyedSuperPropertyLoad(expr, Register::invalid_value()); | 2254 VisitKeyedSuperPropertyLoad(expr, Register::invalid_value()); |
| 2503 break; | 2255 break; |
| 2504 } | 2256 } |
| 2505 execution_result()->SetResultInAccumulator(); | |
| 2506 } | 2257 } |
| 2507 | 2258 |
| 2508 void BytecodeGenerator::VisitPropertyLoadForAccumulator(Register obj, | 2259 void BytecodeGenerator::VisitPropertyLoadForAccumulator(Register obj, |
| 2509 Property* expr) { | 2260 Property* expr) { |
| 2510 AccumulatorResultScope result_scope(this); | 2261 ValueResultScope result_scope(this); |
| 2511 VisitPropertyLoad(obj, expr); | 2262 VisitPropertyLoad(obj, expr); |
| 2512 } | 2263 } |
| 2513 | 2264 |
| 2514 void BytecodeGenerator::VisitNamedSuperPropertyLoad(Property* property, | 2265 void BytecodeGenerator::VisitNamedSuperPropertyLoad(Property* property, |
| 2515 Register opt_receiver_out) { | 2266 Register opt_receiver_out) { |
| 2516 RegisterAllocationScope register_scope(this); | 2267 RegisterAllocationScope register_scope(this); |
| 2517 register_allocator()->PrepareForConsecutiveAllocations(3); | |
| 2518 | |
| 2519 Register receiver, home_object, name; | |
| 2520 receiver = register_allocator()->NextConsecutiveRegister(); | |
| 2521 home_object = register_allocator()->NextConsecutiveRegister(); | |
| 2522 name = register_allocator()->NextConsecutiveRegister(); | |
| 2523 SuperPropertyReference* super_property = | 2268 SuperPropertyReference* super_property = |
| 2524 property->obj()->AsSuperPropertyReference(); | 2269 property->obj()->AsSuperPropertyReference(); |
| 2525 VisitForRegisterValue(super_property->this_var(), receiver); | 2270 RegisterList args = register_allocator()->NewRegisterList(3); |
| 2526 VisitForRegisterValue(super_property->home_object(), home_object); | 2271 VisitForRegisterValue(super_property->this_var(), args[0]); |
| 2272 VisitForRegisterValue(super_property->home_object(), args[1]); |
| 2527 builder() | 2273 builder() |
| 2528 ->LoadLiteral(property->key()->AsLiteral()->AsPropertyName()) | 2274 ->LoadLiteral(property->key()->AsLiteral()->AsPropertyName()) |
| 2529 .StoreAccumulatorInRegister(name); | 2275 .StoreAccumulatorInRegister(args[2]) |
| 2530 BuildNamedSuperPropertyLoad(receiver, home_object, name); | 2276 .CallRuntime(Runtime::kLoadFromSuper, args); |
| 2531 | 2277 |
| 2532 if (opt_receiver_out.is_valid()) { | 2278 if (opt_receiver_out.is_valid()) { |
| 2533 builder()->MoveRegister(receiver, opt_receiver_out); | 2279 builder()->MoveRegister(args[0], opt_receiver_out); |
| 2534 } | 2280 } |
| 2535 } | 2281 } |
| 2536 | 2282 |
| 2537 void BytecodeGenerator::VisitKeyedSuperPropertyLoad(Property* property, | 2283 void BytecodeGenerator::VisitKeyedSuperPropertyLoad(Property* property, |
| 2538 Register opt_receiver_out) { | 2284 Register opt_receiver_out) { |
| 2539 RegisterAllocationScope register_scope(this); | 2285 RegisterAllocationScope register_scope(this); |
| 2540 register_allocator()->PrepareForConsecutiveAllocations(3); | |
| 2541 | |
| 2542 Register receiver, home_object, key; | |
| 2543 receiver = register_allocator()->NextConsecutiveRegister(); | |
| 2544 home_object = register_allocator()->NextConsecutiveRegister(); | |
| 2545 key = register_allocator()->NextConsecutiveRegister(); | |
| 2546 SuperPropertyReference* super_property = | 2286 SuperPropertyReference* super_property = |
| 2547 property->obj()->AsSuperPropertyReference(); | 2287 property->obj()->AsSuperPropertyReference(); |
| 2548 VisitForRegisterValue(super_property->this_var(), receiver); | 2288 RegisterList args = register_allocator()->NewRegisterList(3); |
| 2549 VisitForRegisterValue(super_property->home_object(), home_object); | 2289 VisitForRegisterValue(super_property->this_var(), args[0]); |
| 2550 VisitForRegisterValue(property->key(), key); | 2290 VisitForRegisterValue(super_property->home_object(), args[1]); |
| 2551 BuildKeyedSuperPropertyLoad(receiver, home_object, key); | 2291 VisitForRegisterValue(property->key(), args[2]); |
| 2292 builder()->CallRuntime(Runtime::kLoadKeyedFromSuper, args); |
| 2552 | 2293 |
| 2553 if (opt_receiver_out.is_valid()) { | 2294 if (opt_receiver_out.is_valid()) { |
| 2554 builder()->MoveRegister(receiver, opt_receiver_out); | 2295 builder()->MoveRegister(args[0], opt_receiver_out); |
| 2555 } | 2296 } |
| 2556 } | 2297 } |
| 2557 | 2298 |
| 2558 void BytecodeGenerator::VisitProperty(Property* expr) { | 2299 void BytecodeGenerator::VisitProperty(Property* expr) { |
| 2559 LhsKind property_kind = Property::GetAssignType(expr); | 2300 LhsKind property_kind = Property::GetAssignType(expr); |
| 2560 if (property_kind != NAMED_SUPER_PROPERTY && | 2301 if (property_kind != NAMED_SUPER_PROPERTY && |
| 2561 property_kind != KEYED_SUPER_PROPERTY) { | 2302 property_kind != KEYED_SUPER_PROPERTY) { |
| 2562 Register obj = VisitForRegisterValue(expr->obj()); | 2303 Register obj = VisitForRegisterValue(expr->obj()); |
| 2563 VisitPropertyLoad(obj, expr); | 2304 VisitPropertyLoad(obj, expr); |
| 2564 } else { | 2305 } else { |
| 2565 VisitPropertyLoad(Register::invalid_value(), expr); | 2306 VisitPropertyLoad(Register::invalid_value(), expr); |
| 2566 } | 2307 } |
| 2567 } | 2308 } |
| 2568 | 2309 |
| 2569 Register BytecodeGenerator::VisitArguments(ZoneList<Expression*>* args) { | 2310 void BytecodeGenerator::VisitArguments(ZoneList<Expression*>* args, |
| 2570 if (args->length() == 0) { | 2311 RegisterList arg_regs, |
| 2571 return Register(); | 2312 size_t first_argument_register) { |
| 2313 // Visit arguments. |
| 2314 for (int i = 0; i < static_cast<int>(args->length()); i++) { |
| 2315 VisitForRegisterValue(args->at(i), arg_regs[first_argument_register + i]); |
| 2572 } | 2316 } |
| 2573 | |
| 2574 // Visit arguments and place in a contiguous block of temporary | |
| 2575 // registers. Return the first temporary register corresponding to | |
| 2576 // the first argument. | |
| 2577 // | |
| 2578 // NB the caller may have already called | |
| 2579 // PrepareForConsecutiveAllocations() with args->length() + N. The | |
| 2580 // second call here will be a no-op provided there have been N or | |
| 2581 // less calls to NextConsecutiveRegister(). Otherwise, the arguments | |
| 2582 // here will be consecutive, but they will not be consecutive with | |
| 2583 // earlier consecutive allocations made by the caller. | |
| 2584 register_allocator()->PrepareForConsecutiveAllocations(args->length()); | |
| 2585 | |
| 2586 // Visit for first argument that goes into returned register | |
| 2587 Register first_arg = register_allocator()->NextConsecutiveRegister(); | |
| 2588 VisitForAccumulatorValue(args->at(0)); | |
| 2589 builder()->StoreAccumulatorInRegister(first_arg); | |
| 2590 | |
| 2591 // Visit remaining arguments | |
| 2592 for (int i = 1; i < static_cast<int>(args->length()); i++) { | |
| 2593 Register ith_arg = register_allocator()->NextConsecutiveRegister(); | |
| 2594 VisitForAccumulatorValue(args->at(i)); | |
| 2595 builder()->StoreAccumulatorInRegister(ith_arg); | |
| 2596 DCHECK(ith_arg.index() - i == first_arg.index()); | |
| 2597 } | |
| 2598 return first_arg; | |
| 2599 } | 2317 } |
| 2600 | 2318 |
| 2601 void BytecodeGenerator::VisitCall(Call* expr) { | 2319 void BytecodeGenerator::VisitCall(Call* expr) { |
| 2602 Expression* callee_expr = expr->expression(); | 2320 Expression* callee_expr = expr->expression(); |
| 2603 Call::CallType call_type = expr->GetCallType(); | 2321 Call::CallType call_type = expr->GetCallType(); |
| 2604 | 2322 |
| 2605 if (call_type == Call::SUPER_CALL) { | 2323 if (call_type == Call::SUPER_CALL) { |
| 2606 return VisitCallSuper(expr); | 2324 return VisitCallSuper(expr); |
| 2607 } | 2325 } |
| 2608 | 2326 |
| 2327 Register callee = register_allocator()->NewRegister(); |
| 2328 |
| 2329 // Add an argument register for the receiver. |
| 2330 RegisterList args = |
| 2331 register_allocator()->NewRegisterList(expr->arguments()->length() + 1); |
| 2332 Register receiver = args[0]; |
| 2333 |
| 2609 // Prepare the callee and the receiver to the function call. This depends on | 2334 // Prepare the callee and the receiver to the function call. This depends on |
| 2610 // the semantics of the underlying call type. | 2335 // the semantics of the underlying call type. |
| 2611 | |
| 2612 // The receiver and arguments need to be allocated consecutively for | |
| 2613 // Call(). We allocate the callee and receiver consecutively for calls to | |
| 2614 // %LoadLookupSlotForCall. Future optimizations could avoid this there are | |
| 2615 // no arguments or the receiver and arguments are already consecutive. | |
| 2616 ZoneList<Expression*>* args = expr->arguments(); | |
| 2617 register_allocator()->PrepareForConsecutiveAllocations(args->length() + 2); | |
| 2618 Register callee = register_allocator()->NextConsecutiveRegister(); | |
| 2619 Register receiver = register_allocator()->NextConsecutiveRegister(); | |
| 2620 | |
| 2621 switch (call_type) { | 2336 switch (call_type) { |
| 2622 case Call::NAMED_PROPERTY_CALL: | 2337 case Call::NAMED_PROPERTY_CALL: |
| 2623 case Call::KEYED_PROPERTY_CALL: { | 2338 case Call::KEYED_PROPERTY_CALL: { |
| 2624 Property* property = callee_expr->AsProperty(); | 2339 Property* property = callee_expr->AsProperty(); |
| 2625 VisitForAccumulatorValue(property->obj()); | 2340 VisitForAccumulatorValue(property->obj()); |
| 2626 builder()->StoreAccumulatorInRegister(receiver); | 2341 builder()->StoreAccumulatorInRegister(receiver); |
| 2627 VisitPropertyLoadForAccumulator(receiver, property); | 2342 VisitPropertyLoadForAccumulator(receiver, property); |
| 2628 builder()->StoreAccumulatorInRegister(callee); | 2343 builder()->StoreAccumulatorInRegister(callee); |
| 2629 break; | 2344 break; |
| 2630 } | 2345 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2643 if (callee_expr->AsVariableProxy()->var()->IsLookupSlot()) { | 2358 if (callee_expr->AsVariableProxy()->var()->IsLookupSlot()) { |
| 2644 RegisterAllocationScope inner_register_scope(this); | 2359 RegisterAllocationScope inner_register_scope(this); |
| 2645 Register name = register_allocator()->NewRegister(); | 2360 Register name = register_allocator()->NewRegister(); |
| 2646 | 2361 |
| 2647 // Call %LoadLookupSlotForCall to get the callee and receiver. | 2362 // Call %LoadLookupSlotForCall to get the callee and receiver. |
| 2648 DCHECK(Register::AreContiguous(callee, receiver)); | 2363 DCHECK(Register::AreContiguous(callee, receiver)); |
| 2649 Variable* variable = callee_expr->AsVariableProxy()->var(); | 2364 Variable* variable = callee_expr->AsVariableProxy()->var(); |
| 2650 builder() | 2365 builder() |
| 2651 ->LoadLiteral(variable->name()) | 2366 ->LoadLiteral(variable->name()) |
| 2652 .StoreAccumulatorInRegister(name) | 2367 .StoreAccumulatorInRegister(name) |
| 2653 .CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, name, 1, | 2368 .CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, name, callee); |
| 2654 callee); | |
| 2655 break; | 2369 break; |
| 2656 } | 2370 } |
| 2657 // Fall through. | 2371 // Fall through. |
| 2658 DCHECK_EQ(call_type, Call::POSSIBLY_EVAL_CALL); | 2372 DCHECK_EQ(call_type, Call::POSSIBLY_EVAL_CALL); |
| 2659 } | 2373 } |
| 2660 case Call::OTHER_CALL: { | 2374 case Call::OTHER_CALL: { |
| 2661 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); | 2375 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); |
| 2662 VisitForAccumulatorValue(callee_expr); | 2376 VisitForRegisterValue(callee_expr, callee); |
| 2663 builder()->StoreAccumulatorInRegister(callee); | |
| 2664 break; | 2377 break; |
| 2665 } | 2378 } |
| 2666 case Call::NAMED_SUPER_PROPERTY_CALL: { | 2379 case Call::NAMED_SUPER_PROPERTY_CALL: { |
| 2667 Property* property = callee_expr->AsProperty(); | 2380 Property* property = callee_expr->AsProperty(); |
| 2668 VisitNamedSuperPropertyLoad(property, receiver); | 2381 VisitNamedSuperPropertyLoad(property, receiver); |
| 2669 builder()->StoreAccumulatorInRegister(callee); | 2382 builder()->StoreAccumulatorInRegister(callee); |
| 2670 break; | 2383 break; |
| 2671 } | 2384 } |
| 2672 case Call::KEYED_SUPER_PROPERTY_CALL: { | 2385 case Call::KEYED_SUPER_PROPERTY_CALL: { |
| 2673 Property* property = callee_expr->AsProperty(); | 2386 Property* property = callee_expr->AsProperty(); |
| 2674 VisitKeyedSuperPropertyLoad(property, receiver); | 2387 VisitKeyedSuperPropertyLoad(property, receiver); |
| 2675 builder()->StoreAccumulatorInRegister(callee); | 2388 builder()->StoreAccumulatorInRegister(callee); |
| 2676 break; | 2389 break; |
| 2677 } | 2390 } |
| 2678 case Call::SUPER_CALL: | 2391 case Call::SUPER_CALL: |
| 2679 UNREACHABLE(); | 2392 UNREACHABLE(); |
| 2680 break; | 2393 break; |
| 2681 } | 2394 } |
| 2682 | 2395 |
| 2683 // Evaluate all arguments to the function call and store in sequential | 2396 // Evaluate all arguments to the function call and store in sequential args |
| 2684 // registers. | 2397 // registers. |
| 2685 Register arg = VisitArguments(args); | 2398 VisitArguments(expr->arguments(), args, 1); |
| 2686 CHECK(args->length() == 0 || arg.index() == receiver.index() + 1); | |
| 2687 | 2399 |
| 2688 // Resolve callee for a potential direct eval call. This block will mutate the | 2400 // Resolve callee for a potential direct eval call. This block will mutate the |
| 2689 // callee value. | 2401 // callee value. |
| 2690 if (call_type == Call::POSSIBLY_EVAL_CALL && args->length() > 0) { | 2402 if (call_type == Call::POSSIBLY_EVAL_CALL && |
| 2403 expr->arguments()->length() > 0) { |
| 2691 RegisterAllocationScope inner_register_scope(this); | 2404 RegisterAllocationScope inner_register_scope(this); |
| 2692 register_allocator()->PrepareForConsecutiveAllocations(6); | |
| 2693 Register callee_for_eval = register_allocator()->NextConsecutiveRegister(); | |
| 2694 Register source = register_allocator()->NextConsecutiveRegister(); | |
| 2695 Register function = register_allocator()->NextConsecutiveRegister(); | |
| 2696 Register language = register_allocator()->NextConsecutiveRegister(); | |
| 2697 Register eval_scope_position = | |
| 2698 register_allocator()->NextConsecutiveRegister(); | |
| 2699 Register eval_position = register_allocator()->NextConsecutiveRegister(); | |
| 2700 | |
| 2701 // Set up arguments for ResolvePossiblyDirectEval by copying callee, source | 2405 // Set up arguments for ResolvePossiblyDirectEval by copying callee, source |
| 2702 // strings and function closure, and loading language and | 2406 // strings and function closure, and loading language and |
| 2703 // position. | 2407 // position. |
| 2408 RegisterList runtime_call_args = register_allocator()->NewRegisterList(6); |
| 2704 builder() | 2409 builder() |
| 2705 ->MoveRegister(callee, callee_for_eval) | 2410 ->MoveRegister(callee, runtime_call_args[0]) |
| 2706 .MoveRegister(arg, source) | 2411 .MoveRegister(args[1], runtime_call_args[1]) |
| 2707 .MoveRegister(Register::function_closure(), function) | 2412 .MoveRegister(Register::function_closure(), runtime_call_args[2]) |
| 2708 .LoadLiteral(Smi::FromInt(language_mode())) | 2413 .LoadLiteral(Smi::FromInt(language_mode())) |
| 2709 .StoreAccumulatorInRegister(language) | 2414 .StoreAccumulatorInRegister(runtime_call_args[3]) |
| 2710 .LoadLiteral( | 2415 .LoadLiteral( |
| 2711 Smi::FromInt(execution_context()->scope()->start_position())) | 2416 Smi::FromInt(execution_context()->scope()->start_position())) |
| 2712 .StoreAccumulatorInRegister(eval_scope_position) | 2417 .StoreAccumulatorInRegister(runtime_call_args[4]) |
| 2713 .LoadLiteral(Smi::FromInt(expr->position())) | 2418 .LoadLiteral(Smi::FromInt(expr->position())) |
| 2714 .StoreAccumulatorInRegister(eval_position); | 2419 .StoreAccumulatorInRegister(runtime_call_args[5]); |
| 2715 | 2420 |
| 2716 // Call ResolvePossiblyDirectEval and modify the callee. | 2421 // Call ResolvePossiblyDirectEval and modify the callee. |
| 2717 builder() | 2422 builder() |
| 2718 ->CallRuntime(Runtime::kResolvePossiblyDirectEval, callee_for_eval, 6) | 2423 ->CallRuntime(Runtime::kResolvePossiblyDirectEval, runtime_call_args) |
| 2719 .StoreAccumulatorInRegister(callee); | 2424 .StoreAccumulatorInRegister(callee); |
| 2720 } | 2425 } |
| 2721 | 2426 |
| 2722 builder()->SetExpressionPosition(expr); | 2427 builder()->SetExpressionPosition(expr); |
| 2723 | 2428 |
| 2724 int feedback_slot_index; | 2429 int feedback_slot_index; |
| 2725 if (expr->CallFeedbackICSlot().IsInvalid()) { | 2430 if (expr->CallFeedbackICSlot().IsInvalid()) { |
| 2726 DCHECK(call_type == Call::POSSIBLY_EVAL_CALL); | 2431 DCHECK(call_type == Call::POSSIBLY_EVAL_CALL); |
| 2727 // Valid type feedback slots can only be greater than kReservedIndexCount. | 2432 // Valid type feedback slots can only be greater than kReservedIndexCount. |
| 2728 // We use 0 to indicate an invalid slot id. Statically assert that 0 cannot | 2433 // We use 0 to indicate an invalid slot id. Statically assert that 0 cannot |
| 2729 // be a valid slot id. | 2434 // be a valid slot id. |
| 2730 STATIC_ASSERT(TypeFeedbackVector::kReservedIndexCount > 0); | 2435 STATIC_ASSERT(TypeFeedbackVector::kReservedIndexCount > 0); |
| 2731 feedback_slot_index = 0; | 2436 feedback_slot_index = 0; |
| 2732 } else { | 2437 } else { |
| 2733 feedback_slot_index = feedback_index(expr->CallFeedbackICSlot()); | 2438 feedback_slot_index = feedback_index(expr->CallFeedbackICSlot()); |
| 2734 } | 2439 } |
| 2735 builder()->Call(callee, receiver, 1 + args->length(), feedback_slot_index, | 2440 builder()->Call(callee, args, feedback_slot_index, expr->tail_call_mode()); |
| 2736 expr->tail_call_mode()); | |
| 2737 execution_result()->SetResultInAccumulator(); | |
| 2738 } | 2441 } |
| 2739 | 2442 |
| 2740 void BytecodeGenerator::VisitCallSuper(Call* expr) { | 2443 void BytecodeGenerator::VisitCallSuper(Call* expr) { |
| 2741 RegisterAllocationScope register_scope(this); | 2444 RegisterAllocationScope register_scope(this); |
| 2742 SuperCallReference* super = expr->expression()->AsSuperCallReference(); | 2445 SuperCallReference* super = expr->expression()->AsSuperCallReference(); |
| 2743 | 2446 |
| 2744 // Prepare the constructor to the super call. | 2447 // Prepare the constructor to the super call. |
| 2745 Register this_function = register_allocator()->NewRegister(); | 2448 Register this_function = VisitForRegisterValue(super->this_function_var()); |
| 2746 VisitForAccumulatorValue(super->this_function_var()); | 2449 builder()->CallRuntime(Runtime::kInlineGetSuperConstructor, this_function); |
| 2747 builder() | |
| 2748 ->StoreAccumulatorInRegister(this_function) | |
| 2749 .CallRuntime(Runtime::kInlineGetSuperConstructor, this_function, 1); | |
| 2750 | 2450 |
| 2751 Register constructor = this_function; // Re-use dead this_function register. | 2451 Register constructor = this_function; // Re-use dead this_function register. |
| 2752 builder()->StoreAccumulatorInRegister(constructor); | 2452 builder()->StoreAccumulatorInRegister(constructor); |
| 2753 | 2453 |
| 2754 ZoneList<Expression*>* args = expr->arguments(); | 2454 RegisterList args = |
| 2755 Register first_arg = VisitArguments(args); | 2455 register_allocator()->NewRegisterList(expr->arguments()->length()); |
| 2456 VisitArguments(expr->arguments(), args); |
| 2756 | 2457 |
| 2757 // The new target is loaded into the accumulator from the | 2458 // The new target is loaded into the accumulator from the |
| 2758 // {new.target} variable. | 2459 // {new.target} variable. |
| 2759 VisitForAccumulatorValue(super->new_target_var()); | 2460 VisitForAccumulatorValue(super->new_target_var()); |
| 2760 | 2461 |
| 2761 // Call construct. | 2462 // Call construct. |
| 2762 builder()->SetExpressionPosition(expr); | 2463 builder()->SetExpressionPosition(expr); |
| 2763 // Valid type feedback slots can only be greater than kReservedIndexCount. | 2464 // Valid type feedback slots can only be greater than kReservedIndexCount. |
| 2764 // Assert that 0 cannot be valid a valid slot id. | 2465 // Assert that 0 cannot be valid a valid slot id. |
| 2765 STATIC_ASSERT(TypeFeedbackVector::kReservedIndexCount > 0); | 2466 STATIC_ASSERT(TypeFeedbackVector::kReservedIndexCount > 0); |
| 2766 // Type feedback is not necessary for super constructor calls. The type | 2467 // Type feedback is not necessary for super constructor calls. The type |
| 2767 // information can be inferred in most cases. Slot id 0 indicates type | 2468 // information can be inferred in most cases. Slot id 0 indicates type |
| 2768 // feedback is not required. | 2469 // feedback is not required. |
| 2769 builder()->New(constructor, first_arg, args->length(), 0); | 2470 builder()->New(constructor, args, 0); |
| 2770 execution_result()->SetResultInAccumulator(); | |
| 2771 } | 2471 } |
| 2772 | 2472 |
| 2773 void BytecodeGenerator::VisitCallNew(CallNew* expr) { | 2473 void BytecodeGenerator::VisitCallNew(CallNew* expr) { |
| 2774 Register constructor = register_allocator()->NewRegister(); | 2474 Register constructor = VisitForRegisterValue(expr->expression()); |
| 2775 VisitForAccumulatorValue(expr->expression()); | 2475 RegisterList args = |
| 2776 builder()->StoreAccumulatorInRegister(constructor); | 2476 register_allocator()->NewRegisterList(expr->arguments()->length()); |
| 2777 | 2477 VisitArguments(expr->arguments(), args); |
| 2778 ZoneList<Expression*>* args = expr->arguments(); | |
| 2779 Register first_arg = VisitArguments(args); | |
| 2780 | 2478 |
| 2781 builder()->SetExpressionPosition(expr); | 2479 builder()->SetExpressionPosition(expr); |
| 2782 // The accumulator holds new target which is the same as the | 2480 // The accumulator holds new target which is the same as the |
| 2783 // constructor for CallNew. | 2481 // constructor for CallNew. |
| 2784 builder() | 2482 builder() |
| 2785 ->LoadAccumulatorWithRegister(constructor) | 2483 ->LoadAccumulatorWithRegister(constructor) |
| 2786 .New(constructor, first_arg, args->length(), | 2484 .New(constructor, args, feedback_index(expr->CallNewFeedbackSlot())); |
| 2787 feedback_index(expr->CallNewFeedbackSlot())); | |
| 2788 execution_result()->SetResultInAccumulator(); | |
| 2789 } | 2485 } |
| 2790 | 2486 |
| 2791 void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) { | 2487 void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
| 2792 ZoneList<Expression*>* args = expr->arguments(); | |
| 2793 if (expr->is_jsruntime()) { | 2488 if (expr->is_jsruntime()) { |
| 2794 // Allocate a register for the receiver and load it with undefined. | 2489 // Allocate a register for the receiver and load it with undefined. |
| 2795 register_allocator()->PrepareForConsecutiveAllocations(1 + args->length()); | 2490 RegisterList args = |
| 2796 Register receiver = register_allocator()->NextConsecutiveRegister(); | 2491 register_allocator()->NewRegisterList(expr->arguments()->length() + 1); |
| 2492 Register receiver = args[0]; |
| 2797 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); | 2493 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); |
| 2798 Register first_arg = VisitArguments(args); | 2494 VisitArguments(expr->arguments(), args, 1); |
| 2799 CHECK(args->length() == 0 || first_arg.index() == receiver.index() + 1); | 2495 builder()->CallJSRuntime(expr->context_index(), args); |
| 2800 builder()->CallJSRuntime(expr->context_index(), receiver, | |
| 2801 1 + args->length()); | |
| 2802 } else { | 2496 } else { |
| 2803 // Evaluate all arguments to the runtime call. | 2497 // Evaluate all arguments to the runtime call. |
| 2804 Register first_arg = VisitArguments(args); | 2498 RegisterList args = |
| 2499 register_allocator()->NewRegisterList(expr->arguments()->length()); |
| 2500 VisitArguments(expr->arguments(), args); |
| 2805 Runtime::FunctionId function_id = expr->function()->function_id; | 2501 Runtime::FunctionId function_id = expr->function()->function_id; |
| 2806 builder()->CallRuntime(function_id, first_arg, args->length()); | 2502 builder()->CallRuntime(function_id, args); |
| 2807 } | 2503 } |
| 2808 execution_result()->SetResultInAccumulator(); | |
| 2809 } | 2504 } |
| 2810 | 2505 |
| 2811 void BytecodeGenerator::VisitVoid(UnaryOperation* expr) { | 2506 void BytecodeGenerator::VisitVoid(UnaryOperation* expr) { |
| 2812 VisitForEffect(expr->expression()); | 2507 VisitForEffect(expr->expression()); |
| 2813 builder()->LoadUndefined(); | 2508 builder()->LoadUndefined(); |
| 2814 execution_result()->SetResultInAccumulator(); | |
| 2815 } | 2509 } |
| 2816 | 2510 |
| 2817 void BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) { | 2511 void BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) { |
| 2818 if (expr->expression()->IsVariableProxy()) { | 2512 if (expr->expression()->IsVariableProxy()) { |
| 2819 // Typeof does not throw a reference error on global variables, hence we | 2513 // Typeof does not throw a reference error on global variables, hence we |
| 2820 // perform a non-contextual load in case the operand is a variable proxy. | 2514 // perform a non-contextual load in case the operand is a variable proxy. |
| 2821 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 2515 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 2822 VisitVariableLoadForAccumulatorValue( | 2516 VisitVariableLoadForAccumulatorValue( |
| 2823 proxy->var(), proxy->VariableFeedbackSlot(), INSIDE_TYPEOF); | 2517 proxy->var(), proxy->VariableFeedbackSlot(), INSIDE_TYPEOF); |
| 2824 } else { | 2518 } else { |
| 2825 VisitForAccumulatorValue(expr->expression()); | 2519 VisitForAccumulatorValue(expr->expression()); |
| 2826 } | 2520 } |
| 2827 builder()->TypeOf(); | 2521 builder()->TypeOf(); |
| 2828 execution_result()->SetResultInAccumulator(); | |
| 2829 } | 2522 } |
| 2830 | 2523 |
| 2831 void BytecodeGenerator::VisitNot(UnaryOperation* expr) { | 2524 void BytecodeGenerator::VisitNot(UnaryOperation* expr) { |
| 2832 if (execution_result()->IsEffect()) { | 2525 if (execution_result()->IsEffect()) { |
| 2833 VisitForEffect(expr->expression()); | 2526 VisitForEffect(expr->expression()); |
| 2834 } else if (execution_result()->IsTest()) { | 2527 } else if (execution_result()->IsTest()) { |
| 2835 TestResultScope* test_result = execution_result()->AsTest(); | 2528 TestResultScope* test_result = execution_result()->AsTest(); |
| 2836 // No actual logical negation happening, we just swap the control flow by | 2529 // No actual logical negation happening, we just swap the control flow by |
| 2837 // swapping the target labels and the fallthrough branch. | 2530 // swapping the target labels and the fallthrough branch. |
| 2838 VisitForTest(expr->expression(), test_result->else_labels(), | 2531 VisitForTest(expr->expression(), test_result->else_labels(), |
| 2839 test_result->then_labels(), | 2532 test_result->then_labels(), |
| 2840 test_result->inverted_fallthrough()); | 2533 test_result->inverted_fallthrough()); |
| 2841 test_result->SetResultConsumedByTest(); | 2534 test_result->SetResultConsumedByTest(); |
| 2842 } else { | 2535 } else { |
| 2843 VisitForAccumulatorValue(expr->expression()); | 2536 VisitForAccumulatorValue(expr->expression()); |
| 2844 builder()->LogicalNot(); | 2537 builder()->LogicalNot(); |
| 2845 execution_result()->SetResultInAccumulator(); | |
| 2846 } | 2538 } |
| 2847 } | 2539 } |
| 2848 | 2540 |
| 2849 void BytecodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 2541 void BytecodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
| 2850 switch (expr->op()) { | 2542 switch (expr->op()) { |
| 2851 case Token::Value::NOT: | 2543 case Token::Value::NOT: |
| 2852 VisitNot(expr); | 2544 VisitNot(expr); |
| 2853 break; | 2545 break; |
| 2854 case Token::Value::TYPEOF: | 2546 case Token::Value::TYPEOF: |
| 2855 VisitTypeOf(expr); | 2547 VisitTypeOf(expr); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2910 } else { | 2602 } else { |
| 2911 builder()->LoadFalse(); | 2603 builder()->LoadFalse(); |
| 2912 } | 2604 } |
| 2913 break; | 2605 break; |
| 2914 } | 2606 } |
| 2915 case VariableLocation::LOOKUP: { | 2607 case VariableLocation::LOOKUP: { |
| 2916 Register name_reg = register_allocator()->NewRegister(); | 2608 Register name_reg = register_allocator()->NewRegister(); |
| 2917 builder() | 2609 builder() |
| 2918 ->LoadLiteral(variable->name()) | 2610 ->LoadLiteral(variable->name()) |
| 2919 .StoreAccumulatorInRegister(name_reg) | 2611 .StoreAccumulatorInRegister(name_reg) |
| 2920 .CallRuntime(Runtime::kDeleteLookupSlot, name_reg, 1); | 2612 .CallRuntime(Runtime::kDeleteLookupSlot, name_reg); |
| 2921 break; | 2613 break; |
| 2922 } | 2614 } |
| 2923 default: | 2615 default: |
| 2924 UNREACHABLE(); | 2616 UNREACHABLE(); |
| 2925 } | 2617 } |
| 2926 } else { | 2618 } else { |
| 2927 // Delete of an unresolvable reference returns true. | 2619 // Delete of an unresolvable reference returns true. |
| 2928 VisitForEffect(expr->expression()); | 2620 VisitForEffect(expr->expression()); |
| 2929 builder()->LoadTrue(); | 2621 builder()->LoadTrue(); |
| 2930 } | 2622 } |
| 2931 execution_result()->SetResultInAccumulator(); | |
| 2932 } | 2623 } |
| 2933 | 2624 |
| 2934 void BytecodeGenerator::VisitCountOperation(CountOperation* expr) { | 2625 void BytecodeGenerator::VisitCountOperation(CountOperation* expr) { |
| 2935 DCHECK(expr->expression()->IsValidReferenceExpressionOrThis()); | 2626 DCHECK(expr->expression()->IsValidReferenceExpressionOrThis()); |
| 2936 | 2627 |
| 2937 // Left-hand side can only be a property, a global or a variable slot. | 2628 // Left-hand side can only be a property, a global or a variable slot. |
| 2938 Property* property = expr->expression()->AsProperty(); | 2629 Property* property = expr->expression()->AsProperty(); |
| 2939 LhsKind assign_type = Property::GetAssignType(property); | 2630 LhsKind assign_type = Property::GetAssignType(property); |
| 2940 | 2631 |
| 2941 bool is_postfix = expr->is_postfix() && !execution_result()->IsEffect(); | 2632 bool is_postfix = expr->is_postfix() && !execution_result()->IsEffect(); |
| 2942 | 2633 |
| 2943 // Evaluate LHS expression and get old value. | 2634 // Evaluate LHS expression and get old value. |
| 2944 Register object, home_object, key, old_value, value; | 2635 Register object, key, old_value; |
| 2636 RegisterList super_property_args; |
| 2945 Handle<String> name; | 2637 Handle<String> name; |
| 2946 switch (assign_type) { | 2638 switch (assign_type) { |
| 2947 case VARIABLE: { | 2639 case VARIABLE: { |
| 2948 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 2640 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 2949 VisitVariableLoadForAccumulatorValue(proxy->var(), | 2641 VisitVariableLoadForAccumulatorValue(proxy->var(), |
| 2950 proxy->VariableFeedbackSlot()); | 2642 proxy->VariableFeedbackSlot()); |
| 2951 break; | 2643 break; |
| 2952 } | 2644 } |
| 2953 case NAMED_PROPERTY: { | 2645 case NAMED_PROPERTY: { |
| 2954 FeedbackVectorSlot slot = property->PropertyFeedbackSlot(); | 2646 FeedbackVectorSlot slot = property->PropertyFeedbackSlot(); |
| 2955 object = VisitForRegisterValue(property->obj()); | 2647 object = VisitForRegisterValue(property->obj()); |
| 2956 name = property->key()->AsLiteral()->AsPropertyName(); | 2648 name = property->key()->AsLiteral()->AsPropertyName(); |
| 2957 builder()->LoadNamedProperty(object, name, feedback_index(slot)); | 2649 builder()->LoadNamedProperty(object, name, feedback_index(slot)); |
| 2958 break; | 2650 break; |
| 2959 } | 2651 } |
| 2960 case KEYED_PROPERTY: { | 2652 case KEYED_PROPERTY: { |
| 2961 FeedbackVectorSlot slot = property->PropertyFeedbackSlot(); | 2653 FeedbackVectorSlot slot = property->PropertyFeedbackSlot(); |
| 2962 object = VisitForRegisterValue(property->obj()); | 2654 object = VisitForRegisterValue(property->obj()); |
| 2963 // Use visit for accumulator here since we need the key in the accumulator | 2655 // Use visit for accumulator here since we need the key in the accumulator |
| 2964 // for the LoadKeyedProperty. | 2656 // for the LoadKeyedProperty. |
| 2965 key = register_allocator()->NewRegister(); | 2657 key = register_allocator()->NewRegister(); |
| 2966 VisitForAccumulatorValue(property->key()); | 2658 VisitForAccumulatorValue(property->key()); |
| 2967 builder()->StoreAccumulatorInRegister(key).LoadKeyedProperty( | 2659 builder()->StoreAccumulatorInRegister(key).LoadKeyedProperty( |
| 2968 object, feedback_index(slot)); | 2660 object, feedback_index(slot)); |
| 2969 break; | 2661 break; |
| 2970 } | 2662 } |
| 2971 case NAMED_SUPER_PROPERTY: { | 2663 case NAMED_SUPER_PROPERTY: { |
| 2972 register_allocator()->PrepareForConsecutiveAllocations(4); | 2664 super_property_args = register_allocator()->NewRegisterList(4); |
| 2973 object = register_allocator()->NextConsecutiveRegister(); | 2665 RegisterList load_super_args = super_property_args.Truncate(3); |
| 2974 home_object = register_allocator()->NextConsecutiveRegister(); | |
| 2975 key = register_allocator()->NextConsecutiveRegister(); | |
| 2976 value = register_allocator()->NextConsecutiveRegister(); | |
| 2977 SuperPropertyReference* super_property = | 2666 SuperPropertyReference* super_property = |
| 2978 property->obj()->AsSuperPropertyReference(); | 2667 property->obj()->AsSuperPropertyReference(); |
| 2979 VisitForRegisterValue(super_property->this_var(), object); | 2668 VisitForRegisterValue(super_property->this_var(), load_super_args[0]); |
| 2980 VisitForRegisterValue(super_property->home_object(), home_object); | 2669 VisitForRegisterValue(super_property->home_object(), load_super_args[1]); |
| 2981 builder() | 2670 builder() |
| 2982 ->LoadLiteral(property->key()->AsLiteral()->AsPropertyName()) | 2671 ->LoadLiteral(property->key()->AsLiteral()->AsPropertyName()) |
| 2983 .StoreAccumulatorInRegister(key); | 2672 .StoreAccumulatorInRegister(load_super_args[2]) |
| 2984 BuildNamedSuperPropertyLoad(object, home_object, key); | 2673 .CallRuntime(Runtime::kLoadFromSuper, load_super_args); |
| 2985 break; | 2674 break; |
| 2986 } | 2675 } |
| 2987 case KEYED_SUPER_PROPERTY: { | 2676 case KEYED_SUPER_PROPERTY: { |
| 2988 register_allocator()->PrepareForConsecutiveAllocations(4); | 2677 super_property_args = register_allocator()->NewRegisterList(4); |
| 2989 object = register_allocator()->NextConsecutiveRegister(); | 2678 RegisterList load_super_args = super_property_args.Truncate(3); |
| 2990 home_object = register_allocator()->NextConsecutiveRegister(); | |
| 2991 key = register_allocator()->NextConsecutiveRegister(); | |
| 2992 value = register_allocator()->NextConsecutiveRegister(); | |
| 2993 builder()->StoreAccumulatorInRegister(value); | |
| 2994 SuperPropertyReference* super_property = | 2679 SuperPropertyReference* super_property = |
| 2995 property->obj()->AsSuperPropertyReference(); | 2680 property->obj()->AsSuperPropertyReference(); |
| 2996 VisitForRegisterValue(super_property->this_var(), object); | 2681 VisitForRegisterValue(super_property->this_var(), load_super_args[0]); |
| 2997 VisitForRegisterValue(super_property->home_object(), home_object); | 2682 VisitForRegisterValue(super_property->home_object(), load_super_args[1]); |
| 2998 VisitForRegisterValue(property->key(), key); | 2683 VisitForRegisterValue(property->key(), load_super_args[2]); |
| 2999 BuildKeyedSuperPropertyLoad(object, home_object, key); | 2684 builder()->CallRuntime(Runtime::kLoadKeyedFromSuper, load_super_args); |
| 3000 break; | 2685 break; |
| 3001 } | 2686 } |
| 3002 } | 2687 } |
| 3003 | 2688 |
| 3004 // Save result for postfix expressions. | 2689 // Save result for postfix expressions. |
| 3005 if (is_postfix) { | 2690 if (is_postfix) { |
| 3006 old_value = register_allocator()->outer()->NewRegister(); | |
| 3007 | |
| 3008 // Convert old value into a number before saving it. | 2691 // Convert old value into a number before saving it. |
| 2692 old_value = register_allocator()->NewRegister(); |
| 3009 builder()->ConvertAccumulatorToNumber(old_value); | 2693 builder()->ConvertAccumulatorToNumber(old_value); |
| 3010 } | 2694 } |
| 3011 | 2695 |
| 3012 // Perform +1/-1 operation. | 2696 // Perform +1/-1 operation. |
| 3013 FeedbackVectorSlot slot = expr->CountBinaryOpFeedbackSlot(); | 2697 FeedbackVectorSlot slot = expr->CountBinaryOpFeedbackSlot(); |
| 3014 builder()->CountOperation(expr->binary_op(), feedback_index(slot)); | 2698 builder()->CountOperation(expr->binary_op(), feedback_index(slot)); |
| 3015 | 2699 |
| 3016 // Store the value. | 2700 // Store the value. |
| 3017 builder()->SetExpressionPosition(expr); | 2701 builder()->SetExpressionPosition(expr); |
| 3018 FeedbackVectorSlot feedback_slot = expr->CountSlot(); | 2702 FeedbackVectorSlot feedback_slot = expr->CountSlot(); |
| 3019 switch (assign_type) { | 2703 switch (assign_type) { |
| 3020 case VARIABLE: { | 2704 case VARIABLE: { |
| 3021 Variable* variable = expr->expression()->AsVariableProxy()->var(); | 2705 Variable* variable = expr->expression()->AsVariableProxy()->var(); |
| 3022 VisitVariableAssignment(variable, expr->op(), feedback_slot); | 2706 VisitVariableAssignment(variable, expr->op(), feedback_slot); |
| 3023 break; | 2707 break; |
| 3024 } | 2708 } |
| 3025 case NAMED_PROPERTY: { | 2709 case NAMED_PROPERTY: { |
| 3026 builder()->StoreNamedProperty(object, name, feedback_index(feedback_slot), | 2710 builder()->StoreNamedProperty(object, name, feedback_index(feedback_slot), |
| 3027 language_mode()); | 2711 language_mode()); |
| 3028 break; | 2712 break; |
| 3029 } | 2713 } |
| 3030 case KEYED_PROPERTY: { | 2714 case KEYED_PROPERTY: { |
| 3031 builder()->StoreKeyedProperty(object, key, feedback_index(feedback_slot), | 2715 builder()->StoreKeyedProperty(object, key, feedback_index(feedback_slot), |
| 3032 language_mode()); | 2716 language_mode()); |
| 3033 break; | 2717 break; |
| 3034 } | 2718 } |
| 3035 case NAMED_SUPER_PROPERTY: { | 2719 case NAMED_SUPER_PROPERTY: { |
| 3036 builder()->StoreAccumulatorInRegister(value); | 2720 builder() |
| 3037 BuildNamedSuperPropertyStore(object, home_object, key, value); | 2721 ->StoreAccumulatorInRegister(super_property_args[3]) |
| 2722 .CallRuntime(StoreToSuperRuntimeId(), super_property_args); |
| 3038 break; | 2723 break; |
| 3039 } | 2724 } |
| 3040 case KEYED_SUPER_PROPERTY: { | 2725 case KEYED_SUPER_PROPERTY: { |
| 3041 builder()->StoreAccumulatorInRegister(value); | 2726 builder() |
| 3042 BuildKeyedSuperPropertyStore(object, home_object, key, value); | 2727 ->StoreAccumulatorInRegister(super_property_args[3]) |
| 2728 .CallRuntime(StoreKeyedToSuperRuntimeId(), super_property_args); |
| 3043 break; | 2729 break; |
| 3044 } | 2730 } |
| 3045 } | 2731 } |
| 3046 | 2732 |
| 3047 // Restore old value for postfix expressions. | 2733 // Restore old value for postfix expressions. |
| 3048 if (is_postfix) { | 2734 if (is_postfix) { |
| 3049 execution_result()->SetResultInRegister(old_value); | 2735 builder()->LoadAccumulatorWithRegister(old_value); |
| 3050 } else { | |
| 3051 execution_result()->SetResultInAccumulator(); | |
| 3052 } | 2736 } |
| 3053 } | 2737 } |
| 3054 | 2738 |
| 3055 void BytecodeGenerator::VisitBinaryOperation(BinaryOperation* binop) { | 2739 void BytecodeGenerator::VisitBinaryOperation(BinaryOperation* binop) { |
| 3056 switch (binop->op()) { | 2740 switch (binop->op()) { |
| 3057 case Token::COMMA: | 2741 case Token::COMMA: |
| 3058 VisitCommaExpression(binop); | 2742 VisitCommaExpression(binop); |
| 3059 break; | 2743 break; |
| 3060 case Token::OR: | 2744 case Token::OR: |
| 3061 VisitLogicalOrExpression(binop); | 2745 VisitLogicalOrExpression(binop); |
| 3062 break; | 2746 break; |
| 3063 case Token::AND: | 2747 case Token::AND: |
| 3064 VisitLogicalAndExpression(binop); | 2748 VisitLogicalAndExpression(binop); |
| 3065 break; | 2749 break; |
| 3066 default: | 2750 default: |
| 3067 VisitArithmeticExpression(binop); | 2751 VisitArithmeticExpression(binop); |
| 3068 break; | 2752 break; |
| 3069 } | 2753 } |
| 3070 } | 2754 } |
| 3071 | 2755 |
| 3072 void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) { | 2756 void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) { |
| 3073 Register lhs = VisitForRegisterValue(expr->left()); | 2757 Register lhs = VisitForRegisterValue(expr->left()); |
| 3074 VisitForAccumulatorValue(expr->right()); | 2758 VisitForAccumulatorValue(expr->right()); |
| 3075 builder()->SetExpressionPosition(expr); | 2759 builder()->SetExpressionPosition(expr); |
| 3076 FeedbackVectorSlot slot = expr->CompareOperationFeedbackSlot(); | 2760 FeedbackVectorSlot slot = expr->CompareOperationFeedbackSlot(); |
| 3077 builder()->CompareOperation(expr->op(), lhs, feedback_index(slot)); | 2761 builder()->CompareOperation(expr->op(), lhs, feedback_index(slot)); |
| 3078 execution_result()->SetResultInAccumulator(); | |
| 3079 } | 2762 } |
| 3080 | 2763 |
| 3081 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) { | 2764 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) { |
| 3082 // TODO(rmcilroy): Special case "x * 1.0" and "x * -1" which are generated for | 2765 // TODO(rmcilroy): Special case "x * 1.0" and "x * -1" which are generated for |
| 3083 // +x and -x by the parser. | 2766 // +x and -x by the parser. |
| 3084 Register lhs = VisitForRegisterValue(expr->left()); | 2767 Register lhs = VisitForRegisterValue(expr->left()); |
| 3085 VisitForAccumulatorValue(expr->right()); | 2768 VisitForAccumulatorValue(expr->right()); |
| 3086 FeedbackVectorSlot slot = expr->BinaryOperationFeedbackSlot(); | 2769 FeedbackVectorSlot slot = expr->BinaryOperationFeedbackSlot(); |
| 3087 builder()->BinaryOperation(expr->op(), lhs, feedback_index(slot)); | 2770 builder()->BinaryOperation(expr->op(), lhs, feedback_index(slot)); |
| 3088 execution_result()->SetResultInAccumulator(); | |
| 3089 } | 2771 } |
| 3090 | 2772 |
| 3091 void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); } | 2773 void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); } |
| 3092 | 2774 |
| 3093 void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) { | 2775 void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) { |
| 3094 UNREACHABLE(); | 2776 UNREACHABLE(); |
| 3095 } | 2777 } |
| 3096 | 2778 |
| 3097 void BytecodeGenerator::VisitThisFunction(ThisFunction* expr) { | 2779 void BytecodeGenerator::VisitThisFunction(ThisFunction* expr) { |
| 3098 execution_result()->SetResultInRegister(Register::function_closure()); | 2780 builder()->LoadAccumulatorWithRegister(Register::function_closure()); |
| 3099 } | 2781 } |
| 3100 | 2782 |
| 3101 void BytecodeGenerator::VisitSuperCallReference(SuperCallReference* expr) { | 2783 void BytecodeGenerator::VisitSuperCallReference(SuperCallReference* expr) { |
| 3102 // Handled by VisitCall(). | 2784 // Handled by VisitCall(). |
| 3103 UNREACHABLE(); | 2785 UNREACHABLE(); |
| 3104 } | 2786 } |
| 3105 | 2787 |
| 3106 void BytecodeGenerator::VisitSuperPropertyReference( | 2788 void BytecodeGenerator::VisitSuperPropertyReference( |
| 3107 SuperPropertyReference* expr) { | 2789 SuperPropertyReference* expr) { |
| 3108 builder()->CallRuntime(Runtime::kThrowUnsupportedSuperError, Register(0), 0); | 2790 builder()->CallRuntime(Runtime::kThrowUnsupportedSuperError); |
| 3109 execution_result()->SetResultInAccumulator(); | |
| 3110 } | 2791 } |
| 3111 | 2792 |
| 3112 void BytecodeGenerator::VisitCommaExpression(BinaryOperation* binop) { | 2793 void BytecodeGenerator::VisitCommaExpression(BinaryOperation* binop) { |
| 3113 VisitForEffect(binop->left()); | 2794 VisitForEffect(binop->left()); |
| 3114 Visit(binop->right()); | 2795 Visit(binop->right()); |
| 3115 } | 2796 } |
| 3116 | 2797 |
| 3117 void BytecodeGenerator::VisitLogicalOrExpression(BinaryOperation* binop) { | 2798 void BytecodeGenerator::VisitLogicalOrExpression(BinaryOperation* binop) { |
| 3118 Expression* left = binop->left(); | 2799 Expression* left = binop->left(); |
| 3119 Expression* right = binop->right(); | 2800 Expression* right = binop->right(); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 3139 VisitForAccumulatorValue(left); | 2820 VisitForAccumulatorValue(left); |
| 3140 } else if (left->ToBooleanIsFalse()) { | 2821 } else if (left->ToBooleanIsFalse()) { |
| 3141 VisitForAccumulatorValue(right); | 2822 VisitForAccumulatorValue(right); |
| 3142 } else { | 2823 } else { |
| 3143 BytecodeLabel end_label; | 2824 BytecodeLabel end_label; |
| 3144 VisitForAccumulatorValue(left); | 2825 VisitForAccumulatorValue(left); |
| 3145 builder()->JumpIfTrue(&end_label); | 2826 builder()->JumpIfTrue(&end_label); |
| 3146 VisitForAccumulatorValue(right); | 2827 VisitForAccumulatorValue(right); |
| 3147 builder()->Bind(&end_label); | 2828 builder()->Bind(&end_label); |
| 3148 } | 2829 } |
| 3149 execution_result()->SetResultInAccumulator(); | |
| 3150 } | 2830 } |
| 3151 } | 2831 } |
| 3152 | 2832 |
| 3153 void BytecodeGenerator::VisitLogicalAndExpression(BinaryOperation* binop) { | 2833 void BytecodeGenerator::VisitLogicalAndExpression(BinaryOperation* binop) { |
| 3154 Expression* left = binop->left(); | 2834 Expression* left = binop->left(); |
| 3155 Expression* right = binop->right(); | 2835 Expression* right = binop->right(); |
| 3156 | 2836 |
| 3157 if (execution_result()->IsTest()) { | 2837 if (execution_result()->IsTest()) { |
| 3158 TestResultScope* test_result = execution_result()->AsTest(); | 2838 TestResultScope* test_result = execution_result()->AsTest(); |
| 3159 | 2839 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 3175 VisitForAccumulatorValue(left); | 2855 VisitForAccumulatorValue(left); |
| 3176 } else if (left->ToBooleanIsTrue()) { | 2856 } else if (left->ToBooleanIsTrue()) { |
| 3177 VisitForAccumulatorValue(right); | 2857 VisitForAccumulatorValue(right); |
| 3178 } else { | 2858 } else { |
| 3179 BytecodeLabel end_label; | 2859 BytecodeLabel end_label; |
| 3180 VisitForAccumulatorValue(left); | 2860 VisitForAccumulatorValue(left); |
| 3181 builder()->JumpIfFalse(&end_label); | 2861 builder()->JumpIfFalse(&end_label); |
| 3182 VisitForAccumulatorValue(right); | 2862 VisitForAccumulatorValue(right); |
| 3183 builder()->Bind(&end_label); | 2863 builder()->Bind(&end_label); |
| 3184 } | 2864 } |
| 3185 execution_result()->SetResultInAccumulator(); | |
| 3186 } | 2865 } |
| 3187 } | 2866 } |
| 3188 | 2867 |
| 3189 void BytecodeGenerator::VisitRewritableExpression(RewritableExpression* expr) { | 2868 void BytecodeGenerator::VisitRewritableExpression(RewritableExpression* expr) { |
| 3190 Visit(expr->expression()); | 2869 Visit(expr->expression()); |
| 3191 } | 2870 } |
| 3192 | 2871 |
| 3193 void BytecodeGenerator::BuildNewLocalActivationContext() { | 2872 void BytecodeGenerator::BuildNewLocalActivationContext() { |
| 3194 AccumulatorResultScope accumulator_execution_result(this); | 2873 ValueResultScope value_execution_result(this); |
| 3195 Scope* scope = this->scope(); | 2874 Scope* scope = this->scope(); |
| 3196 | 2875 |
| 3197 // Create the appropriate context. | 2876 // Create the appropriate context. |
| 3198 if (scope->is_script_scope()) { | 2877 if (scope->is_script_scope()) { |
| 3199 RegisterAllocationScope register_scope(this); | 2878 RegisterList args = register_allocator()->NewRegisterList(2); |
| 3200 register_allocator()->PrepareForConsecutiveAllocations(2); | |
| 3201 Register closure = register_allocator()->NextConsecutiveRegister(); | |
| 3202 Register scope_info = register_allocator()->NextConsecutiveRegister(); | |
| 3203 builder() | 2879 builder() |
| 3204 ->LoadAccumulatorWithRegister(Register::function_closure()) | 2880 ->LoadAccumulatorWithRegister(Register::function_closure()) |
| 3205 .StoreAccumulatorInRegister(closure) | 2881 .StoreAccumulatorInRegister(args[0]) |
| 3206 .LoadLiteral(scope->scope_info()) | 2882 .LoadLiteral(scope->scope_info()) |
| 3207 .StoreAccumulatorInRegister(scope_info) | 2883 .StoreAccumulatorInRegister(args[1]) |
| 3208 .CallRuntime(Runtime::kNewScriptContext, closure, 2); | 2884 .CallRuntime(Runtime::kNewScriptContext, args); |
| 3209 } else if (scope->is_module_scope()) { | 2885 } else if (scope->is_module_scope()) { |
| 3210 // We don't need to do anything for the outer script scope. | 2886 // We don't need to do anything for the outer script scope. |
| 3211 DCHECK(scope->outer_scope()->is_script_scope()); | 2887 DCHECK(scope->outer_scope()->is_script_scope()); |
| 3212 | 2888 |
| 3213 RegisterAllocationScope register_scope(this); | |
| 3214 register_allocator()->PrepareForConsecutiveAllocations(3); | |
| 3215 Register module = register_allocator()->NextConsecutiveRegister(); | |
| 3216 Register closure = register_allocator()->NextConsecutiveRegister(); | |
| 3217 Register scope_info = register_allocator()->NextConsecutiveRegister(); | |
| 3218 // A JSFunction representing a module is called with the module object as | 2889 // A JSFunction representing a module is called with the module object as |
| 3219 // its sole argument, which we pass on to PushModuleContext. | 2890 // its sole argument, which we pass on to PushModuleContext. |
| 2891 RegisterList args = register_allocator()->NewRegisterList(3); |
| 3220 builder() | 2892 builder() |
| 3221 ->MoveRegister(builder()->Parameter(1), module) | 2893 ->MoveRegister(builder()->Parameter(1), args[0]) |
| 3222 .LoadAccumulatorWithRegister(Register::function_closure()) | 2894 .LoadAccumulatorWithRegister(Register::function_closure()) |
| 3223 .StoreAccumulatorInRegister(closure) | 2895 .StoreAccumulatorInRegister(args[1]) |
| 3224 .LoadLiteral(scope->scope_info()) | 2896 .LoadLiteral(scope->scope_info()) |
| 3225 .StoreAccumulatorInRegister(scope_info) | 2897 .StoreAccumulatorInRegister(args[2]) |
| 3226 .CallRuntime(Runtime::kPushModuleContext, module, 3); | 2898 .CallRuntime(Runtime::kPushModuleContext, args); |
| 3227 } else { | 2899 } else { |
| 3228 int slot_count = scope->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 2900 int slot_count = scope->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
| 3229 builder()->CreateFunctionContext(slot_count); | 2901 builder()->CreateFunctionContext(slot_count); |
| 3230 } | 2902 } |
| 3231 execution_result()->SetResultInAccumulator(); | |
| 3232 } | 2903 } |
| 3233 | 2904 |
| 3234 void BytecodeGenerator::BuildLocalActivationContextInitialization() { | 2905 void BytecodeGenerator::BuildLocalActivationContextInitialization() { |
| 3235 DeclarationScope* scope = this->scope(); | 2906 DeclarationScope* scope = this->scope(); |
| 3236 | 2907 |
| 3237 if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) { | 2908 if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) { |
| 3238 Variable* variable = scope->receiver(); | 2909 Variable* variable = scope->receiver(); |
| 3239 Register receiver(builder()->Parameter(0)); | 2910 Register receiver(builder()->Parameter(0)); |
| 3240 // Context variable (at bottom of the context chain). | 2911 // Context variable (at bottom of the context chain). |
| 3241 DCHECK_EQ(0, scope->ContextChainLength(variable->scope())); | 2912 DCHECK_EQ(0, scope->ContextChainLength(variable->scope())); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 3253 // index -1 but is parameter index 0 in BytecodeArrayBuilder). | 2924 // index -1 but is parameter index 0 in BytecodeArrayBuilder). |
| 3254 Register parameter(builder()->Parameter(i + 1)); | 2925 Register parameter(builder()->Parameter(i + 1)); |
| 3255 // Context variable (at bottom of the context chain). | 2926 // Context variable (at bottom of the context chain). |
| 3256 DCHECK_EQ(0, scope->ContextChainLength(variable->scope())); | 2927 DCHECK_EQ(0, scope->ContextChainLength(variable->scope())); |
| 3257 builder()->LoadAccumulatorWithRegister(parameter).StoreContextSlot( | 2928 builder()->LoadAccumulatorWithRegister(parameter).StoreContextSlot( |
| 3258 execution_context()->reg(), variable->index(), 0); | 2929 execution_context()->reg(), variable->index(), 0); |
| 3259 } | 2930 } |
| 3260 } | 2931 } |
| 3261 | 2932 |
| 3262 void BytecodeGenerator::BuildNewLocalBlockContext(Scope* scope) { | 2933 void BytecodeGenerator::BuildNewLocalBlockContext(Scope* scope) { |
| 3263 AccumulatorResultScope accumulator_execution_result(this); | 2934 ValueResultScope value_execution_result(this); |
| 3264 DCHECK(scope->is_block_scope()); | 2935 DCHECK(scope->is_block_scope()); |
| 3265 | 2936 |
| 3266 VisitFunctionClosureForContext(); | 2937 VisitFunctionClosureForContext(); |
| 3267 builder()->CreateBlockContext(scope->scope_info()); | 2938 builder()->CreateBlockContext(scope->scope_info()); |
| 3268 execution_result()->SetResultInAccumulator(); | |
| 3269 } | 2939 } |
| 3270 | 2940 |
| 3271 void BytecodeGenerator::BuildNewLocalWithContext(Scope* scope) { | 2941 void BytecodeGenerator::BuildNewLocalWithContext(Scope* scope) { |
| 3272 AccumulatorResultScope accumulator_execution_result(this); | 2942 ValueResultScope value_execution_result(this); |
| 3273 | 2943 |
| 3274 Register extension_object = register_allocator()->NewRegister(); | 2944 Register extension_object = register_allocator()->NewRegister(); |
| 3275 | 2945 |
| 3276 builder()->ConvertAccumulatorToObject(extension_object); | 2946 builder()->ConvertAccumulatorToObject(extension_object); |
| 3277 VisitFunctionClosureForContext(); | 2947 VisitFunctionClosureForContext(); |
| 3278 builder()->CreateWithContext(extension_object, scope->scope_info()); | 2948 builder()->CreateWithContext(extension_object, scope->scope_info()); |
| 3279 execution_result()->SetResultInAccumulator(); | |
| 3280 } | 2949 } |
| 3281 | 2950 |
| 3282 void BytecodeGenerator::BuildNewLocalCatchContext(Variable* variable, | 2951 void BytecodeGenerator::BuildNewLocalCatchContext(Variable* variable, |
| 3283 Scope* scope) { | 2952 Scope* scope) { |
| 3284 AccumulatorResultScope accumulator_execution_result(this); | 2953 ValueResultScope value_execution_result(this); |
| 3285 DCHECK(variable->IsContextSlot()); | 2954 DCHECK(variable->IsContextSlot()); |
| 3286 | 2955 |
| 3287 Register exception = register_allocator()->NewRegister(); | 2956 Register exception = register_allocator()->NewRegister(); |
| 3288 builder()->StoreAccumulatorInRegister(exception); | 2957 builder()->StoreAccumulatorInRegister(exception); |
| 3289 VisitFunctionClosureForContext(); | 2958 VisitFunctionClosureForContext(); |
| 3290 builder()->CreateCatchContext(exception, variable->name(), | 2959 builder()->CreateCatchContext(exception, variable->name(), |
| 3291 scope->scope_info()); | 2960 scope->scope_info()); |
| 3292 execution_result()->SetResultInAccumulator(); | |
| 3293 } | 2961 } |
| 3294 | 2962 |
| 3295 void BytecodeGenerator::VisitObjectLiteralAccessor( | 2963 void BytecodeGenerator::VisitObjectLiteralAccessor( |
| 3296 Register home_object, ObjectLiteralProperty* property, Register value_out) { | 2964 Register home_object, ObjectLiteralProperty* property, Register value_out) { |
| 3297 // TODO(rmcilroy): Replace value_out with VisitForRegister(); | |
| 3298 if (property == nullptr) { | 2965 if (property == nullptr) { |
| 3299 builder()->LoadNull().StoreAccumulatorInRegister(value_out); | 2966 builder()->LoadNull().StoreAccumulatorInRegister(value_out); |
| 3300 } else { | 2967 } else { |
| 3301 VisitForAccumulatorValue(property->value()); | 2968 VisitForRegisterValue(property->value(), value_out); |
| 3302 builder()->StoreAccumulatorInRegister(value_out); | |
| 3303 VisitSetHomeObject(value_out, home_object, property); | 2969 VisitSetHomeObject(value_out, home_object, property); |
| 3304 } | 2970 } |
| 3305 } | 2971 } |
| 3306 | 2972 |
| 3307 void BytecodeGenerator::VisitSetHomeObject(Register value, Register home_object, | 2973 void BytecodeGenerator::VisitSetHomeObject(Register value, Register home_object, |
| 3308 LiteralProperty* property, | 2974 LiteralProperty* property, |
| 3309 int slot_number) { | 2975 int slot_number) { |
| 3310 Expression* expr = property->value(); | 2976 Expression* expr = property->value(); |
| 3311 if (FunctionLiteral::NeedsHomeObject(expr)) { | 2977 if (FunctionLiteral::NeedsHomeObject(expr)) { |
| 3312 FeedbackVectorSlot slot = property->GetSlot(slot_number); | 2978 FeedbackVectorSlot slot = property->GetSlot(slot_number); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3360 | 3026 |
| 3361 // TODO(mstarzinger): The <new.target> register is not set by the deoptimizer | 3027 // TODO(mstarzinger): The <new.target> register is not set by the deoptimizer |
| 3362 // and we need to make sure {BytecodeRegisterOptimizer} flushes its state | 3028 // and we need to make sure {BytecodeRegisterOptimizer} flushes its state |
| 3363 // before a local variable containing the <new.target> is used. Using a label | 3029 // before a local variable containing the <new.target> is used. Using a label |
| 3364 // as below flushes the entire pipeline, we should be more specific here. | 3030 // as below flushes the entire pipeline, we should be more specific here. |
| 3365 BytecodeLabel flush_state_label; | 3031 BytecodeLabel flush_state_label; |
| 3366 builder()->Bind(&flush_state_label); | 3032 builder()->Bind(&flush_state_label); |
| 3367 } | 3033 } |
| 3368 | 3034 |
| 3369 void BytecodeGenerator::VisitFunctionClosureForContext() { | 3035 void BytecodeGenerator::VisitFunctionClosureForContext() { |
| 3370 AccumulatorResultScope accumulator_execution_result(this); | 3036 ValueResultScope value_execution_result(this); |
| 3371 DeclarationScope* closure_scope = | 3037 DeclarationScope* closure_scope = |
| 3372 execution_context()->scope()->GetClosureScope(); | 3038 execution_context()->scope()->GetClosureScope(); |
| 3373 if (closure_scope->is_script_scope()) { | 3039 if (closure_scope->is_script_scope()) { |
| 3374 // Contexts nested in the native context have a canonical empty function as | 3040 // Contexts nested in the native context have a canonical empty function as |
| 3375 // their closure, not the anonymous closure containing the global code. | 3041 // their closure, not the anonymous closure containing the global code. |
| 3376 Register native_context = register_allocator()->NewRegister(); | 3042 Register native_context = register_allocator()->NewRegister(); |
| 3377 builder() | 3043 builder() |
| 3378 ->LoadContextSlot(execution_context()->reg(), | 3044 ->LoadContextSlot(execution_context()->reg(), |
| 3379 Context::NATIVE_CONTEXT_INDEX, 0) | 3045 Context::NATIVE_CONTEXT_INDEX, 0) |
| 3380 .StoreAccumulatorInRegister(native_context) | 3046 .StoreAccumulatorInRegister(native_context) |
| 3381 .LoadContextSlot(native_context, Context::CLOSURE_INDEX, 0); | 3047 .LoadContextSlot(native_context, Context::CLOSURE_INDEX, 0); |
| 3382 } else if (closure_scope->is_eval_scope()) { | 3048 } else if (closure_scope->is_eval_scope()) { |
| 3383 // Contexts created by a call to eval have the same closure as the | 3049 // Contexts created by a call to eval have the same closure as the |
| 3384 // context calling eval, not the anonymous closure containing the eval | 3050 // context calling eval, not the anonymous closure containing the eval |
| 3385 // code. Fetch it from the context. | 3051 // code. Fetch it from the context. |
| 3386 builder()->LoadContextSlot(execution_context()->reg(), | 3052 builder()->LoadContextSlot(execution_context()->reg(), |
| 3387 Context::CLOSURE_INDEX, 0); | 3053 Context::CLOSURE_INDEX, 0); |
| 3388 } else { | 3054 } else { |
| 3389 DCHECK(closure_scope->is_function_scope() || | 3055 DCHECK(closure_scope->is_function_scope() || |
| 3390 closure_scope->is_module_scope()); | 3056 closure_scope->is_module_scope()); |
| 3391 builder()->LoadAccumulatorWithRegister(Register::function_closure()); | 3057 builder()->LoadAccumulatorWithRegister(Register::function_closure()); |
| 3392 } | 3058 } |
| 3393 execution_result()->SetResultInAccumulator(); | |
| 3394 } | 3059 } |
| 3395 | 3060 |
| 3396 // Visits the expression |expr| and places the result in the accumulator. | 3061 // Visits the expression |expr| and places the result in the accumulator. |
| 3397 void BytecodeGenerator::VisitForAccumulatorValue(Expression* expr) { | 3062 void BytecodeGenerator::VisitForAccumulatorValue(Expression* expr) { |
| 3398 AccumulatorResultScope accumulator_scope(this); | 3063 ValueResultScope accumulator_scope(this); |
| 3399 Visit(expr); | 3064 Visit(expr); |
| 3400 } | 3065 } |
| 3401 | 3066 |
| 3402 void BytecodeGenerator::VisitForAccumulatorValueOrTheHole(Expression* expr) { | 3067 void BytecodeGenerator::VisitForAccumulatorValueOrTheHole(Expression* expr) { |
| 3403 if (expr == nullptr) { | 3068 if (expr == nullptr) { |
| 3404 builder()->LoadTheHole(); | 3069 builder()->LoadTheHole(); |
| 3405 } else { | 3070 } else { |
| 3406 VisitForAccumulatorValue(expr); | 3071 VisitForAccumulatorValue(expr); |
| 3407 } | 3072 } |
| 3408 } | 3073 } |
| 3409 | 3074 |
| 3410 // Visits the expression |expr| and discards the result. | 3075 // Visits the expression |expr| and discards the result. |
| 3411 void BytecodeGenerator::VisitForEffect(Expression* expr) { | 3076 void BytecodeGenerator::VisitForEffect(Expression* expr) { |
| 3412 EffectResultScope effect_scope(this); | 3077 EffectResultScope effect_scope(this); |
| 3413 Visit(expr); | 3078 Visit(expr); |
| 3414 } | 3079 } |
| 3415 | 3080 |
| 3416 // Visits the expression |expr| and returns the register containing | 3081 // Visits the expression |expr| and returns the register containing |
| 3417 // the expression result. | 3082 // the expression result. |
| 3418 Register BytecodeGenerator::VisitForRegisterValue(Expression* expr) { | 3083 Register BytecodeGenerator::VisitForRegisterValue(Expression* expr) { |
| 3419 RegisterResultScope register_scope(this); | 3084 VisitForAccumulatorValue(expr); |
| 3420 Visit(expr); | 3085 Register result = register_allocator()->NewRegister(); |
| 3421 return register_scope.ResultRegister(); | 3086 builder()->StoreAccumulatorInRegister(result); |
| 3087 return result; |
| 3422 } | 3088 } |
| 3423 | 3089 |
| 3424 // Visits the expression |expr| and stores the expression result in | 3090 // Visits the expression |expr| and stores the expression result in |
| 3425 // |destination|. | 3091 // |destination|. |
| 3426 void BytecodeGenerator::VisitForRegisterValue(Expression* expr, | 3092 void BytecodeGenerator::VisitForRegisterValue(Expression* expr, |
| 3427 Register destination) { | 3093 Register destination) { |
| 3428 AccumulatorResultScope register_scope(this); | 3094 ValueResultScope register_scope(this); |
| 3429 Visit(expr); | 3095 Visit(expr); |
| 3430 builder()->StoreAccumulatorInRegister(destination); | 3096 builder()->StoreAccumulatorInRegister(destination); |
| 3431 } | 3097 } |
| 3432 | 3098 |
| 3433 // Visits the expression |expr| for testing its boolean value and jumping to the | 3099 // Visits the expression |expr| for testing its boolean value and jumping to the |
| 3434 // |then| or |other| label depending on value and short-circuit semantics | 3100 // |then| or |other| label depending on value and short-circuit semantics |
| 3435 void BytecodeGenerator::VisitForTest(Expression* expr, | 3101 void BytecodeGenerator::VisitForTest(Expression* expr, |
| 3436 BytecodeLabels* then_labels, | 3102 BytecodeLabels* then_labels, |
| 3437 BytecodeLabels* else_labels, | 3103 BytecodeLabels* else_labels, |
| 3438 TestFallthrough fallthrough) { | 3104 TestFallthrough fallthrough) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 3467 } | 3133 } |
| 3468 | 3134 |
| 3469 LanguageMode BytecodeGenerator::language_mode() const { | 3135 LanguageMode BytecodeGenerator::language_mode() const { |
| 3470 return execution_context()->scope()->language_mode(); | 3136 return execution_context()->scope()->language_mode(); |
| 3471 } | 3137 } |
| 3472 | 3138 |
| 3473 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 3139 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
| 3474 return TypeFeedbackVector::GetIndex(slot); | 3140 return TypeFeedbackVector::GetIndex(slot); |
| 3475 } | 3141 } |
| 3476 | 3142 |
| 3143 Runtime::FunctionId BytecodeGenerator::StoreToSuperRuntimeId() { |
| 3144 return is_strict(language_mode()) ? Runtime::kStoreToSuper_Strict |
| 3145 : Runtime::kStoreToSuper_Sloppy; |
| 3146 } |
| 3147 |
| 3148 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() { |
| 3149 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict |
| 3150 : Runtime::kStoreKeyedToSuper_Sloppy; |
| 3151 } |
| 3152 |
| 3477 } // namespace interpreter | 3153 } // namespace interpreter |
| 3478 } // namespace internal | 3154 } // namespace internal |
| 3479 } // namespace v8 | 3155 } // namespace v8 |
| OLD | NEW |