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