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

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

Issue 10105026: Version 3.10.3 (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
Patch Set: Created 8 years, 8 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 | « src/ia32/codegen-ia32.cc ('k') | src/ia32/lithium-codegen-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 244 matching lines...) Expand 10 before | Expand all | Expand 10 after
255 if (scope()->HasIllegalRedeclaration()) { 255 if (scope()->HasIllegalRedeclaration()) {
256 Comment cmnt(masm_, "[ Declarations"); 256 Comment cmnt(masm_, "[ Declarations");
257 scope()->VisitIllegalRedeclaration(this); 257 scope()->VisitIllegalRedeclaration(this);
258 258
259 } else { 259 } else {
260 PrepareForBailoutForId(AstNode::kFunctionEntryId, NO_REGISTERS); 260 PrepareForBailoutForId(AstNode::kFunctionEntryId, NO_REGISTERS);
261 { Comment cmnt(masm_, "[ Declarations"); 261 { Comment cmnt(masm_, "[ Declarations");
262 // For named function expressions, declare the function name as a 262 // For named function expressions, declare the function name as a
263 // constant. 263 // constant.
264 if (scope()->is_function_scope() && scope()->function() != NULL) { 264 if (scope()->is_function_scope() && scope()->function() != NULL) {
265 VariableProxy* proxy = scope()->function(); 265 VariableDeclaration* function = scope()->function();
266 ASSERT(proxy->var()->mode() == CONST || 266 ASSERT(function->proxy()->var()->mode() == CONST ||
267 proxy->var()->mode() == CONST_HARMONY); 267 function->proxy()->var()->mode() == CONST_HARMONY);
268 ASSERT(proxy->var()->location() != Variable::UNALLOCATED); 268 ASSERT(function->proxy()->var()->location() != Variable::UNALLOCATED);
269 EmitDeclaration(proxy, proxy->var()->mode(), NULL); 269 VisitVariableDeclaration(function);
270 } 270 }
271 VisitDeclarations(scope()->declarations()); 271 VisitDeclarations(scope()->declarations());
272 } 272 }
273 273
274 { Comment cmnt(masm_, "[ Stack check"); 274 { Comment cmnt(masm_, "[ Stack check");
275 PrepareForBailoutForId(AstNode::kDeclarationsId, NO_REGISTERS); 275 PrepareForBailoutForId(AstNode::kDeclarationsId, NO_REGISTERS);
276 Label ok; 276 Label ok;
277 ExternalReference stack_limit = 277 ExternalReference stack_limit =
278 ExternalReference::address_of_stack_limit(isolate()); 278 ExternalReference::address_of_stack_limit(isolate());
279 __ cmp(esp, Operand::StaticVariable(stack_limit)); 279 __ cmp(esp, Operand::StaticVariable(stack_limit));
(...skipping 469 matching lines...) Expand 10 before | Expand all | Expand 10 after
749 if (should_normalize) __ jmp(&skip, Label::kNear); 749 if (should_normalize) __ jmp(&skip, Label::kNear);
750 PrepareForBailout(expr, TOS_REG); 750 PrepareForBailout(expr, TOS_REG);
751 if (should_normalize) { 751 if (should_normalize) {
752 __ cmp(eax, isolate()->factory()->true_value()); 752 __ cmp(eax, isolate()->factory()->true_value());
753 Split(equal, if_true, if_false, NULL); 753 Split(equal, if_true, if_false, NULL);
754 __ bind(&skip); 754 __ bind(&skip);
755 } 755 }
756 } 756 }
757 757
758 758
759 void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy, 759 void FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) {
760 VariableMode mode, 760 // The variable in the declaration always resides in the current function
761 FunctionLiteral* function) { 761 // context.
762 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
763 if (FLAG_debug_code) {
764 // Check that we're not inside a with or catch context.
765 __ mov(ebx, FieldOperand(esi, HeapObject::kMapOffset));
766 __ cmp(ebx, isolate()->factory()->with_context_map());
767 __ Check(not_equal, "Declaration in with context.");
768 __ cmp(ebx, isolate()->factory()->catch_context_map());
769 __ Check(not_equal, "Declaration in catch context.");
770 }
771 }
772
773
774 void FullCodeGenerator::VisitVariableDeclaration(
775 VariableDeclaration* declaration) {
762 // If it was not possible to allocate the variable at compile time, we 776 // If it was not possible to allocate the variable at compile time, we
763 // need to "declare" it at runtime to make sure it actually exists in the 777 // need to "declare" it at runtime to make sure it actually exists in the
764 // local context. 778 // local context.
779 VariableProxy* proxy = declaration->proxy();
780 VariableMode mode = declaration->mode();
765 Variable* variable = proxy->var(); 781 Variable* variable = proxy->var();
766 bool binding_needs_init = (function == NULL) && 782 bool hole_init = mode == CONST || mode == CONST_HARMONY || mode == LET;
767 (mode == CONST || mode == CONST_HARMONY || mode == LET);
768 switch (variable->location()) { 783 switch (variable->location()) {
769 case Variable::UNALLOCATED: 784 case Variable::UNALLOCATED:
770 ++global_count_; 785 globals_->Add(variable->name());
786 globals_->Add(variable->binding_needs_init()
787 ? isolate()->factory()->the_hole_value()
788 : isolate()->factory()->undefined_value());
771 break; 789 break;
772 790
773 case Variable::PARAMETER: 791 case Variable::PARAMETER:
774 case Variable::LOCAL: 792 case Variable::LOCAL:
775 if (function != NULL) { 793 if (hole_init) {
776 Comment cmnt(masm_, "[ Declaration"); 794 Comment cmnt(masm_, "[ VariableDeclaration");
777 VisitForAccumulatorValue(function);
778 __ mov(StackOperand(variable), result_register());
779 } else if (binding_needs_init) {
780 Comment cmnt(masm_, "[ Declaration");
781 __ mov(StackOperand(variable), 795 __ mov(StackOperand(variable),
782 Immediate(isolate()->factory()->the_hole_value())); 796 Immediate(isolate()->factory()->the_hole_value()));
783 } 797 }
784 break; 798 break;
785 799
786 case Variable::CONTEXT: 800 case Variable::CONTEXT:
787 // The variable in the decl always resides in the current function 801 if (hole_init) {
788 // context. 802 Comment cmnt(masm_, "[ VariableDeclaration");
789 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); 803 EmitDebugCheckDeclarationContext(variable);
790 if (FLAG_debug_code) {
791 // Check that we're not inside a with or catch context.
792 __ mov(ebx, FieldOperand(esi, HeapObject::kMapOffset));
793 __ cmp(ebx, isolate()->factory()->with_context_map());
794 __ Check(not_equal, "Declaration in with context.");
795 __ cmp(ebx, isolate()->factory()->catch_context_map());
796 __ Check(not_equal, "Declaration in catch context.");
797 }
798 if (function != NULL) {
799 Comment cmnt(masm_, "[ Declaration");
800 VisitForAccumulatorValue(function);
801 __ mov(ContextOperand(esi, variable->index()), result_register());
802 // We know that we have written a function, which is not a smi.
803 __ RecordWriteContextSlot(esi,
804 Context::SlotOffset(variable->index()),
805 result_register(),
806 ecx,
807 kDontSaveFPRegs,
808 EMIT_REMEMBERED_SET,
809 OMIT_SMI_CHECK);
810 PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
811 } else if (binding_needs_init) {
812 Comment cmnt(masm_, "[ Declaration");
813 __ mov(ContextOperand(esi, variable->index()), 804 __ mov(ContextOperand(esi, variable->index()),
814 Immediate(isolate()->factory()->the_hole_value())); 805 Immediate(isolate()->factory()->the_hole_value()));
815 // No write barrier since the hole value is in old space. 806 // No write barrier since the hole value is in old space.
816 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); 807 PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
817 } 808 }
818 break; 809 break;
819 810
820 case Variable::LOOKUP: { 811 case Variable::LOOKUP: {
821 Comment cmnt(masm_, "[ Declaration"); 812 Comment cmnt(masm_, "[ VariableDeclaration");
822 __ push(esi); 813 __ push(esi);
823 __ push(Immediate(variable->name())); 814 __ push(Immediate(variable->name()));
824 // Declaration nodes are always introduced in one of four modes. 815 // VariableDeclaration nodes are always introduced in one of four modes.
825 ASSERT(mode == VAR || 816 ASSERT(mode == VAR || mode == LET ||
826 mode == CONST || 817 mode == CONST || mode == CONST_HARMONY);
827 mode == CONST_HARMONY ||
828 mode == LET);
829 PropertyAttributes attr = (mode == CONST || mode == CONST_HARMONY) 818 PropertyAttributes attr = (mode == CONST || mode == CONST_HARMONY)
830 ? READ_ONLY : NONE; 819 ? READ_ONLY : NONE;
831 __ push(Immediate(Smi::FromInt(attr))); 820 __ push(Immediate(Smi::FromInt(attr)));
832 // Push initial value, if any. 821 // Push initial value, if any.
833 // Note: For variables we must not push an initial value (such as 822 // Note: For variables we must not push an initial value (such as
834 // 'undefined') because we may have a (legal) redeclaration and we 823 // 'undefined') because we may have a (legal) redeclaration and we
835 // must not destroy the current value. 824 // must not destroy the current value.
836 if (function != NULL) { 825 if (hole_init) {
837 VisitForStackValue(function);
838 } else if (binding_needs_init) {
839 __ push(Immediate(isolate()->factory()->the_hole_value())); 826 __ push(Immediate(isolate()->factory()->the_hole_value()));
840 } else { 827 } else {
841 __ push(Immediate(Smi::FromInt(0))); // Indicates no initial value. 828 __ push(Immediate(Smi::FromInt(0))); // Indicates no initial value.
842 } 829 }
843 __ CallRuntime(Runtime::kDeclareContextSlot, 4); 830 __ CallRuntime(Runtime::kDeclareContextSlot, 4);
844 break; 831 break;
845 } 832 }
846 } 833 }
847 } 834 }
848 835
849 836
837 void FullCodeGenerator::VisitFunctionDeclaration(
838 FunctionDeclaration* declaration) {
839 VariableProxy* proxy = declaration->proxy();
840 Variable* variable = proxy->var();
841 switch (variable->location()) {
842 case Variable::UNALLOCATED: {
843 globals_->Add(variable->name());
844 Handle<SharedFunctionInfo> function =
845 Compiler::BuildFunctionInfo(declaration->fun(), script());
846 // Check for stack-overflow exception.
847 if (function.is_null()) return SetStackOverflow();
848 globals_->Add(function);
849 break;
850 }
851
852 case Variable::PARAMETER:
853 case Variable::LOCAL: {
854 Comment cmnt(masm_, "[ FunctionDeclaration");
855 VisitForAccumulatorValue(declaration->fun());
856 __ mov(StackOperand(variable), result_register());
857 break;
858 }
859
860 case Variable::CONTEXT: {
861 Comment cmnt(masm_, "[ FunctionDeclaration");
862 EmitDebugCheckDeclarationContext(variable);
863 VisitForAccumulatorValue(declaration->fun());
864 __ mov(ContextOperand(esi, variable->index()), result_register());
865 // We know that we have written a function, which is not a smi.
866 __ RecordWriteContextSlot(esi,
867 Context::SlotOffset(variable->index()),
868 result_register(),
869 ecx,
870 kDontSaveFPRegs,
871 EMIT_REMEMBERED_SET,
872 OMIT_SMI_CHECK);
873 PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
874 break;
875 }
876
877 case Variable::LOOKUP: {
878 Comment cmnt(masm_, "[ FunctionDeclaration");
879 __ push(esi);
880 __ push(Immediate(variable->name()));
881 __ push(Immediate(Smi::FromInt(NONE)));
882 VisitForStackValue(declaration->fun());
883 __ CallRuntime(Runtime::kDeclareContextSlot, 4);
884 break;
885 }
886 }
887 }
888
889
890 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) {
891 VariableProxy* proxy = declaration->proxy();
892 Variable* variable = proxy->var();
893 Handle<JSModule> instance = declaration->module()->interface()->Instance();
894 ASSERT(!instance.is_null());
895
896 switch (variable->location()) {
897 case Variable::UNALLOCATED: {
898 Comment cmnt(masm_, "[ ModuleDeclaration");
899 globals_->Add(variable->name());
900 globals_->Add(instance);
901 Visit(declaration->module());
902 break;
903 }
904
905 case Variable::CONTEXT: {
906 Comment cmnt(masm_, "[ ModuleDeclaration");
907 EmitDebugCheckDeclarationContext(variable);
908 __ mov(ContextOperand(esi, variable->index()), Immediate(instance));
909 Visit(declaration->module());
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::VisitImportDeclaration(ImportDeclaration* declaration) {
922 VariableProxy* proxy = declaration->proxy();
923 Variable* variable = proxy->var();
924 switch (variable->location()) {
925 case Variable::UNALLOCATED:
926 // TODO(rossberg)
927 break;
928
929 case Variable::CONTEXT: {
930 Comment cmnt(masm_, "[ ImportDeclaration");
931 EmitDebugCheckDeclarationContext(variable);
932 // TODO(rossberg)
933 break;
934 }
935
936 case Variable::PARAMETER:
937 case Variable::LOCAL:
938 case Variable::LOOKUP:
939 UNREACHABLE();
940 }
941 }
942
943
944 void FullCodeGenerator::VisitExportDeclaration(ExportDeclaration* declaration) {
945 // TODO(rossberg)
946 }
947
948
850 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 949 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
851 // Call the runtime to declare the globals. 950 // Call the runtime to declare the globals.
852 __ push(esi); // The context is the first argument. 951 __ push(esi); // The context is the first argument.
853 __ push(Immediate(pairs)); 952 __ push(Immediate(pairs));
854 __ push(Immediate(Smi::FromInt(DeclareGlobalsFlags()))); 953 __ push(Immediate(Smi::FromInt(DeclareGlobalsFlags())));
855 __ CallRuntime(Runtime::kDeclareGlobals, 3); 954 __ CallRuntime(Runtime::kDeclareGlobals, 3);
856 // Return value is ignored. 955 // Return value is ignored.
857 } 956 }
858 957
859 958
(...skipping 3563 matching lines...) Expand 10 before | Expand all | Expand 10 after
4423 } 4522 }
4424 4523
4425 4524
4426 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { 4525 void FullCodeGenerator::LoadContextField(Register dst, int context_index) {
4427 __ mov(dst, ContextOperand(esi, context_index)); 4526 __ mov(dst, ContextOperand(esi, context_index));
4428 } 4527 }
4429 4528
4430 4529
4431 void FullCodeGenerator::PushFunctionArgumentForContextAllocation() { 4530 void FullCodeGenerator::PushFunctionArgumentForContextAllocation() {
4432 Scope* declaration_scope = scope()->DeclarationScope(); 4531 Scope* declaration_scope = scope()->DeclarationScope();
4433 if (declaration_scope->is_global_scope()) { 4532 if (declaration_scope->is_global_scope() ||
4533 declaration_scope->is_module_scope()) {
4434 // Contexts nested in the global context have a canonical empty function 4534 // Contexts nested in the global context have a canonical empty function
4435 // as their closure, not the anonymous closure containing the global 4535 // as their closure, not the anonymous closure containing the global
4436 // code. Pass a smi sentinel and let the runtime look up the empty 4536 // code. Pass a smi sentinel and let the runtime look up the empty
4437 // function. 4537 // function.
4438 __ push(Immediate(Smi::FromInt(0))); 4538 __ push(Immediate(Smi::FromInt(0)));
4439 } else if (declaration_scope->is_eval_scope()) { 4539 } else if (declaration_scope->is_eval_scope()) {
4440 // Contexts nested inside eval code have the same closure as the context 4540 // Contexts nested inside eval code have the same closure as the context
4441 // calling eval, not the anonymous closure containing the eval code. 4541 // calling eval, not the anonymous closure containing the eval code.
4442 // Fetch it from the context. 4542 // Fetch it from the context.
4443 __ push(ContextOperand(esi, Context::CLOSURE_INDEX)); 4543 __ push(ContextOperand(esi, Context::CLOSURE_INDEX));
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
4502 *context_length = 0; 4602 *context_length = 0;
4503 return previous_; 4603 return previous_;
4504 } 4604 }
4505 4605
4506 4606
4507 #undef __ 4607 #undef __
4508 4608
4509 } } // namespace v8::internal 4609 } } // namespace v8::internal
4510 4610
4511 #endif // V8_TARGET_ARCH_IA32 4611 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/codegen-ia32.cc ('k') | src/ia32/lithium-codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698