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