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

Side by Side Diff: src/arm/full-codegen-arm.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
« no previous file with comments | « no previous file | src/contexts.h » ('j') | test/mjsunit/harmony/block-let-crankshaft.js » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 682 matching lines...) Expand 10 before | Expand all | Expand 10 after
693 FunctionLiteral* function) { 693 FunctionLiteral* function) {
694 Comment cmnt(masm_, "[ Declaration"); 694 Comment cmnt(masm_, "[ Declaration");
695 ASSERT(variable != NULL); // Must have been resolved. 695 ASSERT(variable != NULL); // Must have been resolved.
696 Slot* slot = variable->AsSlot(); 696 Slot* slot = variable->AsSlot();
697 Property* prop = variable->AsProperty(); 697 Property* prop = variable->AsProperty();
698 698
699 if (slot != NULL) { 699 if (slot != NULL) {
700 switch (slot->type()) { 700 switch (slot->type()) {
701 case Slot::PARAMETER: 701 case Slot::PARAMETER:
702 case Slot::LOCAL: 702 case Slot::LOCAL:
703 if (mode == Variable::CONST) { 703 if (function != NULL) {
704 VisitForAccumulatorValue(function);
705 __ str(result_register(), MemOperand(fp, SlotOffset(slot)));
706 } else if (mode == Variable::CONST || mode == Variable::LET) {
704 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 707 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
705 __ str(ip, MemOperand(fp, SlotOffset(slot))); 708 __ str(ip, MemOperand(fp, SlotOffset(slot)));
706 } else if (function != NULL) {
707 VisitForAccumulatorValue(function);
708 __ str(result_register(), MemOperand(fp, SlotOffset(slot)));
709 } 709 }
710 break; 710 break;
711 711
712 case Slot::CONTEXT: 712 case Slot::CONTEXT:
713 // We bypass the general EmitSlotSearch because we know more about 713 // We bypass the general EmitSlotSearch because we know more about
714 // this specific context. 714 // this specific context.
715 715
716 // The variable in the decl always resides in the current function 716 // The variable in the decl always resides in the current function
717 // context. 717 // context.
718 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); 718 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
719 if (FLAG_debug_code) { 719 if (FLAG_debug_code) {
720 // Check that we're not inside a with or catch context. 720 // Check that we're not inside a with or catch context.
721 __ ldr(r1, FieldMemOperand(cp, HeapObject::kMapOffset)); 721 __ ldr(r1, FieldMemOperand(cp, HeapObject::kMapOffset));
722 __ CompareRoot(r1, Heap::kWithContextMapRootIndex); 722 __ CompareRoot(r1, Heap::kWithContextMapRootIndex);
723 __ Check(ne, "Declaration in with context."); 723 __ Check(ne, "Declaration in with context.");
724 __ CompareRoot(r1, Heap::kCatchContextMapRootIndex); 724 __ CompareRoot(r1, Heap::kCatchContextMapRootIndex);
725 __ Check(ne, "Declaration in catch context."); 725 __ Check(ne, "Declaration in catch context.");
726 } 726 }
727 if (mode == Variable::CONST) { 727 if (function != NULL) {
728 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
729 __ str(ip, ContextOperand(cp, slot->index()));
730 // No write barrier since the_hole_value is in old space.
731 } else if (function != NULL) {
732 VisitForAccumulatorValue(function); 728 VisitForAccumulatorValue(function);
733 __ str(result_register(), ContextOperand(cp, slot->index())); 729 __ str(result_register(), ContextOperand(cp, slot->index()));
734 int offset = Context::SlotOffset(slot->index()); 730 int offset = Context::SlotOffset(slot->index());
735 // We know that we have written a function, which is not a smi. 731 // We know that we have written a function, which is not a smi.
736 __ mov(r1, Operand(cp)); 732 __ mov(r1, Operand(cp));
737 __ RecordWrite(r1, Operand(offset), r2, result_register()); 733 __ RecordWrite(r1, Operand(offset), r2, result_register());
734 } else if (mode == Variable::CONST || mode == Variable::LET) {
735 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
736 __ str(ip, ContextOperand(cp, slot->index()));
737 // No write barrier since the_hole_value is in old space.
738 } 738 }
739 break; 739 break;
740
741 case Slot::LOOKUP: { 740 case Slot::LOOKUP: {
742 __ mov(r2, Operand(variable->name())); 741 __ mov(r2, Operand(variable->name()));
743 // Declaration nodes are always introduced in one of two modes. 742 // Declaration nodes are always introduced in one of two modes.
744 ASSERT(mode == Variable::VAR || 743 ASSERT(mode == Variable::VAR ||
745 mode == Variable::CONST || 744 mode == Variable::CONST ||
746 mode == Variable::LET); 745 mode == Variable::LET);
747 PropertyAttributes attr = (mode == Variable::CONST) ? READ_ONLY : NONE; 746 PropertyAttributes attr = (mode == Variable::CONST) ? READ_ONLY : NONE;
748 __ mov(r1, Operand(Smi::FromInt(attr))); 747 __ mov(r1, Operand(Smi::FromInt(attr)));
749 // Push initial value, if any. 748 // Push initial value, if any.
750 // Note: For variables we must not push an initial value (such as 749 // Note: For variables we must not push an initial value (such as
751 // 'undefined') because we may have a (legal) redeclaration and we 750 // 'undefined') because we may have a (legal) redeclaration and we
752 // must not destroy the current value. 751 // must not destroy the current value.
753 if (mode == Variable::CONST) { 752 if (function != NULL) {
754 __ LoadRoot(r0, Heap::kTheHoleValueRootIndex);
755 __ Push(cp, r2, r1, r0);
756 } else if (function != NULL) {
757 __ Push(cp, r2, r1); 753 __ Push(cp, r2, r1);
758 // Push initial value for function declaration. 754 // Push initial value for function declaration.
759 VisitForStackValue(function); 755 VisitForStackValue(function);
756 } else if (mode == Variable::CONST || mode == Variable::LET) {
757 __ LoadRoot(r0, Heap::kTheHoleValueRootIndex);
758 __ Push(cp, r2, r1, r0);
760 } else { 759 } else {
761 __ mov(r0, Operand(Smi::FromInt(0))); // No initial value! 760 __ mov(r0, Operand(Smi::FromInt(0))); // No initial value!
762 __ Push(cp, r2, r1, r0); 761 __ Push(cp, r2, r1, r0);
763 } 762 }
764 __ CallRuntime(Runtime::kDeclareContextSlot, 4); 763 __ CallRuntime(Runtime::kDeclareContextSlot, 4);
765 break; 764 break;
766 } 765 }
767 } 766 }
768 767
769 } else if (prop != NULL) { 768 } else if (prop != NULL) {
(...skipping 534 matching lines...) Expand 10 before | Expand all | Expand 10 after
1304 : "Stack slot"); 1303 : "Stack slot");
1305 if (var->mode() == Variable::CONST) { 1304 if (var->mode() == Variable::CONST) {
1306 // Constants may be the hole value if they have not been initialized. 1305 // Constants may be the hole value if they have not been initialized.
1307 // Unhole them. 1306 // Unhole them.
1308 MemOperand slot_operand = EmitSlotSearch(slot, r0); 1307 MemOperand slot_operand = EmitSlotSearch(slot, r0);
1309 __ ldr(r0, slot_operand); 1308 __ ldr(r0, slot_operand);
1310 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 1309 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
1311 __ cmp(r0, ip); 1310 __ cmp(r0, ip);
1312 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); 1311 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq);
1313 context()->Plug(r0); 1312 context()->Plug(r0);
1313 } else if (var->mode() == Variable::LET) {
1314 // Let bindings may be the hole value if they have not been initialized.
1315 // Throw a type error in this case.
1316 Label done;
1317 MemOperand slot_operand = EmitSlotSearch(slot, r0);
1318 __ ldr(r0, slot_operand);
1319 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
1320 __ cmp(r0, ip);
1321 __ b(ne, &done);
1322 __ mov(r0, Operand(var->name()));
1323 __ push(r0);
1324 __ CallRuntime(Runtime::kThrowReferenceError, 1);
1325 __ bind(&done);
1326 context()->Plug(r0);
1314 } else { 1327 } else {
1315 context()->Plug(slot); 1328 context()->Plug(slot);
1316 } 1329 }
1317 } 1330 }
1318 } 1331 }
1319 1332
1320 1333
1321 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { 1334 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
1322 Comment cmnt(masm_, "[ RegExpLiteral"); 1335 Comment cmnt(masm_, "[ RegExpLiteral");
1323 Label materialized; 1336 Label materialized;
(...skipping 560 matching lines...) Expand 10 before | Expand all | Expand 10 after
1884 case Slot::CONTEXT: 1897 case Slot::CONTEXT:
1885 case Slot::LOOKUP: 1898 case Slot::LOOKUP:
1886 __ push(r0); 1899 __ push(r0);
1887 __ mov(r0, Operand(slot->var()->name())); 1900 __ mov(r0, Operand(slot->var()->name()));
1888 __ Push(cp, r0); // Context and name. 1901 __ Push(cp, r0); // Context and name.
1889 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); 1902 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
1890 break; 1903 break;
1891 } 1904 }
1892 __ bind(&skip); 1905 __ bind(&skip);
1893 1906
1907 } else if (var->mode() == Variable::LET && op != Token::INIT_LET) {
1908 // Perform the assignment for non-const variables. Const assignments
1909 // are simply skipped.
1910 Slot* slot = var->AsSlot();
1911 switch (slot->type()) {
1912 case Slot::PARAMETER:
1913 case Slot::LOCAL: {
1914 Label assign;
1915 // Check for an initialized let binding.
1916 __ ldr(r1, MemOperand(fp, SlotOffset(slot)));
1917 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
1918 __ cmp(r1, ip);
1919 __ b(ne, &assign);
1920 __ mov(r1, Operand(var->name()));
1921 __ push(r1);
1922 __ CallRuntime(Runtime::kThrowReferenceError, 1);
1923 // Perform the assignment.
1924 __ bind(&assign);
1925 __ str(result_register(), MemOperand(fp, SlotOffset(slot)));
1926 break;
1927 }
1928 case Slot::CONTEXT: {
1929 // Let variables may be the hole value if they have not been
1930 // initialized. Throw a type error in this case.
1931 Label assign;
1932 MemOperand target = EmitSlotSearch(slot, r1);
1933 // Check for an initialized let binding.
1934 __ ldr(r3, target);
1935 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
1936 __ cmp(r3, ip);
1937 __ b(ne, &assign);
1938 __ mov(r3, Operand(var->name()));
1939 __ push(r3);
1940 __ CallRuntime(Runtime::kThrowReferenceError, 1);
1941 // Perform the assignment.
1942 __ bind(&assign);
1943 __ str(result_register(), target);
1944 // RecordWrite may destroy all its register arguments.
1945 __ mov(r3, result_register());
1946 int offset = Context::SlotOffset(slot->index());
1947 __ RecordWrite(r1, Operand(offset), r2, r3);
1948 break;
1949 }
1950 case Slot::LOOKUP:
1951 // Call the runtime for the assignment.
1952 __ push(r0); // Value.
1953 __ mov(r1, Operand(slot->var()->name()));
1954 __ mov(r0, Operand(Smi::FromInt(strict_mode_flag())));
1955 __ Push(cp, r1, r0); // Context, name, strict mode.
1956 __ CallRuntime(Runtime::kStoreContextSlot, 4);
1957 break;
1958 }
1959
1894 } else if (var->mode() != Variable::CONST) { 1960 } else if (var->mode() != Variable::CONST) {
1895 // Perform the assignment for non-const variables. Const assignments 1961 // Perform the assignment for non-const variables. Const assignments
1896 // are simply skipped. 1962 // are simply skipped.
1897 Slot* slot = var->AsSlot(); 1963 Slot* slot = var->AsSlot();
1898 switch (slot->type()) { 1964 switch (slot->type()) {
1899 case Slot::PARAMETER: 1965 case Slot::PARAMETER:
1900 case Slot::LOCAL: 1966 case Slot::LOCAL:
1901 // Perform the assignment. 1967 // Perform the assignment.
1902 __ str(result_register(), MemOperand(fp, SlotOffset(slot))); 1968 __ str(result_register(), MemOperand(fp, SlotOffset(slot)));
1903 break; 1969 break;
(...skipping 2394 matching lines...) Expand 10 before | Expand all | Expand 10 after
4298 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. 4364 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value.
4299 __ add(pc, r1, Operand(masm_->CodeObject())); 4365 __ add(pc, r1, Operand(masm_->CodeObject()));
4300 } 4366 }
4301 4367
4302 4368
4303 #undef __ 4369 #undef __
4304 4370
4305 } } // namespace v8::internal 4371 } } // namespace v8::internal
4306 4372
4307 #endif // V8_TARGET_ARCH_ARM 4373 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « no previous file | src/contexts.h » ('j') | test/mjsunit/harmony/block-let-crankshaft.js » ('J')

Powered by Google App Engine
This is Rietveld 408576698