Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(229)

Side by Side Diff: src/x64/full-codegen-x64.cc

Issue 7671042: Temporal dead zone behaviour for let bindings. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Bailout in hydrogen and X64 and ARM code. Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 653 matching lines...) Expand 10 before | Expand all | Expand 10 after
664 FunctionLiteral* function) { 664 FunctionLiteral* function) {
665 Comment cmnt(masm_, "[ Declaration"); 665 Comment cmnt(masm_, "[ Declaration");
666 ASSERT(variable != NULL); // Must have been resolved. 666 ASSERT(variable != NULL); // Must have been resolved.
667 Slot* slot = variable->AsSlot(); 667 Slot* slot = variable->AsSlot();
668 Property* prop = variable->AsProperty(); 668 Property* prop = variable->AsProperty();
669 669
670 if (slot != NULL) { 670 if (slot != NULL) {
671 switch (slot->type()) { 671 switch (slot->type()) {
672 case Slot::PARAMETER: 672 case Slot::PARAMETER:
673 case Slot::LOCAL: 673 case Slot::LOCAL:
674 if (mode == Variable::CONST) { 674 if (function != NULL) {
675 VisitForAccumulatorValue(function);
676 __ movq(Operand(rbp, SlotOffset(slot)), result_register());
677 } else if (mode == Variable::CONST || mode == Variable::LET) {
675 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); 678 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
676 __ movq(Operand(rbp, SlotOffset(slot)), kScratchRegister); 679 __ movq(Operand(rbp, SlotOffset(slot)), kScratchRegister);
677 } else if (function != NULL) {
678 VisitForAccumulatorValue(function);
679 __ movq(Operand(rbp, SlotOffset(slot)), result_register());
680 } 680 }
681 break; 681 break;
682 682
683 case Slot::CONTEXT: 683 case Slot::CONTEXT:
684 // We bypass the general EmitSlotSearch because we know more about 684 // We bypass the general EmitSlotSearch because we know more about
685 // this specific context. 685 // this specific context.
686 686
687 // The variable in the decl always resides in the current function 687 // The variable in the decl always resides in the current function
688 // context. 688 // context.
689 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); 689 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
690 if (FLAG_debug_code) { 690 if (FLAG_debug_code) {
691 // Check that we're not inside a with or catch context. 691 // Check that we're not inside a with or catch context.
692 __ movq(rbx, FieldOperand(rsi, HeapObject::kMapOffset)); 692 __ movq(rbx, FieldOperand(rsi, HeapObject::kMapOffset));
693 __ CompareRoot(rbx, Heap::kWithContextMapRootIndex); 693 __ CompareRoot(rbx, Heap::kWithContextMapRootIndex);
694 __ Check(not_equal, "Declaration in with context."); 694 __ Check(not_equal, "Declaration in with context.");
695 __ CompareRoot(rbx, Heap::kCatchContextMapRootIndex); 695 __ CompareRoot(rbx, Heap::kCatchContextMapRootIndex);
696 __ Check(not_equal, "Declaration in catch context."); 696 __ Check(not_equal, "Declaration in catch context.");
697 } 697 }
698 if (mode == Variable::CONST) { 698 if (function != NULL) {
699 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
700 __ movq(ContextOperand(rsi, slot->index()), kScratchRegister);
701 // No write barrier since the hole value is in old space.
702 } else if (function != NULL) {
703 VisitForAccumulatorValue(function); 699 VisitForAccumulatorValue(function);
704 __ movq(ContextOperand(rsi, slot->index()), result_register()); 700 __ movq(ContextOperand(rsi, slot->index()), result_register());
705 int offset = Context::SlotOffset(slot->index()); 701 int offset = Context::SlotOffset(slot->index());
706 __ movq(rbx, rsi); 702 __ movq(rbx, rsi);
707 __ RecordWrite(rbx, offset, result_register(), rcx); 703 __ RecordWrite(rbx, offset, result_register(), rcx);
704 } else if (mode == Variable::CONST || mode == Variable::LET) {
705 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
706 __ movq(ContextOperand(rsi, slot->index()), kScratchRegister);
707 // No write barrier since the hole value is in old space.
708 } 708 }
709 break; 709 break;
710 710
711 case Slot::LOOKUP: { 711 case Slot::LOOKUP: {
712 __ push(rsi); 712 __ push(rsi);
713 __ Push(variable->name()); 713 __ Push(variable->name());
714 // Declaration nodes are always introduced in one of two modes. 714 // Declaration nodes are always introduced in one of two modes.
715 ASSERT(mode == Variable::VAR || 715 ASSERT(mode == Variable::VAR ||
716 mode == Variable::CONST || 716 mode == Variable::CONST ||
717 mode == Variable::LET); 717 mode == Variable::LET);
718 PropertyAttributes attr = (mode == Variable::CONST) ? READ_ONLY : NONE; 718 PropertyAttributes attr = (mode == Variable::CONST) ? READ_ONLY : NONE;
719 __ Push(Smi::FromInt(attr)); 719 __ Push(Smi::FromInt(attr));
720 // Push initial value, if any. 720 // Push initial value, if any.
721 // Note: For variables we must not push an initial value (such as 721 // Note: For variables we must not push an initial value (such as
722 // 'undefined') because we may have a (legal) redeclaration and we 722 // 'undefined') because we may have a (legal) redeclaration and we
723 // must not destroy the current value. 723 // must not destroy the current value.
724 if (mode == Variable::CONST) { 724 if (function != NULL) {
725 VisitForStackValue(function);
726 } else if (mode == Variable::CONST || mode == Variable::LET) {
725 __ PushRoot(Heap::kTheHoleValueRootIndex); 727 __ PushRoot(Heap::kTheHoleValueRootIndex);
726 } else if (function != NULL) {
727 VisitForStackValue(function);
728 } else { 728 } else {
729 __ Push(Smi::FromInt(0)); // no initial value! 729 __ Push(Smi::FromInt(0)); // no initial value!
730 } 730 }
731 __ CallRuntime(Runtime::kDeclareContextSlot, 4); 731 __ CallRuntime(Runtime::kDeclareContextSlot, 4);
732 break; 732 break;
733 } 733 }
734 } 734 }
735 735
736 } else if (prop != NULL) { 736 } else if (prop != NULL) {
737 // A const declaration aliasing a parameter is an illegal redeclaration. 737 // A const declaration aliasing a parameter is an illegal redeclaration.
(...skipping 530 matching lines...) Expand 10 before | Expand all | Expand 10 after
1268 // Constants may be the hole value if they have not been initialized. 1268 // Constants may be the hole value if they have not been initialized.
1269 // Unhole them. 1269 // Unhole them.
1270 Label done; 1270 Label done;
1271 MemOperand slot_operand = EmitSlotSearch(slot, rax); 1271 MemOperand slot_operand = EmitSlotSearch(slot, rax);
1272 __ movq(rax, slot_operand); 1272 __ movq(rax, slot_operand);
1273 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); 1273 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
1274 __ j(not_equal, &done, Label::kNear); 1274 __ j(not_equal, &done, Label::kNear);
1275 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 1275 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
1276 __ bind(&done); 1276 __ bind(&done);
1277 context()->Plug(rax); 1277 context()->Plug(rax);
1278 } else if (var->mode() == Variable::LET) {
1279 // Let bindings may be the hole value if they have not been initialized.
1280 // Throw a type error in this case.
1281 Label done;
1282 MemOperand slot_operand = EmitSlotSearch(slot, rax);
1283 __ movq(rax, slot_operand);
1284 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
1285 __ j(not_equal, &done, Label::kNear);
1286 __ Push(var->name());
1287 __ CallRuntime(Runtime::kThrowReferenceError, 1);
1288 __ bind(&done);
1289 context()->Plug(rax);
1278 } else { 1290 } else {
1279 context()->Plug(slot); 1291 context()->Plug(slot);
1280 } 1292 }
1281 } 1293 }
1282 } 1294 }
1283 1295
1284 1296
1285 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { 1297 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
1286 Comment cmnt(masm_, "[ RegExpLiteral"); 1298 Comment cmnt(masm_, "[ RegExpLiteral");
1287 Label materialized; 1299 Label materialized;
(...skipping 509 matching lines...) Expand 10 before | Expand all | Expand 10 after
1797 case Slot::CONTEXT: 1809 case Slot::CONTEXT:
1798 case Slot::LOOKUP: 1810 case Slot::LOOKUP:
1799 __ push(rax); 1811 __ push(rax);
1800 __ push(rsi); 1812 __ push(rsi);
1801 __ Push(var->name()); 1813 __ Push(var->name());
1802 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); 1814 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
1803 break; 1815 break;
1804 } 1816 }
1805 __ bind(&skip); 1817 __ bind(&skip);
1806 1818
1819 } else if (var->mode() == Variable::LET && op != Token::INIT_LET) {
1820 // Perform the assignment for non-const variables. Const assignments
1821 // are simply skipped.
1822 Slot* slot = var->AsSlot();
1823 switch (slot->type()) {
1824 case Slot::PARAMETER:
1825 case Slot::LOCAL: {
1826 Label assign;
1827 // Check for an initialized let binding.
1828 __ movq(rdx, Operand(rbp, SlotOffset(slot)));
1829 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
1830 __ j(not_equal, &assign);
1831 __ Push(var->name());
1832 __ CallRuntime(Runtime::kThrowReferenceError, 1);
1833 // Perform the assignment.
1834 __ bind(&assign);
1835 __ movq(Operand(rbp, SlotOffset(slot)), rax);
1836 break;
1837 }
1838
1839 case Slot::CONTEXT: {
1840 // Let variables may be the hole value if they have not been
1841 // initialized. Throw a type error in this case.
1842 Label assign;
1843 MemOperand target = EmitSlotSearch(slot, rcx);
1844 // Check for an initialized let binding.
1845 __ movq(rdx, target);
1846 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
1847 __ j(not_equal, &assign, Label::kNear);
1848 __ Push(var->name());
1849 __ CallRuntime(Runtime::kThrowReferenceError, 1);
1850 // Perform the assignment.
1851 __ bind(&assign);
1852 __ movq(target, rax);
1853 // The value of the assignment is in eax. RecordWrite clobbers its
1854 // register arguments.
1855 __ movq(rdx, rax);
1856 int offset = Context::SlotOffset(slot->index());
1857 __ RecordWrite(rcx, offset, rdx, rbx);
1858 break;
1859 }
1860
1861 case Slot::LOOKUP:
1862 // Call the runtime for the assignment.
1863 __ push(rax); // Value.
1864 __ push(rsi); // Context.
1865 __ Push(var->name());
1866 __ Push(Smi::FromInt(strict_mode_flag()));
1867 __ CallRuntime(Runtime::kStoreContextSlot, 4);
1868 break;
1869 }
1807 } else if (var->mode() != Variable::CONST) { 1870 } else if (var->mode() != Variable::CONST) {
1808 // Perform the assignment for non-const variables. Const assignments 1871 // Perform the assignment for non-const variables. Const assignments
1809 // are simply skipped. 1872 // are simply skipped.
1810 Slot* slot = var->AsSlot(); 1873 Slot* slot = var->AsSlot();
1811 switch (slot->type()) { 1874 switch (slot->type()) {
1812 case Slot::PARAMETER: 1875 case Slot::PARAMETER:
1813 case Slot::LOCAL: 1876 case Slot::LOCAL:
1814 // Perform the assignment. 1877 // Perform the assignment.
1815 __ movq(Operand(rbp, SlotOffset(slot)), rax); 1878 __ movq(Operand(rbp, SlotOffset(slot)), rax);
1816 break; 1879 break;
(...skipping 2420 matching lines...) Expand 10 before | Expand all | Expand 10 after
4237 __ jmp(rdx); 4300 __ jmp(rdx);
4238 } 4301 }
4239 4302
4240 4303
4241 #undef __ 4304 #undef __
4242 4305
4243 4306
4244 } } // namespace v8::internal 4307 } } // namespace v8::internal
4245 4308
4246 #endif // V8_TARGET_ARCH_X64 4309 #endif // V8_TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698