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

Side by Side Diff: src/x64/full-codegen-x64.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/x64/code-stubs-x64.cc ('k') | src/x64/lithium-codegen-x64.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 239 matching lines...) Expand 10 before | Expand all | Expand 10 after
250 if (scope()->HasIllegalRedeclaration()) { 250 if (scope()->HasIllegalRedeclaration()) {
251 Comment cmnt(masm_, "[ Declarations"); 251 Comment cmnt(masm_, "[ Declarations");
252 scope()->VisitIllegalRedeclaration(this); 252 scope()->VisitIllegalRedeclaration(this);
253 253
254 } else { 254 } else {
255 PrepareForBailoutForId(AstNode::kFunctionEntryId, NO_REGISTERS); 255 PrepareForBailoutForId(AstNode::kFunctionEntryId, NO_REGISTERS);
256 { Comment cmnt(masm_, "[ Declarations"); 256 { Comment cmnt(masm_, "[ Declarations");
257 // For named function expressions, declare the function name as a 257 // For named function expressions, declare the function name as a
258 // constant. 258 // constant.
259 if (scope()->is_function_scope() && scope()->function() != NULL) { 259 if (scope()->is_function_scope() && scope()->function() != NULL) {
260 VariableProxy* proxy = scope()->function(); 260 VariableDeclaration* function = scope()->function();
261 ASSERT(proxy->var()->mode() == CONST || 261 ASSERT(function->proxy()->var()->mode() == CONST ||
262 proxy->var()->mode() == CONST_HARMONY); 262 function->proxy()->var()->mode() == CONST_HARMONY);
263 ASSERT(proxy->var()->location() != Variable::UNALLOCATED); 263 ASSERT(function->proxy()->var()->location() != Variable::UNALLOCATED);
264 EmitDeclaration(proxy, proxy->var()->mode(), NULL); 264 VisitVariableDeclaration(function);
265 } 265 }
266 VisitDeclarations(scope()->declarations()); 266 VisitDeclarations(scope()->declarations());
267 } 267 }
268 268
269 { Comment cmnt(masm_, "[ Stack check"); 269 { Comment cmnt(masm_, "[ Stack check");
270 PrepareForBailoutForId(AstNode::kDeclarationsId, NO_REGISTERS); 270 PrepareForBailoutForId(AstNode::kDeclarationsId, NO_REGISTERS);
271 Label ok; 271 Label ok;
272 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); 272 __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
273 __ j(above_equal, &ok, Label::kNear); 273 __ j(above_equal, &ok, Label::kNear);
274 StackCheckStub stub; 274 StackCheckStub stub;
(...skipping 471 matching lines...) Expand 10 before | Expand all | Expand 10 after
746 if (should_normalize) __ jmp(&skip, Label::kNear); 746 if (should_normalize) __ jmp(&skip, Label::kNear);
747 PrepareForBailout(expr, TOS_REG); 747 PrepareForBailout(expr, TOS_REG);
748 if (should_normalize) { 748 if (should_normalize) {
749 __ CompareRoot(rax, Heap::kTrueValueRootIndex); 749 __ CompareRoot(rax, Heap::kTrueValueRootIndex);
750 Split(equal, if_true, if_false, NULL); 750 Split(equal, if_true, if_false, NULL);
751 __ bind(&skip); 751 __ bind(&skip);
752 } 752 }
753 } 753 }
754 754
755 755
756 void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy, 756 void FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) {
757 VariableMode mode, 757 // The variable in the declaration always resides in the current function
758 FunctionLiteral* function) { 758 // context.
759 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
760 if (FLAG_debug_code) {
761 // Check that we're not inside a with or catch context.
762 __ movq(rbx, FieldOperand(rsi, HeapObject::kMapOffset));
763 __ CompareRoot(rbx, Heap::kWithContextMapRootIndex);
764 __ Check(not_equal, "Declaration in with context.");
765 __ CompareRoot(rbx, Heap::kCatchContextMapRootIndex);
766 __ Check(not_equal, "Declaration in catch context.");
767 }
768 }
769
770
771 void FullCodeGenerator::VisitVariableDeclaration(
772 VariableDeclaration* declaration) {
759 // If it was not possible to allocate the variable at compile time, we 773 // If it was not possible to allocate the variable at compile time, we
760 // need to "declare" it at runtime to make sure it actually exists in the 774 // need to "declare" it at runtime to make sure it actually exists in the
761 // local context. 775 // local context.
776 VariableProxy* proxy = declaration->proxy();
777 VariableMode mode = declaration->mode();
762 Variable* variable = proxy->var(); 778 Variable* variable = proxy->var();
763 bool binding_needs_init = (function == NULL) && 779 bool hole_init = mode == CONST || mode == CONST_HARMONY || mode == LET;
764 (mode == CONST || mode == CONST_HARMONY || mode == LET);
765 switch (variable->location()) { 780 switch (variable->location()) {
766 case Variable::UNALLOCATED: 781 case Variable::UNALLOCATED:
767 ++global_count_; 782 globals_->Add(variable->name());
783 globals_->Add(variable->binding_needs_init()
784 ? isolate()->factory()->the_hole_value()
785 : isolate()->factory()->undefined_value());
768 break; 786 break;
769 787
770 case Variable::PARAMETER: 788 case Variable::PARAMETER:
771 case Variable::LOCAL: 789 case Variable::LOCAL:
772 if (function != NULL) { 790 if (hole_init) {
773 Comment cmnt(masm_, "[ Declaration"); 791 Comment cmnt(masm_, "[ VariableDeclaration");
774 VisitForAccumulatorValue(function);
775 __ movq(StackOperand(variable), result_register());
776 } else if (binding_needs_init) {
777 Comment cmnt(masm_, "[ Declaration");
778 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); 792 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
779 __ movq(StackOperand(variable), kScratchRegister); 793 __ movq(StackOperand(variable), kScratchRegister);
780 } 794 }
781 break; 795 break;
782 796
783 case Variable::CONTEXT: 797 case Variable::CONTEXT:
784 // The variable in the decl always resides in the current function 798 if (hole_init) {
785 // context. 799 Comment cmnt(masm_, "[ VariableDeclaration");
786 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); 800 EmitDebugCheckDeclarationContext(variable);
787 if (FLAG_debug_code) {
788 // Check that we're not inside a with or catch context.
789 __ movq(rbx, FieldOperand(rsi, HeapObject::kMapOffset));
790 __ CompareRoot(rbx, Heap::kWithContextMapRootIndex);
791 __ Check(not_equal, "Declaration in with context.");
792 __ CompareRoot(rbx, Heap::kCatchContextMapRootIndex);
793 __ Check(not_equal, "Declaration in catch context.");
794 }
795 if (function != NULL) {
796 Comment cmnt(masm_, "[ Declaration");
797 VisitForAccumulatorValue(function);
798 __ movq(ContextOperand(rsi, variable->index()), result_register());
799 int offset = Context::SlotOffset(variable->index());
800 // We know that we have written a function, which is not a smi.
801 __ RecordWriteContextSlot(rsi,
802 offset,
803 result_register(),
804 rcx,
805 kDontSaveFPRegs,
806 EMIT_REMEMBERED_SET,
807 OMIT_SMI_CHECK);
808 PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
809 } else if (binding_needs_init) {
810 Comment cmnt(masm_, "[ Declaration");
811 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); 801 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
812 __ movq(ContextOperand(rsi, variable->index()), kScratchRegister); 802 __ movq(ContextOperand(rsi, variable->index()), kScratchRegister);
813 // No write barrier since the hole value is in old space. 803 // No write barrier since the hole value is in old space.
814 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); 804 PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
815 } 805 }
816 break; 806 break;
817 807
818 case Variable::LOOKUP: { 808 case Variable::LOOKUP: {
819 Comment cmnt(masm_, "[ Declaration"); 809 Comment cmnt(masm_, "[ VariableDeclaration");
820 __ push(rsi); 810 __ push(rsi);
821 __ Push(variable->name()); 811 __ Push(variable->name());
822 // Declaration nodes are always introduced in one of four modes. 812 // Declaration nodes are always introduced in one of four modes.
823 ASSERT(mode == VAR || 813 ASSERT(mode == VAR || mode == LET ||
824 mode == CONST || 814 mode == CONST || mode == CONST_HARMONY);
825 mode == CONST_HARMONY ||
826 mode == LET);
827 PropertyAttributes attr = 815 PropertyAttributes attr =
828 (mode == CONST || mode == CONST_HARMONY) ? READ_ONLY : NONE; 816 (mode == CONST || mode == CONST_HARMONY) ? READ_ONLY : NONE;
829 __ Push(Smi::FromInt(attr)); 817 __ Push(Smi::FromInt(attr));
830 // Push initial value, if any. 818 // Push initial value, if any.
831 // Note: For variables we must not push an initial value (such as 819 // Note: For variables we must not push an initial value (such as
832 // 'undefined') because we may have a (legal) redeclaration and we 820 // 'undefined') because we may have a (legal) redeclaration and we
833 // must not destroy the current value. 821 // must not destroy the current value.
834 if (function != NULL) { 822 if (hole_init) {
835 VisitForStackValue(function);
836 } else if (binding_needs_init) {
837 __ PushRoot(Heap::kTheHoleValueRootIndex); 823 __ PushRoot(Heap::kTheHoleValueRootIndex);
838 } else { 824 } else {
839 __ Push(Smi::FromInt(0)); // Indicates no initial value. 825 __ Push(Smi::FromInt(0)); // Indicates no initial value.
840 } 826 }
841 __ CallRuntime(Runtime::kDeclareContextSlot, 4); 827 __ CallRuntime(Runtime::kDeclareContextSlot, 4);
842 break; 828 break;
843 } 829 }
844 } 830 }
845 } 831 }
846 832
847 833
834 void FullCodeGenerator::VisitFunctionDeclaration(
835 FunctionDeclaration* declaration) {
836 VariableProxy* proxy = declaration->proxy();
837 Variable* variable = proxy->var();
838 switch (variable->location()) {
839 case Variable::UNALLOCATED: {
840 globals_->Add(variable->name());
841 Handle<SharedFunctionInfo> function =
842 Compiler::BuildFunctionInfo(declaration->fun(), script());
843 // Check for stack-overflow exception.
844 if (function.is_null()) return SetStackOverflow();
845 globals_->Add(function);
846 break;
847 }
848
849 case Variable::PARAMETER:
850 case Variable::LOCAL: {
851 Comment cmnt(masm_, "[ FunctionDeclaration");
852 VisitForAccumulatorValue(declaration->fun());
853 __ movq(StackOperand(variable), result_register());
854 break;
855 }
856
857 case Variable::CONTEXT: {
858 Comment cmnt(masm_, "[ FunctionDeclaration");
859 EmitDebugCheckDeclarationContext(variable);
860 VisitForAccumulatorValue(declaration->fun());
861 __ movq(ContextOperand(rsi, variable->index()), result_register());
862 int offset = Context::SlotOffset(variable->index());
863 // We know that we have written a function, which is not a smi.
864 __ RecordWriteContextSlot(rsi,
865 offset,
866 result_register(),
867 rcx,
868 kDontSaveFPRegs,
869 EMIT_REMEMBERED_SET,
870 OMIT_SMI_CHECK);
871 PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
872 break;
873 }
874
875 case Variable::LOOKUP: {
876 Comment cmnt(masm_, "[ FunctionDeclaration");
877 __ push(rsi);
878 __ Push(variable->name());
879 __ Push(Smi::FromInt(NONE));
880 VisitForStackValue(declaration->fun());
881 __ CallRuntime(Runtime::kDeclareContextSlot, 4);
882 break;
883 }
884 }
885 }
886
887
888 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) {
889 VariableProxy* proxy = declaration->proxy();
890 Variable* variable = proxy->var();
891 Handle<JSModule> instance = declaration->module()->interface()->Instance();
892 ASSERT(!instance.is_null());
893
894 switch (variable->location()) {
895 case Variable::UNALLOCATED: {
896 Comment cmnt(masm_, "[ ModuleDeclaration");
897 globals_->Add(variable->name());
898 globals_->Add(instance);
899 Visit(declaration->module());
900 break;
901 }
902
903 case Variable::CONTEXT: {
904 Comment cmnt(masm_, "[ ModuleDeclaration");
905 EmitDebugCheckDeclarationContext(variable);
906 __ Move(ContextOperand(rsi, variable->index()), instance);
907 Visit(declaration->module());
908 break;
909 }
910
911 case Variable::PARAMETER:
912 case Variable::LOCAL:
913 case Variable::LOOKUP:
914 UNREACHABLE();
915 }
916 }
917
918
919 void FullCodeGenerator::VisitImportDeclaration(ImportDeclaration* declaration) {
920 VariableProxy* proxy = declaration->proxy();
921 Variable* variable = proxy->var();
922 switch (variable->location()) {
923 case Variable::UNALLOCATED:
924 // TODO(rossberg)
925 break;
926
927 case Variable::CONTEXT: {
928 Comment cmnt(masm_, "[ ImportDeclaration");
929 EmitDebugCheckDeclarationContext(variable);
930 // TODO(rossberg)
931 break;
932 }
933
934 case Variable::PARAMETER:
935 case Variable::LOCAL:
936 case Variable::LOOKUP:
937 UNREACHABLE();
938 }
939 }
940
941
942 void FullCodeGenerator::VisitExportDeclaration(ExportDeclaration* declaration) {
943 // TODO(rossberg)
944 }
945
946
848 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 947 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
849 // Call the runtime to declare the globals. 948 // Call the runtime to declare the globals.
850 __ push(rsi); // The context is the first argument. 949 __ push(rsi); // The context is the first argument.
851 __ Push(pairs); 950 __ Push(pairs);
852 __ Push(Smi::FromInt(DeclareGlobalsFlags())); 951 __ Push(Smi::FromInt(DeclareGlobalsFlags()));
853 __ CallRuntime(Runtime::kDeclareGlobals, 3); 952 __ CallRuntime(Runtime::kDeclareGlobals, 3);
854 // Return value is ignored. 953 // Return value is ignored.
855 } 954 }
856 955
857 956
(...skipping 3547 matching lines...) Expand 10 before | Expand all | Expand 10 after
4405 } 4504 }
4406 4505
4407 4506
4408 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { 4507 void FullCodeGenerator::LoadContextField(Register dst, int context_index) {
4409 __ movq(dst, ContextOperand(rsi, context_index)); 4508 __ movq(dst, ContextOperand(rsi, context_index));
4410 } 4509 }
4411 4510
4412 4511
4413 void FullCodeGenerator::PushFunctionArgumentForContextAllocation() { 4512 void FullCodeGenerator::PushFunctionArgumentForContextAllocation() {
4414 Scope* declaration_scope = scope()->DeclarationScope(); 4513 Scope* declaration_scope = scope()->DeclarationScope();
4415 if (declaration_scope->is_global_scope()) { 4514 if (declaration_scope->is_global_scope() ||
4515 declaration_scope->is_module_scope()) {
4416 // Contexts nested in the global context have a canonical empty function 4516 // Contexts nested in the global context have a canonical empty function
4417 // as their closure, not the anonymous closure containing the global 4517 // as their closure, not the anonymous closure containing the global
4418 // code. Pass a smi sentinel and let the runtime look up the empty 4518 // code. Pass a smi sentinel and let the runtime look up the empty
4419 // function. 4519 // function.
4420 __ Push(Smi::FromInt(0)); 4520 __ Push(Smi::FromInt(0));
4421 } else if (declaration_scope->is_eval_scope()) { 4521 } else if (declaration_scope->is_eval_scope()) {
4422 // Contexts created by a call to eval have the same closure as the 4522 // Contexts created by a call to eval have the same closure as the
4423 // context calling eval, not the anonymous closure containing the eval 4523 // context calling eval, not the anonymous closure containing the eval
4424 // code. Fetch it from the context. 4524 // code. Fetch it from the context.
4425 __ push(ContextOperand(rsi, Context::CLOSURE_INDEX)); 4525 __ push(ContextOperand(rsi, Context::CLOSURE_INDEX));
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
4487 *context_length = 0; 4587 *context_length = 0;
4488 return previous_; 4588 return previous_;
4489 } 4589 }
4490 4590
4491 4591
4492 #undef __ 4592 #undef __
4493 4593
4494 } } // namespace v8::internal 4594 } } // namespace v8::internal
4495 4595
4496 #endif // V8_TARGET_ARCH_X64 4596 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/code-stubs-x64.cc ('k') | src/x64/lithium-codegen-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698