blob: 3a9980beabd405d60fba64d5deba848350f98d32 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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
3// found in the LICENSE file.
4
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005#if V8_TARGET_ARCH_MIPS64
6
7#include "src/codegen.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008#include "src/debug/debug.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009#include "src/deoptimizer.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010#include "src/full-codegen/full-codegen.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040011#include "src/runtime/runtime.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012
13namespace v8 {
14namespace internal {
15
16
17#define __ ACCESS_MASM(masm)
18
19
20void Builtins::Generate_Adaptor(MacroAssembler* masm,
21 CFunctionId id,
22 BuiltinExtraArguments extra_args) {
23 // ----------- S t a t e -------------
24 // -- a0 : number of arguments excluding receiver
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000025 // -- a1 : target
26 // -- a3 : new.target
Ben Murdochb8a8cc12014-11-26 15:28:44 +000027 // -- sp[0] : last argument
28 // -- ...
29 // -- sp[8 * (argc - 1)] : first argument
30 // -- sp[8 * agrc] : receiver
31 // -----------------------------------
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000032 __ AssertFunction(a1);
33
34 // Make sure we operate in the context of the called function (for example
35 // ConstructStubs implemented in C++ will be run in the context of the caller
36 // instead of the callee, due to the way that [[Construct]] is defined for
37 // ordinary functions).
38 __ ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000039
40 // Insert extra arguments.
41 int num_extra_args = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000042 switch (extra_args) {
43 case BuiltinExtraArguments::kTarget:
44 __ Push(a1);
45 ++num_extra_args;
46 break;
47 case BuiltinExtraArguments::kNewTarget:
48 __ Push(a3);
49 ++num_extra_args;
50 break;
51 case BuiltinExtraArguments::kTargetAndNewTarget:
52 __ Push(a1, a3);
53 num_extra_args += 2;
54 break;
55 case BuiltinExtraArguments::kNone:
56 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000057 }
58
Emily Bernierd0a1eb72015-03-24 16:35:39 -040059 // JumpToExternalReference expects a0 to contain the number of arguments
Ben Murdochb8a8cc12014-11-26 15:28:44 +000060 // including the receiver and the extra arguments.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040061 __ Daddu(a0, a0, num_extra_args + 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000062
Ben Murdochb8a8cc12014-11-26 15:28:44 +000063 __ JumpToExternalReference(ExternalReference(id, masm->isolate()));
64}
65
66
67// Load the built-in InternalArray function from the current context.
68static void GenerateLoadInternalArrayFunction(MacroAssembler* masm,
69 Register result) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000070 // Load the InternalArray function from the native context.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000071 __ LoadNativeContextSlot(Context::INTERNAL_ARRAY_FUNCTION_INDEX, result);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000072}
73
74
75// Load the built-in Array function from the current context.
76static void GenerateLoadArrayFunction(MacroAssembler* masm, Register result) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000077 // Load the Array function from the native context.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000078 __ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, result);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000079}
80
81
82void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) {
83 // ----------- S t a t e -------------
84 // -- a0 : number of arguments
85 // -- ra : return address
86 // -- sp[...]: constructor arguments
87 // -----------------------------------
88 Label generic_array_code, one_or_more_arguments, two_or_more_arguments;
89
90 // Get the InternalArray function.
91 GenerateLoadInternalArrayFunction(masm, a1);
92
93 if (FLAG_debug_code) {
94 // Initial map for the builtin InternalArray functions should be maps.
95 __ ld(a2, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
96 __ SmiTst(a2, a4);
97 __ Assert(ne, kUnexpectedInitialMapForInternalArrayFunction,
98 a4, Operand(zero_reg));
99 __ GetObjectType(a2, a3, a4);
100 __ Assert(eq, kUnexpectedInitialMapForInternalArrayFunction,
101 a4, Operand(MAP_TYPE));
102 }
103
104 // Run the native code for the InternalArray function called as a normal
105 // function.
106 // Tail call a stub.
107 InternalArrayConstructorStub stub(masm->isolate());
108 __ TailCallStub(&stub);
109}
110
111
112void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
113 // ----------- S t a t e -------------
114 // -- a0 : number of arguments
115 // -- ra : return address
116 // -- sp[...]: constructor arguments
117 // -----------------------------------
118 Label generic_array_code;
119
120 // Get the Array function.
121 GenerateLoadArrayFunction(masm, a1);
122
123 if (FLAG_debug_code) {
124 // Initial map for the builtin Array functions should be maps.
125 __ ld(a2, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
126 __ SmiTst(a2, a4);
127 __ Assert(ne, kUnexpectedInitialMapForArrayFunction1,
128 a4, Operand(zero_reg));
129 __ GetObjectType(a2, a3, a4);
130 __ Assert(eq, kUnexpectedInitialMapForArrayFunction2,
131 a4, Operand(MAP_TYPE));
132 }
133
134 // Run the native code for the Array function called as a normal function.
135 // Tail call a stub.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000136 __ mov(a3, a1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000137 __ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
138 ArrayConstructorStub stub(masm->isolate());
139 __ TailCallStub(&stub);
140}
141
142
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000143// static
144void Builtins::Generate_NumberConstructor(MacroAssembler* masm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000145 // ----------- S t a t e -------------
146 // -- a0 : number of arguments
147 // -- a1 : constructor function
148 // -- ra : return address
149 // -- sp[(argc - n - 1) * 8] : arg[n] (zero based)
150 // -- sp[argc * 8] : receiver
151 // -----------------------------------
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000152
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000153 // 1. Load the first argument into a0 and get rid of the rest (including the
154 // receiver).
155 Label no_arguments;
156 {
157 __ Branch(USE_DELAY_SLOT, &no_arguments, eq, a0, Operand(zero_reg));
158 __ Dsubu(a0, a0, Operand(1));
159 __ dsll(a0, a0, kPointerSizeLog2);
160 __ Daddu(sp, a0, sp);
161 __ ld(a0, MemOperand(sp));
162 __ Drop(2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000163 }
164
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000165 // 2a. Convert first argument to number.
166 ToNumberStub stub(masm->isolate());
167 __ TailCallStub(&stub);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000168
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000169 // 2b. No arguments, return +0.
170 __ bind(&no_arguments);
171 __ Move(v0, Smi::FromInt(0));
172 __ DropAndRet(1);
173}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000174
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000175
176void Builtins::Generate_NumberConstructor_ConstructStub(MacroAssembler* masm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000177 // ----------- S t a t e -------------
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000178 // -- a0 : number of arguments
179 // -- a1 : constructor function
180 // -- a3 : new target
181 // -- ra : return address
182 // -- sp[(argc - n - 1) * 8] : arg[n] (zero based)
183 // -- sp[argc * 8] : receiver
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000184 // -----------------------------------
185
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000186 // 1. Make sure we operate in the context of the called function.
187 __ ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000188
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000189 // 2. Load the first argument into a0 and get rid of the rest (including the
190 // receiver).
191 {
192 Label no_arguments, done;
193 __ Branch(USE_DELAY_SLOT, &no_arguments, eq, a0, Operand(zero_reg));
194 __ Dsubu(a0, a0, Operand(1));
195 __ dsll(a0, a0, kPointerSizeLog2);
196 __ Daddu(sp, a0, sp);
197 __ ld(a0, MemOperand(sp));
198 __ Drop(2);
199 __ jmp(&done);
200 __ bind(&no_arguments);
201 __ Move(a0, Smi::FromInt(0));
202 __ Drop(1);
203 __ bind(&done);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000204 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000205
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000206 // 3. Make sure a0 is a number.
207 {
208 Label done_convert;
209 __ JumpIfSmi(a0, &done_convert);
210 __ GetObjectType(a0, a2, a2);
211 __ Branch(&done_convert, eq, t0, Operand(HEAP_NUMBER_TYPE));
212 {
213 FrameScope scope(masm, StackFrame::INTERNAL);
214 __ Push(a1, a3);
215 ToNumberStub stub(masm->isolate());
216 __ CallStub(&stub);
217 __ Move(a0, v0);
218 __ Pop(a1, a3);
219 }
220 __ bind(&done_convert);
221 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000222
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000223 // 4. Check if new target and constructor differ.
224 Label new_object;
225 __ Branch(&new_object, ne, a1, Operand(a3));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000226
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000227 // 5. Allocate a JSValue wrapper for the number.
228 __ AllocateJSValue(v0, a1, a0, a2, t0, &new_object);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000229 __ Ret();
230
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000231 // 6. Fallback to the runtime to create new object.
232 __ bind(&new_object);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000233 {
234 FrameScope scope(masm, StackFrame::INTERNAL);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000235 __ Push(a0, a1, a3); // first argument, constructor, new target
236 __ CallRuntime(Runtime::kNewObject);
237 __ Pop(a0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000238 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000239 __ Ret(USE_DELAY_SLOT);
240 __ sd(a0, FieldMemOperand(v0, JSValue::kValueOffset)); // In delay slot.
241}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000242
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000243
244// static
245void Builtins::Generate_StringConstructor(MacroAssembler* masm) {
246 // ----------- S t a t e -------------
247 // -- a0 : number of arguments
248 // -- a1 : constructor function
249 // -- ra : return address
250 // -- sp[(argc - n - 1) * 8] : arg[n] (zero based)
251 // -- sp[argc * 8] : receiver
252 // -----------------------------------
253
254 // 1. Load the first argument into a0 and get rid of the rest (including the
255 // receiver).
256 Label no_arguments;
257 {
258 __ Branch(USE_DELAY_SLOT, &no_arguments, eq, a0, Operand(zero_reg));
259 __ Dsubu(a0, a0, Operand(1));
260 __ dsll(a0, a0, kPointerSizeLog2);
261 __ Daddu(sp, a0, sp);
262 __ ld(a0, MemOperand(sp));
263 __ Drop(2);
264 }
265
266 // 2a. At least one argument, return a0 if it's a string, otherwise
267 // dispatch to appropriate conversion.
268 Label to_string, symbol_descriptive_string;
269 {
270 __ JumpIfSmi(a0, &to_string);
271 __ GetObjectType(a0, a1, a1);
272 STATIC_ASSERT(FIRST_NONSTRING_TYPE == SYMBOL_TYPE);
273 __ Subu(a1, a1, Operand(FIRST_NONSTRING_TYPE));
274 __ Branch(&symbol_descriptive_string, eq, a1, Operand(zero_reg));
275 __ Branch(&to_string, gt, a1, Operand(zero_reg));
276 __ Ret(USE_DELAY_SLOT);
277 __ mov(v0, a0);
278 }
279
280 // 2b. No arguments, return the empty string (and pop the receiver).
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000281 __ bind(&no_arguments);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000282 {
283 __ LoadRoot(v0, Heap::kempty_stringRootIndex);
284 __ DropAndRet(1);
285 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000286
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000287 // 3a. Convert a0 to a string.
288 __ bind(&to_string);
289 {
290 ToStringStub stub(masm->isolate());
291 __ TailCallStub(&stub);
292 }
293
294 // 3b. Convert symbol in a0 to a string.
295 __ bind(&symbol_descriptive_string);
296 {
297 __ Push(a0);
298 __ TailCallRuntime(Runtime::kSymbolDescriptiveString);
299 }
300}
301
302
303void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) {
304 // ----------- S t a t e -------------
305 // -- a0 : number of arguments
306 // -- a1 : constructor function
307 // -- a3 : new target
308 // -- ra : return address
309 // -- sp[(argc - n - 1) * 8] : arg[n] (zero based)
310 // -- sp[argc * 8] : receiver
311 // -----------------------------------
312
313 // 1. Make sure we operate in the context of the called function.
314 __ ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
315
316 // 2. Load the first argument into a0 and get rid of the rest (including the
317 // receiver).
318 {
319 Label no_arguments, done;
320 __ Branch(USE_DELAY_SLOT, &no_arguments, eq, a0, Operand(zero_reg));
321 __ Dsubu(a0, a0, Operand(1));
322 __ dsll(a0, a0, kPointerSizeLog2);
323 __ Daddu(sp, a0, sp);
324 __ ld(a0, MemOperand(sp));
325 __ Drop(2);
326 __ jmp(&done);
327 __ bind(&no_arguments);
328 __ LoadRoot(a0, Heap::kempty_stringRootIndex);
329 __ Drop(1);
330 __ bind(&done);
331 }
332
333 // 3. Make sure a0 is a string.
334 {
335 Label convert, done_convert;
336 __ JumpIfSmi(a0, &convert);
337 __ GetObjectType(a0, a2, a2);
338 __ And(t0, a2, Operand(kIsNotStringMask));
339 __ Branch(&done_convert, eq, t0, Operand(zero_reg));
340 __ bind(&convert);
341 {
342 FrameScope scope(masm, StackFrame::INTERNAL);
343 ToStringStub stub(masm->isolate());
344 __ Push(a1, a3);
345 __ CallStub(&stub);
346 __ Move(a0, v0);
347 __ Pop(a1, a3);
348 }
349 __ bind(&done_convert);
350 }
351
352 // 4. Check if new target and constructor differ.
353 Label new_object;
354 __ Branch(&new_object, ne, a1, Operand(a3));
355
356 // 5. Allocate a JSValue wrapper for the string.
357 __ AllocateJSValue(v0, a1, a0, a2, t0, &new_object);
358 __ Ret();
359
360 // 6. Fallback to the runtime to create new object.
361 __ bind(&new_object);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000362 {
363 FrameScope scope(masm, StackFrame::INTERNAL);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000364 __ Push(a0, a1, a3); // first argument, constructor, new target
365 __ CallRuntime(Runtime::kNewObject);
366 __ Pop(a0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000367 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000368 __ Ret(USE_DELAY_SLOT);
369 __ sd(a0, FieldMemOperand(v0, JSValue::kValueOffset)); // In delay slot.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000370}
371
372
373static void CallRuntimePassFunction(
374 MacroAssembler* masm, Runtime::FunctionId function_id) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000375 // ----------- S t a t e -------------
376 // -- a1 : target function (preserved for callee)
377 // -- a3 : new target (preserved for callee)
378 // -----------------------------------
379
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000380 FrameScope scope(masm, StackFrame::INTERNAL);
381 // Push a copy of the function onto the stack.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000382 // Push a copy of the target function and the new target.
383 __ Push(a1, a3, a1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000384
385 __ CallRuntime(function_id, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000386 // Restore target function and new target.
387 __ Pop(a1, a3);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000388}
389
390
391static void GenerateTailCallToSharedCode(MacroAssembler* masm) {
392 __ ld(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
393 __ ld(a2, FieldMemOperand(a2, SharedFunctionInfo::kCodeOffset));
394 __ Daddu(at, a2, Operand(Code::kHeaderSize - kHeapObjectTag));
395 __ Jump(at);
396}
397
398
399static void GenerateTailCallToReturnedCode(MacroAssembler* masm) {
400 __ Daddu(at, v0, Operand(Code::kHeaderSize - kHeapObjectTag));
401 __ Jump(at);
402}
403
404
405void Builtins::Generate_InOptimizationQueue(MacroAssembler* masm) {
406 // Checking whether the queued function is ready for install is optional,
407 // since we come across interrupts and stack checks elsewhere. However,
408 // not checking may delay installing ready functions, and always checking
409 // would be quite expensive. A good compromise is to first check against
410 // stack limit as a cue for an interrupt signal.
411 Label ok;
412 __ LoadRoot(a4, Heap::kStackLimitRootIndex);
413 __ Branch(&ok, hs, sp, Operand(a4));
414
415 CallRuntimePassFunction(masm, Runtime::kTryInstallOptimizedCode);
416 GenerateTailCallToReturnedCode(masm);
417
418 __ bind(&ok);
419 GenerateTailCallToSharedCode(masm);
420}
421
422
423static void Generate_JSConstructStubHelper(MacroAssembler* masm,
424 bool is_api_function,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000425 bool create_implicit_receiver) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000426 // ----------- S t a t e -------------
427 // -- a0 : number of arguments
428 // -- a1 : constructor function
429 // -- a2 : allocation site or undefined
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000430 // -- a3 : new target
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000431 // -- ra : return address
432 // -- sp[...]: constructor arguments
433 // -----------------------------------
434
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000435 Isolate* isolate = masm->isolate();
436
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000437 // Enter a construct frame.
438 {
439 FrameScope scope(masm, StackFrame::CONSTRUCT);
440
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000441 // Preserve the incoming parameters on the stack.
442 __ AssertUndefinedOrAllocationSite(a2, t0);
443 __ SmiTag(a0);
444 __ Push(a2, a0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000445
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000446 if (create_implicit_receiver) {
447 // Try to allocate the object without transitioning into C code. If any of
448 // the preconditions is not met, the code bails out to the runtime call.
449 Label rt_call, allocated;
450 if (FLAG_inline_new) {
451 // Verify that the new target is a JSFunction.
452 __ GetObjectType(a3, a5, a4);
453 __ Branch(&rt_call, ne, a4, Operand(JS_FUNCTION_TYPE));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000454
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000455 // Load the initial map and verify that it is in fact a map.
456 // a3: new target
457 __ ld(a2,
458 FieldMemOperand(a3, JSFunction::kPrototypeOrInitialMapOffset));
459 __ JumpIfSmi(a2, &rt_call);
460 __ GetObjectType(a2, t1, t0);
461 __ Branch(&rt_call, ne, t0, Operand(MAP_TYPE));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000462
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000463 // Fall back to runtime if the expected base constructor and base
464 // constructor differ.
465 __ ld(a5, FieldMemOperand(a2, Map::kConstructorOrBackPointerOffset));
466 __ Branch(&rt_call, ne, a1, Operand(a5));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000467
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000468 // Check that the constructor is not constructing a JSFunction (see
469 // comments in Runtime_NewObject in runtime.cc). In which case the
470 // initial map's instance type would be JS_FUNCTION_TYPE.
471 // a1: constructor function
472 // a2: initial map
473 __ lbu(t1, FieldMemOperand(a2, Map::kInstanceTypeOffset));
474 __ Branch(&rt_call, eq, t1, Operand(JS_FUNCTION_TYPE));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000475
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000476 // Now allocate the JSObject on the heap.
477 // a1: constructor function
478 // a2: initial map
479 __ lbu(a4, FieldMemOperand(a2, Map::kInstanceSizeOffset));
480 __ Allocate(a4, t0, a4, t2, &rt_call, SIZE_IN_WORDS);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000481
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000482 // Allocated the JSObject, now initialize the fields. Map is set to
483 // initial map and properties and elements are set to empty fixed array.
484 // a1: constructor function
485 // a2: initial map
486 // a3: object size
487 // t0: JSObject (not HeapObject tagged - the actual address).
488 // a4: start of next object
489 __ LoadRoot(t2, Heap::kEmptyFixedArrayRootIndex);
490 __ mov(t1, t0);
491 STATIC_ASSERT(0 * kPointerSize == JSObject::kMapOffset);
492 __ sd(a2, MemOperand(t1, JSObject::kMapOffset));
493 STATIC_ASSERT(1 * kPointerSize == JSObject::kPropertiesOffset);
494 __ sd(t2, MemOperand(t1, JSObject::kPropertiesOffset));
495 STATIC_ASSERT(2 * kPointerSize == JSObject::kElementsOffset);
496 __ sd(t2, MemOperand(t1, JSObject::kElementsOffset));
497 STATIC_ASSERT(3 * kPointerSize == JSObject::kHeaderSize);
498 __ Daddu(t1, t1, Operand(3 * kPointerSize));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000499
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000500 // Add the object tag to make the JSObject real, so that we can continue
501 // and jump into the continuation code at any time from now on.
502 __ Daddu(t0, t0, Operand(kHeapObjectTag));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000503
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000504 // Fill all the in-object properties with appropriate filler.
505 // t0: JSObject (tagged)
506 // t1: First in-object property of JSObject (not tagged)
507 __ LoadRoot(t3, Heap::kUndefinedValueRootIndex);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000508
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000509 if (!is_api_function) {
510 Label no_inobject_slack_tracking;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000511
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000512 MemOperand bit_field3 = FieldMemOperand(a2, Map::kBitField3Offset);
513 // Check if slack tracking is enabled.
514 __ lwu(t2, bit_field3);
515 __ DecodeField<Map::ConstructionCounter>(a6, t2);
516 // a6: slack tracking counter
517 __ Branch(&no_inobject_slack_tracking, lt, a6,
518 Operand(Map::kSlackTrackingCounterEnd));
519 // Decrease generous allocation count.
520 __ Dsubu(t2, t2, Operand(1 << Map::ConstructionCounter::kShift));
521 __ sw(t2, bit_field3);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000522
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000523 // Allocate object with a slack.
524 __ lbu(a0, FieldMemOperand(a2, Map::kUnusedPropertyFieldsOffset));
525 __ dsll(a0, a0, kPointerSizeLog2);
526 __ dsubu(a0, a4, a0);
527 // a0: offset of first field after pre-allocated fields
528 if (FLAG_debug_code) {
529 __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields, t1,
530 Operand(a0));
531 }
532 __ InitializeFieldsWithFiller(t1, a0, t3);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000533
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000534 // To allow truncation fill the remaining fields with one pointer
535 // filler map.
536 __ LoadRoot(t3, Heap::kOnePointerFillerMapRootIndex);
537 __ InitializeFieldsWithFiller(t1, a4, t3);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000538
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000539 // a6: slack tracking counter value before decreasing.
540 __ Branch(&allocated, ne, a6, Operand(Map::kSlackTrackingCounterEnd));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000541
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000542 // Push the constructor, new_target and the object to the stack,
543 // and then the initial map as an argument to the runtime call.
544 __ Push(a1, a3, t0, a2);
545 __ CallRuntime(Runtime::kFinalizeInstanceSize);
546 __ Pop(a1, a3, t0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000547
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000548 // Continue with JSObject being successfully allocated.
549 // a1: constructor function
550 // a3: new target
551 // t0: JSObject
552 __ jmp(&allocated);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000553
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000554 __ bind(&no_inobject_slack_tracking);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000555 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000556
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000557 __ InitializeFieldsWithFiller(t1, a4, t3);
558
559 // Continue with JSObject being successfully allocated.
560 // a1: constructor function
561 // a3: new target
562 // t0: JSObject
563 __ jmp(&allocated);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000564 }
565
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000566 // Allocate the new receiver object using the runtime call.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000567 // a1: constructor function
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000568 // a3: new target
569 __ bind(&rt_call);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000570
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000571 // Push the constructor and new_target twice, second pair as arguments
572 // to the runtime call.
573 __ Push(a1, a3, a1, a3); // constructor function, new target
574 __ CallRuntime(Runtime::kNewObject);
575 __ mov(t0, v0);
576 __ Pop(a1, a3);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000577
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000578 // Receiver for constructor call allocated.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000579 // a1: constructor function
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000580 // a3: new target
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000581 // t0: JSObject
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000582 __ bind(&allocated);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000583
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000584 __ ld(a0, MemOperand(sp));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000585 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000586 __ SmiUntag(a0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000587
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000588 if (create_implicit_receiver) {
589 // Push the allocated receiver to the stack. We need two copies
590 // because we may have to return the original one and the calling
591 // conventions dictate that the called function pops the receiver.
592 __ Push(t0, t0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000593 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000594 __ PushRoot(Heap::kTheHoleValueRootIndex);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000595 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000596
597 // Set up pointer to last argument.
598 __ Daddu(a2, fp, Operand(StandardFrameConstants::kCallerSPOffset));
599
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000600 // Copy arguments and receiver to the expression stack.
601 // a0: number of arguments
602 // a1: constructor function
603 // a2: address of last argument (caller sp)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000604 // a3: new target
605 // t0: number of arguments (smi-tagged)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000606 // sp[0]: receiver
607 // sp[1]: receiver
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000608 // sp[2]: number of arguments (smi-tagged)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000609 Label loop, entry;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000610 __ mov(t0, a0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000611 __ jmp(&entry);
612 __ bind(&loop);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000613 __ dsll(a4, t0, kPointerSizeLog2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000614 __ Daddu(a4, a2, Operand(a4));
615 __ ld(a5, MemOperand(a4));
616 __ push(a5);
617 __ bind(&entry);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000618 __ Daddu(t0, t0, Operand(-1));
619 __ Branch(&loop, greater_equal, t0, Operand(zero_reg));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000620
621 // Call the function.
622 // a0: number of arguments
623 // a1: constructor function
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000624 // a3: new target
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000625 if (is_api_function) {
626 __ ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
627 Handle<Code> code =
628 masm->isolate()->builtins()->HandleApiCallConstruct();
629 __ Call(code, RelocInfo::CODE_TARGET);
630 } else {
631 ParameterCount actual(a0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000632 __ InvokeFunction(a1, a3, actual, CALL_FUNCTION,
633 CheckDebugStepCallWrapper());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000634 }
635
636 // Store offset of return address for deoptimizer.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000637 if (create_implicit_receiver && !is_api_function) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000638 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset());
639 }
640
641 // Restore context from the frame.
642 __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
643
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000644 if (create_implicit_receiver) {
645 // If the result is an object (in the ECMA sense), we should get rid
646 // of the receiver and use the result; see ECMA-262 section 13.2.2-7
647 // on page 74.
648 Label use_receiver, exit;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000649
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000650 // If the result is a smi, it is *not* an object in the ECMA sense.
651 // v0: result
652 // sp[0]: receiver (newly allocated object)
653 // sp[1]: number of arguments (smi-tagged)
654 __ JumpIfSmi(v0, &use_receiver);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000655
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000656 // If the type of the result (stored in its map) is less than
657 // FIRST_JS_RECEIVER_TYPE, it is not an object in the ECMA sense.
658 __ GetObjectType(v0, a1, a3);
659 __ Branch(&exit, greater_equal, a3, Operand(FIRST_JS_RECEIVER_TYPE));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000660
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000661 // Throw away the result of the constructor invocation and use the
662 // on-stack receiver as the result.
663 __ bind(&use_receiver);
664 __ ld(v0, MemOperand(sp));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000665
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000666 // Remove receiver from the stack, remove caller arguments, and
667 // return.
668 __ bind(&exit);
669 // v0: result
670 // sp[0]: receiver (newly allocated object)
671 // sp[1]: number of arguments (smi-tagged)
672 __ ld(a1, MemOperand(sp, 1 * kPointerSize));
673 } else {
674 __ ld(a1, MemOperand(sp));
675 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000676
677 // Leave construct frame.
678 }
679
680 __ SmiScale(a4, a1, kPointerSizeLog2);
681 __ Daddu(sp, sp, a4);
682 __ Daddu(sp, sp, kPointerSize);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000683 if (create_implicit_receiver) {
684 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, a1, a2);
685 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000686 __ Ret();
687}
688
689
690void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000691 Generate_JSConstructStubHelper(masm, false, true);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000692}
693
694
695void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000696 Generate_JSConstructStubHelper(masm, true, true);
697}
698
699
700void Builtins::Generate_JSBuiltinsConstructStub(MacroAssembler* masm) {
701 Generate_JSConstructStubHelper(masm, false, false);
702}
703
704
705void Builtins::Generate_ConstructedNonConstructable(MacroAssembler* masm) {
706 FrameScope scope(masm, StackFrame::INTERNAL);
707 __ Push(a1);
708 __ CallRuntime(Runtime::kThrowConstructedNonConstructable);
709}
710
711
712enum IsTagged { kArgcIsSmiTagged, kArgcIsUntaggedInt };
713
714
715// Clobbers a2; preserves all other registers.
716static void Generate_CheckStackOverflow(MacroAssembler* masm, Register argc,
717 IsTagged argc_is_tagged) {
718 // Check the stack for overflow. We are not trying to catch
719 // interruptions (e.g. debug break and preemption) here, so the "real stack
720 // limit" is checked.
721 Label okay;
722 __ LoadRoot(a2, Heap::kRealStackLimitRootIndex);
723 // Make a2 the space we have left. The stack might already be overflowed
724 // here which will cause r2 to become negative.
725 __ dsubu(a2, sp, a2);
726 // Check if the arguments will overflow the stack.
727 if (argc_is_tagged == kArgcIsSmiTagged) {
728 __ SmiScale(a7, v0, kPointerSizeLog2);
729 } else {
730 DCHECK(argc_is_tagged == kArgcIsUntaggedInt);
731 __ dsll(a7, argc, kPointerSizeLog2);
732 }
733 __ Branch(&okay, gt, a2, Operand(a7)); // Signed comparison.
734
735 // Out of stack space.
736 __ CallRuntime(Runtime::kThrowStackOverflow);
737
738 __ bind(&okay);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000739}
740
741
742static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
743 bool is_construct) {
744 // Called from JSEntryStub::GenerateBody
745
746 // ----------- S t a t e -------------
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000747 // -- a0: new.target
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000748 // -- a1: function
749 // -- a2: receiver_pointer
750 // -- a3: argc
751 // -- s0: argv
752 // -----------------------------------
753 ProfileEntryHookStub::MaybeCallEntryHook(masm);
754 // Clear the context before we push it when entering the JS frame.
755 __ mov(cp, zero_reg);
756
757 // Enter an internal frame.
758 {
759 FrameScope scope(masm, StackFrame::INTERNAL);
760
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000761 // Setup the context (we need to use the caller context from the isolate).
762 ExternalReference context_address(Isolate::kContextAddress,
763 masm->isolate());
764 __ li(cp, Operand(context_address));
765 __ ld(cp, MemOperand(cp));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000766
767 // Push the function and the receiver onto the stack.
768 __ Push(a1, a2);
769
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000770 // Check if we have enough stack space to push all arguments.
771 // Clobbers a2.
772 Generate_CheckStackOverflow(masm, a3, kArgcIsUntaggedInt);
773
774 // Remember new.target.
775 __ mov(a5, a0);
776
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000777 // Copy arguments to the stack in a loop.
778 // a3: argc
779 // s0: argv, i.e. points to first arg
780 Label loop, entry;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000781 __ dsll(a4, a3, kPointerSizeLog2);
782 __ daddu(a6, s0, a4);
783 __ b(&entry);
784 __ nop(); // Branch delay slot nop.
785 // a6 points past last arg.
786 __ bind(&loop);
787 __ ld(a4, MemOperand(s0)); // Read next parameter.
788 __ daddiu(s0, s0, kPointerSize);
789 __ ld(a4, MemOperand(a4)); // Dereference handle.
790 __ push(a4); // Push parameter.
791 __ bind(&entry);
792 __ Branch(&loop, ne, s0, Operand(a6));
793
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000794 // Setup new.target and argc.
795 __ mov(a0, a3);
796 __ mov(a3, a5);
797
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000798 // Initialize all JavaScript callee-saved registers, since they will be seen
799 // by the garbage collector as part of handlers.
800 __ LoadRoot(a4, Heap::kUndefinedValueRootIndex);
801 __ mov(s1, a4);
802 __ mov(s2, a4);
803 __ mov(s3, a4);
804 __ mov(s4, a4);
805 __ mov(s5, a4);
806 // s6 holds the root address. Do not clobber.
807 // s7 is cp. Do not init.
808
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000809 // Invoke the code.
810 Handle<Code> builtin = is_construct
811 ? masm->isolate()->builtins()->Construct()
812 : masm->isolate()->builtins()->Call();
813 __ Call(builtin, RelocInfo::CODE_TARGET);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000814
815 // Leave internal frame.
816 }
817 __ Jump(ra);
818}
819
820
821void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) {
822 Generate_JSEntryTrampolineHelper(masm, false);
823}
824
825
826void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
827 Generate_JSEntryTrampolineHelper(masm, true);
828}
829
830
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000831// Generate code for entering a JS function with the interpreter.
832// On entry to the function the receiver and arguments have been pushed on the
833// stack left to right. The actual argument count matches the formal parameter
834// count expected by the function.
835//
836// The live registers are:
837// o a1: the JS function object being called.
838// o a3: the new target
839// o cp: our context
840// o fp: the caller's frame pointer
841// o sp: stack pointer
842// o ra: return address
843//
844// The function builds a JS frame. Please see JavaScriptFrameConstants in
845// frames-mips.h for its layout.
846// TODO(rmcilroy): We will need to include the current bytecode pointer in the
847// frame.
848void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
849 // Open a frame scope to indicate that there is a frame on the stack. The
850 // MANUAL indicates that the scope shouldn't actually generate code to set up
851 // the frame (that is done below).
852 FrameScope frame_scope(masm, StackFrame::MANUAL);
853
854 __ Push(ra, fp, cp, a1);
855 __ Daddu(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
856 __ Push(a3);
857
858 // Push zero for bytecode array offset.
859 __ Push(zero_reg);
860
861 // Get the bytecode array from the function object and load the pointer to the
862 // first entry into kInterpreterBytecodeRegister.
863 __ ld(a0, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
864 __ ld(kInterpreterBytecodeArrayRegister,
865 FieldMemOperand(a0, SharedFunctionInfo::kFunctionDataOffset));
866
867 if (FLAG_debug_code) {
868 // Check function data field is actually a BytecodeArray object.
869 __ SmiTst(kInterpreterBytecodeArrayRegister, a4);
870 __ Assert(ne, kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry, a4,
871 Operand(zero_reg));
872 __ GetObjectType(kInterpreterBytecodeArrayRegister, a4, a4);
873 __ Assert(eq, kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry, a4,
874 Operand(BYTECODE_ARRAY_TYPE));
875 }
876
877 // Allocate the local and temporary register file on the stack.
878 {
879 // Load frame size (word) from the BytecodeArray object.
880 __ lw(a4, FieldMemOperand(kInterpreterBytecodeArrayRegister,
881 BytecodeArray::kFrameSizeOffset));
882
883 // Do a stack check to ensure we don't go over the limit.
884 Label ok;
885 __ Dsubu(a5, sp, Operand(a4));
886 __ LoadRoot(a2, Heap::kRealStackLimitRootIndex);
887 __ Branch(&ok, hs, a5, Operand(a2));
888 __ CallRuntime(Runtime::kThrowStackOverflow);
889 __ bind(&ok);
890
891 // If ok, push undefined as the initial value for all register file entries.
892 Label loop_header;
893 Label loop_check;
894 __ LoadRoot(a5, Heap::kUndefinedValueRootIndex);
895 __ Branch(&loop_check);
896 __ bind(&loop_header);
897 // TODO(rmcilroy): Consider doing more than one push per loop iteration.
898 __ push(a5);
899 // Continue loop if not done.
900 __ bind(&loop_check);
901 __ Dsubu(a4, a4, Operand(kPointerSize));
902 __ Branch(&loop_header, ge, a4, Operand(zero_reg));
903 }
904
905 // TODO(rmcilroy): List of things not currently dealt with here but done in
906 // fullcodegen's prologue:
907 // - Support profiler (specifically profiling_counter).
908 // - Call ProfileEntryHookStub when isolate has a function_entry_hook.
909 // - Allow simulator stop operations if FLAG_stop_at is set.
910 // - Code aging of the BytecodeArray object.
911
912 // Perform stack guard check.
913 {
914 Label ok;
915 __ LoadRoot(at, Heap::kStackLimitRootIndex);
916 __ Branch(&ok, hs, sp, Operand(at));
917 __ push(kInterpreterBytecodeArrayRegister);
918 __ CallRuntime(Runtime::kStackGuard);
919 __ pop(kInterpreterBytecodeArrayRegister);
920 __ bind(&ok);
921 }
922
923 // Load bytecode offset and dispatch table into registers.
924 __ LoadRoot(kInterpreterAccumulatorRegister, Heap::kUndefinedValueRootIndex);
925 __ Daddu(kInterpreterRegisterFileRegister, fp,
926 Operand(InterpreterFrameConstants::kRegisterFilePointerFromFp));
927 __ li(kInterpreterBytecodeOffsetRegister,
928 Operand(BytecodeArray::kHeaderSize - kHeapObjectTag));
929 __ LoadRoot(kInterpreterDispatchTableRegister,
930 Heap::kInterpreterTableRootIndex);
931 __ Daddu(kInterpreterDispatchTableRegister, kInterpreterDispatchTableRegister,
932 Operand(FixedArray::kHeaderSize - kHeapObjectTag));
933
934 // Dispatch to the first bytecode handler for the function.
935 __ Daddu(a0, kInterpreterBytecodeArrayRegister,
936 kInterpreterBytecodeOffsetRegister);
937 __ lbu(a0, MemOperand(a0));
938 __ dsll(at, a0, kPointerSizeLog2);
939 __ Daddu(at, kInterpreterDispatchTableRegister, at);
940 __ ld(at, MemOperand(at));
941 // TODO(rmcilroy): Make dispatch table point to code entrys to avoid untagging
942 // and header removal.
943 __ Daddu(at, at, Operand(Code::kHeaderSize - kHeapObjectTag));
944 __ Call(at);
945}
946
947
948void Builtins::Generate_InterpreterExitTrampoline(MacroAssembler* masm) {
949 // TODO(rmcilroy): List of things not currently dealt with here but done in
950 // fullcodegen's EmitReturnSequence.
951 // - Supporting FLAG_trace for Runtime::TraceExit.
952 // - Support profiler (specifically decrementing profiling_counter
953 // appropriately and calling out to HandleInterrupts if necessary).
954
955 // The return value is in accumulator, which is already in v0.
956
957 // Leave the frame (also dropping the register file).
958 __ LeaveFrame(StackFrame::JAVA_SCRIPT);
959
960 // Drop receiver + arguments and return.
961 __ lw(at, FieldMemOperand(kInterpreterBytecodeArrayRegister,
962 BytecodeArray::kParameterSizeOffset));
963 __ Daddu(sp, sp, at);
964 __ Jump(ra);
965}
966
967
968// static
969void Builtins::Generate_InterpreterPushArgsAndCall(MacroAssembler* masm) {
970 // ----------- S t a t e -------------
971 // -- a0 : the number of arguments (not including the receiver)
972 // -- a2 : the address of the first argument to be pushed. Subsequent
973 // arguments should be consecutive above this, in the same order as
974 // they are to be pushed onto the stack.
975 // -- a1 : the target to call (can be any Object).
976 // -----------------------------------
977
978 // Find the address of the last argument.
979 __ Daddu(a3, a0, Operand(1)); // Add one for receiver.
980 __ dsll(a3, a3, kPointerSizeLog2);
981 __ Dsubu(a3, a2, Operand(a3));
982
983 // Push the arguments.
984 Label loop_header, loop_check;
985 __ Branch(&loop_check);
986 __ bind(&loop_header);
987 __ ld(t0, MemOperand(a2));
988 __ Daddu(a2, a2, Operand(-kPointerSize));
989 __ push(t0);
990 __ bind(&loop_check);
991 __ Branch(&loop_header, gt, a2, Operand(a3));
992
993 // Call the target.
994 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
995}
996
997
998// static
999void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
1000 // ----------- S t a t e -------------
1001 // -- a0 : argument count (not including receiver)
1002 // -- a3 : new target
1003 // -- a1 : constructor to call
1004 // -- a2 : address of the first argument
1005 // -----------------------------------
1006
1007 // Find the address of the last argument.
1008 __ dsll(t0, a0, kPointerSizeLog2);
1009 __ Dsubu(t0, a2, Operand(t0));
1010
1011 // Push a slot for the receiver.
1012 __ push(zero_reg);
1013
1014 // Push the arguments.
1015 Label loop_header, loop_check;
1016 __ Branch(&loop_check);
1017 __ bind(&loop_header);
1018 __ ld(t1, MemOperand(a2));
1019 __ Daddu(a2, a2, Operand(-kPointerSize));
1020 __ push(t1);
1021 __ bind(&loop_check);
1022 __ Branch(&loop_header, gt, a2, Operand(t0));
1023
1024 // Call the constructor with a0, a1, and a3 unmodified.
1025 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
1026}
1027
1028
1029static void Generate_InterpreterNotifyDeoptimizedHelper(
1030 MacroAssembler* masm, Deoptimizer::BailoutType type) {
1031 // Enter an internal frame.
1032 {
1033 FrameScope scope(masm, StackFrame::INTERNAL);
1034 __ push(kInterpreterAccumulatorRegister); // Save accumulator register.
1035
1036 // Pass the deoptimization type to the runtime system.
1037 __ li(a1, Operand(Smi::FromInt(static_cast<int>(type))));
1038 __ push(a1);
1039 __ CallRuntime(Runtime::kNotifyDeoptimized);
1040
1041 __ pop(kInterpreterAccumulatorRegister); // Restore accumulator register.
1042 // Tear down internal frame.
1043 }
1044
1045 // Drop state (we don't use this for interpreter deopts).
1046 __ Drop(1);
1047
1048 // Initialize register file register and dispatch table register.
1049 __ Daddu(kInterpreterRegisterFileRegister, fp,
1050 Operand(InterpreterFrameConstants::kRegisterFilePointerFromFp));
1051 __ LoadRoot(kInterpreterDispatchTableRegister,
1052 Heap::kInterpreterTableRootIndex);
1053 __ Daddu(kInterpreterDispatchTableRegister, kInterpreterDispatchTableRegister,
1054 Operand(FixedArray::kHeaderSize - kHeapObjectTag));
1055
1056 // Get the context from the frame.
1057 // TODO(rmcilroy): Update interpreter frame to expect current context at the
1058 // context slot instead of the function context.
1059 __ ld(kContextRegister,
1060 MemOperand(kInterpreterRegisterFileRegister,
1061 InterpreterFrameConstants::kContextFromRegisterPointer));
1062
1063 // Get the bytecode array pointer from the frame.
1064 __ ld(a1,
1065 MemOperand(kInterpreterRegisterFileRegister,
1066 InterpreterFrameConstants::kFunctionFromRegisterPointer));
1067 __ ld(a1, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
1068 __ ld(kInterpreterBytecodeArrayRegister,
1069 FieldMemOperand(a1, SharedFunctionInfo::kFunctionDataOffset));
1070
1071 if (FLAG_debug_code) {
1072 // Check function data field is actually a BytecodeArray object.
1073 __ SmiTst(kInterpreterBytecodeArrayRegister, at);
1074 __ Assert(ne, kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry, at,
1075 Operand(zero_reg));
1076 __ GetObjectType(kInterpreterBytecodeArrayRegister, a1, a1);
1077 __ Assert(eq, kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry, a1,
1078 Operand(BYTECODE_ARRAY_TYPE));
1079 }
1080
1081 // Get the target bytecode offset from the frame.
1082 __ ld(kInterpreterBytecodeOffsetRegister,
1083 MemOperand(
1084 kInterpreterRegisterFileRegister,
1085 InterpreterFrameConstants::kBytecodeOffsetFromRegisterPointer));
1086 __ SmiUntag(kInterpreterBytecodeOffsetRegister);
1087
1088 // Dispatch to the target bytecode.
1089 __ Daddu(a1, kInterpreterBytecodeArrayRegister,
1090 kInterpreterBytecodeOffsetRegister);
1091 __ lbu(a1, MemOperand(a1));
1092 __ dsll(a1, a1, kPointerSizeLog2);
1093 __ Daddu(a1, kInterpreterDispatchTableRegister, a1);
1094 __ ld(a1, MemOperand(a1));
1095 __ Daddu(a1, a1, Operand(Code::kHeaderSize - kHeapObjectTag));
1096 __ Jump(a1);
1097}
1098
1099
1100void Builtins::Generate_InterpreterNotifyDeoptimized(MacroAssembler* masm) {
1101 Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::EAGER);
1102}
1103
1104
1105void Builtins::Generate_InterpreterNotifySoftDeoptimized(MacroAssembler* masm) {
1106 Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::SOFT);
1107}
1108
1109
1110void Builtins::Generate_InterpreterNotifyLazyDeoptimized(MacroAssembler* masm) {
1111 Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
1112}
1113
1114
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001115void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
1116 CallRuntimePassFunction(masm, Runtime::kCompileLazy);
1117 GenerateTailCallToReturnedCode(masm);
1118}
1119
1120
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001121void Builtins::Generate_CompileOptimized(MacroAssembler* masm) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001122 CallRuntimePassFunction(masm, Runtime::kCompileOptimized_NotConcurrent);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001123 GenerateTailCallToReturnedCode(masm);
1124}
1125
1126
1127void Builtins::Generate_CompileOptimizedConcurrent(MacroAssembler* masm) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001128 CallRuntimePassFunction(masm, Runtime::kCompileOptimized_Concurrent);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001129 GenerateTailCallToReturnedCode(masm);
1130}
1131
1132
1133static void GenerateMakeCodeYoungAgainCommon(MacroAssembler* masm) {
1134 // For now, we are relying on the fact that make_code_young doesn't do any
1135 // garbage collection which allows us to save/restore the registers without
1136 // worrying about which of them contain pointers. We also don't build an
1137 // internal frame to make the code faster, since we shouldn't have to do stack
1138 // crawls in MakeCodeYoung. This seems a bit fragile.
1139
1140 // Set a0 to point to the head of the PlatformCodeAge sequence.
1141 __ Dsubu(a0, a0,
1142 Operand(kNoCodeAgeSequenceLength - Assembler::kInstrSize));
1143
1144 // The following registers must be saved and restored when calling through to
1145 // the runtime:
1146 // a0 - contains return address (beginning of patch sequence)
1147 // a1 - isolate
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001148 // a3 - new target
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001149 RegList saved_regs =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001150 (a0.bit() | a1.bit() | a3.bit() | ra.bit() | fp.bit()) & ~sp.bit();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001151 FrameScope scope(masm, StackFrame::MANUAL);
1152 __ MultiPush(saved_regs);
1153 __ PrepareCallCFunction(2, 0, a2);
1154 __ li(a1, Operand(ExternalReference::isolate_address(masm->isolate())));
1155 __ CallCFunction(
1156 ExternalReference::get_make_code_young_function(masm->isolate()), 2);
1157 __ MultiPop(saved_regs);
1158 __ Jump(a0);
1159}
1160
1161#define DEFINE_CODE_AGE_BUILTIN_GENERATOR(C) \
1162void Builtins::Generate_Make##C##CodeYoungAgainEvenMarking( \
1163 MacroAssembler* masm) { \
1164 GenerateMakeCodeYoungAgainCommon(masm); \
1165} \
1166void Builtins::Generate_Make##C##CodeYoungAgainOddMarking( \
1167 MacroAssembler* masm) { \
1168 GenerateMakeCodeYoungAgainCommon(masm); \
1169}
1170CODE_AGE_LIST(DEFINE_CODE_AGE_BUILTIN_GENERATOR)
1171#undef DEFINE_CODE_AGE_BUILTIN_GENERATOR
1172
1173
1174void Builtins::Generate_MarkCodeAsExecutedOnce(MacroAssembler* masm) {
1175 // For now, as in GenerateMakeCodeYoungAgainCommon, we are relying on the fact
1176 // that make_code_young doesn't do any garbage collection which allows us to
1177 // save/restore the registers without worrying about which of them contain
1178 // pointers.
1179
1180 // Set a0 to point to the head of the PlatformCodeAge sequence.
1181 __ Dsubu(a0, a0,
1182 Operand(kNoCodeAgeSequenceLength - Assembler::kInstrSize));
1183
1184 // The following registers must be saved and restored when calling through to
1185 // the runtime:
1186 // a0 - contains return address (beginning of patch sequence)
1187 // a1 - isolate
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001188 // a3 - new target
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001189 RegList saved_regs =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001190 (a0.bit() | a1.bit() | a3.bit() | ra.bit() | fp.bit()) & ~sp.bit();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001191 FrameScope scope(masm, StackFrame::MANUAL);
1192 __ MultiPush(saved_regs);
1193 __ PrepareCallCFunction(2, 0, a2);
1194 __ li(a1, Operand(ExternalReference::isolate_address(masm->isolate())));
1195 __ CallCFunction(
1196 ExternalReference::get_mark_code_as_executed_function(masm->isolate()),
1197 2);
1198 __ MultiPop(saved_regs);
1199
1200 // Perform prologue operations usually performed by the young code stub.
1201 __ Push(ra, fp, cp, a1);
1202 __ Daddu(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
1203
1204 // Jump to point after the code-age stub.
1205 __ Daddu(a0, a0, Operand((kNoCodeAgeSequenceLength)));
1206 __ Jump(a0);
1207}
1208
1209
1210void Builtins::Generate_MarkCodeAsExecutedTwice(MacroAssembler* masm) {
1211 GenerateMakeCodeYoungAgainCommon(masm);
1212}
1213
1214
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001215void Builtins::Generate_MarkCodeAsToBeExecutedOnce(MacroAssembler* masm) {
1216 Generate_MarkCodeAsExecutedOnce(masm);
1217}
1218
1219
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001220static void Generate_NotifyStubFailureHelper(MacroAssembler* masm,
1221 SaveFPRegsMode save_doubles) {
1222 {
1223 FrameScope scope(masm, StackFrame::INTERNAL);
1224
1225 // Preserve registers across notification, this is important for compiled
1226 // stubs that tail call the runtime on deopts passing their parameters in
1227 // registers.
1228 __ MultiPush(kJSCallerSaved | kCalleeSaved);
1229 // Pass the function and deoptimization type to the runtime system.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001230 __ CallRuntime(Runtime::kNotifyStubFailure, save_doubles);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001231 __ MultiPop(kJSCallerSaved | kCalleeSaved);
1232 }
1233
1234 __ Daddu(sp, sp, Operand(kPointerSize)); // Ignore state
1235 __ Jump(ra); // Jump to miss handler
1236}
1237
1238
1239void Builtins::Generate_NotifyStubFailure(MacroAssembler* masm) {
1240 Generate_NotifyStubFailureHelper(masm, kDontSaveFPRegs);
1241}
1242
1243
1244void Builtins::Generate_NotifyStubFailureSaveDoubles(MacroAssembler* masm) {
1245 Generate_NotifyStubFailureHelper(masm, kSaveFPRegs);
1246}
1247
1248
1249static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm,
1250 Deoptimizer::BailoutType type) {
1251 {
1252 FrameScope scope(masm, StackFrame::INTERNAL);
1253 // Pass the function and deoptimization type to the runtime system.
1254 __ li(a0, Operand(Smi::FromInt(static_cast<int>(type))));
1255 __ push(a0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001256 __ CallRuntime(Runtime::kNotifyDeoptimized);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001257 }
1258
1259 // Get the full codegen state from the stack and untag it -> a6.
1260 __ ld(a6, MemOperand(sp, 0 * kPointerSize));
1261 __ SmiUntag(a6);
1262 // Switch on the state.
1263 Label with_tos_register, unknown_state;
1264 __ Branch(&with_tos_register,
1265 ne, a6, Operand(FullCodeGenerator::NO_REGISTERS));
1266 __ Ret(USE_DELAY_SLOT);
1267 // Safe to fill delay slot Addu will emit one instruction.
1268 __ Daddu(sp, sp, Operand(1 * kPointerSize)); // Remove state.
1269
1270 __ bind(&with_tos_register);
1271 __ ld(v0, MemOperand(sp, 1 * kPointerSize));
1272 __ Branch(&unknown_state, ne, a6, Operand(FullCodeGenerator::TOS_REG));
1273
1274 __ Ret(USE_DELAY_SLOT);
1275 // Safe to fill delay slot Addu will emit one instruction.
1276 __ Daddu(sp, sp, Operand(2 * kPointerSize)); // Remove state.
1277
1278 __ bind(&unknown_state);
1279 __ stop("no cases left");
1280}
1281
1282
1283void Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) {
1284 Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::EAGER);
1285}
1286
1287
1288void Builtins::Generate_NotifySoftDeoptimized(MacroAssembler* masm) {
1289 Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::SOFT);
1290}
1291
1292
1293void Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) {
1294 Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
1295}
1296
1297
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001298// Clobbers {t2, t3, a4, a5}.
1299static void CompatibleReceiverCheck(MacroAssembler* masm, Register receiver,
1300 Register function_template_info,
1301 Label* receiver_check_failed) {
1302 Register signature = t2;
1303 Register map = t3;
1304 Register constructor = a4;
1305 Register scratch = a5;
1306
1307 // If there is no signature, return the holder.
1308 __ ld(signature, FieldMemOperand(function_template_info,
1309 FunctionTemplateInfo::kSignatureOffset));
1310 Label receiver_check_passed;
1311 __ JumpIfRoot(signature, Heap::kUndefinedValueRootIndex,
1312 &receiver_check_passed);
1313
1314 // Walk the prototype chain.
1315 __ ld(map, FieldMemOperand(receiver, HeapObject::kMapOffset));
1316 Label prototype_loop_start;
1317 __ bind(&prototype_loop_start);
1318
1319 // Get the constructor, if any.
1320 __ GetMapConstructor(constructor, map, scratch, scratch);
1321 Label next_prototype;
1322 __ Branch(&next_prototype, ne, scratch, Operand(JS_FUNCTION_TYPE));
1323 Register type = constructor;
1324 __ ld(type,
1325 FieldMemOperand(constructor, JSFunction::kSharedFunctionInfoOffset));
1326 __ ld(type, FieldMemOperand(type, SharedFunctionInfo::kFunctionDataOffset));
1327
1328 // Loop through the chain of inheriting function templates.
1329 Label function_template_loop;
1330 __ bind(&function_template_loop);
1331
1332 // If the signatures match, we have a compatible receiver.
1333 __ Branch(&receiver_check_passed, eq, signature, Operand(type),
1334 USE_DELAY_SLOT);
1335
1336 // If the current type is not a FunctionTemplateInfo, load the next prototype
1337 // in the chain.
1338 __ JumpIfSmi(type, &next_prototype);
1339 __ GetObjectType(type, scratch, scratch);
1340 __ Branch(&next_prototype, ne, scratch, Operand(FUNCTION_TEMPLATE_INFO_TYPE));
1341
1342 // Otherwise load the parent function template and iterate.
1343 __ ld(type,
1344 FieldMemOperand(type, FunctionTemplateInfo::kParentTemplateOffset));
1345 __ Branch(&function_template_loop);
1346
1347 // Load the next prototype.
1348 __ bind(&next_prototype);
1349 __ ld(receiver, FieldMemOperand(map, Map::kPrototypeOffset));
1350 // End if the prototype is null or not hidden.
1351 __ JumpIfRoot(receiver, Heap::kNullValueRootIndex, receiver_check_failed);
1352 __ ld(map, FieldMemOperand(receiver, HeapObject::kMapOffset));
1353 __ lwu(scratch, FieldMemOperand(map, Map::kBitField3Offset));
1354 __ DecodeField<Map::IsHiddenPrototype>(scratch);
1355 __ Branch(receiver_check_failed, eq, scratch, Operand(zero_reg));
1356 // Iterate.
1357 __ Branch(&prototype_loop_start);
1358
1359 __ bind(&receiver_check_passed);
1360}
1361
1362
1363void Builtins::Generate_HandleFastApiCall(MacroAssembler* masm) {
1364 // ----------- S t a t e -------------
1365 // -- a0 : number of arguments excluding receiver
1366 // -- a1 : callee
1367 // -- ra : return address
1368 // -- sp[0] : last argument
1369 // -- ...
1370 // -- sp[8 * (argc - 1)] : first argument
1371 // -- sp[8 * argc] : receiver
1372 // -----------------------------------
1373
1374 // Load the FunctionTemplateInfo.
1375 __ ld(t1, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
1376 __ ld(t1, FieldMemOperand(t1, SharedFunctionInfo::kFunctionDataOffset));
1377
1378 // Do the compatible receiver check
1379 Label receiver_check_failed;
1380 __ sll(at, a0, kPointerSizeLog2);
1381 __ Daddu(t8, sp, at);
1382 __ ld(t0, MemOperand(t8));
1383 CompatibleReceiverCheck(masm, t0, t1, &receiver_check_failed);
1384
1385 // Get the callback offset from the FunctionTemplateInfo, and jump to the
1386 // beginning of the code.
1387 __ ld(t2, FieldMemOperand(t1, FunctionTemplateInfo::kCallCodeOffset));
1388 __ ld(t2, FieldMemOperand(t2, CallHandlerInfo::kFastHandlerOffset));
1389 __ Daddu(t2, t2, Operand(Code::kHeaderSize - kHeapObjectTag));
1390 __ Jump(t2);
1391
1392 // Compatible receiver check failed: throw an Illegal Invocation exception.
1393 __ bind(&receiver_check_failed);
1394 // Drop the arguments (including the receiver);
1395 __ Daddu(t8, t8, Operand(kPointerSize));
1396 __ daddu(sp, t8, zero_reg);
1397 __ TailCallRuntime(Runtime::kThrowIllegalInvocation);
1398}
1399
1400
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001401void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
1402 // Lookup the function in the JavaScript frame.
1403 __ ld(a0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
1404 {
1405 FrameScope scope(masm, StackFrame::INTERNAL);
1406 // Pass function as argument.
1407 __ push(a0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001408 __ CallRuntime(Runtime::kCompileForOnStackReplacement);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001409 }
1410
1411 // If the code object is null, just return to the unoptimized code.
1412 __ Ret(eq, v0, Operand(Smi::FromInt(0)));
1413
1414 // Load deoptimization data from the code object.
1415 // <deopt_data> = <code>[#deoptimization_data_offset]
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001416 __ ld(a1, MemOperand(v0, Code::kDeoptimizationDataOffset - kHeapObjectTag));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001417
1418 // Load the OSR entrypoint offset from the deoptimization data.
1419 // <osr_offset> = <deopt_data>[#header_size + #osr_pc_offset]
1420 __ ld(a1, MemOperand(a1, FixedArray::OffsetOfElementAt(
1421 DeoptimizationInputData::kOsrPcOffsetIndex) - kHeapObjectTag));
1422 __ SmiUntag(a1);
1423
1424 // Compute the target address = code_obj + header_size + osr_offset
1425 // <entry_addr> = <code_obj> + #header_size + <osr_offset>
1426 __ daddu(v0, v0, a1);
1427 __ daddiu(ra, v0, Code::kHeaderSize - kHeapObjectTag);
1428
1429 // And "return" to the OSR entry point of the function.
1430 __ Ret();
1431}
1432
1433
1434void Builtins::Generate_OsrAfterStackCheck(MacroAssembler* masm) {
1435 // We check the stack limit as indicator that recompilation might be done.
1436 Label ok;
1437 __ LoadRoot(at, Heap::kStackLimitRootIndex);
1438 __ Branch(&ok, hs, sp, Operand(at));
1439 {
1440 FrameScope scope(masm, StackFrame::INTERNAL);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001441 __ CallRuntime(Runtime::kStackGuard);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001442 }
1443 __ Jump(masm->isolate()->builtins()->OnStackReplacement(),
1444 RelocInfo::CODE_TARGET);
1445
1446 __ bind(&ok);
1447 __ Ret();
1448}
1449
1450
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001451// static
1452void Builtins::Generate_DatePrototype_GetField(MacroAssembler* masm,
1453 int field_index) {
1454 // ----------- S t a t e -------------
1455 // -- sp[0] : receiver
1456 // -----------------------------------
1457
1458 // 1. Pop receiver into a0 and check that it's actually a JSDate object.
1459 Label receiver_not_date;
1460 {
1461 __ Pop(a0);
1462 __ JumpIfSmi(a0, &receiver_not_date);
1463 __ GetObjectType(a0, t0, t0);
1464 __ Branch(&receiver_not_date, ne, t0, Operand(JS_DATE_TYPE));
1465 }
1466
1467 // 2. Load the specified date field, falling back to the runtime as necessary.
1468 if (field_index == JSDate::kDateValue) {
1469 __ Ret(USE_DELAY_SLOT);
1470 __ ld(v0, FieldMemOperand(a0, JSDate::kValueOffset)); // In delay slot.
1471 } else {
1472 if (field_index < JSDate::kFirstUncachedField) {
1473 Label stamp_mismatch;
1474 __ li(a1, Operand(ExternalReference::date_cache_stamp(masm->isolate())));
1475 __ ld(a1, MemOperand(a1));
1476 __ ld(t0, FieldMemOperand(a0, JSDate::kCacheStampOffset));
1477 __ Branch(&stamp_mismatch, ne, t0, Operand(a1));
1478 __ Ret(USE_DELAY_SLOT);
1479 __ ld(v0, FieldMemOperand(
1480 a0, JSDate::kValueOffset +
1481 field_index * kPointerSize)); // In delay slot.
1482 __ bind(&stamp_mismatch);
1483 }
1484 FrameScope scope(masm, StackFrame::INTERNAL);
1485 __ PrepareCallCFunction(2, t0);
1486 __ li(a1, Operand(Smi::FromInt(field_index)));
1487 __ CallCFunction(
1488 ExternalReference::get_date_field_function(masm->isolate()), 2);
1489 }
1490 __ Ret();
1491
1492 // 3. Raise a TypeError if the receiver is not a date.
1493 __ bind(&receiver_not_date);
1494 __ TailCallRuntime(Runtime::kThrowNotDateError);
1495}
1496
1497
1498// static
1499void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) {
1500 // ----------- S t a t e -------------
1501 // -- a0 : argc
1502 // -- sp[0] : argArray
1503 // -- sp[4] : thisArg
1504 // -- sp[8] : receiver
1505 // -----------------------------------
1506
1507 // 1. Load receiver into a1, argArray into a0 (if present), remove all
1508 // arguments from the stack (including the receiver), and push thisArg (if
1509 // present) instead.
1510 {
1511 Label no_arg;
1512 Register scratch = a4;
1513 __ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
1514 __ mov(a3, a2);
1515 __ dsll(scratch, a0, kPointerSizeLog2);
1516 __ Daddu(a0, sp, Operand(scratch));
1517 __ ld(a1, MemOperand(a0)); // receiver
1518 __ Dsubu(a0, a0, Operand(kPointerSize));
1519 __ Branch(&no_arg, lt, a0, Operand(sp));
1520 __ ld(a2, MemOperand(a0)); // thisArg
1521 __ Dsubu(a0, a0, Operand(kPointerSize));
1522 __ Branch(&no_arg, lt, a0, Operand(sp));
1523 __ ld(a3, MemOperand(a0)); // argArray
1524 __ bind(&no_arg);
1525 __ Daddu(sp, sp, Operand(scratch));
1526 __ sd(a2, MemOperand(sp));
1527 __ mov(a0, a3);
1528 }
1529
1530 // ----------- S t a t e -------------
1531 // -- a0 : argArray
1532 // -- a1 : receiver
1533 // -- sp[0] : thisArg
1534 // -----------------------------------
1535
1536 // 2. Make sure the receiver is actually callable.
1537 Label receiver_not_callable;
1538 __ JumpIfSmi(a1, &receiver_not_callable);
1539 __ ld(a4, FieldMemOperand(a1, HeapObject::kMapOffset));
1540 __ lbu(a4, FieldMemOperand(a4, Map::kBitFieldOffset));
1541 __ And(a4, a4, Operand(1 << Map::kIsCallable));
1542 __ Branch(&receiver_not_callable, eq, a4, Operand(zero_reg));
1543
1544 // 3. Tail call with no arguments if argArray is null or undefined.
1545 Label no_arguments;
1546 __ JumpIfRoot(a0, Heap::kNullValueRootIndex, &no_arguments);
1547 __ JumpIfRoot(a0, Heap::kUndefinedValueRootIndex, &no_arguments);
1548
1549 // 4a. Apply the receiver to the given argArray (passing undefined for
1550 // new.target).
1551 __ LoadRoot(a3, Heap::kUndefinedValueRootIndex);
1552 __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET);
1553
1554 // 4b. The argArray is either null or undefined, so we tail call without any
1555 // arguments to the receiver.
1556 __ bind(&no_arguments);
1557 {
1558 __ mov(a0, zero_reg);
1559 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
1560 }
1561
1562 // 4c. The receiver is not callable, throw an appropriate TypeError.
1563 __ bind(&receiver_not_callable);
1564 {
1565 __ sd(a1, MemOperand(sp));
1566 __ TailCallRuntime(Runtime::kThrowApplyNonFunction);
1567 }
1568}
1569
1570
1571// static
1572void Builtins::Generate_FunctionPrototypeCall(MacroAssembler* masm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001573 // 1. Make sure we have at least one argument.
1574 // a0: actual number of arguments
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001575 {
1576 Label done;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001577 __ Branch(&done, ne, a0, Operand(zero_reg));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001578 __ PushRoot(Heap::kUndefinedValueRootIndex);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001579 __ Daddu(a0, a0, Operand(1));
1580 __ bind(&done);
1581 }
1582
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001583 // 2. Get the function to call (passed as receiver) from the stack.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001584 // a0: actual number of arguments
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001585 __ dsll(at, a0, kPointerSizeLog2);
1586 __ daddu(at, sp, at);
1587 __ ld(a1, MemOperand(at));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001588
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001589 // 3. Shift arguments and return address one slot down on the stack
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001590 // (overwriting the original receiver). Adjust argument count to make
1591 // the original first argument the new receiver.
1592 // a0: actual number of arguments
1593 // a1: function
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001594 {
1595 Label loop;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001596 // Calculate the copy start address (destination). Copy end address is sp.
1597 __ dsll(at, a0, kPointerSizeLog2);
1598 __ daddu(a2, sp, at);
1599
1600 __ bind(&loop);
1601 __ ld(at, MemOperand(a2, -kPointerSize));
1602 __ sd(at, MemOperand(a2));
1603 __ Dsubu(a2, a2, Operand(kPointerSize));
1604 __ Branch(&loop, ne, a2, Operand(sp));
1605 // Adjust the actual number of arguments and remove the top element
1606 // (which is a copy of the last argument).
1607 __ Dsubu(a0, a0, Operand(1));
1608 __ Pop();
1609 }
1610
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001611 // 4. Call the callable.
1612 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001613}
1614
1615
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001616void Builtins::Generate_ReflectApply(MacroAssembler* masm) {
1617 // ----------- S t a t e -------------
1618 // -- a0 : argc
1619 // -- sp[0] : argumentsList
1620 // -- sp[4] : thisArgument
1621 // -- sp[8] : target
1622 // -- sp[12] : receiver
1623 // -----------------------------------
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001624
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001625 // 1. Load target into a1 (if present), argumentsList into a0 (if present),
1626 // remove all arguments from the stack (including the receiver), and push
1627 // thisArgument (if present) instead.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001628 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001629 Label no_arg;
1630 Register scratch = a4;
1631 __ LoadRoot(a1, Heap::kUndefinedValueRootIndex);
1632 __ mov(a2, a1);
1633 __ mov(a3, a1);
1634 __ dsll(scratch, a0, kPointerSizeLog2);
1635 __ mov(a0, scratch);
1636 __ Dsubu(a0, a0, Operand(kPointerSize));
1637 __ Branch(&no_arg, lt, a0, Operand(zero_reg));
1638 __ Daddu(a0, sp, Operand(a0));
1639 __ ld(a1, MemOperand(a0)); // target
1640 __ Dsubu(a0, a0, Operand(kPointerSize));
1641 __ Branch(&no_arg, lt, a0, Operand(sp));
1642 __ ld(a2, MemOperand(a0)); // thisArgument
1643 __ Dsubu(a0, a0, Operand(kPointerSize));
1644 __ Branch(&no_arg, lt, a0, Operand(sp));
1645 __ ld(a3, MemOperand(a0)); // argumentsList
1646 __ bind(&no_arg);
1647 __ Daddu(sp, sp, Operand(scratch));
1648 __ sd(a2, MemOperand(sp));
1649 __ mov(a0, a3);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001650 }
1651
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001652 // ----------- S t a t e -------------
1653 // -- a0 : argumentsList
1654 // -- a1 : target
1655 // -- sp[0] : thisArgument
1656 // -----------------------------------
1657
1658 // 2. Make sure the target is actually callable.
1659 Label target_not_callable;
1660 __ JumpIfSmi(a1, &target_not_callable);
1661 __ ld(a4, FieldMemOperand(a1, HeapObject::kMapOffset));
1662 __ lbu(a4, FieldMemOperand(a4, Map::kBitFieldOffset));
1663 __ And(a4, a4, Operand(1 << Map::kIsCallable));
1664 __ Branch(&target_not_callable, eq, a4, Operand(zero_reg));
1665
1666 // 3a. Apply the target to the given argumentsList (passing undefined for
1667 // new.target).
1668 __ LoadRoot(a3, Heap::kUndefinedValueRootIndex);
1669 __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET);
1670
1671 // 3b. The target is not callable, throw an appropriate TypeError.
1672 __ bind(&target_not_callable);
1673 {
1674 __ sd(a1, MemOperand(sp));
1675 __ TailCallRuntime(Runtime::kThrowApplyNonFunction);
1676 }
1677}
1678
1679
1680void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
1681 // ----------- S t a t e -------------
1682 // -- a0 : argc
1683 // -- sp[0] : new.target (optional)
1684 // -- sp[4] : argumentsList
1685 // -- sp[8] : target
1686 // -- sp[12] : receiver
1687 // -----------------------------------
1688
1689 // 1. Load target into a1 (if present), argumentsList into a0 (if present),
1690 // new.target into a3 (if present, otherwise use target), remove all
1691 // arguments from the stack (including the receiver), and push thisArgument
1692 // (if present) instead.
1693 {
1694 Label no_arg;
1695 Register scratch = a4;
1696 __ LoadRoot(a1, Heap::kUndefinedValueRootIndex);
1697 __ mov(a2, a1);
1698 __ dsll(scratch, a0, kPointerSizeLog2);
1699 __ Daddu(a0, sp, Operand(scratch));
1700 __ sd(a2, MemOperand(a0)); // receiver
1701 __ Dsubu(a0, a0, Operand(kPointerSize));
1702 __ Branch(&no_arg, lt, a0, Operand(sp));
1703 __ ld(a1, MemOperand(a0)); // target
1704 __ mov(a3, a1); // new.target defaults to target
1705 __ Dsubu(a0, a0, Operand(kPointerSize));
1706 __ Branch(&no_arg, lt, a0, Operand(sp));
1707 __ ld(a2, MemOperand(a0)); // argumentsList
1708 __ Dsubu(a0, a0, Operand(kPointerSize));
1709 __ Branch(&no_arg, lt, a0, Operand(sp));
1710 __ ld(a3, MemOperand(a0)); // new.target
1711 __ bind(&no_arg);
1712 __ Daddu(sp, sp, Operand(scratch));
1713 __ mov(a0, a2);
1714 }
1715
1716 // ----------- S t a t e -------------
1717 // -- a0 : argumentsList
1718 // -- a3 : new.target
1719 // -- a1 : target
1720 // -- sp[0] : receiver (undefined)
1721 // -----------------------------------
1722
1723 // 2. Make sure the target is actually a constructor.
1724 Label target_not_constructor;
1725 __ JumpIfSmi(a1, &target_not_constructor);
1726 __ ld(a4, FieldMemOperand(a1, HeapObject::kMapOffset));
1727 __ lbu(a4, FieldMemOperand(a4, Map::kBitFieldOffset));
1728 __ And(a4, a4, Operand(1 << Map::kIsConstructor));
1729 __ Branch(&target_not_constructor, eq, a4, Operand(zero_reg));
1730
1731 // 3. Make sure the target is actually a constructor.
1732 Label new_target_not_constructor;
1733 __ JumpIfSmi(a3, &new_target_not_constructor);
1734 __ ld(a4, FieldMemOperand(a3, HeapObject::kMapOffset));
1735 __ lbu(a4, FieldMemOperand(a4, Map::kBitFieldOffset));
1736 __ And(a4, a4, Operand(1 << Map::kIsConstructor));
1737 __ Branch(&new_target_not_constructor, eq, a4, Operand(zero_reg));
1738
1739 // 4a. Construct the target with the given new.target and argumentsList.
1740 __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET);
1741
1742 // 4b. The target is not a constructor, throw an appropriate TypeError.
1743 __ bind(&target_not_constructor);
1744 {
1745 __ sd(a1, MemOperand(sp));
1746 __ TailCallRuntime(Runtime::kThrowCalledNonCallable);
1747 }
1748
1749 // 4c. The new.target is not a constructor, throw an appropriate TypeError.
1750 __ bind(&new_target_not_constructor);
1751 {
1752 __ sd(a3, MemOperand(sp));
1753 __ TailCallRuntime(Runtime::kThrowCalledNonCallable);
1754 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001755}
1756
1757
1758static void ArgumentAdaptorStackCheck(MacroAssembler* masm,
1759 Label* stack_overflow) {
1760 // ----------- S t a t e -------------
1761 // -- a0 : actual number of arguments
1762 // -- a1 : function (passed through to callee)
1763 // -- a2 : expected number of arguments
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001764 // -- a3 : new target (passed through to callee)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001765 // -----------------------------------
1766 // Check the stack for overflow. We are not trying to catch
1767 // interruptions (e.g. debug break and preemption) here, so the "real stack
1768 // limit" is checked.
1769 __ LoadRoot(a5, Heap::kRealStackLimitRootIndex);
1770 // Make a5 the space we have left. The stack might already be overflowed
1771 // here which will cause a5 to become negative.
1772 __ dsubu(a5, sp, a5);
1773 // Check if the arguments will overflow the stack.
1774 __ dsll(at, a2, kPointerSizeLog2);
1775 // Signed comparison.
1776 __ Branch(stack_overflow, le, a5, Operand(at));
1777}
1778
1779
1780static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
1781 // __ sll(a0, a0, kSmiTagSize);
1782 __ dsll32(a0, a0, 0);
1783 __ li(a4, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
1784 __ MultiPush(a0.bit() | a1.bit() | a4.bit() | fp.bit() | ra.bit());
1785 __ Daddu(fp, sp,
1786 Operand(StandardFrameConstants::kFixedFrameSizeFromFp + kPointerSize));
1787}
1788
1789
1790static void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) {
1791 // ----------- S t a t e -------------
1792 // -- v0 : result being passed through
1793 // -----------------------------------
1794 // Get the number of arguments passed (as a smi), tear down the frame and
1795 // then tear down the parameters.
1796 __ ld(a1, MemOperand(fp, -(StandardFrameConstants::kFixedFrameSizeFromFp +
1797 kPointerSize)));
1798 __ mov(sp, fp);
1799 __ MultiPop(fp.bit() | ra.bit());
1800 __ SmiScale(a4, a1, kPointerSizeLog2);
1801 __ Daddu(sp, sp, a4);
1802 // Adjust for the receiver.
1803 __ Daddu(sp, sp, Operand(kPointerSize));
1804}
1805
1806
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001807// static
1808void Builtins::Generate_Apply(MacroAssembler* masm) {
1809 // ----------- S t a t e -------------
1810 // -- a0 : argumentsList
1811 // -- a1 : target
1812 // -- a3 : new.target (checked to be constructor or undefined)
1813 // -- sp[0] : thisArgument
1814 // -----------------------------------
1815
1816 // Create the list of arguments from the array-like argumentsList.
1817 {
1818 Label create_arguments, create_array, create_runtime, done_create;
1819 __ JumpIfSmi(a0, &create_runtime);
1820
1821 // Load the map of argumentsList into a2.
1822 __ ld(a2, FieldMemOperand(a0, HeapObject::kMapOffset));
1823
1824 // Load native context into a4.
1825 __ ld(a4, NativeContextMemOperand());
1826
1827 // Check if argumentsList is an (unmodified) arguments object.
1828 __ ld(at, ContextMemOperand(a4, Context::SLOPPY_ARGUMENTS_MAP_INDEX));
1829 __ Branch(&create_arguments, eq, a2, Operand(at));
1830 __ ld(at, ContextMemOperand(a4, Context::STRICT_ARGUMENTS_MAP_INDEX));
1831 __ Branch(&create_arguments, eq, a2, Operand(at));
1832
1833 // Check if argumentsList is a fast JSArray.
1834 __ ld(v0, FieldMemOperand(a2, HeapObject::kMapOffset));
1835 __ lbu(v0, FieldMemOperand(v0, Map::kInstanceTypeOffset));
1836 __ Branch(&create_array, eq, v0, Operand(JS_ARRAY_TYPE));
1837
1838 // Ask the runtime to create the list (actually a FixedArray).
1839 __ bind(&create_runtime);
1840 {
1841 FrameScope scope(masm, StackFrame::INTERNAL);
1842 __ Push(a1, a3, a0);
1843 __ CallRuntime(Runtime::kCreateListFromArrayLike);
1844 __ mov(a0, v0);
1845 __ Pop(a1, a3);
1846 __ ld(a2, FieldMemOperand(v0, FixedArray::kLengthOffset));
1847 __ SmiUntag(a2);
1848 }
1849 __ Branch(&done_create);
1850
1851 // Try to create the list from an arguments object.
1852 __ bind(&create_arguments);
1853 __ ld(a2,
1854 FieldMemOperand(a0, JSObject::kHeaderSize +
1855 Heap::kArgumentsLengthIndex * kPointerSize));
1856 __ ld(a4, FieldMemOperand(a0, JSObject::kElementsOffset));
1857 __ ld(at, FieldMemOperand(a4, FixedArray::kLengthOffset));
1858 __ Branch(&create_runtime, ne, a2, Operand(at));
1859 __ SmiUntag(a2);
1860 __ mov(a0, a4);
1861 __ Branch(&done_create);
1862
1863 // Try to create the list from a JSArray object.
1864 __ bind(&create_array);
1865 __ ld(a2, FieldMemOperand(a2, Map::kBitField2Offset));
1866 __ DecodeField<Map::ElementsKindBits>(a2);
1867 STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
1868 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
1869 STATIC_ASSERT(FAST_ELEMENTS == 2);
1870 __ Branch(&create_runtime, hi, a2, Operand(FAST_ELEMENTS));
1871 __ Branch(&create_runtime, eq, a2, Operand(FAST_HOLEY_SMI_ELEMENTS));
1872 __ ld(a2, FieldMemOperand(a0, JSArray::kLengthOffset));
1873 __ ld(a0, FieldMemOperand(a0, JSArray::kElementsOffset));
1874 __ SmiUntag(a2);
1875
1876 __ bind(&done_create);
1877 }
1878
1879 // Check for stack overflow.
1880 {
1881 // Check the stack for overflow. We are not trying to catch interruptions
1882 // (i.e. debug break and preemption) here, so check the "real stack limit".
1883 Label done;
1884 __ LoadRoot(a4, Heap::kRealStackLimitRootIndex);
1885 // Make ip the space we have left. The stack might already be overflowed
1886 // here which will cause ip to become negative.
1887 __ Dsubu(a4, sp, a4);
1888 // Check if the arguments will overflow the stack.
1889 __ dsll(at, a2, kPointerSizeLog2);
1890 __ Branch(&done, gt, a4, Operand(at)); // Signed comparison.
1891 __ TailCallRuntime(Runtime::kThrowStackOverflow);
1892 __ bind(&done);
1893 }
1894
1895 // ----------- S t a t e -------------
1896 // -- a1 : target
1897 // -- a0 : args (a FixedArray built from argumentsList)
1898 // -- a2 : len (number of elements to push from args)
1899 // -- a3 : new.target (checked to be constructor or undefined)
1900 // -- sp[0] : thisArgument
1901 // -----------------------------------
1902
1903 // Push arguments onto the stack (thisArgument is already on the stack).
1904 {
1905 __ mov(a4, zero_reg);
1906 Label done, loop;
1907 __ bind(&loop);
1908 __ Branch(&done, eq, a4, Operand(a2));
1909 __ dsll(at, a4, kPointerSizeLog2);
1910 __ Daddu(at, a0, at);
1911 __ ld(at, FieldMemOperand(at, FixedArray::kHeaderSize));
1912 __ Push(at);
1913 __ Daddu(a4, a4, Operand(1));
1914 __ Branch(&loop);
1915 __ bind(&done);
1916 __ Move(a0, a4);
1917 }
1918
1919 // Dispatch to Call or Construct depending on whether new.target is undefined.
1920 {
1921 Label construct;
1922 __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
1923 __ Branch(&construct, ne, a3, Operand(at));
1924 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
1925 __ bind(&construct);
1926 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
1927 }
1928}
1929
1930
1931// static
1932void Builtins::Generate_CallFunction(MacroAssembler* masm,
1933 ConvertReceiverMode mode) {
1934 // ----------- S t a t e -------------
1935 // -- a0 : the number of arguments (not including the receiver)
1936 // -- a1 : the function to call (checked to be a JSFunction)
1937 // -----------------------------------
1938 __ AssertFunction(a1);
1939
1940 // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList)
1941 // Check that function is not a "classConstructor".
1942 Label class_constructor;
1943 __ ld(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
1944 __ lbu(a3, FieldMemOperand(a2, SharedFunctionInfo::kFunctionKindByteOffset));
1945 __ And(at, a3, Operand(SharedFunctionInfo::kClassConstructorBitsWithinByte));
1946 __ Branch(&class_constructor, ne, at, Operand(zero_reg));
1947
1948 // Enter the context of the function; ToObject has to run in the function
1949 // context, and we also need to take the global proxy from the function
1950 // context in case of conversion.
1951 STATIC_ASSERT(SharedFunctionInfo::kNativeByteOffset ==
1952 SharedFunctionInfo::kStrictModeByteOffset);
1953 __ ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
1954 // We need to convert the receiver for non-native sloppy mode functions.
1955 Label done_convert;
1956 __ lbu(a3, FieldMemOperand(a2, SharedFunctionInfo::kNativeByteOffset));
1957 __ And(at, a3, Operand((1 << SharedFunctionInfo::kNativeBitWithinByte) |
1958 (1 << SharedFunctionInfo::kStrictModeBitWithinByte)));
1959 __ Branch(&done_convert, ne, at, Operand(zero_reg));
1960 {
1961 // ----------- S t a t e -------------
1962 // -- a0 : the number of arguments (not including the receiver)
1963 // -- a1 : the function to call (checked to be a JSFunction)
1964 // -- a2 : the shared function info.
1965 // -- cp : the function context.
1966 // -----------------------------------
1967
1968 if (mode == ConvertReceiverMode::kNullOrUndefined) {
1969 // Patch receiver to global proxy.
1970 __ LoadGlobalProxy(a3);
1971 } else {
1972 Label convert_to_object, convert_receiver;
1973 __ dsll(at, a0, kPointerSizeLog2);
1974 __ daddu(at, sp, at);
1975 __ ld(a3, MemOperand(at));
1976 __ JumpIfSmi(a3, &convert_to_object);
1977 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
1978 __ GetObjectType(a3, a4, a4);
1979 __ Branch(&done_convert, hs, a4, Operand(FIRST_JS_RECEIVER_TYPE));
1980 if (mode != ConvertReceiverMode::kNotNullOrUndefined) {
1981 Label convert_global_proxy;
1982 __ JumpIfRoot(a3, Heap::kUndefinedValueRootIndex,
1983 &convert_global_proxy);
1984 __ JumpIfNotRoot(a3, Heap::kNullValueRootIndex, &convert_to_object);
1985 __ bind(&convert_global_proxy);
1986 {
1987 // Patch receiver to global proxy.
1988 __ LoadGlobalProxy(a3);
1989 }
1990 __ Branch(&convert_receiver);
1991 }
1992 __ bind(&convert_to_object);
1993 {
1994 // Convert receiver using ToObject.
1995 // TODO(bmeurer): Inline the allocation here to avoid building the frame
1996 // in the fast case? (fall back to AllocateInNewSpace?)
1997 FrameScope scope(masm, StackFrame::INTERNAL);
1998 __ SmiTag(a0);
1999 __ Push(a0, a1);
2000 __ mov(a0, a3);
2001 ToObjectStub stub(masm->isolate());
2002 __ CallStub(&stub);
2003 __ mov(a3, v0);
2004 __ Pop(a0, a1);
2005 __ SmiUntag(a0);
2006 }
2007 __ ld(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
2008 __ bind(&convert_receiver);
2009 }
2010 __ dsll(at, a0, kPointerSizeLog2);
2011 __ daddu(at, sp, at);
2012 __ sd(a3, MemOperand(at));
2013 }
2014 __ bind(&done_convert);
2015
2016 // ----------- S t a t e -------------
2017 // -- a0 : the number of arguments (not including the receiver)
2018 // -- a1 : the function to call (checked to be a JSFunction)
2019 // -- a2 : the shared function info.
2020 // -- cp : the function context.
2021 // -----------------------------------
2022
2023 __ lw(a2,
2024 FieldMemOperand(a2, SharedFunctionInfo::kFormalParameterCountOffset));
2025 ParameterCount actual(a0);
2026 ParameterCount expected(a2);
2027 __ InvokeFunctionCode(a1, no_reg, expected, actual, JUMP_FUNCTION,
2028 CheckDebugStepCallWrapper());
2029
2030 // The function is a "classConstructor", need to raise an exception.
2031 __ bind(&class_constructor);
2032 {
2033 FrameScope frame(masm, StackFrame::INTERNAL);
2034 __ Push(a1);
2035 __ CallRuntime(Runtime::kThrowConstructorNonCallableError);
2036 }
2037}
2038
2039
2040// static
2041void Builtins::Generate_CallBoundFunction(MacroAssembler* masm) {
2042 // ----------- S t a t e -------------
2043 // -- a0 : the number of arguments (not including the receiver)
2044 // -- a1 : the function to call (checked to be a JSBoundFunction)
2045 // -----------------------------------
2046 __ AssertBoundFunction(a1);
2047
2048 // Patch the receiver to [[BoundThis]].
2049 {
2050 __ ld(at, FieldMemOperand(a1, JSBoundFunction::kBoundThisOffset));
2051 __ dsll(a4, a0, kPointerSizeLog2);
2052 __ daddu(a4, a4, sp);
2053 __ sd(at, MemOperand(a4));
2054 }
2055
2056 // Load [[BoundArguments]] into a2 and length of that into a4.
2057 __ ld(a2, FieldMemOperand(a1, JSBoundFunction::kBoundArgumentsOffset));
2058 __ ld(a4, FieldMemOperand(a2, FixedArray::kLengthOffset));
2059 __ SmiUntag(a4);
2060
2061 // ----------- S t a t e -------------
2062 // -- a0 : the number of arguments (not including the receiver)
2063 // -- a1 : the function to call (checked to be a JSBoundFunction)
2064 // -- a2 : the [[BoundArguments]] (implemented as FixedArray)
2065 // -- a4 : the number of [[BoundArguments]]
2066 // -----------------------------------
2067
2068 // Reserve stack space for the [[BoundArguments]].
2069 {
2070 Label done;
2071 __ dsll(a5, a4, kPointerSizeLog2);
2072 __ Dsubu(sp, sp, Operand(a5));
2073 // Check the stack for overflow. We are not trying to catch interruptions
2074 // (i.e. debug break and preemption) here, so check the "real stack limit".
2075 __ LoadRoot(at, Heap::kRealStackLimitRootIndex);
2076 __ Branch(&done, gt, sp, Operand(at)); // Signed comparison.
2077 // Restore the stack pointer.
2078 __ Daddu(sp, sp, Operand(a5));
2079 {
2080 FrameScope scope(masm, StackFrame::MANUAL);
2081 __ EnterFrame(StackFrame::INTERNAL);
2082 __ CallRuntime(Runtime::kThrowStackOverflow);
2083 }
2084 __ bind(&done);
2085 }
2086
2087 // Relocate arguments down the stack.
2088 {
2089 Label loop, done_loop;
2090 __ mov(a5, zero_reg);
2091 __ bind(&loop);
2092 __ Branch(&done_loop, gt, a5, Operand(a0));
2093 __ dsll(a6, a4, kPointerSizeLog2);
2094 __ daddu(a6, a6, sp);
2095 __ ld(at, MemOperand(a6));
2096 __ dsll(a6, a5, kPointerSizeLog2);
2097 __ daddu(a6, a6, sp);
2098 __ sd(at, MemOperand(a6));
2099 __ Daddu(a4, a4, Operand(1));
2100 __ Daddu(a5, a5, Operand(1));
2101 __ Branch(&loop);
2102 __ bind(&done_loop);
2103 }
2104
2105 // Copy [[BoundArguments]] to the stack (below the arguments).
2106 {
2107 Label loop, done_loop;
2108 __ ld(a4, FieldMemOperand(a2, FixedArray::kLengthOffset));
2109 __ SmiUntag(a4);
2110 __ Daddu(a2, a2, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
2111 __ bind(&loop);
2112 __ Dsubu(a4, a4, Operand(1));
2113 __ Branch(&done_loop, lt, a4, Operand(zero_reg));
2114 __ dsll(a5, a4, kPointerSizeLog2);
2115 __ daddu(a5, a5, a2);
2116 __ ld(at, MemOperand(a5));
2117 __ dsll(a5, a0, kPointerSizeLog2);
2118 __ daddu(a5, a5, sp);
2119 __ sd(at, MemOperand(a5));
2120 __ Daddu(a0, a0, Operand(1));
2121 __ Branch(&loop);
2122 __ bind(&done_loop);
2123 }
2124
2125 // Call the [[BoundTargetFunction]] via the Call builtin.
2126 __ ld(a1, FieldMemOperand(a1, JSBoundFunction::kBoundTargetFunctionOffset));
2127 __ li(at, Operand(ExternalReference(Builtins::kCall_ReceiverIsAny,
2128 masm->isolate())));
2129 __ ld(at, MemOperand(at));
2130 __ Daddu(at, at, Operand(Code::kHeaderSize - kHeapObjectTag));
2131 __ Jump(at);
2132}
2133
2134
2135// static
2136void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) {
2137 // ----------- S t a t e -------------
2138 // -- a0 : the number of arguments (not including the receiver)
2139 // -- a1 : the target to call (can be any Object).
2140 // -----------------------------------
2141
2142 Label non_callable, non_function, non_smi;
2143 __ JumpIfSmi(a1, &non_callable);
2144 __ bind(&non_smi);
2145 __ GetObjectType(a1, t1, t2);
2146 __ Jump(masm->isolate()->builtins()->CallFunction(mode),
2147 RelocInfo::CODE_TARGET, eq, t2, Operand(JS_FUNCTION_TYPE));
2148 __ Jump(masm->isolate()->builtins()->CallBoundFunction(),
2149 RelocInfo::CODE_TARGET, eq, t2, Operand(JS_BOUND_FUNCTION_TYPE));
2150 __ Branch(&non_function, ne, t2, Operand(JS_PROXY_TYPE));
2151
2152 // 1. Runtime fallback for Proxy [[Call]].
2153 __ Push(a1);
2154 // Increase the arguments size to include the pushed function and the
2155 // existing receiver on the stack.
2156 __ Daddu(a0, a0, 2);
2157 // Tail-call to the runtime.
2158 __ JumpToExternalReference(
2159 ExternalReference(Runtime::kJSProxyCall, masm->isolate()));
2160
2161 // 2. Call to something else, which might have a [[Call]] internal method (if
2162 // not we raise an exception).
2163 __ bind(&non_function);
2164 // Check if target has a [[Call]] internal method.
2165 __ lbu(t1, FieldMemOperand(t1, Map::kBitFieldOffset));
2166 __ And(t1, t1, Operand(1 << Map::kIsCallable));
2167 __ Branch(&non_callable, eq, t1, Operand(zero_reg));
2168 // Overwrite the original receiver with the (original) target.
2169 __ dsll(at, a0, kPointerSizeLog2);
2170 __ daddu(at, sp, at);
2171 __ sd(a1, MemOperand(at));
2172 // Let the "call_as_function_delegate" take care of the rest.
2173 __ LoadNativeContextSlot(Context::CALL_AS_FUNCTION_DELEGATE_INDEX, a1);
2174 __ Jump(masm->isolate()->builtins()->CallFunction(
2175 ConvertReceiverMode::kNotNullOrUndefined),
2176 RelocInfo::CODE_TARGET);
2177
2178 // 3. Call to something that is not callable.
2179 __ bind(&non_callable);
2180 {
2181 FrameScope scope(masm, StackFrame::INTERNAL);
2182 __ Push(a1);
2183 __ CallRuntime(Runtime::kThrowCalledNonCallable);
2184 }
2185}
2186
2187
2188void Builtins::Generate_ConstructFunction(MacroAssembler* masm) {
2189 // ----------- S t a t e -------------
2190 // -- a0 : the number of arguments (not including the receiver)
2191 // -- a1 : the constructor to call (checked to be a JSFunction)
2192 // -- a3 : the new target (checked to be a constructor)
2193 // -----------------------------------
2194 __ AssertFunction(a1);
2195
2196 // Calling convention for function specific ConstructStubs require
2197 // a2 to contain either an AllocationSite or undefined.
2198 __ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
2199
2200 // Tail call to the function-specific construct stub (still in the caller
2201 // context at this point).
2202 __ ld(a4, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
2203 __ ld(a4, FieldMemOperand(a4, SharedFunctionInfo::kConstructStubOffset));
2204 __ Daddu(at, a4, Operand(Code::kHeaderSize - kHeapObjectTag));
2205 __ Jump(at);
2206}
2207
2208
2209// static
2210void Builtins::Generate_ConstructBoundFunction(MacroAssembler* masm) {
2211 // ----------- S t a t e -------------
2212 // -- a0 : the number of arguments (not including the receiver)
2213 // -- a1 : the function to call (checked to be a JSBoundFunction)
2214 // -- a3 : the new target (checked to be a constructor)
2215 // -----------------------------------
2216 __ AssertBoundFunction(a1);
2217
2218 // Load [[BoundArguments]] into a2 and length of that into a4.
2219 __ ld(a2, FieldMemOperand(a1, JSBoundFunction::kBoundArgumentsOffset));
2220 __ ld(a4, FieldMemOperand(a2, FixedArray::kLengthOffset));
2221 __ SmiUntag(a4);
2222
2223 // ----------- S t a t e -------------
2224 // -- a0 : the number of arguments (not including the receiver)
2225 // -- a1 : the function to call (checked to be a JSBoundFunction)
2226 // -- a2 : the [[BoundArguments]] (implemented as FixedArray)
2227 // -- a3 : the new target (checked to be a constructor)
2228 // -- a4 : the number of [[BoundArguments]]
2229 // -----------------------------------
2230
2231 // Reserve stack space for the [[BoundArguments]].
2232 {
2233 Label done;
2234 __ dsll(a5, a4, kPointerSizeLog2);
2235 __ Dsubu(sp, sp, Operand(a5));
2236 // Check the stack for overflow. We are not trying to catch interruptions
2237 // (i.e. debug break and preemption) here, so check the "real stack limit".
2238 __ LoadRoot(at, Heap::kRealStackLimitRootIndex);
2239 __ Branch(&done, gt, sp, Operand(at)); // Signed comparison.
2240 // Restore the stack pointer.
2241 __ Daddu(sp, sp, Operand(a5));
2242 {
2243 FrameScope scope(masm, StackFrame::MANUAL);
2244 __ EnterFrame(StackFrame::INTERNAL);
2245 __ CallRuntime(Runtime::kThrowStackOverflow);
2246 }
2247 __ bind(&done);
2248 }
2249
2250 // Relocate arguments down the stack.
2251 {
2252 Label loop, done_loop;
2253 __ mov(a5, zero_reg);
2254 __ bind(&loop);
2255 __ Branch(&done_loop, ge, a5, Operand(a0));
2256 __ dsll(a6, a4, kPointerSizeLog2);
2257 __ daddu(a6, a6, sp);
2258 __ ld(at, MemOperand(a6));
2259 __ dsll(a6, a5, kPointerSizeLog2);
2260 __ daddu(a6, a6, sp);
2261 __ sd(at, MemOperand(a6));
2262 __ Daddu(a4, a4, Operand(1));
2263 __ Daddu(a5, a5, Operand(1));
2264 __ Branch(&loop);
2265 __ bind(&done_loop);
2266 }
2267
2268 // Copy [[BoundArguments]] to the stack (below the arguments).
2269 {
2270 Label loop, done_loop;
2271 __ ld(a4, FieldMemOperand(a2, FixedArray::kLengthOffset));
2272 __ SmiUntag(a4);
2273 __ Daddu(a2, a2, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
2274 __ bind(&loop);
2275 __ Dsubu(a4, a4, Operand(1));
2276 __ Branch(&done_loop, lt, a4, Operand(zero_reg));
2277 __ dsll(a5, a4, kPointerSizeLog2);
2278 __ daddu(a5, a5, a2);
2279 __ ld(at, MemOperand(a5));
2280 __ dsll(a5, a0, kPointerSizeLog2);
2281 __ daddu(a5, a5, sp);
2282 __ sd(at, MemOperand(a5));
2283 __ Daddu(a0, a0, Operand(1));
2284 __ Branch(&loop);
2285 __ bind(&done_loop);
2286 }
2287
2288 // Patch new.target to [[BoundTargetFunction]] if new.target equals target.
2289 {
2290 Label skip_load;
2291 __ Branch(&skip_load, ne, a1, Operand(a3));
2292 __ ld(a3, FieldMemOperand(a1, JSBoundFunction::kBoundTargetFunctionOffset));
2293 __ bind(&skip_load);
2294 }
2295
2296 // Construct the [[BoundTargetFunction]] via the Construct builtin.
2297 __ ld(a1, FieldMemOperand(a1, JSBoundFunction::kBoundTargetFunctionOffset));
2298 __ li(at, Operand(ExternalReference(Builtins::kConstruct, masm->isolate())));
2299 __ ld(at, MemOperand(at));
2300 __ Daddu(at, at, Operand(Code::kHeaderSize - kHeapObjectTag));
2301 __ Jump(at);
2302}
2303
2304
2305// static
2306void Builtins::Generate_ConstructProxy(MacroAssembler* masm) {
2307 // ----------- S t a t e -------------
2308 // -- a0 : the number of arguments (not including the receiver)
2309 // -- a1 : the constructor to call (checked to be a JSProxy)
2310 // -- a3 : the new target (either the same as the constructor or
2311 // the JSFunction on which new was invoked initially)
2312 // -----------------------------------
2313
2314 // Call into the Runtime for Proxy [[Construct]].
2315 __ Push(a1, a3);
2316 // Include the pushed new_target, constructor and the receiver.
2317 __ Daddu(a0, a0, Operand(3));
2318 // Tail-call to the runtime.
2319 __ JumpToExternalReference(
2320 ExternalReference(Runtime::kJSProxyConstruct, masm->isolate()));
2321}
2322
2323
2324// static
2325void Builtins::Generate_Construct(MacroAssembler* masm) {
2326 // ----------- S t a t e -------------
2327 // -- a0 : the number of arguments (not including the receiver)
2328 // -- a1 : the constructor to call (can be any Object)
2329 // -- a3 : the new target (either the same as the constructor or
2330 // the JSFunction on which new was invoked initially)
2331 // -----------------------------------
2332
2333 // Check if target is a Smi.
2334 Label non_constructor;
2335 __ JumpIfSmi(a1, &non_constructor);
2336
2337 // Dispatch based on instance type.
2338 __ ld(t1, FieldMemOperand(a1, HeapObject::kMapOffset));
2339 __ lbu(t2, FieldMemOperand(t1, Map::kInstanceTypeOffset));
2340 __ Jump(masm->isolate()->builtins()->ConstructFunction(),
2341 RelocInfo::CODE_TARGET, eq, t2, Operand(JS_FUNCTION_TYPE));
2342
2343 // Check if target has a [[Construct]] internal method.
2344 __ lbu(t3, FieldMemOperand(t1, Map::kBitFieldOffset));
2345 __ And(t3, t3, Operand(1 << Map::kIsConstructor));
2346 __ Branch(&non_constructor, eq, t3, Operand(zero_reg));
2347
2348 // Only dispatch to bound functions after checking whether they are
2349 // constructors.
2350 __ Jump(masm->isolate()->builtins()->ConstructBoundFunction(),
2351 RelocInfo::CODE_TARGET, eq, t2, Operand(JS_BOUND_FUNCTION_TYPE));
2352
2353 // Only dispatch to proxies after checking whether they are constructors.
2354 __ Jump(masm->isolate()->builtins()->ConstructProxy(), RelocInfo::CODE_TARGET,
2355 eq, t2, Operand(JS_PROXY_TYPE));
2356
2357 // Called Construct on an exotic Object with a [[Construct]] internal method.
2358 {
2359 // Overwrite the original receiver with the (original) target.
2360 __ dsll(at, a0, kPointerSizeLog2);
2361 __ daddu(at, sp, at);
2362 __ sd(a1, MemOperand(at));
2363 // Let the "call_as_constructor_delegate" take care of the rest.
2364 __ LoadNativeContextSlot(Context::CALL_AS_CONSTRUCTOR_DELEGATE_INDEX, a1);
2365 __ Jump(masm->isolate()->builtins()->CallFunction(),
2366 RelocInfo::CODE_TARGET);
2367 }
2368
2369 // Called Construct on an Object that doesn't have a [[Construct]] internal
2370 // method.
2371 __ bind(&non_constructor);
2372 __ Jump(masm->isolate()->builtins()->ConstructedNonConstructable(),
2373 RelocInfo::CODE_TARGET);
2374}
2375
2376
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002377void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
2378 // State setup as expected by MacroAssembler::InvokePrologue.
2379 // ----------- S t a t e -------------
2380 // -- a0: actual arguments count
2381 // -- a1: function (passed through to callee)
2382 // -- a2: expected arguments count
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002383 // -- a3: new target (passed through to callee)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002384 // -----------------------------------
2385
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002386 Label invoke, dont_adapt_arguments, stack_overflow;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002387
2388 Label enough, too_few;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002389 __ Branch(&dont_adapt_arguments, eq,
2390 a2, Operand(SharedFunctionInfo::kDontAdaptArgumentsSentinel));
2391 // We use Uless as the number of argument should always be greater than 0.
2392 __ Branch(&too_few, Uless, a0, Operand(a2));
2393
2394 { // Enough parameters: actual >= expected.
2395 // a0: actual number of arguments as a smi
2396 // a1: function
2397 // a2: expected number of arguments
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002398 // a3: new target (passed through to callee)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002399 __ bind(&enough);
2400 EnterArgumentsAdaptorFrame(masm);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002401 ArgumentAdaptorStackCheck(masm, &stack_overflow);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002402
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002403 // Calculate copy start address into a0 and copy end address into a4.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002404 __ SmiScale(a0, a0, kPointerSizeLog2);
2405 __ Daddu(a0, fp, a0);
2406 // Adjust for return address and receiver.
2407 __ Daddu(a0, a0, Operand(2 * kPointerSize));
2408 // Compute copy end address.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002409 __ dsll(a4, a2, kPointerSizeLog2);
2410 __ dsubu(a4, a0, a4);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002411
2412 // Copy the arguments (including the receiver) to the new stack frame.
2413 // a0: copy start address
2414 // a1: function
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002415 // a2: expected number of arguments
2416 // a3: new target (passed through to callee)
2417 // a4: copy end address
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002418
2419 Label copy;
2420 __ bind(&copy);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002421 __ ld(a5, MemOperand(a0));
2422 __ push(a5);
2423 __ Branch(USE_DELAY_SLOT, &copy, ne, a0, Operand(a4));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002424 __ daddiu(a0, a0, -kPointerSize); // In delay slot.
2425
2426 __ jmp(&invoke);
2427 }
2428
2429 { // Too few parameters: Actual < expected.
2430 __ bind(&too_few);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002431
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002432 // If the function is strong we need to throw an error.
2433 Label no_strong_error;
2434 __ ld(a4, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
2435 __ lbu(a5, FieldMemOperand(a4, SharedFunctionInfo::kStrongModeByteOffset));
2436 __ And(a5, a5, Operand(1 << SharedFunctionInfo::kStrongModeBitWithinByte));
2437 __ Branch(&no_strong_error, eq, a5, Operand(zero_reg));
2438
2439 // What we really care about is the required number of arguments.
2440 DCHECK_EQ(kPointerSize, kInt64Size);
2441 __ lw(a5, FieldMemOperand(a4, SharedFunctionInfo::kLengthOffset));
2442 __ srl(a5, a5, 1);
2443 __ Branch(&no_strong_error, ge, a0, Operand(a5));
2444
2445 {
2446 FrameScope frame(masm, StackFrame::MANUAL);
2447 EnterArgumentsAdaptorFrame(masm);
2448 __ CallRuntime(Runtime::kThrowStrongModeTooFewArguments);
2449 }
2450
2451 __ bind(&no_strong_error);
2452 EnterArgumentsAdaptorFrame(masm);
2453 ArgumentAdaptorStackCheck(masm, &stack_overflow);
2454
2455 // Calculate copy start address into a0 and copy end address into a7.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002456 // a0: actual number of arguments as a smi
2457 // a1: function
2458 // a2: expected number of arguments
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002459 // a3: new target (passed through to callee)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002460 __ SmiScale(a0, a0, kPointerSizeLog2);
2461 __ Daddu(a0, fp, a0);
2462 // Adjust for return address and receiver.
2463 __ Daddu(a0, a0, Operand(2 * kPointerSize));
2464 // Compute copy end address. Also adjust for return address.
2465 __ Daddu(a7, fp, kPointerSize);
2466
2467 // Copy the arguments (including the receiver) to the new stack frame.
2468 // a0: copy start address
2469 // a1: function
2470 // a2: expected number of arguments
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002471 // a3: new target (passed through to callee)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002472 // a7: copy end address
2473 Label copy;
2474 __ bind(&copy);
2475 __ ld(a4, MemOperand(a0)); // Adjusted above for return addr and receiver.
2476 __ Dsubu(sp, sp, kPointerSize);
2477 __ Dsubu(a0, a0, kPointerSize);
2478 __ Branch(USE_DELAY_SLOT, &copy, ne, a0, Operand(a7));
2479 __ sd(a4, MemOperand(sp)); // In the delay slot.
2480
2481 // Fill the remaining expected arguments with undefined.
2482 // a1: function
2483 // a2: expected number of arguments
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002484 // a3: new target (passed through to callee)
2485 __ LoadRoot(a5, Heap::kUndefinedValueRootIndex);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002486 __ dsll(a6, a2, kPointerSizeLog2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002487 __ Dsubu(a4, fp, Operand(a6));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002488 // Adjust for frame.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002489 __ Dsubu(a4, a4, Operand(StandardFrameConstants::kFixedFrameSizeFromFp +
2490 2 * kPointerSize));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002491
2492 Label fill;
2493 __ bind(&fill);
2494 __ Dsubu(sp, sp, kPointerSize);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002495 __ Branch(USE_DELAY_SLOT, &fill, ne, sp, Operand(a4));
2496 __ sd(a5, MemOperand(sp));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002497 }
2498
2499 // Call the entry point.
2500 __ bind(&invoke);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002501 __ mov(a0, a2);
2502 // a0 : expected number of arguments
2503 // a1 : function (passed through to callee)
2504 // a3: new target (passed through to callee)
2505 __ ld(a4, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
2506 __ Call(a4);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002507
2508 // Store offset of return address for deoptimizer.
2509 masm->isolate()->heap()->SetArgumentsAdaptorDeoptPCOffset(masm->pc_offset());
2510
2511 // Exit frame and return.
2512 LeaveArgumentsAdaptorFrame(masm);
2513 __ Ret();
2514
2515
2516 // -------------------------------------------
2517 // Don't adapt arguments.
2518 // -------------------------------------------
2519 __ bind(&dont_adapt_arguments);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002520 __ ld(a4, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
2521 __ Jump(a4);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002522
2523 __ bind(&stack_overflow);
2524 {
2525 FrameScope frame(masm, StackFrame::MANUAL);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002526 __ CallRuntime(Runtime::kThrowStackOverflow);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002527 __ break_(0xCC);
2528 }
2529}
2530
2531
2532#undef __
2533
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002534} // namespace internal
2535} // namespace v8
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002536
2537#endif // V8_TARGET_ARCH_MIPS64