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

Side by Side Diff: src/ia32/full-codegen-ia32.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 678 matching lines...) Expand 10 before | Expand all | Expand 10 after
689 FunctionLiteral* function) { 689 FunctionLiteral* function) {
690 Comment cmnt(masm_, "[ Declaration"); 690 Comment cmnt(masm_, "[ Declaration");
691 ASSERT(variable != NULL); // Must have been resolved. 691 ASSERT(variable != NULL); // Must have been resolved.
692 Slot* slot = variable->AsSlot(); 692 Slot* slot = variable->AsSlot();
693 Property* prop = variable->AsProperty(); 693 Property* prop = variable->AsProperty();
694 694
695 if (slot != NULL) { 695 if (slot != NULL) {
696 switch (slot->type()) { 696 switch (slot->type()) {
697 case Slot::PARAMETER: 697 case Slot::PARAMETER:
698 case Slot::LOCAL: 698 case Slot::LOCAL:
699 if (mode == Variable::CONST) { 699 if (function != NULL) {
700 VisitForAccumulatorValue(function);
701 __ mov(Operand(ebp, SlotOffset(slot)), result_register());
702 } else if (mode == Variable::CONST || mode == Variable::LET) {
700 __ mov(Operand(ebp, SlotOffset(slot)), 703 __ mov(Operand(ebp, SlotOffset(slot)),
701 Immediate(isolate()->factory()->the_hole_value())); 704 Immediate(isolate()->factory()->the_hole_value()));
702 } else if (function != NULL) {
703 VisitForAccumulatorValue(function);
704 __ mov(Operand(ebp, SlotOffset(slot)), result_register());
705 } 705 }
706 break; 706 break;
707 707
708 case Slot::CONTEXT: 708 case Slot::CONTEXT:
709 // We bypass the general EmitSlotSearch because we know more about 709 // We bypass the general EmitSlotSearch because we know more about
710 // this specific context. 710 // this specific context.
711 711
712 // The variable in the decl always resides in the current function 712 // The variable in the decl always resides in the current function
713 // context. 713 // context.
714 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); 714 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
715 if (FLAG_debug_code) { 715 if (FLAG_debug_code) {
716 // Check that we're not inside a with or catch context. 716 // Check that we're not inside a with or catch context.
717 __ mov(ebx, FieldOperand(esi, HeapObject::kMapOffset)); 717 __ mov(ebx, FieldOperand(esi, HeapObject::kMapOffset));
718 __ cmp(ebx, isolate()->factory()->with_context_map()); 718 __ cmp(ebx, isolate()->factory()->with_context_map());
719 __ Check(not_equal, "Declaration in with context."); 719 __ Check(not_equal, "Declaration in with context.");
720 __ cmp(ebx, isolate()->factory()->catch_context_map()); 720 __ cmp(ebx, isolate()->factory()->catch_context_map());
721 __ Check(not_equal, "Declaration in catch context."); 721 __ Check(not_equal, "Declaration in catch context.");
722 } 722 }
723 if (mode == Variable::CONST) { 723 if (function != NULL) {
724 __ mov(ContextOperand(esi, slot->index()),
725 Immediate(isolate()->factory()->the_hole_value()));
726 // No write barrier since the hole value is in old space.
727 } else if (function != NULL) {
728 VisitForAccumulatorValue(function); 724 VisitForAccumulatorValue(function);
729 __ mov(ContextOperand(esi, slot->index()), result_register()); 725 __ mov(ContextOperand(esi, slot->index()), result_register());
730 int offset = Context::SlotOffset(slot->index()); 726 int offset = Context::SlotOffset(slot->index());
731 __ mov(ebx, esi); 727 __ mov(ebx, esi);
732 __ RecordWrite(ebx, offset, result_register(), ecx); 728 __ RecordWrite(ebx, offset, result_register(), ecx);
729 } else if (mode == Variable::CONST || mode == Variable::LET) {
730 __ mov(ContextOperand(esi, slot->index()),
731 Immediate(isolate()->factory()->the_hole_value()));
732 // No write barrier since the hole value is in old space.
733 } 733 }
734 break; 734 break;
735 735
736 case Slot::LOOKUP: { 736 case Slot::LOOKUP: {
737 __ push(esi); 737 __ push(esi);
738 __ push(Immediate(variable->name())); 738 __ push(Immediate(variable->name()));
739 // Declaration nodes are always introduced in one of two modes. 739 // Declaration nodes are always introduced in one of two modes.
740 ASSERT(mode == Variable::VAR || 740 ASSERT(mode == Variable::VAR ||
741 mode == Variable::CONST || 741 mode == Variable::CONST ||
742 mode == Variable::LET); 742 mode == Variable::LET);
743 PropertyAttributes attr = (mode == Variable::CONST) ? READ_ONLY : NONE; 743 PropertyAttributes attr = (mode == Variable::CONST) ? READ_ONLY : NONE;
744 __ push(Immediate(Smi::FromInt(attr))); 744 __ push(Immediate(Smi::FromInt(attr)));
745 // Push initial value, if any. 745 // Push initial value, if any.
746 // Note: For variables we must not push an initial value (such as 746 // Note: For variables we must not push an initial value (such as
747 // 'undefined') because we may have a (legal) redeclaration and we 747 // 'undefined') because we may have a (legal) redeclaration and we
748 // must not destroy the current value. 748 // must not destroy the current value.
749 increment_stack_height(3); 749 increment_stack_height(3);
750 if (mode == Variable::CONST) { 750 if (function != NULL) {
751 VisitForStackValue(function);
752 } else if (mode == Variable::CONST || mode == Variable::LET) {
751 __ push(Immediate(isolate()->factory()->the_hole_value())); 753 __ push(Immediate(isolate()->factory()->the_hole_value()));
752 increment_stack_height(); 754 increment_stack_height();
753 } else if (function != NULL) {
754 VisitForStackValue(function);
755 } else { 755 } else {
756 __ push(Immediate(Smi::FromInt(0))); // No initial value! 756 __ push(Immediate(Smi::FromInt(0))); // No initial value!
757 increment_stack_height(); 757 increment_stack_height();
758 } 758 }
759 __ CallRuntime(Runtime::kDeclareContextSlot, 4); 759 __ CallRuntime(Runtime::kDeclareContextSlot, 4);
760 decrement_stack_height(4); 760 decrement_stack_height(4);
761 break; 761 break;
762 } 762 }
763 } 763 }
764 764
(...skipping 528 matching lines...) Expand 10 before | Expand all | Expand 10 after
1293 // Constants may be the hole value if they have not been initialized. 1293 // Constants may be the hole value if they have not been initialized.
1294 // Unhole them. 1294 // Unhole them.
1295 Label done; 1295 Label done;
1296 MemOperand slot_operand = EmitSlotSearch(slot, eax); 1296 MemOperand slot_operand = EmitSlotSearch(slot, eax);
1297 __ mov(eax, slot_operand); 1297 __ mov(eax, slot_operand);
1298 __ cmp(eax, isolate()->factory()->the_hole_value()); 1298 __ cmp(eax, isolate()->factory()->the_hole_value());
1299 __ j(not_equal, &done, Label::kNear); 1299 __ j(not_equal, &done, Label::kNear);
1300 __ mov(eax, isolate()->factory()->undefined_value()); 1300 __ mov(eax, isolate()->factory()->undefined_value());
1301 __ bind(&done); 1301 __ bind(&done);
1302 context()->Plug(eax); 1302 context()->Plug(eax);
1303 } else if (var->mode() == Variable::LET) {
1304 // Let bindings may be the hole value if they have not been initialized.
1305 // Throw a type error in this case.
1306 Label done;
1307 MemOperand slot_operand = EmitSlotSearch(slot, eax);
1308 __ mov(eax, slot_operand);
1309 __ cmp(eax, isolate()->factory()->the_hole_value());
1310 __ j(not_equal, &done, Label::kNear);
1311 __ push(Immediate(var->name()));
1312 __ CallRuntime(Runtime::kThrowReferenceError, 1);
1313 __ bind(&done);
1314 context()->Plug(eax);
1303 } else { 1315 } else {
1304 context()->Plug(slot); 1316 context()->Plug(slot);
1305 } 1317 }
1306 } 1318 }
1307 } 1319 }
1308 1320
1309 1321
1310 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { 1322 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
1311 Comment cmnt(masm_, "[ RegExpLiteral"); 1323 Comment cmnt(masm_, "[ RegExpLiteral");
1312 Label materialized; 1324 Label materialized;
(...skipping 577 matching lines...) Expand 10 before | Expand all | Expand 10 after
1890 case Slot::CONTEXT: 1902 case Slot::CONTEXT:
1891 case Slot::LOOKUP: 1903 case Slot::LOOKUP:
1892 __ push(eax); 1904 __ push(eax);
1893 __ push(esi); 1905 __ push(esi);
1894 __ push(Immediate(var->name())); 1906 __ push(Immediate(var->name()));
1895 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); 1907 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
1896 break; 1908 break;
1897 } 1909 }
1898 __ bind(&skip); 1910 __ bind(&skip);
1899 1911
1912 } else if (var->mode() == Variable::LET && op != Token::INIT_LET) {
1913 // Perform the assignment for non-const variables. Const assignments
1914 // are simply skipped.
1915 Slot* slot = var->AsSlot();
1916 switch (slot->type()) {
1917 case Slot::PARAMETER:
1918 case Slot::LOCAL: {
1919 Label assign;
1920 // Check for an initialized let binding.
1921 __ mov(edx, Operand(ebp, SlotOffset(slot)));
1922 __ cmp(edx, isolate()->factory()->the_hole_value());
1923 __ j(not_equal, &assign);
1924 __ push(Immediate(var->name()));
1925 __ CallRuntime(Runtime::kThrowReferenceError, 1);
1926 // Perform the assignment.
1927 __ bind(&assign);
1928 __ mov(Operand(ebp, SlotOffset(slot)), eax);
1929 break;
1930 }
1931
1932 case Slot::CONTEXT: {
1933 // Let variables may be the hole value if they have not been
1934 // initialized. Throw a type error in this case.
1935 Label assign;
1936 MemOperand target = EmitSlotSearch(slot, ecx);
1937 // Check for an initialized let binding.
1938 __ mov(edx, target);
1939 __ cmp(edx, isolate()->factory()->the_hole_value());
1940 __ j(not_equal, &assign, Label::kNear);
1941 __ push(Immediate(var->name()));
1942 __ CallRuntime(Runtime::kThrowReferenceError, 1);
1943 // Perform the assignment.
1944 __ bind(&assign);
1945 __ mov(target, eax);
1946 // The value of the assignment is in eax. RecordWrite clobbers its
1947 // register arguments.
1948 __ mov(edx, eax);
1949 int offset = Context::SlotOffset(slot->index());
1950 __ RecordWrite(ecx, offset, edx, ebx);
1951 break;
1952 }
1953
1954 case Slot::LOOKUP:
1955 // Call the runtime for the assignment.
1956 __ push(eax); // Value.
1957 __ push(esi); // Context.
1958 __ push(Immediate(var->name()));
1959 __ push(Immediate(Smi::FromInt(strict_mode_flag())));
1960 __ CallRuntime(Runtime::kStoreContextSlot, 4);
1961 break;
1962 }
1900 } else if (var->mode() != Variable::CONST) { 1963 } else if (var->mode() != Variable::CONST) {
1901 // Perform the assignment for non-const variables. Const assignments 1964 // Perform the assignment for non-const variables. Const assignments
1902 // are simply skipped. 1965 // are simply skipped.
1903 Slot* slot = var->AsSlot(); 1966 Slot* slot = var->AsSlot();
1904 switch (slot->type()) { 1967 switch (slot->type()) {
1905 case Slot::PARAMETER: 1968 case Slot::PARAMETER:
1906 case Slot::LOCAL: 1969 case Slot::LOCAL:
1907 // Perform the assignment. 1970 // Perform the assignment.
1908 __ mov(Operand(ebp, SlotOffset(slot)), eax); 1971 __ mov(Operand(ebp, SlotOffset(slot)), eax);
1909 break; 1972 break;
(...skipping 2461 matching lines...) Expand 10 before | Expand all | Expand 10 after
4371 __ add(Operand(edx), Immediate(masm_->CodeObject())); 4434 __ add(Operand(edx), Immediate(masm_->CodeObject()));
4372 __ jmp(Operand(edx)); 4435 __ jmp(Operand(edx));
4373 } 4436 }
4374 4437
4375 4438
4376 #undef __ 4439 #undef __
4377 4440
4378 } } // namespace v8::internal 4441 } } // namespace v8::internal
4379 4442
4380 #endif // V8_TARGET_ARCH_IA32 4443 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/hydrogen.cc ('k') | src/parser.cc » ('j') | test/mjsunit/harmony/block-let-crankshaft.js » ('J')

Powered by Google App Engine
This is Rietveld 408576698