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

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

Issue 1492793002: [fullcode] Switch passing of new.target to register. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Ported. Created 5 years 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
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #if V8_TARGET_ARCH_X64 5 #if V8_TARGET_ARCH_X64
6 6
7 #include "src/ast/scopes.h" 7 #include "src/ast/scopes.h"
8 #include "src/code-factory.h" 8 #include "src/code-factory.h"
9 #include "src/code-stubs.h" 9 #include "src/code-stubs.h"
10 #include "src/codegen.h" 10 #include "src/codegen.h"
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
75 }; 75 };
76 76
77 77
78 // Generate code for a JS function. On entry to the function the receiver 78 // Generate code for a JS function. On entry to the function the receiver
79 // and arguments have been pushed on the stack left to right, with the 79 // and arguments have been pushed on the stack left to right, with the
80 // return address on top of them. The actual argument count matches the 80 // return address on top of them. The actual argument count matches the
81 // formal parameter count expected by the function. 81 // formal parameter count expected by the function.
82 // 82 //
83 // The live registers are: 83 // The live registers are:
84 // o rdi: the JS function object being called (i.e. ourselves) 84 // o rdi: the JS function object being called (i.e. ourselves)
85 // o rdx: the new target value
85 // o rsi: our context 86 // o rsi: our context
86 // o rbp: our caller's frame pointer 87 // o rbp: our caller's frame pointer
87 // o rsp: stack pointer (pointing to return address) 88 // o rsp: stack pointer (pointing to return address)
88 // 89 //
89 // The function builds a JS frame. Please see JavaScriptFrameConstants in 90 // The function builds a JS frame. Please see JavaScriptFrameConstants in
90 // frames-x64.h for its layout. 91 // frames-x64.h for its layout.
91 void FullCodeGenerator::Generate() { 92 void FullCodeGenerator::Generate() {
92 CompilationInfo* info = info_; 93 CompilationInfo* info = info_;
93 profiling_counter_ = isolate()->factory()->NewCell( 94 profiling_counter_ = isolate()->factory()->NewCell(
94 Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate())); 95 Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
129 } else if (locals_count > 1) { 130 } else if (locals_count > 1) {
130 if (locals_count >= 128) { 131 if (locals_count >= 128) {
131 Label ok; 132 Label ok;
132 __ movp(rcx, rsp); 133 __ movp(rcx, rsp);
133 __ subp(rcx, Immediate(locals_count * kPointerSize)); 134 __ subp(rcx, Immediate(locals_count * kPointerSize));
134 __ CompareRoot(rcx, Heap::kRealStackLimitRootIndex); 135 __ CompareRoot(rcx, Heap::kRealStackLimitRootIndex);
135 __ j(above_equal, &ok, Label::kNear); 136 __ j(above_equal, &ok, Label::kNear);
136 __ CallRuntime(Runtime::kThrowStackOverflow, 0); 137 __ CallRuntime(Runtime::kThrowStackOverflow, 0);
137 __ bind(&ok); 138 __ bind(&ok);
138 } 139 }
139 __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex); 140 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
140 const int kMaxPushes = 32; 141 const int kMaxPushes = 32;
141 if (locals_count >= kMaxPushes) { 142 if (locals_count >= kMaxPushes) {
142 int loop_iterations = locals_count / kMaxPushes; 143 int loop_iterations = locals_count / kMaxPushes;
143 __ movp(rcx, Immediate(loop_iterations)); 144 __ movp(rcx, Immediate(loop_iterations));
144 Label loop_header; 145 Label loop_header;
145 __ bind(&loop_header); 146 __ bind(&loop_header);
146 // Do pushes. 147 // Do pushes.
147 for (int i = 0; i < kMaxPushes; i++) { 148 for (int i = 0; i < kMaxPushes; i++) {
148 __ Push(rdx); 149 __ Push(rax);
149 } 150 }
150 // Continue loop if not done. 151 // Continue loop if not done.
151 __ decp(rcx); 152 __ decp(rcx);
152 __ j(not_zero, &loop_header, Label::kNear); 153 __ j(not_zero, &loop_header, Label::kNear);
153 } 154 }
154 int remaining = locals_count % kMaxPushes; 155 int remaining = locals_count % kMaxPushes;
155 // Emit the remaining pushes. 156 // Emit the remaining pushes.
156 for (int i = 0; i < remaining; i++) { 157 for (int i = 0; i < remaining; i++) {
157 __ Push(rdx); 158 __ Push(rax);
158 } 159 }
159 } 160 }
160 } 161 }
161 162
162 bool function_in_register = true; 163 bool function_in_register = true;
163 164
164 // Possibly allocate a local context. 165 // Possibly allocate a local context.
165 if (info->scope()->num_heap_slots() > 0) { 166 if (info->scope()->num_heap_slots() > 0) {
166 Comment cmnt(masm_, "[ Allocate context"); 167 Comment cmnt(masm_, "[ Allocate context");
167 bool need_write_barrier = true; 168 bool need_write_barrier = true;
168 int slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; 169 int slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
169 // Argument to NewContext is the function, which is still in rdi. 170 // Argument to NewContext is the function, which is still in rdi.
170 if (info->scope()->is_script_scope()) { 171 if (info->scope()->is_script_scope()) {
171 __ Push(rdi); 172 __ Push(rdi);
172 __ Push(info->scope()->GetScopeInfo(info->isolate())); 173 __ Push(info->scope()->GetScopeInfo(info->isolate()));
173 __ CallRuntime(Runtime::kNewScriptContext, 2); 174 __ CallRuntime(Runtime::kNewScriptContext, 2);
174 PrepareForBailoutForId(BailoutId::ScriptContext(), TOS_REG); 175 PrepareForBailoutForId(BailoutId::ScriptContext(), TOS_REG);
175 } else if (slots <= FastNewContextStub::kMaximumSlots) { 176 // The new target value is not used, clobbering is safe.
176 FastNewContextStub stub(isolate(), slots); 177 DCHECK_NULL(info->scope()->new_target_var());
177 __ CallStub(&stub);
178 // Result of FastNewContextStub is always in new space.
179 need_write_barrier = false;
180 } else { 178 } else {
181 __ Push(rdi); 179 if (info->scope()->new_target_var() != nullptr) {
182 __ CallRuntime(Runtime::kNewFunctionContext, 1); 180 __ Push(rdx); // Preserve new target.
181 }
182 if (slots <= FastNewContextStub::kMaximumSlots) {
183 FastNewContextStub stub(isolate(), slots);
184 __ CallStub(&stub);
185 // Result of FastNewContextStub is always in new space.
186 need_write_barrier = false;
187 } else {
188 __ Push(rdi);
189 __ CallRuntime(Runtime::kNewFunctionContext, 1);
190 }
191 if (info->scope()->new_target_var() != nullptr) {
192 __ Pop(rdx); // Restore new target.
193 }
183 } 194 }
184 function_in_register = false; 195 function_in_register = false;
185 // Context is returned in rax. It replaces the context passed to us. 196 // Context is returned in rax. It replaces the context passed to us.
186 // It's saved in the stack and kept live in rsi. 197 // It's saved in the stack and kept live in rsi.
187 __ movp(rsi, rax); 198 __ movp(rsi, rax);
188 __ movp(Operand(rbp, StandardFrameConstants::kContextOffset), rax); 199 __ movp(Operand(rbp, StandardFrameConstants::kContextOffset), rax);
189 200
190 // Copy any necessary parameters into the context. 201 // Copy any necessary parameters into the context.
191 int num_parameters = info->scope()->num_parameters(); 202 int num_parameters = info->scope()->num_parameters();
192 int first_parameter = info->scope()->has_this_declaration() ? -1 : 0; 203 int first_parameter = info->scope()->has_this_declaration() ? -1 : 0;
(...skipping 13 matching lines...) Expand all
206 rsi, context_offset, rax, rbx, kDontSaveFPRegs); 217 rsi, context_offset, rax, rbx, kDontSaveFPRegs);
207 } else if (FLAG_debug_code) { 218 } else if (FLAG_debug_code) {
208 Label done; 219 Label done;
209 __ JumpIfInNewSpace(rsi, rax, &done, Label::kNear); 220 __ JumpIfInNewSpace(rsi, rax, &done, Label::kNear);
210 __ Abort(kExpectedNewSpaceObject); 221 __ Abort(kExpectedNewSpaceObject);
211 __ bind(&done); 222 __ bind(&done);
212 } 223 }
213 } 224 }
214 } 225 }
215 } 226 }
227
228 // Register holding this function and new target are both trashed in case we
229 // bailout here. But since that can happen only when new target is not used
230 // and we allocate a context, the value of |function_in_register| is correct.
216 PrepareForBailoutForId(BailoutId::FunctionContext(), NO_REGISTERS); 231 PrepareForBailoutForId(BailoutId::FunctionContext(), NO_REGISTERS);
217 232
218 // Function register is trashed in case we bailout here. But since that
219 // could happen only when we allocate a context the value of
220 // |function_in_register| is correct.
221
222 // Possibly set up a local binding to the this function which is used in 233 // Possibly set up a local binding to the this function which is used in
223 // derived constructors with super calls. 234 // derived constructors with super calls.
224 Variable* this_function_var = scope()->this_function_var(); 235 Variable* this_function_var = scope()->this_function_var();
225 if (this_function_var != nullptr) { 236 if (this_function_var != nullptr) {
226 Comment cmnt(masm_, "[ This function"); 237 Comment cmnt(masm_, "[ This function");
227 if (!function_in_register) { 238 if (!function_in_register) {
228 __ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 239 __ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
229 // The write barrier clobbers register again, keep it marked as such. 240 // The write barrier clobbers register again, keep it marked as such.
230 } 241 }
231 SetVar(this_function_var, rdi, rbx, rdx); 242 SetVar(this_function_var, rdi, rbx, rcx);
232 } 243 }
233 244
245 // Possibly set up a local binding to the new target value.
234 Variable* new_target_var = scope()->new_target_var(); 246 Variable* new_target_var = scope()->new_target_var();
235 if (new_target_var != nullptr) { 247 if (new_target_var != nullptr) {
236 Comment cmnt(masm_, "[ new.target"); 248 Comment cmnt(masm_, "[ new.target");
237 249 SetVar(new_target_var, rdx, rbx, rcx);
238 __ movp(rax, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
239 Label non_adaptor_frame;
240 __ Cmp(Operand(rax, StandardFrameConstants::kContextOffset),
241 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
242 __ j(not_equal, &non_adaptor_frame);
243 __ movp(rax, Operand(rax, StandardFrameConstants::kCallerFPOffset));
244
245 __ bind(&non_adaptor_frame);
246 __ Cmp(Operand(rax, StandardFrameConstants::kMarkerOffset),
247 Smi::FromInt(StackFrame::CONSTRUCT));
248
249 Label non_construct_frame, done;
250 __ j(not_equal, &non_construct_frame);
251
252 // Construct frame
253 __ movp(rax, Operand(rax, ConstructFrameConstants::kNewTargetOffset));
254 __ jmp(&done);
255
256 // Non-construct frame
257 __ bind(&non_construct_frame);
258 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
259
260 __ bind(&done);
261 SetVar(new_target_var, rax, rbx, rdx);
262 } 250 }
263 251
264 // Possibly allocate an arguments object. 252 // Possibly allocate an arguments object.
265 Variable* arguments = scope()->arguments(); 253 Variable* arguments = scope()->arguments();
266 if (arguments != NULL) { 254 if (arguments != NULL) {
267 // Arguments object must be allocated after the context object, in 255 // Arguments object must be allocated after the context object, in
268 // case the "arguments" or ".arguments" variables are in the context. 256 // case the "arguments" or ".arguments" variables are in the context.
269 Comment cmnt(masm_, "[ Allocate arguments object"); 257 Comment cmnt(masm_, "[ Allocate arguments object");
270 DCHECK(rdi.is(ArgumentsAccessNewDescriptor::function())); 258 DCHECK(rdi.is(ArgumentsAccessNewDescriptor::function()));
271 if (!function_in_register) { 259 if (!function_in_register) {
(...skipping 4576 matching lines...) Expand 10 before | Expand all | Expand 10 after
4848 Assembler::target_address_at(call_target_address, 4836 Assembler::target_address_at(call_target_address,
4849 unoptimized_code)); 4837 unoptimized_code));
4850 return OSR_AFTER_STACK_CHECK; 4838 return OSR_AFTER_STACK_CHECK;
4851 } 4839 }
4852 4840
4853 4841
4854 } // namespace internal 4842 } // namespace internal
4855 } // namespace v8 4843 } // namespace v8
4856 4844
4857 #endif // V8_TARGET_ARCH_X64 4845 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/full-codegen/mips64/full-codegen-mips64.cc ('k') | test/mjsunit/es6/regress/regress-new-target-context.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698