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

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

Issue 566008: Incorporate the arguments to the code generator constructors and their (Closed)
Patch Set: Incorporate the arguments to the code generator constructors and their... Created 10 years, 10 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
« no previous file with comments | « src/x64/fast-codegen-x64.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
44 // formal parameter count expected by the function. 44 // formal parameter count expected by the function.
45 // 45 //
46 // The live registers are: 46 // The live registers are:
47 // o rdi: the JS function object being called (ie, ourselves) 47 // o rdi: the JS function object being called (ie, ourselves)
48 // o rsi: our context 48 // o rsi: our context
49 // o rbp: our caller's frame pointer 49 // o rbp: our caller's frame pointer
50 // o rsp: stack pointer (pointing to return address) 50 // o rsp: stack pointer (pointing to return address)
51 // 51 //
52 // The function builds a JS frame. Please see JavaScriptFrameConstants in 52 // The function builds a JS frame. Please see JavaScriptFrameConstants in
53 // frames-x64.h for its layout. 53 // frames-x64.h for its layout.
54 void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) { 54 void FullCodeGenerator::Generate(CompilationInfo* info, Mode mode) {
55 function_ = fun; 55 ASSERT(info_ == NULL);
56 SetFunctionPosition(fun); 56 info_ = info;
57 SetFunctionPosition(function());
57 58
58 if (mode == PRIMARY) { 59 if (mode == PRIMARY) {
59 __ push(rbp); // Caller's frame pointer. 60 __ push(rbp); // Caller's frame pointer.
60 __ movq(rbp, rsp); 61 __ movq(rbp, rsp);
61 __ push(rsi); // Callee's context. 62 __ push(rsi); // Callee's context.
62 __ push(rdi); // Callee's JS Function. 63 __ push(rdi); // Callee's JS Function.
63 64
64 { Comment cmnt(masm_, "[ Allocate locals"); 65 { Comment cmnt(masm_, "[ Allocate locals");
65 int locals_count = fun->scope()->num_stack_slots(); 66 int locals_count = scope()->num_stack_slots();
66 if (locals_count == 1) { 67 if (locals_count == 1) {
67 __ PushRoot(Heap::kUndefinedValueRootIndex); 68 __ PushRoot(Heap::kUndefinedValueRootIndex);
68 } else if (locals_count > 1) { 69 } else if (locals_count > 1) {
69 __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex); 70 __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex);
70 for (int i = 0; i < locals_count; i++) { 71 for (int i = 0; i < locals_count; i++) {
71 __ push(rdx); 72 __ push(rdx);
72 } 73 }
73 } 74 }
74 } 75 }
75 76
76 bool function_in_register = true; 77 bool function_in_register = true;
77 78
78 // Possibly allocate a local context. 79 // Possibly allocate a local context.
79 if (fun->scope()->num_heap_slots() > 0) { 80 if (scope()->num_heap_slots() > 0) {
80 Comment cmnt(masm_, "[ Allocate local context"); 81 Comment cmnt(masm_, "[ Allocate local context");
81 // Argument to NewContext is the function, which is still in rdi. 82 // Argument to NewContext is the function, which is still in rdi.
82 __ push(rdi); 83 __ push(rdi);
83 __ CallRuntime(Runtime::kNewContext, 1); 84 __ CallRuntime(Runtime::kNewContext, 1);
84 function_in_register = false; 85 function_in_register = false;
85 // Context is returned in both rax and rsi. It replaces the context 86 // Context is returned in both rax and rsi. It replaces the context
86 // passed to us. It's saved in the stack and kept live in rsi. 87 // passed to us. It's saved in the stack and kept live in rsi.
87 __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi); 88 __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi);
88 89
89 // Copy any necessary parameters into the context. 90 // Copy any necessary parameters into the context.
90 int num_parameters = fun->scope()->num_parameters(); 91 int num_parameters = scope()->num_parameters();
91 for (int i = 0; i < num_parameters; i++) { 92 for (int i = 0; i < num_parameters; i++) {
92 Slot* slot = fun->scope()->parameter(i)->slot(); 93 Slot* slot = scope()->parameter(i)->slot();
93 if (slot != NULL && slot->type() == Slot::CONTEXT) { 94 if (slot != NULL && slot->type() == Slot::CONTEXT) {
94 int parameter_offset = StandardFrameConstants::kCallerSPOffset + 95 int parameter_offset = StandardFrameConstants::kCallerSPOffset +
95 (num_parameters - 1 - i) * kPointerSize; 96 (num_parameters - 1 - i) * kPointerSize;
96 // Load parameter from stack. 97 // Load parameter from stack.
97 __ movq(rax, Operand(rbp, parameter_offset)); 98 __ movq(rax, Operand(rbp, parameter_offset));
98 // Store it in the context. 99 // Store it in the context.
99 int context_offset = Context::SlotOffset(slot->index()); 100 int context_offset = Context::SlotOffset(slot->index());
100 __ movq(Operand(rsi, context_offset), rax); 101 __ movq(Operand(rsi, context_offset), rax);
101 // Update the write barrier. This clobbers all involved 102 // Update the write barrier. This clobbers all involved
102 // registers, so we have use a third register to avoid 103 // registers, so we have use a third register to avoid
103 // clobbering rsi. 104 // clobbering rsi.
104 __ movq(rcx, rsi); 105 __ movq(rcx, rsi);
105 __ RecordWrite(rcx, context_offset, rax, rbx); 106 __ RecordWrite(rcx, context_offset, rax, rbx);
106 } 107 }
107 } 108 }
108 } 109 }
109 110
110 // Possibly allocate an arguments object. 111 // Possibly allocate an arguments object.
111 Variable* arguments = fun->scope()->arguments()->AsVariable(); 112 Variable* arguments = scope()->arguments()->AsVariable();
112 if (arguments != NULL) { 113 if (arguments != NULL) {
113 // Arguments object must be allocated after the context object, in 114 // Arguments object must be allocated after the context object, in
114 // case the "arguments" or ".arguments" variables are in the context. 115 // case the "arguments" or ".arguments" variables are in the context.
115 Comment cmnt(masm_, "[ Allocate arguments object"); 116 Comment cmnt(masm_, "[ Allocate arguments object");
116 if (function_in_register) { 117 if (function_in_register) {
117 __ push(rdi); 118 __ push(rdi);
118 } else { 119 } else {
119 __ push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 120 __ push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
120 } 121 }
121 // The receiver is just before the parameters on the caller's stack. 122 // The receiver is just before the parameters on the caller's stack.
122 __ lea(rdx, Operand(rbp, StandardFrameConstants::kCallerSPOffset + 123 int offset = scope()->num_parameters() * kPointerSize;
123 fun->num_parameters() * kPointerSize)); 124 __ lea(rdx,
125 Operand(rbp, StandardFrameConstants::kCallerSPOffset + offset));
124 __ push(rdx); 126 __ push(rdx);
125 __ Push(Smi::FromInt(fun->num_parameters())); 127 __ Push(Smi::FromInt(scope()->num_parameters()));
126 // Arguments to ArgumentsAccessStub: 128 // Arguments to ArgumentsAccessStub:
127 // function, receiver address, parameter count. 129 // function, receiver address, parameter count.
128 // The stub will rewrite receiver and parameter count if the previous 130 // The stub will rewrite receiver and parameter count if the previous
129 // stack frame was an arguments adapter frame. 131 // stack frame was an arguments adapter frame.
130 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); 132 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
131 __ CallStub(&stub); 133 __ CallStub(&stub);
132 // Store new arguments object in both "arguments" and ".arguments" slots. 134 // Store new arguments object in both "arguments" and ".arguments" slots.
133 __ movq(rcx, rax); 135 __ movq(rcx, rax);
134 Move(arguments->slot(), rax, rbx, rdx); 136 Move(arguments->slot(), rax, rbx, rdx);
135 Slot* dot_arguments_slot = 137 Slot* dot_arguments_slot =
136 fun->scope()->arguments_shadow()->AsVariable()->slot(); 138 scope()->arguments_shadow()->AsVariable()->slot();
137 Move(dot_arguments_slot, rcx, rbx, rdx); 139 Move(dot_arguments_slot, rcx, rbx, rdx);
138 } 140 }
139 } 141 }
140 142
141 { Comment cmnt(masm_, "[ Declarations"); 143 { Comment cmnt(masm_, "[ Declarations");
142 VisitDeclarations(fun->scope()->declarations()); 144 VisitDeclarations(scope()->declarations());
143 } 145 }
144 146
145 { Comment cmnt(masm_, "[ Stack check"); 147 { Comment cmnt(masm_, "[ Stack check");
146 Label ok; 148 Label ok;
147 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); 149 __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
148 __ j(above_equal, &ok); 150 __ j(above_equal, &ok);
149 StackCheckStub stub; 151 StackCheckStub stub;
150 __ CallStub(&stub); 152 __ CallStub(&stub);
151 __ bind(&ok); 153 __ bind(&ok);
152 } 154 }
153 155
154 if (FLAG_trace) { 156 if (FLAG_trace) {
155 __ CallRuntime(Runtime::kTraceEnter, 0); 157 __ CallRuntime(Runtime::kTraceEnter, 0);
156 } 158 }
157 159
158 { Comment cmnt(masm_, "[ Body"); 160 { Comment cmnt(masm_, "[ Body");
159 ASSERT(loop_depth() == 0); 161 ASSERT(loop_depth() == 0);
160 VisitStatements(fun->body()); 162 VisitStatements(function()->body());
161 ASSERT(loop_depth() == 0); 163 ASSERT(loop_depth() == 0);
162 } 164 }
163 165
164 { Comment cmnt(masm_, "[ return <undefined>;"); 166 { Comment cmnt(masm_, "[ return <undefined>;");
165 // Emit a 'return undefined' in case control fell off the end of the body. 167 // Emit a 'return undefined' in case control fell off the end of the body.
166 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 168 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
167 EmitReturnSequence(function_->end_position()); 169 EmitReturnSequence(function()->end_position());
168 } 170 }
169 } 171 }
170 172
171 173
172 void FullCodeGenerator::EmitReturnSequence(int position) { 174 void FullCodeGenerator::EmitReturnSequence(int position) {
173 Comment cmnt(masm_, "[ Return sequence"); 175 Comment cmnt(masm_, "[ Return sequence");
174 if (return_label_.is_bound()) { 176 if (return_label_.is_bound()) {
175 __ jmp(&return_label_); 177 __ jmp(&return_label_);
176 } else { 178 } else {
177 __ bind(&return_label_); 179 __ bind(&return_label_);
178 if (FLAG_trace) { 180 if (FLAG_trace) {
179 __ push(rax); 181 __ push(rax);
180 __ CallRuntime(Runtime::kTraceExit, 1); 182 __ CallRuntime(Runtime::kTraceExit, 1);
181 } 183 }
182 #ifdef DEBUG 184 #ifdef DEBUG
183 // Add a label for checking the size of the code used for returning. 185 // Add a label for checking the size of the code used for returning.
184 Label check_exit_codesize; 186 Label check_exit_codesize;
185 masm_->bind(&check_exit_codesize); 187 masm_->bind(&check_exit_codesize);
186 #endif 188 #endif
187 CodeGenerator::RecordPositions(masm_, position); 189 CodeGenerator::RecordPositions(masm_, position);
188 __ RecordJSReturn(); 190 __ RecordJSReturn();
189 // Do not use the leave instruction here because it is too short to 191 // Do not use the leave instruction here because it is too short to
190 // patch with the code required by the debugger. 192 // patch with the code required by the debugger.
191 __ movq(rsp, rbp); 193 __ movq(rsp, rbp);
192 __ pop(rbp); 194 __ pop(rbp);
193 __ ret((function_->scope()->num_parameters() + 1) * kPointerSize); 195 __ ret((scope()->num_parameters() + 1) * kPointerSize);
194 #ifdef ENABLE_DEBUGGER_SUPPORT 196 #ifdef ENABLE_DEBUGGER_SUPPORT
195 // Add padding that will be overwritten by a debugger breakpoint. We 197 // Add padding that will be overwritten by a debugger breakpoint. We
196 // have just generated "movq rsp, rbp; pop rbp; ret k" with length 7 198 // have just generated "movq rsp, rbp; pop rbp; ret k" with length 7
197 // (3 + 1 + 3). 199 // (3 + 1 + 3).
198 const int kPadding = Assembler::kJSReturnSequenceLength - 7; 200 const int kPadding = Assembler::kJSReturnSequenceLength - 7;
199 for (int i = 0; i < kPadding; ++i) { 201 for (int i = 0; i < kPadding; ++i) {
200 masm_->int3(); 202 masm_->int3();
201 } 203 }
202 // Check that the size of the code used for returning matches what is 204 // Check that the size of the code used for returning matches what is
203 // expected by the debugger. 205 // expected by the debugger.
(...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after
622 } 624 }
623 625
624 626
625 MemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { 627 MemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) {
626 switch (slot->type()) { 628 switch (slot->type()) {
627 case Slot::PARAMETER: 629 case Slot::PARAMETER:
628 case Slot::LOCAL: 630 case Slot::LOCAL:
629 return Operand(rbp, SlotOffset(slot)); 631 return Operand(rbp, SlotOffset(slot));
630 case Slot::CONTEXT: { 632 case Slot::CONTEXT: {
631 int context_chain_length = 633 int context_chain_length =
632 function_->scope()->ContextChainLength(slot->var()->scope()); 634 scope()->ContextChainLength(slot->var()->scope());
633 __ LoadContext(scratch, context_chain_length); 635 __ LoadContext(scratch, context_chain_length);
634 return CodeGenerator::ContextOperand(scratch, slot->index()); 636 return CodeGenerator::ContextOperand(scratch, slot->index());
635 } 637 }
636 case Slot::LOOKUP: 638 case Slot::LOOKUP:
637 UNREACHABLE(); 639 UNREACHABLE();
638 } 640 }
639 UNREACHABLE(); 641 UNREACHABLE();
640 return Operand(rax, 0); 642 return Operand(rax, 0);
641 } 643 }
642 644
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
681 VisitForValue(decl->fun(), kAccumulator); 683 VisitForValue(decl->fun(), kAccumulator);
682 __ movq(Operand(rbp, SlotOffset(slot)), result_register()); 684 __ movq(Operand(rbp, SlotOffset(slot)), result_register());
683 } 685 }
684 break; 686 break;
685 687
686 case Slot::CONTEXT: 688 case Slot::CONTEXT:
687 // We bypass the general EmitSlotSearch because we know more about 689 // We bypass the general EmitSlotSearch because we know more about
688 // this specific context. 690 // this specific context.
689 691
690 // The variable in the decl always resides in the current context. 692 // The variable in the decl always resides in the current context.
691 ASSERT_EQ(0, function_->scope()->ContextChainLength(var->scope())); 693 ASSERT_EQ(0, scope()->ContextChainLength(var->scope()));
692 if (FLAG_debug_code) { 694 if (FLAG_debug_code) {
693 // Check if we have the correct context pointer. 695 // Check if we have the correct context pointer.
694 __ movq(rbx, 696 __ movq(rbx,
695 CodeGenerator::ContextOperand(rsi, Context::FCONTEXT_INDEX)); 697 CodeGenerator::ContextOperand(rsi, Context::FCONTEXT_INDEX));
696 __ cmpq(rbx, rsi); 698 __ cmpq(rbx, rsi);
697 __ Check(equal, "Unexpected declaration in current context."); 699 __ Check(equal, "Unexpected declaration in current context.");
698 } 700 }
699 if (decl->mode() == Variable::CONST) { 701 if (decl->mode() == Variable::CONST) {
700 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); 702 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
701 __ movq(CodeGenerator::ContextOperand(rsi, slot->index()), 703 __ movq(CodeGenerator::ContextOperand(rsi, slot->index()),
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
760 __ Drop(2); 762 __ Drop(2);
761 } 763 }
762 } 764 }
763 } 765 }
764 766
765 767
766 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 768 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
767 // Call the runtime to declare the globals. 769 // Call the runtime to declare the globals.
768 __ push(rsi); // The context is the first argument. 770 __ push(rsi); // The context is the first argument.
769 __ Push(pairs); 771 __ Push(pairs);
770 __ Push(Smi::FromInt(is_eval_ ? 1 : 0)); 772 __ Push(Smi::FromInt(is_eval() ? 1 : 0));
771 __ CallRuntime(Runtime::kDeclareGlobals, 3); 773 __ CallRuntime(Runtime::kDeclareGlobals, 3);
772 // Return value is ignored. 774 // Return value is ignored.
773 } 775 }
774 776
775 777
776 void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { 778 void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
777 Comment cmnt(masm_, "[ FunctionLiteral"); 779 Comment cmnt(masm_, "[ FunctionLiteral");
778 780
779 // Build the function boilerplate and instantiate it. 781 // Build the function boilerplate and instantiate it.
780 Handle<JSFunction> boilerplate = 782 Handle<JSFunction> boilerplate =
781 Compiler::BuildBoilerplate(expr, script_, this); 783 Compiler::BuildBoilerplate(expr, script(), this);
782 if (HasStackOverflow()) return; 784 if (HasStackOverflow()) return;
783 785
784 ASSERT(boilerplate->IsBoilerplate()); 786 ASSERT(boilerplate->IsBoilerplate());
785 787
786 // Create a new closure. 788 // Create a new closure.
787 __ push(rsi); 789 __ push(rsi);
788 __ Push(boilerplate); 790 __ Push(boilerplate);
789 __ CallRuntime(Runtime::kNewClosure, 2); 791 __ CallRuntime(Runtime::kNewClosure, 2);
790 Apply(context_, rax); 792 Apply(context_, rax);
791 } 793 }
(...skipping 1106 matching lines...) Expand 10 before | Expand all | Expand 10 after
1898 __ movq(Operand(rsp, 0), rdx); 1900 __ movq(Operand(rsp, 0), rdx);
1899 // And return. 1901 // And return.
1900 __ ret(0); 1902 __ ret(0);
1901 } 1903 }
1902 1904
1903 1905
1904 #undef __ 1906 #undef __
1905 1907
1906 1908
1907 } } // namespace v8::internal 1909 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/x64/fast-codegen-x64.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698