builtins-arm.cc revision 592a9fc1d8ea420377a2e7efd0600e20b058be2b
1// Copyright 2011 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6//     * Redistributions of source code must retain the above copyright
7//       notice, this list of conditions and the following disclaimer.
8//     * Redistributions in binary form must reproduce the above
9//       copyright notice, this list of conditions and the following
10//       disclaimer in the documentation and/or other materials provided
11//       with the distribution.
12//     * Neither the name of Google Inc. nor the names of its
13//       contributors may be used to endorse or promote products derived
14//       from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
30#if defined(V8_TARGET_ARCH_ARM)
31
32#include "codegen.h"
33#include "debug.h"
34#include "deoptimizer.h"
35#include "full-codegen.h"
36#include "runtime.h"
37
38namespace v8 {
39namespace internal {
40
41
42#define __ ACCESS_MASM(masm)
43
44
45void Builtins::Generate_Adaptor(MacroAssembler* masm,
46                                CFunctionId id,
47                                BuiltinExtraArguments extra_args) {
48  // ----------- S t a t e -------------
49  //  -- r0                 : number of arguments excluding receiver
50  //  -- r1                 : called function (only guaranteed when
51  //                          extra_args requires it)
52  //  -- cp                 : context
53  //  -- sp[0]              : last argument
54  //  -- ...
55  //  -- sp[4 * (argc - 1)] : first argument (argc == r0)
56  //  -- sp[4 * argc]       : receiver
57  // -----------------------------------
58
59  // Insert extra arguments.
60  int num_extra_args = 0;
61  if (extra_args == NEEDS_CALLED_FUNCTION) {
62    num_extra_args = 1;
63    __ push(r1);
64  } else {
65    ASSERT(extra_args == NO_EXTRA_ARGUMENTS);
66  }
67
68  // JumpToExternalReference expects r0 to contain the number of arguments
69  // including the receiver and the extra arguments.
70  __ add(r0, r0, Operand(num_extra_args + 1));
71  __ JumpToExternalReference(ExternalReference(id, masm->isolate()));
72}
73
74
75// Load the built-in Array function from the current context.
76static void GenerateLoadArrayFunction(MacroAssembler* masm, Register result) {
77  // Load the global context.
78
79  __ ldr(result, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
80  __ ldr(result,
81         FieldMemOperand(result, GlobalObject::kGlobalContextOffset));
82  // Load the Array function from the global context.
83  __ ldr(result,
84         MemOperand(result,
85                    Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX)));
86}
87
88
89// Allocate an empty JSArray. The allocated array is put into the result
90// register. An elements backing store is allocated with size initial_capacity
91// and filled with the hole values.
92static void AllocateEmptyJSArray(MacroAssembler* masm,
93                                 Register array_function,
94                                 Register result,
95                                 Register scratch1,
96                                 Register scratch2,
97                                 Register scratch3,
98                                 Label* gc_required) {
99  const int initial_capacity = JSArray::kPreallocatedArrayElements;
100  STATIC_ASSERT(initial_capacity >= 0);
101  // Load the initial map from the array function.
102  __ ldr(scratch1, FieldMemOperand(array_function,
103                                   JSFunction::kPrototypeOrInitialMapOffset));
104
105  // Allocate the JSArray object together with space for a fixed array with the
106  // requested elements.
107  int size = JSArray::kSize;
108  if (initial_capacity > 0) {
109    size += FixedArray::SizeFor(initial_capacity);
110  }
111  __ AllocateInNewSpace(size,
112                        result,
113                        scratch2,
114                        scratch3,
115                        gc_required,
116                        TAG_OBJECT);
117
118  // Allocated the JSArray. Now initialize the fields except for the elements
119  // array.
120  // result: JSObject
121  // scratch1: initial map
122  // scratch2: start of next object
123  __ str(scratch1, FieldMemOperand(result, JSObject::kMapOffset));
124  __ LoadRoot(scratch1, Heap::kEmptyFixedArrayRootIndex);
125  __ str(scratch1, FieldMemOperand(result, JSArray::kPropertiesOffset));
126  // Field JSArray::kElementsOffset is initialized later.
127  __ mov(scratch3,  Operand(0, RelocInfo::NONE));
128  __ str(scratch3, FieldMemOperand(result, JSArray::kLengthOffset));
129
130  if (initial_capacity == 0) {
131    __ str(scratch1, FieldMemOperand(result, JSArray::kElementsOffset));
132    return;
133  }
134
135  // Calculate the location of the elements array and set elements array member
136  // of the JSArray.
137  // result: JSObject
138  // scratch2: start of next object
139  __ add(scratch1, result, Operand(JSArray::kSize));
140  __ str(scratch1, FieldMemOperand(result, JSArray::kElementsOffset));
141
142  // Clear the heap tag on the elements array.
143  __ sub(scratch1, scratch1, Operand(kHeapObjectTag));
144
145  // Initialize the FixedArray and fill it with holes. FixedArray length is
146  // stored as a smi.
147  // result: JSObject
148  // scratch1: elements array (untagged)
149  // scratch2: start of next object
150  __ LoadRoot(scratch3, Heap::kFixedArrayMapRootIndex);
151  STATIC_ASSERT(0 * kPointerSize == FixedArray::kMapOffset);
152  __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex));
153  __ mov(scratch3,  Operand(Smi::FromInt(initial_capacity)));
154  STATIC_ASSERT(1 * kPointerSize == FixedArray::kLengthOffset);
155  __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex));
156
157  // Fill the FixedArray with the hole value. Inline the code if short.
158  STATIC_ASSERT(2 * kPointerSize == FixedArray::kHeaderSize);
159  __ LoadRoot(scratch3, Heap::kTheHoleValueRootIndex);
160  static const int kLoopUnfoldLimit = 4;
161  if (initial_capacity <= kLoopUnfoldLimit) {
162    for (int i = 0; i < initial_capacity; i++) {
163      __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex));
164    }
165  } else {
166    Label loop, entry;
167    __ add(scratch2, scratch1, Operand(initial_capacity * kPointerSize));
168    __ b(&entry);
169    __ bind(&loop);
170    __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex));
171    __ bind(&entry);
172    __ cmp(scratch1, scratch2);
173    __ b(lt, &loop);
174  }
175}
176
177// Allocate a JSArray with the number of elements stored in a register. The
178// register array_function holds the built-in Array function and the register
179// array_size holds the size of the array as a smi. The allocated array is put
180// into the result register and beginning and end of the FixedArray elements
181// storage is put into registers elements_array_storage and elements_array_end
182// (see  below for when that is not the case). If the parameter fill_with_holes
183// is true the allocated elements backing store is filled with the hole values
184// otherwise it is left uninitialized. When the backing store is filled the
185// register elements_array_storage is scratched.
186static void AllocateJSArray(MacroAssembler* masm,
187                            Register array_function,  // Array function.
188                            Register array_size,  // As a smi, cannot be 0.
189                            Register result,
190                            Register elements_array_storage,
191                            Register elements_array_end,
192                            Register scratch1,
193                            Register scratch2,
194                            bool fill_with_hole,
195                            Label* gc_required) {
196  // Load the initial map from the array function.
197  __ ldr(elements_array_storage,
198         FieldMemOperand(array_function,
199                         JSFunction::kPrototypeOrInitialMapOffset));
200
201  if (FLAG_debug_code) {  // Assert that array size is not zero.
202    __ tst(array_size, array_size);
203    __ Assert(ne, "array size is unexpectedly 0");
204  }
205
206  // Allocate the JSArray object together with space for a FixedArray with the
207  // requested number of elements.
208  STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
209  __ mov(elements_array_end,
210         Operand((JSArray::kSize + FixedArray::kHeaderSize) / kPointerSize));
211  __ add(elements_array_end,
212         elements_array_end,
213         Operand(array_size, ASR, kSmiTagSize));
214  __ AllocateInNewSpace(
215      elements_array_end,
216      result,
217      scratch1,
218      scratch2,
219      gc_required,
220      static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS));
221
222  // Allocated the JSArray. Now initialize the fields except for the elements
223  // array.
224  // result: JSObject
225  // elements_array_storage: initial map
226  // array_size: size of array (smi)
227  __ str(elements_array_storage, FieldMemOperand(result, JSObject::kMapOffset));
228  __ LoadRoot(elements_array_storage, Heap::kEmptyFixedArrayRootIndex);
229  __ str(elements_array_storage,
230         FieldMemOperand(result, JSArray::kPropertiesOffset));
231  // Field JSArray::kElementsOffset is initialized later.
232  __ str(array_size, FieldMemOperand(result, JSArray::kLengthOffset));
233
234  // Calculate the location of the elements array and set elements array member
235  // of the JSArray.
236  // result: JSObject
237  // array_size: size of array (smi)
238  __ add(elements_array_storage, result, Operand(JSArray::kSize));
239  __ str(elements_array_storage,
240         FieldMemOperand(result, JSArray::kElementsOffset));
241
242  // Clear the heap tag on the elements array.
243  STATIC_ASSERT(kSmiTag == 0);
244  __ sub(elements_array_storage,
245         elements_array_storage,
246         Operand(kHeapObjectTag));
247  // Initialize the fixed array and fill it with holes. FixedArray length is
248  // stored as a smi.
249  // result: JSObject
250  // elements_array_storage: elements array (untagged)
251  // array_size: size of array (smi)
252  __ LoadRoot(scratch1, Heap::kFixedArrayMapRootIndex);
253  ASSERT_EQ(0 * kPointerSize, FixedArray::kMapOffset);
254  __ str(scratch1, MemOperand(elements_array_storage, kPointerSize, PostIndex));
255  STATIC_ASSERT(kSmiTag == 0);
256  ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset);
257  __ str(array_size,
258         MemOperand(elements_array_storage, kPointerSize, PostIndex));
259
260  // Calculate elements array and elements array end.
261  // result: JSObject
262  // elements_array_storage: elements array element storage
263  // array_size: smi-tagged size of elements array
264  STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
265  __ add(elements_array_end,
266         elements_array_storage,
267         Operand(array_size, LSL, kPointerSizeLog2 - kSmiTagSize));
268
269  // Fill the allocated FixedArray with the hole value if requested.
270  // result: JSObject
271  // elements_array_storage: elements array element storage
272  // elements_array_end: start of next object
273  if (fill_with_hole) {
274    Label loop, entry;
275    __ LoadRoot(scratch1, Heap::kTheHoleValueRootIndex);
276    __ jmp(&entry);
277    __ bind(&loop);
278    __ str(scratch1,
279           MemOperand(elements_array_storage, kPointerSize, PostIndex));
280    __ bind(&entry);
281    __ cmp(elements_array_storage, elements_array_end);
282    __ b(lt, &loop);
283  }
284}
285
286// Create a new array for the built-in Array function. This function allocates
287// the JSArray object and the FixedArray elements array and initializes these.
288// If the Array cannot be constructed in native code the runtime is called. This
289// function assumes the following state:
290//   r0: argc
291//   r1: constructor (built-in Array function)
292//   lr: return address
293//   sp[0]: last argument
294// This function is used for both construct and normal calls of Array. The only
295// difference between handling a construct call and a normal call is that for a
296// construct call the constructor function in r1 needs to be preserved for
297// entering the generic code. In both cases argc in r0 needs to be preserved.
298// Both registers are preserved by this code so no need to differentiate between
299// construct call and normal call.
300static void ArrayNativeCode(MacroAssembler* masm,
301                            Label* call_generic_code) {
302  Counters* counters = masm->isolate()->counters();
303  Label argc_one_or_more, argc_two_or_more, not_empty_array, empty_array;
304
305  // Check for array construction with zero arguments or one.
306  __ cmp(r0, Operand(0, RelocInfo::NONE));
307  __ b(ne, &argc_one_or_more);
308
309  // Handle construction of an empty array.
310  __ bind(&empty_array);
311  AllocateEmptyJSArray(masm,
312                       r1,
313                       r2,
314                       r3,
315                       r4,
316                       r5,
317                       call_generic_code);
318  __ IncrementCounter(counters->array_function_native(), 1, r3, r4);
319  // Setup return value, remove receiver from stack and return.
320  __ mov(r0, r2);
321  __ add(sp, sp, Operand(kPointerSize));
322  __ Jump(lr);
323
324  // Check for one argument. Bail out if argument is not smi or if it is
325  // negative.
326  __ bind(&argc_one_or_more);
327  __ cmp(r0, Operand(1));
328  __ b(ne, &argc_two_or_more);
329  STATIC_ASSERT(kSmiTag == 0);
330  __ ldr(r2, MemOperand(sp));  // Get the argument from the stack.
331  __ tst(r2, r2);
332  __ b(ne, &not_empty_array);
333  __ Drop(1);  // Adjust stack.
334  __ mov(r0, Operand(0));  // Treat this as a call with argc of zero.
335  __ b(&empty_array);
336
337  __ bind(&not_empty_array);
338  __ and_(r3, r2, Operand(kIntptrSignBit | kSmiTagMask), SetCC);
339  __ b(ne, call_generic_code);
340
341  // Handle construction of an empty array of a certain size. Bail out if size
342  // is too large to actually allocate an elements array.
343  STATIC_ASSERT(kSmiTag == 0);
344  __ cmp(r2, Operand(JSObject::kInitialMaxFastElementArray << kSmiTagSize));
345  __ b(ge, call_generic_code);
346
347  // r0: argc
348  // r1: constructor
349  // r2: array_size (smi)
350  // sp[0]: argument
351  AllocateJSArray(masm,
352                  r1,
353                  r2,
354                  r3,
355                  r4,
356                  r5,
357                  r6,
358                  r7,
359                  true,
360                  call_generic_code);
361  __ IncrementCounter(counters->array_function_native(), 1, r2, r4);
362  // Setup return value, remove receiver and argument from stack and return.
363  __ mov(r0, r3);
364  __ add(sp, sp, Operand(2 * kPointerSize));
365  __ Jump(lr);
366
367  // Handle construction of an array from a list of arguments.
368  __ bind(&argc_two_or_more);
369  __ mov(r2, Operand(r0, LSL, kSmiTagSize));  // Convet argc to a smi.
370
371  // r0: argc
372  // r1: constructor
373  // r2: array_size (smi)
374  // sp[0]: last argument
375  AllocateJSArray(masm,
376                  r1,
377                  r2,
378                  r3,
379                  r4,
380                  r5,
381                  r6,
382                  r7,
383                  false,
384                  call_generic_code);
385  __ IncrementCounter(counters->array_function_native(), 1, r2, r6);
386
387  // Fill arguments as array elements. Copy from the top of the stack (last
388  // element) to the array backing store filling it backwards. Note:
389  // elements_array_end points after the backing store therefore PreIndex is
390  // used when filling the backing store.
391  // r0: argc
392  // r3: JSArray
393  // r4: elements_array storage start (untagged)
394  // r5: elements_array_end (untagged)
395  // sp[0]: last argument
396  Label loop, entry;
397  __ jmp(&entry);
398  __ bind(&loop);
399  __ ldr(r2, MemOperand(sp, kPointerSize, PostIndex));
400  __ str(r2, MemOperand(r5, -kPointerSize, PreIndex));
401  __ bind(&entry);
402  __ cmp(r4, r5);
403  __ b(lt, &loop);
404
405  // Remove caller arguments and receiver from the stack, setup return value and
406  // return.
407  // r0: argc
408  // r3: JSArray
409  // sp[0]: receiver
410  __ add(sp, sp, Operand(kPointerSize));
411  __ mov(r0, r3);
412  __ Jump(lr);
413}
414
415
416void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
417  // ----------- S t a t e -------------
418  //  -- r0     : number of arguments
419  //  -- lr     : return address
420  //  -- sp[...]: constructor arguments
421  // -----------------------------------
422  Label generic_array_code, one_or_more_arguments, two_or_more_arguments;
423
424  // Get the Array function.
425  GenerateLoadArrayFunction(masm, r1);
426
427  if (FLAG_debug_code) {
428    // Initial map for the builtin Array functions should be maps.
429    __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
430    __ tst(r2, Operand(kSmiTagMask));
431    __ Assert(ne, "Unexpected initial map for Array function");
432    __ CompareObjectType(r2, r3, r4, MAP_TYPE);
433    __ Assert(eq, "Unexpected initial map for Array function");
434  }
435
436  // Run the native code for the Array function called as a normal function.
437  ArrayNativeCode(masm, &generic_array_code);
438
439  // Jump to the generic array code if the specialized code cannot handle
440  // the construction.
441  __ bind(&generic_array_code);
442
443  Handle<Code> array_code =
444      masm->isolate()->builtins()->ArrayCodeGeneric();
445  __ Jump(array_code, RelocInfo::CODE_TARGET);
446}
447
448
449void Builtins::Generate_ArrayConstructCode(MacroAssembler* masm) {
450  // ----------- S t a t e -------------
451  //  -- r0     : number of arguments
452  //  -- r1     : constructor function
453  //  -- lr     : return address
454  //  -- sp[...]: constructor arguments
455  // -----------------------------------
456  Label generic_constructor;
457
458  if (FLAG_debug_code) {
459    // The array construct code is only set for the builtin and internal
460    // Array functions which always have a map.
461    // Initial map for the builtin Array function should be a map.
462    __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
463    __ tst(r2, Operand(kSmiTagMask));
464    __ Assert(ne, "Unexpected initial map for Array function");
465    __ CompareObjectType(r2, r3, r4, MAP_TYPE);
466    __ Assert(eq, "Unexpected initial map for Array function");
467  }
468
469  // Run the native code for the Array function called as a constructor.
470  ArrayNativeCode(masm, &generic_constructor);
471
472  // Jump to the generic construct code in case the specialized code cannot
473  // handle the construction.
474  __ bind(&generic_constructor);
475  Handle<Code> generic_construct_stub =
476      masm->isolate()->builtins()->JSConstructStubGeneric();
477  __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET);
478}
479
480
481void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
482  // ----------- S t a t e -------------
483  //  -- r0                     : number of arguments
484  //  -- r1                     : constructor function
485  //  -- lr                     : return address
486  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero based)
487  //  -- sp[argc * 4]           : receiver
488  // -----------------------------------
489  Counters* counters = masm->isolate()->counters();
490  __ IncrementCounter(counters->string_ctor_calls(), 1, r2, r3);
491
492  Register function = r1;
493  if (FLAG_debug_code) {
494    __ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, r2);
495    __ cmp(function, Operand(r2));
496    __ Assert(eq, "Unexpected String function");
497  }
498
499  // Load the first arguments in r0 and get rid of the rest.
500  Label no_arguments;
501  __ cmp(r0, Operand(0, RelocInfo::NONE));
502  __ b(eq, &no_arguments);
503  // First args = sp[(argc - 1) * 4].
504  __ sub(r0, r0, Operand(1));
505  __ ldr(r0, MemOperand(sp, r0, LSL, kPointerSizeLog2, PreIndex));
506  // sp now point to args[0], drop args[0] + receiver.
507  __ Drop(2);
508
509  Register argument = r2;
510  Label not_cached, argument_is_string;
511  NumberToStringStub::GenerateLookupNumberStringCache(
512      masm,
513      r0,        // Input.
514      argument,  // Result.
515      r3,        // Scratch.
516      r4,        // Scratch.
517      r5,        // Scratch.
518      false,     // Is it a Smi?
519      &not_cached);
520  __ IncrementCounter(counters->string_ctor_cached_number(), 1, r3, r4);
521  __ bind(&argument_is_string);
522
523  // ----------- S t a t e -------------
524  //  -- r2     : argument converted to string
525  //  -- r1     : constructor function
526  //  -- lr     : return address
527  // -----------------------------------
528
529  Label gc_required;
530  __ AllocateInNewSpace(JSValue::kSize,
531                        r0,  // Result.
532                        r3,  // Scratch.
533                        r4,  // Scratch.
534                        &gc_required,
535                        TAG_OBJECT);
536
537  // Initialising the String Object.
538  Register map = r3;
539  __ LoadGlobalFunctionInitialMap(function, map, r4);
540  if (FLAG_debug_code) {
541    __ ldrb(r4, FieldMemOperand(map, Map::kInstanceSizeOffset));
542    __ cmp(r4, Operand(JSValue::kSize >> kPointerSizeLog2));
543    __ Assert(eq, "Unexpected string wrapper instance size");
544    __ ldrb(r4, FieldMemOperand(map, Map::kUnusedPropertyFieldsOffset));
545    __ cmp(r4, Operand(0, RelocInfo::NONE));
546    __ Assert(eq, "Unexpected unused properties of string wrapper");
547  }
548  __ str(map, FieldMemOperand(r0, HeapObject::kMapOffset));
549
550  __ LoadRoot(r3, Heap::kEmptyFixedArrayRootIndex);
551  __ str(r3, FieldMemOperand(r0, JSObject::kPropertiesOffset));
552  __ str(r3, FieldMemOperand(r0, JSObject::kElementsOffset));
553
554  __ str(argument, FieldMemOperand(r0, JSValue::kValueOffset));
555
556  // Ensure the object is fully initialized.
557  STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
558
559  __ Ret();
560
561  // The argument was not found in the number to string cache. Check
562  // if it's a string already before calling the conversion builtin.
563  Label convert_argument;
564  __ bind(&not_cached);
565  __ JumpIfSmi(r0, &convert_argument);
566
567  // Is it a String?
568  __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset));
569  __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceTypeOffset));
570  STATIC_ASSERT(kNotStringTag != 0);
571  __ tst(r3, Operand(kIsNotStringMask));
572  __ b(ne, &convert_argument);
573  __ mov(argument, r0);
574  __ IncrementCounter(counters->string_ctor_conversions(), 1, r3, r4);
575  __ b(&argument_is_string);
576
577  // Invoke the conversion builtin and put the result into r2.
578  __ bind(&convert_argument);
579  __ push(function);  // Preserve the function.
580  __ IncrementCounter(counters->string_ctor_conversions(), 1, r3, r4);
581  {
582    FrameScope scope(masm, StackFrame::INTERNAL);
583    __ push(r0);
584    __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION);
585  }
586  __ pop(function);
587  __ mov(argument, r0);
588  __ b(&argument_is_string);
589
590  // Load the empty string into r2, remove the receiver from the
591  // stack, and jump back to the case where the argument is a string.
592  __ bind(&no_arguments);
593  __ LoadRoot(argument, Heap::kEmptyStringRootIndex);
594  __ Drop(1);
595  __ b(&argument_is_string);
596
597  // At this point the argument is already a string. Call runtime to
598  // create a string wrapper.
599  __ bind(&gc_required);
600  __ IncrementCounter(counters->string_ctor_gc_required(), 1, r3, r4);
601  {
602    FrameScope scope(masm, StackFrame::INTERNAL);
603    __ push(argument);
604    __ CallRuntime(Runtime::kNewStringWrapper, 1);
605  }
606  __ Ret();
607}
608
609
610void Builtins::Generate_JSConstructCall(MacroAssembler* masm) {
611  // ----------- S t a t e -------------
612  //  -- r0     : number of arguments
613  //  -- r1     : constructor function
614  //  -- lr     : return address
615  //  -- sp[...]: constructor arguments
616  // -----------------------------------
617
618  Label slow, non_function_call;
619  // Check that the function is not a smi.
620  __ JumpIfSmi(r1, &non_function_call);
621  // Check that the function is a JSFunction.
622  __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE);
623  __ b(ne, &slow);
624
625  // Jump to the function-specific construct stub.
626  __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
627  __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kConstructStubOffset));
628  __ add(pc, r2, Operand(Code::kHeaderSize - kHeapObjectTag));
629
630  // r0: number of arguments
631  // r1: called object
632  // r2: object type
633  Label do_call;
634  __ bind(&slow);
635  __ cmp(r2, Operand(JS_FUNCTION_PROXY_TYPE));
636  __ b(ne, &non_function_call);
637  __ GetBuiltinEntry(r3, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR);
638  __ jmp(&do_call);
639
640  __ bind(&non_function_call);
641  __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
642  __ bind(&do_call);
643  // Set expected number of arguments to zero (not changing r0).
644  __ mov(r2, Operand(0, RelocInfo::NONE));
645  __ SetCallKind(r5, CALL_AS_METHOD);
646  __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
647          RelocInfo::CODE_TARGET);
648}
649
650
651static void Generate_JSConstructStubHelper(MacroAssembler* masm,
652                                           bool is_api_function,
653                                           bool count_constructions) {
654  // Should never count constructions for api objects.
655  ASSERT(!is_api_function || !count_constructions);
656
657  Isolate* isolate = masm->isolate();
658
659  // Enter a construct frame.
660  {
661    FrameScope scope(masm, StackFrame::CONSTRUCT);
662
663    // Preserve the two incoming parameters on the stack.
664    __ mov(r0, Operand(r0, LSL, kSmiTagSize));
665    __ push(r0);  // Smi-tagged arguments count.
666    __ push(r1);  // Constructor function.
667
668    // Try to allocate the object without transitioning into C code. If any of
669    // the preconditions is not met, the code bails out to the runtime call.
670    Label rt_call, allocated;
671    if (FLAG_inline_new) {
672      Label undo_allocation;
673#ifdef ENABLE_DEBUGGER_SUPPORT
674      ExternalReference debug_step_in_fp =
675          ExternalReference::debug_step_in_fp_address(isolate);
676      __ mov(r2, Operand(debug_step_in_fp));
677      __ ldr(r2, MemOperand(r2));
678      __ tst(r2, r2);
679      __ b(ne, &rt_call);
680#endif
681
682      // Load the initial map and verify that it is in fact a map.
683      // r1: constructor function
684      __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
685      __ JumpIfSmi(r2, &rt_call);
686      __ CompareObjectType(r2, r3, r4, MAP_TYPE);
687      __ b(ne, &rt_call);
688
689      // Check that the constructor is not constructing a JSFunction (see
690      // comments in Runtime_NewObject in runtime.cc). In which case the
691      // initial map's instance type would be JS_FUNCTION_TYPE.
692      // r1: constructor function
693      // r2: initial map
694      __ CompareInstanceType(r2, r3, JS_FUNCTION_TYPE);
695      __ b(eq, &rt_call);
696
697      if (count_constructions) {
698        Label allocate;
699        // Decrease generous allocation count.
700        __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
701        MemOperand constructor_count =
702            FieldMemOperand(r3, SharedFunctionInfo::kConstructionCountOffset);
703        __ ldrb(r4, constructor_count);
704        __ sub(r4, r4, Operand(1), SetCC);
705        __ strb(r4, constructor_count);
706        __ b(ne, &allocate);
707
708        __ Push(r1, r2);
709
710        __ push(r1);  // constructor
711        // The call will replace the stub, so the countdown is only done once.
712        __ CallRuntime(Runtime::kFinalizeInstanceSize, 1);
713
714        __ pop(r2);
715        __ pop(r1);
716
717        __ bind(&allocate);
718      }
719
720      // Now allocate the JSObject on the heap.
721      // r1: constructor function
722      // r2: initial map
723      __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceSizeOffset));
724      __ AllocateInNewSpace(r3, r4, r5, r6, &rt_call, SIZE_IN_WORDS);
725
726      // Allocated the JSObject, now initialize the fields. Map is set to
727      // initial map and properties and elements are set to empty fixed array.
728      // r1: constructor function
729      // r2: initial map
730      // r3: object size
731      // r4: JSObject (not tagged)
732      __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex);
733      __ mov(r5, r4);
734      ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset);
735      __ str(r2, MemOperand(r5, kPointerSize, PostIndex));
736      ASSERT_EQ(1 * kPointerSize, JSObject::kPropertiesOffset);
737      __ str(r6, MemOperand(r5, kPointerSize, PostIndex));
738      ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset);
739      __ str(r6, MemOperand(r5, kPointerSize, PostIndex));
740
741      // Fill all the in-object properties with the appropriate filler.
742      // r1: constructor function
743      // r2: initial map
744      // r3: object size (in words)
745      // r4: JSObject (not tagged)
746      // r5: First in-object property of JSObject (not tagged)
747      __ add(r6, r4, Operand(r3, LSL, kPointerSizeLog2));  // End of object.
748      ASSERT_EQ(3 * kPointerSize, JSObject::kHeaderSize);
749      __ LoadRoot(r7, Heap::kUndefinedValueRootIndex);
750      if (count_constructions) {
751        __ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset));
752        __ Ubfx(r0, r0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte,
753                kBitsPerByte);
754        __ add(r0, r5, Operand(r0, LSL, kPointerSizeLog2));
755        // r0: offset of first field after pre-allocated fields
756        if (FLAG_debug_code) {
757          __ cmp(r0, r6);
758          __ Assert(le, "Unexpected number of pre-allocated property fields.");
759        }
760        __ InitializeFieldsWithFiller(r5, r0, r7);
761        // To allow for truncation.
762        __ LoadRoot(r7, Heap::kOnePointerFillerMapRootIndex);
763      }
764      __ InitializeFieldsWithFiller(r5, r6, r7);
765
766      // Add the object tag to make the JSObject real, so that we can continue
767      // and jump into the continuation code at any time from now on. Any
768      // failures need to undo the allocation, so that the heap is in a
769      // consistent state and verifiable.
770      __ add(r4, r4, Operand(kHeapObjectTag));
771
772      // Check if a non-empty properties array is needed. Continue with
773      // allocated object if not fall through to runtime call if it is.
774      // r1: constructor function
775      // r4: JSObject
776      // r5: start of next object (not tagged)
777      __ ldrb(r3, FieldMemOperand(r2, Map::kUnusedPropertyFieldsOffset));
778      // The field instance sizes contains both pre-allocated property fields
779      // and in-object properties.
780      __ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset));
781      __ Ubfx(r6, r0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte,
782              kBitsPerByte);
783      __ add(r3, r3, Operand(r6));
784      __ Ubfx(r6, r0, Map::kInObjectPropertiesByte * kBitsPerByte,
785              kBitsPerByte);
786      __ sub(r3, r3, Operand(r6), SetCC);
787
788      // Done if no extra properties are to be allocated.
789      __ b(eq, &allocated);
790      __ Assert(pl, "Property allocation count failed.");
791
792      // Scale the number of elements by pointer size and add the header for
793      // FixedArrays to the start of the next object calculation from above.
794      // r1: constructor
795      // r3: number of elements in properties array
796      // r4: JSObject
797      // r5: start of next object
798      __ add(r0, r3, Operand(FixedArray::kHeaderSize / kPointerSize));
799      __ AllocateInNewSpace(
800          r0,
801          r5,
802          r6,
803          r2,
804          &undo_allocation,
805          static_cast<AllocationFlags>(RESULT_CONTAINS_TOP | SIZE_IN_WORDS));
806
807      // Initialize the FixedArray.
808      // r1: constructor
809      // r3: number of elements in properties array
810      // r4: JSObject
811      // r5: FixedArray (not tagged)
812      __ LoadRoot(r6, Heap::kFixedArrayMapRootIndex);
813      __ mov(r2, r5);
814      ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset);
815      __ str(r6, MemOperand(r2, kPointerSize, PostIndex));
816      ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset);
817      __ mov(r0, Operand(r3, LSL, kSmiTagSize));
818      __ str(r0, MemOperand(r2, kPointerSize, PostIndex));
819
820      // Initialize the fields to undefined.
821      // r1: constructor function
822      // r2: First element of FixedArray (not tagged)
823      // r3: number of elements in properties array
824      // r4: JSObject
825      // r5: FixedArray (not tagged)
826      __ add(r6, r2, Operand(r3, LSL, kPointerSizeLog2));  // End of object.
827      ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize);
828      { Label loop, entry;
829        if (count_constructions) {
830          __ LoadRoot(r7, Heap::kUndefinedValueRootIndex);
831        } else if (FLAG_debug_code) {
832          __ LoadRoot(r8, Heap::kUndefinedValueRootIndex);
833          __ cmp(r7, r8);
834          __ Assert(eq, "Undefined value not loaded.");
835        }
836        __ b(&entry);
837        __ bind(&loop);
838        __ str(r7, MemOperand(r2, kPointerSize, PostIndex));
839        __ bind(&entry);
840        __ cmp(r2, r6);
841        __ b(lt, &loop);
842      }
843
844      // Store the initialized FixedArray into the properties field of
845      // the JSObject
846      // r1: constructor function
847      // r4: JSObject
848      // r5: FixedArray (not tagged)
849      __ add(r5, r5, Operand(kHeapObjectTag));  // Add the heap tag.
850      __ str(r5, FieldMemOperand(r4, JSObject::kPropertiesOffset));
851
852      // Continue with JSObject being successfully allocated
853      // r1: constructor function
854      // r4: JSObject
855      __ jmp(&allocated);
856
857      // Undo the setting of the new top so that the heap is verifiable. For
858      // example, the map's unused properties potentially do not match the
859      // allocated objects unused properties.
860      // r4: JSObject (previous new top)
861      __ bind(&undo_allocation);
862      __ UndoAllocationInNewSpace(r4, r5);
863    }
864
865    // Allocate the new receiver object using the runtime call.
866    // r1: constructor function
867    __ bind(&rt_call);
868    __ push(r1);  // argument for Runtime_NewObject
869    __ CallRuntime(Runtime::kNewObject, 1);
870    __ mov(r4, r0);
871
872    // Receiver for constructor call allocated.
873    // r4: JSObject
874    __ bind(&allocated);
875    __ push(r4);
876
877    // Push the function and the allocated receiver from the stack.
878    // sp[0]: receiver (newly allocated object)
879    // sp[1]: constructor function
880    // sp[2]: number of arguments (smi-tagged)
881    __ ldr(r1, MemOperand(sp, kPointerSize));
882    __ push(r1);  // Constructor function.
883    __ push(r4);  // Receiver.
884
885    // Reload the number of arguments from the stack.
886    // r1: constructor function
887    // sp[0]: receiver
888    // sp[1]: constructor function
889    // sp[2]: receiver
890    // sp[3]: constructor function
891    // sp[4]: number of arguments (smi-tagged)
892    __ ldr(r3, MemOperand(sp, 4 * kPointerSize));
893
894    // Setup pointer to last argument.
895    __ add(r2, fp, Operand(StandardFrameConstants::kCallerSPOffset));
896
897    // Setup number of arguments for function call below
898    __ mov(r0, Operand(r3, LSR, kSmiTagSize));
899
900    // Copy arguments and receiver to the expression stack.
901    // r0: number of arguments
902    // r2: address of last argument (caller sp)
903    // r1: constructor function
904    // r3: number of arguments (smi-tagged)
905    // sp[0]: receiver
906    // sp[1]: constructor function
907    // sp[2]: receiver
908    // sp[3]: constructor function
909    // sp[4]: number of arguments (smi-tagged)
910    Label loop, entry;
911    __ b(&entry);
912    __ bind(&loop);
913    __ ldr(ip, MemOperand(r2, r3, LSL, kPointerSizeLog2 - 1));
914    __ push(ip);
915    __ bind(&entry);
916    __ sub(r3, r3, Operand(2), SetCC);
917    __ b(ge, &loop);
918
919    // Call the function.
920    // r0: number of arguments
921    // r1: constructor function
922    if (is_api_function) {
923      __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
924      Handle<Code> code =
925          masm->isolate()->builtins()->HandleApiCallConstruct();
926      ParameterCount expected(0);
927      __ InvokeCode(code, expected, expected,
928                    RelocInfo::CODE_TARGET, CALL_FUNCTION, CALL_AS_METHOD);
929    } else {
930      ParameterCount actual(r0);
931      __ InvokeFunction(r1, actual, CALL_FUNCTION,
932                        NullCallWrapper(), CALL_AS_METHOD);
933    }
934
935    // Pop the function from the stack.
936    // sp[0]: constructor function
937    // sp[2]: receiver
938    // sp[3]: constructor function
939    // sp[4]: number of arguments (smi-tagged)
940    __ pop();
941
942    // Restore context from the frame.
943    // r0: result
944    // sp[0]: receiver
945    // sp[1]: constructor function
946    // sp[2]: number of arguments (smi-tagged)
947    __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
948
949    // If the result is an object (in the ECMA sense), we should get rid
950    // of the receiver and use the result; see ECMA-262 section 13.2.2-7
951    // on page 74.
952    Label use_receiver, exit;
953
954    // If the result is a smi, it is *not* an object in the ECMA sense.
955    // r0: result
956    // sp[0]: receiver (newly allocated object)
957    // sp[1]: constructor function
958    // sp[2]: number of arguments (smi-tagged)
959    __ JumpIfSmi(r0, &use_receiver);
960
961    // If the type of the result (stored in its map) is less than
962    // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense.
963    __ CompareObjectType(r0, r3, r3, FIRST_SPEC_OBJECT_TYPE);
964    __ b(ge, &exit);
965
966    // Throw away the result of the constructor invocation and use the
967    // on-stack receiver as the result.
968    __ bind(&use_receiver);
969    __ ldr(r0, MemOperand(sp));
970
971    // Remove receiver from the stack, remove caller arguments, and
972    // return.
973    __ bind(&exit);
974    // r0: result
975    // sp[0]: receiver (newly allocated object)
976    // sp[1]: constructor function
977    // sp[2]: number of arguments (smi-tagged)
978    __ ldr(r1, MemOperand(sp, 2 * kPointerSize));
979
980    // Leave construct frame.
981  }
982
983  __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1));
984  __ add(sp, sp, Operand(kPointerSize));
985  __ IncrementCounter(isolate->counters()->constructed_objects(), 1, r1, r2);
986  __ Jump(lr);
987}
988
989
990void Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) {
991  Generate_JSConstructStubHelper(masm, false, true);
992}
993
994
995void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
996  Generate_JSConstructStubHelper(masm, false, false);
997}
998
999
1000void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
1001  Generate_JSConstructStubHelper(masm, true, false);
1002}
1003
1004
1005static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
1006                                             bool is_construct) {
1007  // Called from Generate_JS_Entry
1008  // r0: code entry
1009  // r1: function
1010  // r2: receiver
1011  // r3: argc
1012  // r4: argv
1013  // r5-r7, cp may be clobbered
1014
1015  // Clear the context before we push it when entering the internal frame.
1016  __ mov(cp, Operand(0, RelocInfo::NONE));
1017
1018  // Enter an internal frame.
1019  {
1020    FrameScope scope(masm, StackFrame::INTERNAL);
1021
1022    // Set up the context from the function argument.
1023    __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
1024
1025    // Set up the roots register.
1026    ExternalReference roots_array_start =
1027        ExternalReference::roots_array_start(masm->isolate());
1028    __ mov(r10, Operand(roots_array_start));
1029
1030    // Push the function and the receiver onto the stack.
1031    __ push(r1);
1032    __ push(r2);
1033
1034    // Copy arguments to the stack in a loop.
1035    // r1: function
1036    // r3: argc
1037    // r4: argv, i.e. points to first arg
1038    Label loop, entry;
1039    __ add(r2, r4, Operand(r3, LSL, kPointerSizeLog2));
1040    // r2 points past last arg.
1041    __ b(&entry);
1042    __ bind(&loop);
1043    __ ldr(r0, MemOperand(r4, kPointerSize, PostIndex));  // read next parameter
1044    __ ldr(r0, MemOperand(r0));  // dereference handle
1045    __ push(r0);  // push parameter
1046    __ bind(&entry);
1047    __ cmp(r4, r2);
1048    __ b(ne, &loop);
1049
1050    // Initialize all JavaScript callee-saved registers, since they will be seen
1051    // by the garbage collector as part of handlers.
1052    __ LoadRoot(r4, Heap::kUndefinedValueRootIndex);
1053    __ mov(r5, Operand(r4));
1054    __ mov(r6, Operand(r4));
1055    __ mov(r7, Operand(r4));
1056    if (kR9Available == 1) {
1057      __ mov(r9, Operand(r4));
1058    }
1059
1060    // Invoke the code and pass argc as r0.
1061    __ mov(r0, Operand(r3));
1062    if (is_construct) {
1063      __ Call(masm->isolate()->builtins()->JSConstructCall());
1064    } else {
1065      ParameterCount actual(r0);
1066      __ InvokeFunction(r1, actual, CALL_FUNCTION,
1067                        NullCallWrapper(), CALL_AS_METHOD);
1068    }
1069    // Exit the JS frame and remove the parameters (except function), and
1070    // return.
1071    // Respect ABI stack constraint.
1072  }
1073  __ Jump(lr);
1074
1075  // r0: result
1076}
1077
1078
1079void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) {
1080  Generate_JSEntryTrampolineHelper(masm, false);
1081}
1082
1083
1084void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
1085  Generate_JSEntryTrampolineHelper(masm, true);
1086}
1087
1088
1089void Builtins::Generate_LazyCompile(MacroAssembler* masm) {
1090  // Enter an internal frame.
1091  {
1092    FrameScope scope(masm, StackFrame::INTERNAL);
1093
1094    // Preserve the function.
1095    __ push(r1);
1096    // Push call kind information.
1097    __ push(r5);
1098
1099    // Push the function on the stack as the argument to the runtime function.
1100    __ push(r1);
1101    __ CallRuntime(Runtime::kLazyCompile, 1);
1102    // Calculate the entry point.
1103    __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag));
1104
1105    // Restore call kind information.
1106    __ pop(r5);
1107    // Restore saved function.
1108    __ pop(r1);
1109
1110    // Tear down internal frame.
1111  }
1112
1113  // Do a tail-call of the compiled function.
1114  __ Jump(r2);
1115}
1116
1117
1118void Builtins::Generate_LazyRecompile(MacroAssembler* masm) {
1119  // Enter an internal frame.
1120  {
1121    FrameScope scope(masm, StackFrame::INTERNAL);
1122
1123    // Preserve the function.
1124    __ push(r1);
1125    // Push call kind information.
1126    __ push(r5);
1127
1128    // Push the function on the stack as the argument to the runtime function.
1129    __ push(r1);
1130    __ CallRuntime(Runtime::kLazyRecompile, 1);
1131    // Calculate the entry point.
1132    __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag));
1133
1134    // Restore call kind information.
1135    __ pop(r5);
1136    // Restore saved function.
1137    __ pop(r1);
1138
1139    // Tear down internal frame.
1140  }
1141
1142  // Do a tail-call of the compiled function.
1143  __ Jump(r2);
1144}
1145
1146
1147static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm,
1148                                             Deoptimizer::BailoutType type) {
1149  {
1150    FrameScope scope(masm, StackFrame::INTERNAL);
1151    // Pass the function and deoptimization type to the runtime system.
1152    __ mov(r0, Operand(Smi::FromInt(static_cast<int>(type))));
1153    __ push(r0);
1154    __ CallRuntime(Runtime::kNotifyDeoptimized, 1);
1155  }
1156
1157  // Get the full codegen state from the stack and untag it -> r6.
1158  __ ldr(r6, MemOperand(sp, 0 * kPointerSize));
1159  __ SmiUntag(r6);
1160  // Switch on the state.
1161  Label with_tos_register, unknown_state;
1162  __ cmp(r6, Operand(FullCodeGenerator::NO_REGISTERS));
1163  __ b(ne, &with_tos_register);
1164  __ add(sp, sp, Operand(1 * kPointerSize));  // Remove state.
1165  __ Ret();
1166
1167  __ bind(&with_tos_register);
1168  __ ldr(r0, MemOperand(sp, 1 * kPointerSize));
1169  __ cmp(r6, Operand(FullCodeGenerator::TOS_REG));
1170  __ b(ne, &unknown_state);
1171  __ add(sp, sp, Operand(2 * kPointerSize));  // Remove state.
1172  __ Ret();
1173
1174  __ bind(&unknown_state);
1175  __ stop("no cases left");
1176}
1177
1178
1179void Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) {
1180  Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::EAGER);
1181}
1182
1183
1184void Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) {
1185  Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
1186}
1187
1188
1189void Builtins::Generate_NotifyOSR(MacroAssembler* masm) {
1190  // For now, we are relying on the fact that Runtime::NotifyOSR
1191  // doesn't do any garbage collection which allows us to save/restore
1192  // the registers without worrying about which of them contain
1193  // pointers. This seems a bit fragile.
1194  __ stm(db_w, sp, kJSCallerSaved | kCalleeSaved | lr.bit() | fp.bit());
1195  {
1196    FrameScope scope(masm, StackFrame::INTERNAL);
1197    __ CallRuntime(Runtime::kNotifyOSR, 0);
1198  }
1199  __ ldm(ia_w, sp, kJSCallerSaved | kCalleeSaved | lr.bit() | fp.bit());
1200  __ Ret();
1201}
1202
1203
1204void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
1205  CpuFeatures::TryForceFeatureScope scope(VFP3);
1206  if (!CpuFeatures::IsSupported(VFP3)) {
1207    __ Abort("Unreachable code: Cannot optimize without VFP3 support.");
1208    return;
1209  }
1210
1211  // Lookup the function in the JavaScript frame and push it as an
1212  // argument to the on-stack replacement function.
1213  __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
1214  {
1215    FrameScope scope(masm, StackFrame::INTERNAL);
1216    __ push(r0);
1217    __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1);
1218  }
1219
1220  // If the result was -1 it means that we couldn't optimize the
1221  // function. Just return and continue in the unoptimized version.
1222  Label skip;
1223  __ cmp(r0, Operand(Smi::FromInt(-1)));
1224  __ b(ne, &skip);
1225  __ Ret();
1226
1227  __ bind(&skip);
1228  // Untag the AST id and push it on the stack.
1229  __ SmiUntag(r0);
1230  __ push(r0);
1231
1232  // Generate the code for doing the frame-to-frame translation using
1233  // the deoptimizer infrastructure.
1234  Deoptimizer::EntryGenerator generator(masm, Deoptimizer::OSR);
1235  generator.Generate();
1236}
1237
1238
1239void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
1240  // 1. Make sure we have at least one argument.
1241  // r0: actual number of arguments
1242  { Label done;
1243    __ tst(r0, Operand(r0));
1244    __ b(ne, &done);
1245    __ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
1246    __ push(r2);
1247    __ add(r0, r0, Operand(1));
1248    __ bind(&done);
1249  }
1250
1251  // 2. Get the function to call (passed as receiver) from the stack, check
1252  //    if it is a function.
1253  // r0: actual number of arguments
1254  Label slow, non_function;
1255  __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2));
1256  __ JumpIfSmi(r1, &non_function);
1257  __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE);
1258  __ b(ne, &slow);
1259
1260  // 3a. Patch the first argument if necessary when calling a function.
1261  // r0: actual number of arguments
1262  // r1: function
1263  Label shift_arguments;
1264  __ mov(r4, Operand(0, RelocInfo::NONE));  // indicate regular JS_FUNCTION
1265  { Label convert_to_object, use_global_receiver, patch_receiver;
1266    // Change context eagerly in case we need the global receiver.
1267    __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
1268
1269    // Do not transform the receiver for strict mode functions.
1270    __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
1271    __ ldr(r3, FieldMemOperand(r2, SharedFunctionInfo::kCompilerHintsOffset));
1272    __ tst(r3, Operand(1 << (SharedFunctionInfo::kStrictModeFunction +
1273                             kSmiTagSize)));
1274    __ b(ne, &shift_arguments);
1275
1276    // Do not transform the receiver for native (Compilerhints already in r3).
1277    __ tst(r3, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
1278    __ b(ne, &shift_arguments);
1279
1280    // Compute the receiver in non-strict mode.
1281    __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2));
1282    __ ldr(r2, MemOperand(r2, -kPointerSize));
1283    // r0: actual number of arguments
1284    // r1: function
1285    // r2: first argument
1286    __ JumpIfSmi(r2, &convert_to_object);
1287
1288    __ LoadRoot(r3, Heap::kUndefinedValueRootIndex);
1289    __ cmp(r2, r3);
1290    __ b(eq, &use_global_receiver);
1291    __ LoadRoot(r3, Heap::kNullValueRootIndex);
1292    __ cmp(r2, r3);
1293    __ b(eq, &use_global_receiver);
1294
1295    STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
1296    __ CompareObjectType(r2, r3, r3, FIRST_SPEC_OBJECT_TYPE);
1297    __ b(ge, &shift_arguments);
1298
1299    __ bind(&convert_to_object);
1300
1301    {
1302      // Enter an internal frame in order to preserve argument count.
1303      FrameScope scope(masm, StackFrame::INTERNAL);
1304      __ mov(r0, Operand(r0, LSL, kSmiTagSize));  // Smi-tagged.
1305      __ push(r0);
1306
1307      __ push(r2);
1308      __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
1309      __ mov(r2, r0);
1310
1311      __ pop(r0);
1312      __ mov(r0, Operand(r0, ASR, kSmiTagSize));
1313
1314      // Exit the internal frame.
1315    }
1316
1317    // Restore the function to r1, and the flag to r4.
1318    __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2));
1319    __ mov(r4, Operand(0, RelocInfo::NONE));
1320    __ jmp(&patch_receiver);
1321
1322    // Use the global receiver object from the called function as the
1323    // receiver.
1324    __ bind(&use_global_receiver);
1325    const int kGlobalIndex =
1326        Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
1327    __ ldr(r2, FieldMemOperand(cp, kGlobalIndex));
1328    __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalContextOffset));
1329    __ ldr(r2, FieldMemOperand(r2, kGlobalIndex));
1330    __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset));
1331
1332    __ bind(&patch_receiver);
1333    __ add(r3, sp, Operand(r0, LSL, kPointerSizeLog2));
1334    __ str(r2, MemOperand(r3, -kPointerSize));
1335
1336    __ jmp(&shift_arguments);
1337  }
1338
1339  // 3b. Check for function proxy.
1340  __ bind(&slow);
1341  __ mov(r4, Operand(1, RelocInfo::NONE));  // indicate function proxy
1342  __ cmp(r2, Operand(JS_FUNCTION_PROXY_TYPE));
1343  __ b(eq, &shift_arguments);
1344  __ bind(&non_function);
1345  __ mov(r4, Operand(2, RelocInfo::NONE));  // indicate non-function
1346
1347  // 3c. Patch the first argument when calling a non-function.  The
1348  //     CALL_NON_FUNCTION builtin expects the non-function callee as
1349  //     receiver, so overwrite the first argument which will ultimately
1350  //     become the receiver.
1351  // r0: actual number of arguments
1352  // r1: function
1353  // r4: call type (0: JS function, 1: function proxy, 2: non-function)
1354  __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2));
1355  __ str(r1, MemOperand(r2, -kPointerSize));
1356
1357  // 4. Shift arguments and return address one slot down on the stack
1358  //    (overwriting the original receiver).  Adjust argument count to make
1359  //    the original first argument the new receiver.
1360  // r0: actual number of arguments
1361  // r1: function
1362  // r4: call type (0: JS function, 1: function proxy, 2: non-function)
1363  __ bind(&shift_arguments);
1364  { Label loop;
1365    // Calculate the copy start address (destination). Copy end address is sp.
1366    __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2));
1367
1368    __ bind(&loop);
1369    __ ldr(ip, MemOperand(r2, -kPointerSize));
1370    __ str(ip, MemOperand(r2));
1371    __ sub(r2, r2, Operand(kPointerSize));
1372    __ cmp(r2, sp);
1373    __ b(ne, &loop);
1374    // Adjust the actual number of arguments and remove the top element
1375    // (which is a copy of the last argument).
1376    __ sub(r0, r0, Operand(1));
1377    __ pop();
1378  }
1379
1380  // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin,
1381  //     or a function proxy via CALL_FUNCTION_PROXY.
1382  // r0: actual number of arguments
1383  // r1: function
1384  // r4: call type (0: JS function, 1: function proxy, 2: non-function)
1385  { Label function, non_proxy;
1386    __ tst(r4, r4);
1387    __ b(eq, &function);
1388    // Expected number of arguments is 0 for CALL_NON_FUNCTION.
1389    __ mov(r2, Operand(0, RelocInfo::NONE));
1390    __ SetCallKind(r5, CALL_AS_METHOD);
1391    __ cmp(r4, Operand(1));
1392    __ b(ne, &non_proxy);
1393
1394    __ push(r1);  // re-add proxy object as additional argument
1395    __ add(r0, r0, Operand(1));
1396    __ GetBuiltinEntry(r3, Builtins::CALL_FUNCTION_PROXY);
1397    __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1398            RelocInfo::CODE_TARGET);
1399
1400    __ bind(&non_proxy);
1401    __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION);
1402    __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1403            RelocInfo::CODE_TARGET);
1404    __ bind(&function);
1405  }
1406
1407  // 5b. Get the code to call from the function and check that the number of
1408  //     expected arguments matches what we're providing.  If so, jump
1409  //     (tail-call) to the code in register edx without checking arguments.
1410  // r0: actual number of arguments
1411  // r1: function
1412  __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
1413  __ ldr(r2,
1414         FieldMemOperand(r3, SharedFunctionInfo::kFormalParameterCountOffset));
1415  __ mov(r2, Operand(r2, ASR, kSmiTagSize));
1416  __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
1417  __ SetCallKind(r5, CALL_AS_METHOD);
1418  __ cmp(r2, r0);  // Check formal and actual parameter counts.
1419  __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1420          RelocInfo::CODE_TARGET,
1421          ne);
1422
1423  ParameterCount expected(0);
1424  __ InvokeCode(r3, expected, expected, JUMP_FUNCTION,
1425                NullCallWrapper(), CALL_AS_METHOD);
1426}
1427
1428
1429void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
1430  const int kIndexOffset    = -5 * kPointerSize;
1431  const int kLimitOffset    = -4 * kPointerSize;
1432  const int kArgsOffset     =  2 * kPointerSize;
1433  const int kRecvOffset     =  3 * kPointerSize;
1434  const int kFunctionOffset =  4 * kPointerSize;
1435
1436  {
1437    FrameScope frame_scope(masm, StackFrame::INTERNAL);
1438
1439    __ ldr(r0, MemOperand(fp, kFunctionOffset));  // get the function
1440    __ push(r0);
1441    __ ldr(r0, MemOperand(fp, kArgsOffset));  // get the args array
1442    __ push(r0);
1443    __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION);
1444
1445    // Check the stack for overflow. We are not trying to catch
1446    // interruptions (e.g. debug break and preemption) here, so the "real stack
1447    // limit" is checked.
1448    Label okay;
1449    __ LoadRoot(r2, Heap::kRealStackLimitRootIndex);
1450    // Make r2 the space we have left. The stack might already be overflowed
1451    // here which will cause r2 to become negative.
1452    __ sub(r2, sp, r2);
1453    // Check if the arguments will overflow the stack.
1454    __ cmp(r2, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));
1455    __ b(gt, &okay);  // Signed comparison.
1456
1457    // Out of stack space.
1458    __ ldr(r1, MemOperand(fp, kFunctionOffset));
1459    __ push(r1);
1460    __ push(r0);
1461    __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION);
1462    // End of stack check.
1463
1464    // Push current limit and index.
1465    __ bind(&okay);
1466    __ push(r0);  // limit
1467    __ mov(r1, Operand(0, RelocInfo::NONE));  // initial index
1468    __ push(r1);
1469
1470    // Get the receiver.
1471    __ ldr(r0, MemOperand(fp, kRecvOffset));
1472
1473    // Check that the function is a JS function (otherwise it must be a proxy).
1474    Label push_receiver;
1475    __ ldr(r1, MemOperand(fp, kFunctionOffset));
1476    __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE);
1477    __ b(ne, &push_receiver);
1478
1479    // Change context eagerly to get the right global object if necessary.
1480    __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
1481    // Load the shared function info while the function is still in r1.
1482    __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
1483
1484    // Compute the receiver.
1485    // Do not transform the receiver for strict mode functions.
1486    Label call_to_object, use_global_receiver;
1487    __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kCompilerHintsOffset));
1488    __ tst(r2, Operand(1 << (SharedFunctionInfo::kStrictModeFunction +
1489                             kSmiTagSize)));
1490    __ b(ne, &push_receiver);
1491
1492    // Do not transform the receiver for strict mode functions.
1493    __ tst(r2, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
1494    __ b(ne, &push_receiver);
1495
1496    // Compute the receiver in non-strict mode.
1497    __ JumpIfSmi(r0, &call_to_object);
1498    __ LoadRoot(r1, Heap::kNullValueRootIndex);
1499    __ cmp(r0, r1);
1500    __ b(eq, &use_global_receiver);
1501    __ LoadRoot(r1, Heap::kUndefinedValueRootIndex);
1502    __ cmp(r0, r1);
1503    __ b(eq, &use_global_receiver);
1504
1505    // Check if the receiver is already a JavaScript object.
1506    // r0: receiver
1507    STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
1508    __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE);
1509    __ b(ge, &push_receiver);
1510
1511    // Convert the receiver to a regular object.
1512    // r0: receiver
1513    __ bind(&call_to_object);
1514    __ push(r0);
1515    __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
1516    __ b(&push_receiver);
1517
1518    // Use the current global receiver object as the receiver.
1519    __ bind(&use_global_receiver);
1520    const int kGlobalOffset =
1521        Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
1522    __ ldr(r0, FieldMemOperand(cp, kGlobalOffset));
1523    __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalContextOffset));
1524    __ ldr(r0, FieldMemOperand(r0, kGlobalOffset));
1525    __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
1526
1527    // Push the receiver.
1528    // r0: receiver
1529    __ bind(&push_receiver);
1530    __ push(r0);
1531
1532    // Copy all arguments from the array to the stack.
1533    Label entry, loop;
1534    __ ldr(r0, MemOperand(fp, kIndexOffset));
1535    __ b(&entry);
1536
1537    // Load the current argument from the arguments array and push it to the
1538    // stack.
1539    // r0: current argument index
1540    __ bind(&loop);
1541    __ ldr(r1, MemOperand(fp, kArgsOffset));
1542    __ push(r1);
1543    __ push(r0);
1544
1545    // Call the runtime to access the property in the arguments array.
1546    __ CallRuntime(Runtime::kGetProperty, 2);
1547    __ push(r0);
1548
1549    // Use inline caching to access the arguments.
1550    __ ldr(r0, MemOperand(fp, kIndexOffset));
1551    __ add(r0, r0, Operand(1 << kSmiTagSize));
1552    __ str(r0, MemOperand(fp, kIndexOffset));
1553
1554    // Test if the copy loop has finished copying all the elements from the
1555    // arguments object.
1556    __ bind(&entry);
1557    __ ldr(r1, MemOperand(fp, kLimitOffset));
1558    __ cmp(r0, r1);
1559    __ b(ne, &loop);
1560
1561    // Invoke the function.
1562    Label call_proxy;
1563    ParameterCount actual(r0);
1564    __ mov(r0, Operand(r0, ASR, kSmiTagSize));
1565    __ ldr(r1, MemOperand(fp, kFunctionOffset));
1566    __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE);
1567    __ b(ne, &call_proxy);
1568    __ InvokeFunction(r1, actual, CALL_FUNCTION,
1569                      NullCallWrapper(), CALL_AS_METHOD);
1570
1571    frame_scope.GenerateLeaveFrame();
1572    __ add(sp, sp, Operand(3 * kPointerSize));
1573    __ Jump(lr);
1574
1575    // Invoke the function proxy.
1576    __ bind(&call_proxy);
1577    __ push(r1);  // add function proxy as last argument
1578    __ add(r0, r0, Operand(1));
1579    __ mov(r2, Operand(0, RelocInfo::NONE));
1580    __ SetCallKind(r5, CALL_AS_METHOD);
1581    __ GetBuiltinEntry(r3, Builtins::CALL_FUNCTION_PROXY);
1582    __ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1583            RelocInfo::CODE_TARGET);
1584
1585    // Tear down the internal frame and remove function, receiver and args.
1586  }
1587  __ add(sp, sp, Operand(3 * kPointerSize));
1588  __ Jump(lr);
1589}
1590
1591
1592static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
1593  __ mov(r0, Operand(r0, LSL, kSmiTagSize));
1594  __ mov(r4, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
1595  __ stm(db_w, sp, r0.bit() | r1.bit() | r4.bit() | fp.bit() | lr.bit());
1596  __ add(fp, sp, Operand(3 * kPointerSize));
1597}
1598
1599
1600static void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) {
1601  // ----------- S t a t e -------------
1602  //  -- r0 : result being passed through
1603  // -----------------------------------
1604  // Get the number of arguments passed (as a smi), tear down the frame and
1605  // then tear down the parameters.
1606  __ ldr(r1, MemOperand(fp, -3 * kPointerSize));
1607  __ mov(sp, fp);
1608  __ ldm(ia_w, sp, fp.bit() | lr.bit());
1609  __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - kSmiTagSize));
1610  __ add(sp, sp, Operand(kPointerSize));  // adjust for receiver
1611}
1612
1613
1614void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
1615  // ----------- S t a t e -------------
1616  //  -- r0 : actual number of arguments
1617  //  -- r1 : function (passed through to callee)
1618  //  -- r2 : expected number of arguments
1619  //  -- r3 : code entry to call
1620  //  -- r5 : call kind information
1621  // -----------------------------------
1622
1623  Label invoke, dont_adapt_arguments;
1624
1625  Label enough, too_few;
1626  __ cmp(r0, r2);
1627  __ b(lt, &too_few);
1628  __ cmp(r2, Operand(SharedFunctionInfo::kDontAdaptArgumentsSentinel));
1629  __ b(eq, &dont_adapt_arguments);
1630
1631  {  // Enough parameters: actual >= expected
1632    __ bind(&enough);
1633    EnterArgumentsAdaptorFrame(masm);
1634
1635    // Calculate copy start address into r0 and copy end address into r2.
1636    // r0: actual number of arguments as a smi
1637    // r1: function
1638    // r2: expected number of arguments
1639    // r3: code entry to call
1640    __ add(r0, fp, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));
1641    // adjust for return address and receiver
1642    __ add(r0, r0, Operand(2 * kPointerSize));
1643    __ sub(r2, r0, Operand(r2, LSL, kPointerSizeLog2));
1644
1645    // Copy the arguments (including the receiver) to the new stack frame.
1646    // r0: copy start address
1647    // r1: function
1648    // r2: copy end address
1649    // r3: code entry to call
1650
1651    Label copy;
1652    __ bind(&copy);
1653    __ ldr(ip, MemOperand(r0, 0));
1654    __ push(ip);
1655    __ cmp(r0, r2);  // Compare before moving to next argument.
1656    __ sub(r0, r0, Operand(kPointerSize));
1657    __ b(ne, &copy);
1658
1659    __ b(&invoke);
1660  }
1661
1662  {  // Too few parameters: Actual < expected
1663    __ bind(&too_few);
1664    EnterArgumentsAdaptorFrame(masm);
1665
1666    // Calculate copy start address into r0 and copy end address is fp.
1667    // r0: actual number of arguments as a smi
1668    // r1: function
1669    // r2: expected number of arguments
1670    // r3: code entry to call
1671    __ add(r0, fp, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));
1672
1673    // Copy the arguments (including the receiver) to the new stack frame.
1674    // r0: copy start address
1675    // r1: function
1676    // r2: expected number of arguments
1677    // r3: code entry to call
1678    Label copy;
1679    __ bind(&copy);
1680    // Adjust load for return address and receiver.
1681    __ ldr(ip, MemOperand(r0, 2 * kPointerSize));
1682    __ push(ip);
1683    __ cmp(r0, fp);  // Compare before moving to next argument.
1684    __ sub(r0, r0, Operand(kPointerSize));
1685    __ b(ne, &copy);
1686
1687    // Fill the remaining expected arguments with undefined.
1688    // r1: function
1689    // r2: expected number of arguments
1690    // r3: code entry to call
1691    __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
1692    __ sub(r2, fp, Operand(r2, LSL, kPointerSizeLog2));
1693    __ sub(r2, r2, Operand(4 * kPointerSize));  // Adjust for frame.
1694
1695    Label fill;
1696    __ bind(&fill);
1697    __ push(ip);
1698    __ cmp(sp, r2);
1699    __ b(ne, &fill);
1700  }
1701
1702  // Call the entry point.
1703  __ bind(&invoke);
1704  __ Call(r3);
1705
1706  // Exit frame and return.
1707  LeaveArgumentsAdaptorFrame(masm);
1708  __ Jump(lr);
1709
1710
1711  // -------------------------------------------
1712  // Dont adapt arguments.
1713  // -------------------------------------------
1714  __ bind(&dont_adapt_arguments);
1715  __ Jump(r3);
1716}
1717
1718
1719#undef __
1720
1721} }  // namespace v8::internal
1722
1723#endif  // V8_TARGET_ARCH_ARM
1724