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