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