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