OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |