Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 259 if (scope()->HasIllegalRedeclaration()) { | 259 if (scope()->HasIllegalRedeclaration()) { |
| 260 Comment cmnt(masm_, "[ Declarations"); | 260 Comment cmnt(masm_, "[ Declarations"); |
| 261 scope()->VisitIllegalRedeclaration(this); | 261 scope()->VisitIllegalRedeclaration(this); |
| 262 | 262 |
| 263 } else { | 263 } else { |
| 264 PrepareForBailoutForId(AstNode::kFunctionEntryId, NO_REGISTERS); | 264 PrepareForBailoutForId(AstNode::kFunctionEntryId, NO_REGISTERS); |
| 265 { Comment cmnt(masm_, "[ Declarations"); | 265 { Comment cmnt(masm_, "[ Declarations"); |
| 266 // For named function expressions, declare the function name as a | 266 // For named function expressions, declare the function name as a |
| 267 // constant. | 267 // constant. |
| 268 if (scope()->is_function_scope() && scope()->function() != NULL) { | 268 if (scope()->is_function_scope() && scope()->function() != NULL) { |
| 269 VariableProxy* proxy = scope()->function(); | 269 ASSERT(scope()->function()->proxy()->var()->mode() == CONST || |
| 270 ASSERT(proxy->var()->mode() == CONST || | 270 scope()->function()->proxy()->var()->mode() == CONST_HARMONY); |
| 271 proxy->var()->mode() == CONST_HARMONY); | 271 ASSERT(scope()->function()->proxy()->var()->location() |
| 272 ASSERT(proxy->var()->location() != Variable::UNALLOCATED); | 272 != Variable::UNALLOCATED); |
|
fschneider
2012/04/11 11:00:42
Break line after the operator to be consistent wit
rossberg
2012/04/16 11:25:13
Done (here and in other back-ends).
| |
| 273 EmitDeclaration(proxy, proxy->var()->mode(), NULL); | 273 VisitVariableDeclaration(scope()->function()); |
| 274 } | 274 } |
| 275 VisitDeclarations(scope()->declarations()); | 275 VisitDeclarations(scope()->declarations()); |
| 276 } | 276 } |
| 277 | 277 |
| 278 { Comment cmnt(masm_, "[ Stack check"); | 278 { Comment cmnt(masm_, "[ Stack check"); |
| 279 PrepareForBailoutForId(AstNode::kDeclarationsId, NO_REGISTERS); | 279 PrepareForBailoutForId(AstNode::kDeclarationsId, NO_REGISTERS); |
| 280 Label ok; | 280 Label ok; |
| 281 ExternalReference stack_limit = | 281 ExternalReference stack_limit = |
| 282 ExternalReference::address_of_stack_limit(isolate()); | 282 ExternalReference::address_of_stack_limit(isolate()); |
| 283 __ cmp(esp, Operand::StaticVariable(stack_limit)); | 283 __ cmp(esp, Operand::StaticVariable(stack_limit)); |
| (...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 743 if (should_normalize) __ jmp(&skip, Label::kNear); | 743 if (should_normalize) __ jmp(&skip, Label::kNear); |
| 744 PrepareForBailout(expr, TOS_REG); | 744 PrepareForBailout(expr, TOS_REG); |
| 745 if (should_normalize) { | 745 if (should_normalize) { |
| 746 __ cmp(eax, isolate()->factory()->true_value()); | 746 __ cmp(eax, isolate()->factory()->true_value()); |
| 747 Split(equal, if_true, if_false, NULL); | 747 Split(equal, if_true, if_false, NULL); |
| 748 __ bind(&skip); | 748 __ bind(&skip); |
| 749 } | 749 } |
| 750 } | 750 } |
| 751 | 751 |
| 752 | 752 |
| 753 void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy, | 753 void FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) { |
| 754 VariableMode mode, | 754 // The variable in the decl always resides in the current function |
|
fschneider
2012/04/11 11:00:42
s/decl/declaration/
rossberg
2012/04/16 11:25:13
Done (here and in other backends).
| |
| 755 FunctionLiteral* function) { | 755 // context. |
| 756 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); | |
| 757 if (FLAG_debug_code) { | |
| 758 // Check that we're not inside a with or catch context. | |
| 759 __ mov(ebx, FieldOperand(esi, HeapObject::kMapOffset)); | |
| 760 __ cmp(ebx, isolate()->factory()->with_context_map()); | |
| 761 __ Check(not_equal, "Declaration in with context."); | |
| 762 __ cmp(ebx, isolate()->factory()->catch_context_map()); | |
| 763 __ Check(not_equal, "Declaration in catch context."); | |
| 764 } | |
| 765 } | |
| 766 | |
| 767 | |
| 768 void FullCodeGenerator::VisitVariableDeclaration( | |
| 769 VariableDeclaration* declaration) { | |
| 756 // If it was not possible to allocate the variable at compile time, we | 770 // If it was not possible to allocate the variable at compile time, we |
| 757 // need to "declare" it at runtime to make sure it actually exists in the | 771 // need to "declare" it at runtime to make sure it actually exists in the |
| 758 // local context. | 772 // local context. |
| 773 VariableProxy* proxy = declaration->proxy(); | |
| 774 VariableMode mode = declaration->mode(); | |
| 759 Variable* variable = proxy->var(); | 775 Variable* variable = proxy->var(); |
| 760 bool binding_needs_init = (function == NULL) && | 776 bool hole_init = mode == CONST || mode == CONST_HARMONY || mode == LET; |
| 761 (mode == CONST || mode == CONST_HARMONY || mode == LET); | |
| 762 switch (variable->location()) { | 777 switch (variable->location()) { |
| 763 case Variable::UNALLOCATED: | 778 case Variable::UNALLOCATED: |
| 764 ++global_count_; | 779 ++global_count_; |
| 765 break; | 780 break; |
| 766 | 781 |
| 767 case Variable::PARAMETER: | 782 case Variable::PARAMETER: |
| 768 case Variable::LOCAL: | 783 case Variable::LOCAL: |
| 769 if (function != NULL) { | 784 if (hole_init) { |
| 770 Comment cmnt(masm_, "[ Declaration"); | 785 Comment cmnt(masm_, "[ VariableDeclaration"); |
| 771 VisitForAccumulatorValue(function); | |
| 772 __ mov(StackOperand(variable), result_register()); | |
| 773 } else if (binding_needs_init) { | |
| 774 Comment cmnt(masm_, "[ Declaration"); | |
| 775 __ mov(StackOperand(variable), | 786 __ mov(StackOperand(variable), |
| 776 Immediate(isolate()->factory()->the_hole_value())); | 787 Immediate(isolate()->factory()->the_hole_value())); |
| 777 } | 788 } |
| 778 break; | 789 break; |
| 779 | 790 |
| 780 case Variable::CONTEXT: | 791 case Variable::CONTEXT: |
| 781 // The variable in the decl always resides in the current function | 792 if (hole_init) { |
| 782 // context. | 793 Comment cmnt(masm_, "[ VariableDeclaration"); |
| 783 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); | 794 EmitDebugCheckDeclarationContext(variable); |
| 784 if (FLAG_debug_code) { | |
| 785 // Check that we're not inside a with or catch context. | |
| 786 __ mov(ebx, FieldOperand(esi, HeapObject::kMapOffset)); | |
| 787 __ cmp(ebx, isolate()->factory()->with_context_map()); | |
| 788 __ Check(not_equal, "Declaration in with context."); | |
| 789 __ cmp(ebx, isolate()->factory()->catch_context_map()); | |
| 790 __ Check(not_equal, "Declaration in catch context."); | |
| 791 } | |
| 792 if (function != NULL) { | |
| 793 Comment cmnt(masm_, "[ Declaration"); | |
| 794 VisitForAccumulatorValue(function); | |
| 795 __ mov(ContextOperand(esi, variable->index()), result_register()); | |
| 796 // We know that we have written a function, which is not a smi. | |
| 797 __ RecordWriteContextSlot(esi, | |
| 798 Context::SlotOffset(variable->index()), | |
| 799 result_register(), | |
| 800 ecx, | |
| 801 kDontSaveFPRegs, | |
| 802 EMIT_REMEMBERED_SET, | |
| 803 OMIT_SMI_CHECK); | |
| 804 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); | |
| 805 } else if (binding_needs_init) { | |
| 806 Comment cmnt(masm_, "[ Declaration"); | |
| 807 __ mov(ContextOperand(esi, variable->index()), | 795 __ mov(ContextOperand(esi, variable->index()), |
| 808 Immediate(isolate()->factory()->the_hole_value())); | 796 Immediate(isolate()->factory()->the_hole_value())); |
| 809 // No write barrier since the hole value is in old space. | 797 // No write barrier since the hole value is in old space. |
| 810 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); | 798 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); |
| 811 } | 799 } |
| 812 break; | 800 break; |
| 813 | 801 |
| 814 case Variable::LOOKUP: { | 802 case Variable::LOOKUP: { |
| 815 Comment cmnt(masm_, "[ Declaration"); | 803 Comment cmnt(masm_, "[ VariableDeclaration"); |
| 816 __ push(esi); | 804 __ push(esi); |
| 817 __ push(Immediate(variable->name())); | 805 __ push(Immediate(variable->name())); |
| 818 // Declaration nodes are always introduced in one of four modes. | 806 // VariableDeclaration nodes are always introduced in one of four modes. |
| 819 ASSERT(mode == VAR || | 807 ASSERT(mode == VAR || mode == LET || |
| 820 mode == CONST || | 808 mode == CONST || mode == CONST_HARMONY); |
| 821 mode == CONST_HARMONY || | |
| 822 mode == LET); | |
| 823 PropertyAttributes attr = (mode == CONST || mode == CONST_HARMONY) | 809 PropertyAttributes attr = (mode == CONST || mode == CONST_HARMONY) |
| 824 ? READ_ONLY : NONE; | 810 ? READ_ONLY : NONE; |
| 825 __ push(Immediate(Smi::FromInt(attr))); | 811 __ push(Immediate(Smi::FromInt(attr))); |
| 826 // Push initial value, if any. | 812 // Push initial value, if any. |
| 827 // Note: For variables we must not push an initial value (such as | 813 // Note: For variables we must not push an initial value (such as |
| 828 // 'undefined') because we may have a (legal) redeclaration and we | 814 // 'undefined') because we may have a (legal) redeclaration and we |
| 829 // must not destroy the current value. | 815 // must not destroy the current value. |
| 830 if (function != NULL) { | 816 if (hole_init) { |
| 831 VisitForStackValue(function); | |
| 832 } else if (binding_needs_init) { | |
| 833 __ push(Immediate(isolate()->factory()->the_hole_value())); | 817 __ push(Immediate(isolate()->factory()->the_hole_value())); |
| 834 } else { | 818 } else { |
| 835 __ push(Immediate(Smi::FromInt(0))); // Indicates no initial value. | 819 __ push(Immediate(Smi::FromInt(0))); // Indicates no initial value. |
| 836 } | 820 } |
| 837 __ CallRuntime(Runtime::kDeclareContextSlot, 4); | 821 __ CallRuntime(Runtime::kDeclareContextSlot, 4); |
| 838 break; | 822 break; |
| 839 } | 823 } |
| 840 } | 824 } |
| 841 } | 825 } |
| 842 | 826 |
| 843 | 827 |
| 828 void FullCodeGenerator::VisitFunctionDeclaration( | |
| 829 FunctionDeclaration* declaration) { | |
| 830 VariableProxy* proxy = declaration->proxy(); | |
| 831 Variable* variable = proxy->var(); | |
| 832 switch (variable->location()) { | |
| 833 case Variable::UNALLOCATED: | |
| 834 ++global_count_; | |
| 835 break; | |
| 836 | |
| 837 case Variable::PARAMETER: | |
| 838 case Variable::LOCAL: { | |
| 839 Comment cmnt(masm_, "[ FunctionDeclaration"); | |
| 840 VisitForAccumulatorValue(declaration->fun()); | |
| 841 __ mov(StackOperand(variable), result_register()); | |
| 842 break; | |
| 843 } | |
| 844 | |
| 845 case Variable::CONTEXT: { | |
| 846 Comment cmnt(masm_, "[ FunctionDeclaration"); | |
| 847 EmitDebugCheckDeclarationContext(variable); | |
| 848 VisitForAccumulatorValue(declaration->fun()); | |
| 849 __ mov(ContextOperand(esi, variable->index()), result_register()); | |
| 850 // We know that we have written a function, which is not a smi. | |
| 851 __ RecordWriteContextSlot(esi, | |
| 852 Context::SlotOffset(variable->index()), | |
| 853 result_register(), | |
| 854 ecx, | |
| 855 kDontSaveFPRegs, | |
| 856 EMIT_REMEMBERED_SET, | |
| 857 OMIT_SMI_CHECK); | |
| 858 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); | |
| 859 break; | |
| 860 } | |
| 861 | |
| 862 case Variable::LOOKUP: { | |
| 863 Comment cmnt(masm_, "[ FunctionDeclaration"); | |
| 864 __ push(esi); | |
| 865 __ push(Immediate(variable->name())); | |
| 866 __ push(Immediate(Smi::FromInt(NONE))); | |
| 867 VisitForStackValue(declaration->fun()); | |
| 868 __ CallRuntime(Runtime::kDeclareContextSlot, 4); | |
| 869 break; | |
| 870 } | |
| 871 } | |
| 872 } | |
| 873 | |
| 874 | |
| 875 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) { | |
| 876 VariableProxy* proxy = declaration->proxy(); | |
| 877 Variable* variable = proxy->var(); | |
| 878 switch (variable->location()) { | |
| 879 case Variable::UNALLOCATED: | |
| 880 ++global_count_; | |
| 881 break; | |
| 882 | |
| 883 case Variable::CONTEXT: { | |
| 884 Comment cmnt(masm_, "[ ModuleDeclaration"); | |
| 885 EmitDebugCheckDeclarationContext(variable); | |
| 886 // TODO(rossberg): initialize module instance object | |
| 887 break; | |
| 888 } | |
| 889 | |
| 890 case Variable::PARAMETER: | |
| 891 case Variable::LOCAL: | |
| 892 case Variable::LOOKUP: | |
| 893 UNREACHABLE(); | |
| 894 } | |
| 895 } | |
| 896 | |
| 897 | |
| 898 void FullCodeGenerator::VisitImportDeclaration(ImportDeclaration* declaration) { | |
| 899 VariableProxy* proxy = declaration->proxy(); | |
| 900 Variable* variable = proxy->var(); | |
| 901 switch (variable->location()) { | |
| 902 case Variable::UNALLOCATED: | |
| 903 ++global_count_; | |
| 904 break; | |
| 905 | |
| 906 case Variable::CONTEXT: { | |
| 907 Comment cmnt(masm_, "[ ImportDeclaration"); | |
| 908 EmitDebugCheckDeclarationContext(variable); | |
| 909 // TODO(rossberg) | |
| 910 break; | |
| 911 } | |
| 912 | |
| 913 case Variable::PARAMETER: | |
| 914 case Variable::LOCAL: | |
| 915 case Variable::LOOKUP: | |
| 916 UNREACHABLE(); | |
| 917 } | |
| 918 } | |
| 919 | |
| 920 | |
| 921 void FullCodeGenerator::VisitExportDeclaration(ExportDeclaration* declaration) { | |
| 922 // TODO(rossberg) | |
| 923 } | |
| 924 | |
| 925 | |
| 844 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 926 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
| 845 // Call the runtime to declare the globals. | 927 // Call the runtime to declare the globals. |
| 846 __ push(esi); // The context is the first argument. | 928 __ push(esi); // The context is the first argument. |
| 847 __ push(Immediate(pairs)); | 929 __ push(Immediate(pairs)); |
| 848 __ push(Immediate(Smi::FromInt(DeclareGlobalsFlags()))); | 930 __ push(Immediate(Smi::FromInt(DeclareGlobalsFlags()))); |
| 849 __ CallRuntime(Runtime::kDeclareGlobals, 3); | 931 __ CallRuntime(Runtime::kDeclareGlobals, 3); |
| 850 // Return value is ignored. | 932 // Return value is ignored. |
| 851 } | 933 } |
| 852 | 934 |
| 853 | 935 |
| (...skipping 3626 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4480 *context_length = 0; | 4562 *context_length = 0; |
| 4481 return previous_; | 4563 return previous_; |
| 4482 } | 4564 } |
| 4483 | 4565 |
| 4484 | 4566 |
| 4485 #undef __ | 4567 #undef __ |
| 4486 | 4568 |
| 4487 } } // namespace v8::internal | 4569 } } // namespace v8::internal |
| 4488 | 4570 |
| 4489 #endif // V8_TARGET_ARCH_IA32 | 4571 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |