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

Side by Side Diff: src/full-codegen/mips/full-codegen-mips.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_MIPS 5 #if V8_TARGET_ARCH_MIPS
6 6
7 // Note on Mips implementation: 7 // Note on Mips implementation:
8 // 8 //
9 // The result_register() for mips is the 'v0' register, which is defined 9 // The result_register() for mips is the 'v0' register, which is defined
10 // by the ABI to contain function return values. However, the first 10 // by the ABI to contain function return values. However, the first
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 }; 94 };
95 95
96 96
97 // Generate code for a JS function. On entry to the function the receiver 97 // Generate code for a JS function. On entry to the function the receiver
98 // and arguments have been pushed on the stack left to right. The actual 98 // and arguments have been pushed on the stack left to right. The actual
99 // argument count matches the formal parameter count expected by the 99 // argument count matches the formal parameter count expected by the
100 // function. 100 // function.
101 // 101 //
102 // The live registers are: 102 // The live registers are:
103 // o a1: the JS function object being called (i.e. ourselves) 103 // o a1: the JS function object being called (i.e. ourselves)
104 // o a3: the new target value
104 // o cp: our context 105 // o cp: our context
105 // o fp: our caller's frame pointer 106 // o fp: our caller's frame pointer
106 // o sp: stack pointer 107 // o sp: stack pointer
107 // o ra: return address 108 // o ra: return address
108 // 109 //
109 // The function builds a JS frame. Please see JavaScriptFrameConstants in 110 // The function builds a JS frame. Please see JavaScriptFrameConstants in
110 // frames-mips.h for its layout. 111 // frames-mips.h for its layout.
111 void FullCodeGenerator::Generate() { 112 void FullCodeGenerator::Generate() {
112 CompilationInfo* info = info_; 113 CompilationInfo* info = info_;
113 profiling_counter_ = isolate()->factory()->NewCell( 114 profiling_counter_ = isolate()->factory()->NewCell(
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
185 if (info->scope()->num_heap_slots() > 0) { 186 if (info->scope()->num_heap_slots() > 0) {
186 Comment cmnt(masm_, "[ Allocate context"); 187 Comment cmnt(masm_, "[ Allocate context");
187 // Argument to NewContext is the function, which is still in a1. 188 // Argument to NewContext is the function, which is still in a1.
188 bool need_write_barrier = true; 189 bool need_write_barrier = true;
189 int slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; 190 int slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
190 if (info->scope()->is_script_scope()) { 191 if (info->scope()->is_script_scope()) {
191 __ push(a1); 192 __ push(a1);
192 __ Push(info->scope()->GetScopeInfo(info->isolate())); 193 __ Push(info->scope()->GetScopeInfo(info->isolate()));
193 __ CallRuntime(Runtime::kNewScriptContext, 2); 194 __ CallRuntime(Runtime::kNewScriptContext, 2);
194 PrepareForBailoutForId(BailoutId::ScriptContext(), TOS_REG); 195 PrepareForBailoutForId(BailoutId::ScriptContext(), TOS_REG);
195 } else if (slots <= FastNewContextStub::kMaximumSlots) { 196 // The new target value is not used, clobbering is safe.
196 FastNewContextStub stub(isolate(), slots); 197 DCHECK_NULL(info->scope()->new_target_var());
197 __ CallStub(&stub);
198 // Result of FastNewContextStub is always in new space.
199 need_write_barrier = false;
200 } else { 198 } else {
201 __ push(a1); 199 if (info->scope()->new_target_var() != nullptr) {
202 __ CallRuntime(Runtime::kNewFunctionContext, 1); 200 __ push(a3); // Preserve new target.
201 }
202 if (slots <= FastNewContextStub::kMaximumSlots) {
203 FastNewContextStub stub(isolate(), slots);
204 __ CallStub(&stub);
205 // Result of FastNewContextStub is always in new space.
206 need_write_barrier = false;
207 } else {
208 __ push(a1);
209 __ CallRuntime(Runtime::kNewFunctionContext, 1);
210 }
211 if (info->scope()->new_target_var() != nullptr) {
212 __ pop(a3); // Restore new target.
213 }
203 } 214 }
204 function_in_register_a1 = false; 215 function_in_register_a1 = false;
205 // Context is returned in v0. It replaces the context passed to us. 216 // Context is returned in v0. It replaces the context passed to us.
206 // It's saved in the stack and kept live in cp. 217 // It's saved in the stack and kept live in cp.
207 __ mov(cp, v0); 218 __ mov(cp, v0);
208 __ sw(v0, MemOperand(fp, StandardFrameConstants::kContextOffset)); 219 __ sw(v0, MemOperand(fp, StandardFrameConstants::kContextOffset));
209 // Copy any necessary parameters into the context. 220 // Copy any necessary parameters into the context.
210 int num_parameters = info->scope()->num_parameters(); 221 int num_parameters = info->scope()->num_parameters();
211 int first_parameter = info->scope()->has_this_declaration() ? -1 : 0; 222 int first_parameter = info->scope()->has_this_declaration() ? -1 : 0;
212 for (int i = first_parameter; i < num_parameters; i++) { 223 for (int i = first_parameter; i < num_parameters; i++) {
213 Variable* var = (i == -1) ? scope()->receiver() : scope()->parameter(i); 224 Variable* var = (i == -1) ? scope()->receiver() : scope()->parameter(i);
214 if (var->IsContextSlot()) { 225 if (var->IsContextSlot()) {
215 int parameter_offset = StandardFrameConstants::kCallerSPOffset + 226 int parameter_offset = StandardFrameConstants::kCallerSPOffset +
216 (num_parameters - 1 - i) * kPointerSize; 227 (num_parameters - 1 - i) * kPointerSize;
217 // Load parameter from stack. 228 // Load parameter from stack.
218 __ lw(a0, MemOperand(fp, parameter_offset)); 229 __ lw(a0, MemOperand(fp, parameter_offset));
219 // Store it in the context. 230 // Store it in the context.
220 MemOperand target = ContextMemOperand(cp, var->index()); 231 MemOperand target = ContextMemOperand(cp, var->index());
221 __ sw(a0, target); 232 __ sw(a0, target);
222 233
223 // Update the write barrier. 234 // Update the write barrier.
224 if (need_write_barrier) { 235 if (need_write_barrier) {
225 __ RecordWriteContextSlot( 236 __ RecordWriteContextSlot(cp, target.offset(), a0, a2,
226 cp, target.offset(), a0, a3, kRAHasBeenSaved, kDontSaveFPRegs); 237 kRAHasBeenSaved, kDontSaveFPRegs);
227 } else if (FLAG_debug_code) { 238 } else if (FLAG_debug_code) {
228 Label done; 239 Label done;
229 __ JumpIfInNewSpace(cp, a0, &done); 240 __ JumpIfInNewSpace(cp, a0, &done);
230 __ Abort(kExpectedNewSpaceObject); 241 __ Abort(kExpectedNewSpaceObject);
231 __ bind(&done); 242 __ bind(&done);
232 } 243 }
233 } 244 }
234 } 245 }
235 } 246 }
247
248 // Register holding this function and new target are both trashed in case we
249 // bailout here. But since that can happen only when new target is not used
250 // and we allocate a context, the value of |function_in_register| is correct.
236 PrepareForBailoutForId(BailoutId::FunctionContext(), NO_REGISTERS); 251 PrepareForBailoutForId(BailoutId::FunctionContext(), NO_REGISTERS);
237 252
238 // Function register is trashed in case we bailout here. But since that
239 // could happen only when we allocate a context the value of
240 // |function_in_register_a1| is correct.
241
242 // Possibly set up a local binding to the this function which is used in 253 // Possibly set up a local binding to the this function which is used in
243 // derived constructors with super calls. 254 // derived constructors with super calls.
244 Variable* this_function_var = scope()->this_function_var(); 255 Variable* this_function_var = scope()->this_function_var();
245 if (this_function_var != nullptr) { 256 if (this_function_var != nullptr) {
246 Comment cmnt(masm_, "[ This function"); 257 Comment cmnt(masm_, "[ This function");
247 if (!function_in_register_a1) { 258 if (!function_in_register_a1) {
248 __ lw(a1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 259 __ lw(a1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
249 // The write barrier clobbers register again, keep it marked as such. 260 // The write barrier clobbers register again, keep it marked as such.
250 } 261 }
251 SetVar(this_function_var, a1, a2, a3); 262 SetVar(this_function_var, a1, a0, a2);
252 } 263 }
253 264
265 // Possibly set up a local binding to the new target value.
254 Variable* new_target_var = scope()->new_target_var(); 266 Variable* new_target_var = scope()->new_target_var();
255 if (new_target_var != nullptr) { 267 if (new_target_var != nullptr) {
256 Comment cmnt(masm_, "[ new.target"); 268 Comment cmnt(masm_, "[ new.target");
257 269 SetVar(new_target_var, a3, a0, a2);
258 // Get the frame pointer for the calling frame.
259 __ lw(a2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
260
261 // Skip the arguments adaptor frame if it exists.
262 Label check_frame_marker;
263 __ lw(a1, MemOperand(a2, StandardFrameConstants::kContextOffset));
264 __ Branch(&check_frame_marker, ne, a1,
265 Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
266 __ lw(a2, MemOperand(a2, StandardFrameConstants::kCallerFPOffset));
267
268 // Check the marker in the calling frame.
269 __ bind(&check_frame_marker);
270 __ lw(a1, MemOperand(a2, StandardFrameConstants::kMarkerOffset));
271 function_in_register_a1 = false;
272
273 Label non_construct_frame, done;
274 __ Branch(&non_construct_frame, ne, a1,
275 Operand(Smi::FromInt(StackFrame::CONSTRUCT)));
276
277 __ lw(v0, MemOperand(a2, ConstructFrameConstants::kNewTargetOffset));
278 __ Branch(&done);
279
280 __ bind(&non_construct_frame);
281 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex);
282 __ bind(&done);
283
284 SetVar(new_target_var, v0, a2, a3);
285 } 270 }
286 271
287 Variable* arguments = scope()->arguments(); 272 Variable* arguments = scope()->arguments();
288 if (arguments != NULL) { 273 if (arguments != NULL) {
289 // Function uses arguments object. 274 // Function uses arguments object.
290 Comment cmnt(masm_, "[ Allocate arguments object"); 275 Comment cmnt(masm_, "[ Allocate arguments object");
291 DCHECK(a1.is(ArgumentsAccessNewDescriptor::function())); 276 DCHECK(a1.is(ArgumentsAccessNewDescriptor::function()));
292 if (!function_in_register_a1) { 277 if (!function_in_register_a1) {
293 // Load this again, if it's used by the local context below. 278 // Load this again, if it's used by the local context below.
294 __ lw(a1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 279 __ lw(a1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
(...skipping 4643 matching lines...) Expand 10 before | Expand all | Expand 10 after
4938 reinterpret_cast<uint32_t>( 4923 reinterpret_cast<uint32_t>(
4939 isolate->builtins()->OsrAfterStackCheck()->entry())); 4924 isolate->builtins()->OsrAfterStackCheck()->entry()));
4940 return OSR_AFTER_STACK_CHECK; 4925 return OSR_AFTER_STACK_CHECK;
4941 } 4926 }
4942 4927
4943 4928
4944 } // namespace internal 4929 } // namespace internal
4945 } // namespace v8 4930 } // namespace v8
4946 4931
4947 #endif // V8_TARGET_ARCH_MIPS 4932 #endif // V8_TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « src/full-codegen/ia32/full-codegen-ia32.cc ('k') | src/full-codegen/mips64/full-codegen-mips64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698