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 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 CallRuntimePassFunction(MacroAssembler* masm,
78                                    Runtime::FunctionId function_id) {
79  FrameScope scope(masm, StackFrame::INTERNAL);
80  // Push a copy of the function.
81  __ push(edi);
82  // Push call kind information.
83  __ push(ecx);
84  // Function is also the parameter to the runtime call.
85  __ push(edi);
86
87  __ CallRuntime(function_id, 1);
88  // Restore call kind information.
89  __ pop(ecx);
90  // Restore receiver.
91  __ pop(edi);
92}
93
94
95static void GenerateTailCallToSharedCode(MacroAssembler* masm) {
96  __ mov(eax, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
97  __ mov(eax, FieldOperand(eax, SharedFunctionInfo::kCodeOffset));
98  __ lea(eax, FieldOperand(eax, Code::kHeaderSize));
99  __ jmp(eax);
100}
101
102
103void Builtins::Generate_InRecompileQueue(MacroAssembler* masm) {
104  // Checking whether the queued function is ready for install is optional,
105  // since we come across interrupts and stack checks elsewhere.  However,
106  // not checking may delay installing ready functions, and always checking
107  // would be quite expensive.  A good compromise is to first check against
108  // stack limit as a cue for an interrupt signal.
109  Label ok;
110  ExternalReference stack_limit =
111      ExternalReference::address_of_stack_limit(masm->isolate());
112  __ cmp(esp, Operand::StaticVariable(stack_limit));
113  __ j(above_equal, &ok, Label::kNear);
114
115  CallRuntimePassFunction(masm, Runtime::kTryInstallRecompiledCode);
116  // Tail call to returned code.
117  __ lea(eax, FieldOperand(eax, Code::kHeaderSize));
118  __ jmp(eax);
119
120  __ bind(&ok);
121  GenerateTailCallToSharedCode(masm);
122}
123
124
125void Builtins::Generate_ConcurrentRecompile(MacroAssembler* masm) {
126  CallRuntimePassFunction(masm, Runtime::kConcurrentRecompile);
127  GenerateTailCallToSharedCode(masm);
128}
129
130
131static void Generate_JSConstructStubHelper(MacroAssembler* masm,
132                                           bool is_api_function,
133                                           bool count_constructions) {
134  // ----------- S t a t e -------------
135  //  -- eax: number of arguments
136  //  -- edi: constructor function
137  // -----------------------------------
138
139  // Should never count constructions for api objects.
140  ASSERT(!is_api_function || !count_constructions);
141
142  // Enter a construct frame.
143  {
144    FrameScope scope(masm, StackFrame::CONSTRUCT);
145
146    // Store a smi-tagged arguments count on the stack.
147    __ SmiTag(eax);
148    __ push(eax);
149
150    // Push the function to invoke on the stack.
151    __ push(edi);
152
153    // Try to allocate the object without transitioning into C code. If any of
154    // the preconditions is not met, the code bails out to the runtime call.
155    Label rt_call, allocated;
156    if (FLAG_inline_new) {
157      Label undo_allocation;
158#ifdef ENABLE_DEBUGGER_SUPPORT
159      ExternalReference debug_step_in_fp =
160          ExternalReference::debug_step_in_fp_address(masm->isolate());
161      __ cmp(Operand::StaticVariable(debug_step_in_fp), Immediate(0));
162      __ j(not_equal, &rt_call);
163#endif
164
165      // Verified that the constructor is a JSFunction.
166      // Load the initial map and verify that it is in fact a map.
167      // edi: constructor
168      __ mov(eax, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset));
169      // Will both indicate a NULL and a Smi
170      __ JumpIfSmi(eax, &rt_call);
171      // edi: constructor
172      // eax: initial map (if proven valid below)
173      __ CmpObjectType(eax, MAP_TYPE, ebx);
174      __ j(not_equal, &rt_call);
175
176      // Check that the constructor is not constructing a JSFunction (see
177      // comments in Runtime_NewObject in runtime.cc). In which case the
178      // initial map's instance type would be JS_FUNCTION_TYPE.
179      // edi: constructor
180      // eax: initial map
181      __ CmpInstanceType(eax, JS_FUNCTION_TYPE);
182      __ j(equal, &rt_call);
183
184      if (count_constructions) {
185        Label allocate;
186        // Decrease generous allocation count.
187        __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
188        __ dec_b(FieldOperand(ecx,
189                              SharedFunctionInfo::kConstructionCountOffset));
190        __ j(not_zero, &allocate);
191
192        __ push(eax);
193        __ push(edi);
194
195        __ push(edi);  // constructor
196        // The call will replace the stub, so the countdown is only done once.
197        __ CallRuntime(Runtime::kFinalizeInstanceSize, 1);
198
199        __ pop(edi);
200        __ pop(eax);
201
202        __ bind(&allocate);
203      }
204
205      // Now allocate the JSObject on the heap.
206      // edi: constructor
207      // eax: initial map
208      __ movzx_b(edi, FieldOperand(eax, Map::kInstanceSizeOffset));
209      __ shl(edi, kPointerSizeLog2);
210      __ Allocate(edi, ebx, edi, no_reg, &rt_call, NO_ALLOCATION_FLAGS);
211      // Allocated the JSObject, now initialize the fields.
212      // eax: initial map
213      // ebx: JSObject
214      // edi: start of next object
215      __ mov(Operand(ebx, JSObject::kMapOffset), eax);
216      Factory* factory = masm->isolate()->factory();
217      __ mov(ecx, factory->empty_fixed_array());
218      __ mov(Operand(ebx, JSObject::kPropertiesOffset), ecx);
219      __ mov(Operand(ebx, JSObject::kElementsOffset), ecx);
220      // Set extra fields in the newly allocated object.
221      // eax: initial map
222      // ebx: JSObject
223      // edi: start of next object
224      __ lea(ecx, Operand(ebx, JSObject::kHeaderSize));
225      __ mov(edx, factory->undefined_value());
226      if (count_constructions) {
227        __ movzx_b(esi,
228                   FieldOperand(eax, Map::kPreAllocatedPropertyFieldsOffset));
229        __ lea(esi,
230               Operand(ebx, esi, times_pointer_size, JSObject::kHeaderSize));
231        // esi: offset of first field after pre-allocated fields
232        if (FLAG_debug_code) {
233          __ cmp(esi, edi);
234          __ Assert(less_equal,
235                    kUnexpectedNumberOfPreAllocatedPropertyFields);
236        }
237        __ InitializeFieldsWithFiller(ecx, esi, edx);
238        __ mov(edx, factory->one_pointer_filler_map());
239      }
240      __ InitializeFieldsWithFiller(ecx, edi, edx);
241
242      // Add the object tag to make the JSObject real, so that we can continue
243      // and jump into the continuation code at any time from now on. Any
244      // failures need to undo the allocation, so that the heap is in a
245      // consistent state and verifiable.
246      // eax: initial map
247      // ebx: JSObject
248      // edi: start of next object
249      __ or_(ebx, Immediate(kHeapObjectTag));
250
251      // Check if a non-empty properties array is needed.
252      // Allocate and initialize a FixedArray if it is.
253      // eax: initial map
254      // ebx: JSObject
255      // edi: start of next object
256      // Calculate the total number of properties described by the map.
257      __ movzx_b(edx, FieldOperand(eax, Map::kUnusedPropertyFieldsOffset));
258      __ movzx_b(ecx,
259                 FieldOperand(eax, Map::kPreAllocatedPropertyFieldsOffset));
260      __ add(edx, ecx);
261      // Calculate unused properties past the end of the in-object properties.
262      __ movzx_b(ecx, FieldOperand(eax, Map::kInObjectPropertiesOffset));
263      __ sub(edx, ecx);
264      // Done if no extra properties are to be allocated.
265      __ j(zero, &allocated);
266      __ Assert(positive, kPropertyAllocationCountFailed);
267
268      // Scale the number of elements by pointer size and add the header for
269      // FixedArrays to the start of the next object calculation from above.
270      // ebx: JSObject
271      // edi: start of next object (will be start of FixedArray)
272      // edx: number of elements in properties array
273      __ Allocate(FixedArray::kHeaderSize,
274                  times_pointer_size,
275                  edx,
276                  REGISTER_VALUE_IS_INT32,
277                  edi,
278                  ecx,
279                  no_reg,
280                  &undo_allocation,
281                  RESULT_CONTAINS_TOP);
282
283      // Initialize the FixedArray.
284      // ebx: JSObject
285      // edi: FixedArray
286      // edx: number of elements
287      // ecx: start of next object
288      __ mov(eax, factory->fixed_array_map());
289      __ mov(Operand(edi, FixedArray::kMapOffset), eax);  // setup the map
290      __ SmiTag(edx);
291      __ mov(Operand(edi, FixedArray::kLengthOffset), edx);  // and length
292
293      // Initialize the fields to undefined.
294      // ebx: JSObject
295      // edi: FixedArray
296      // ecx: start of next object
297      { Label loop, entry;
298        __ mov(edx, factory->undefined_value());
299        __ lea(eax, Operand(edi, FixedArray::kHeaderSize));
300        __ jmp(&entry);
301        __ bind(&loop);
302        __ mov(Operand(eax, 0), edx);
303        __ add(eax, Immediate(kPointerSize));
304        __ bind(&entry);
305        __ cmp(eax, ecx);
306        __ j(below, &loop);
307      }
308
309      // Store the initialized FixedArray into the properties field of
310      // the JSObject
311      // ebx: JSObject
312      // edi: FixedArray
313      __ or_(edi, Immediate(kHeapObjectTag));  // add the heap tag
314      __ mov(FieldOperand(ebx, JSObject::kPropertiesOffset), edi);
315
316
317      // Continue with JSObject being successfully allocated
318      // ebx: JSObject
319      __ jmp(&allocated);
320
321      // Undo the setting of the new top so that the heap is verifiable. For
322      // example, the map's unused properties potentially do not match the
323      // allocated objects unused properties.
324      // ebx: JSObject (previous new top)
325      __ bind(&undo_allocation);
326      __ UndoAllocationInNewSpace(ebx);
327    }
328
329    // Allocate the new receiver object using the runtime call.
330    __ bind(&rt_call);
331    // Must restore edi (constructor) before calling runtime.
332    __ mov(edi, Operand(esp, 0));
333    // edi: function (constructor)
334    __ push(edi);
335    __ CallRuntime(Runtime::kNewObject, 1);
336    __ mov(ebx, eax);  // store result in ebx
337
338    // New object allocated.
339    // ebx: newly allocated object
340    __ bind(&allocated);
341    // Retrieve the function from the stack.
342    __ pop(edi);
343
344    // Retrieve smi-tagged arguments count from the stack.
345    __ mov(eax, Operand(esp, 0));
346    __ SmiUntag(eax);
347
348    // Push the allocated receiver to the stack. We need two copies
349    // because we may have to return the original one and the calling
350    // conventions dictate that the called function pops the receiver.
351    __ push(ebx);
352    __ push(ebx);
353
354    // Set up pointer to last argument.
355    __ lea(ebx, Operand(ebp, StandardFrameConstants::kCallerSPOffset));
356
357    // Copy arguments and receiver to the expression stack.
358    Label loop, entry;
359    __ mov(ecx, eax);
360    __ jmp(&entry);
361    __ bind(&loop);
362    __ push(Operand(ebx, ecx, times_4, 0));
363    __ bind(&entry);
364    __ dec(ecx);
365    __ j(greater_equal, &loop);
366
367    // Call the function.
368    if (is_api_function) {
369      __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
370      Handle<Code> code =
371          masm->isolate()->builtins()->HandleApiCallConstruct();
372      ParameterCount expected(0);
373      __ InvokeCode(code, expected, expected, RelocInfo::CODE_TARGET,
374                    CALL_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
375    } else {
376      ParameterCount actual(eax);
377      __ InvokeFunction(edi, actual, CALL_FUNCTION,
378                        NullCallWrapper(), CALL_AS_METHOD);
379    }
380
381    // Store offset of return address for deoptimizer.
382    if (!is_api_function && !count_constructions) {
383      masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset());
384    }
385
386    // Restore context from the frame.
387    __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
388
389    // If the result is an object (in the ECMA sense), we should get rid
390    // of the receiver and use the result; see ECMA-262 section 13.2.2-7
391    // on page 74.
392    Label use_receiver, exit;
393
394    // If the result is a smi, it is *not* an object in the ECMA sense.
395    __ JumpIfSmi(eax, &use_receiver);
396
397    // If the type of the result (stored in its map) is less than
398    // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense.
399    __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
400    __ j(above_equal, &exit);
401
402    // Throw away the result of the constructor invocation and use the
403    // on-stack receiver as the result.
404    __ bind(&use_receiver);
405    __ mov(eax, Operand(esp, 0));
406
407    // Restore the arguments count and leave the construct frame.
408    __ bind(&exit);
409    __ mov(ebx, Operand(esp, kPointerSize));  // Get arguments count.
410
411    // Leave construct frame.
412  }
413
414  // Remove caller arguments from the stack and return.
415  STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
416  __ pop(ecx);
417  __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize));  // 1 ~ receiver
418  __ push(ecx);
419  __ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1);
420  __ ret(0);
421}
422
423
424void Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) {
425  Generate_JSConstructStubHelper(masm, false, true);
426}
427
428
429void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
430  Generate_JSConstructStubHelper(masm, false, false);
431}
432
433
434void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
435  Generate_JSConstructStubHelper(masm, true, false);
436}
437
438
439static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
440                                             bool is_construct) {
441  ProfileEntryHookStub::MaybeCallEntryHook(masm);
442
443  // Clear the context before we push it when entering the internal frame.
444  __ Set(esi, Immediate(0));
445
446  {
447    FrameScope scope(masm, StackFrame::INTERNAL);
448
449    // Load the previous frame pointer (ebx) to access C arguments
450    __ mov(ebx, Operand(ebp, 0));
451
452    // Get the function from the frame and setup the context.
453    __ mov(ecx, Operand(ebx, EntryFrameConstants::kFunctionArgOffset));
454    __ mov(esi, FieldOperand(ecx, JSFunction::kContextOffset));
455
456    // Push the function and the receiver onto the stack.
457    __ push(ecx);
458    __ push(Operand(ebx, EntryFrameConstants::kReceiverArgOffset));
459
460    // Load the number of arguments and setup pointer to the arguments.
461    __ mov(eax, Operand(ebx, EntryFrameConstants::kArgcOffset));
462    __ mov(ebx, Operand(ebx, EntryFrameConstants::kArgvOffset));
463
464    // Copy arguments to the stack in a loop.
465    Label loop, entry;
466    __ Set(ecx, Immediate(0));
467    __ jmp(&entry);
468    __ bind(&loop);
469    __ mov(edx, Operand(ebx, ecx, times_4, 0));  // push parameter from argv
470    __ push(Operand(edx, 0));  // dereference handle
471    __ inc(ecx);
472    __ bind(&entry);
473    __ cmp(ecx, eax);
474    __ j(not_equal, &loop);
475
476    // Get the function from the stack and call it.
477    // kPointerSize for the receiver.
478    __ mov(edi, Operand(esp, eax, times_4, kPointerSize));
479
480    // Invoke the code.
481    if (is_construct) {
482      // No type feedback cell is available
483      Handle<Object> undefined_sentinel(
484          masm->isolate()->heap()->undefined_value(), masm->isolate());
485      __ mov(ebx, Immediate(undefined_sentinel));
486      CallConstructStub stub(NO_CALL_FUNCTION_FLAGS);
487      __ CallStub(&stub);
488    } else {
489      ParameterCount actual(eax);
490      __ InvokeFunction(edi, actual, CALL_FUNCTION,
491                        NullCallWrapper(), CALL_AS_METHOD);
492    }
493
494    // Exit the internal frame. Notice that this also removes the empty.
495    // context and the function left on the stack by the code
496    // invocation.
497  }
498  __ ret(kPointerSize);  // Remove receiver.
499}
500
501
502void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) {
503  Generate_JSEntryTrampolineHelper(masm, false);
504}
505
506
507void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
508  Generate_JSEntryTrampolineHelper(masm, true);
509}
510
511
512void Builtins::Generate_LazyCompile(MacroAssembler* masm) {
513  CallRuntimePassFunction(masm, Runtime::kLazyCompile);
514  // Do a tail-call of the compiled function.
515  __ lea(eax, FieldOperand(eax, Code::kHeaderSize));
516  __ jmp(eax);
517}
518
519
520void Builtins::Generate_LazyRecompile(MacroAssembler* masm) {
521  CallRuntimePassFunction(masm, Runtime::kLazyRecompile);
522  // Do a tail-call of the compiled function.
523  __ lea(eax, FieldOperand(eax, Code::kHeaderSize));
524  __ jmp(eax);
525}
526
527
528static void GenerateMakeCodeYoungAgainCommon(MacroAssembler* masm) {
529  // For now, we are relying on the fact that make_code_young doesn't do any
530  // garbage collection which allows us to save/restore the registers without
531  // worrying about which of them contain pointers. We also don't build an
532  // internal frame to make the code faster, since we shouldn't have to do stack
533  // crawls in MakeCodeYoung. This seems a bit fragile.
534
535  // Re-execute the code that was patched back to the young age when
536  // the stub returns.
537  __ sub(Operand(esp, 0), Immediate(5));
538  __ pushad();
539  __ mov(eax, Operand(esp, 8 * kPointerSize));
540  {
541    FrameScope scope(masm, StackFrame::MANUAL);
542    __ PrepareCallCFunction(2, ebx);
543    __ mov(Operand(esp, 1 * kPointerSize),
544           Immediate(ExternalReference::isolate_address(masm->isolate())));
545    __ mov(Operand(esp, 0), eax);
546    __ CallCFunction(
547        ExternalReference::get_make_code_young_function(masm->isolate()), 2);
548  }
549  __ popad();
550  __ ret(0);
551}
552
553#define DEFINE_CODE_AGE_BUILTIN_GENERATOR(C)                 \
554void Builtins::Generate_Make##C##CodeYoungAgainEvenMarking(  \
555    MacroAssembler* masm) {                                  \
556  GenerateMakeCodeYoungAgainCommon(masm);                    \
557}                                                            \
558void Builtins::Generate_Make##C##CodeYoungAgainOddMarking(   \
559    MacroAssembler* masm) {                                  \
560  GenerateMakeCodeYoungAgainCommon(masm);                    \
561}
562CODE_AGE_LIST(DEFINE_CODE_AGE_BUILTIN_GENERATOR)
563#undef DEFINE_CODE_AGE_BUILTIN_GENERATOR
564
565
566void Builtins::Generate_MarkCodeAsExecutedOnce(MacroAssembler* masm) {
567  // For now, as in GenerateMakeCodeYoungAgainCommon, we are relying on the fact
568  // that make_code_young doesn't do any garbage collection which allows us to
569  // save/restore the registers without worrying about which of them contain
570  // pointers.
571  __ pushad();
572  __ mov(eax, Operand(esp, 8 * kPointerSize));
573  __ sub(eax, Immediate(Assembler::kCallInstructionLength));
574  {  // NOLINT
575    FrameScope scope(masm, StackFrame::MANUAL);
576    __ PrepareCallCFunction(2, ebx);
577    __ mov(Operand(esp, 1 * kPointerSize),
578           Immediate(ExternalReference::isolate_address(masm->isolate())));
579    __ mov(Operand(esp, 0), eax);
580    __ CallCFunction(
581        ExternalReference::get_mark_code_as_executed_function(masm->isolate()),
582        2);
583  }
584  __ popad();
585
586  // Perform prologue operations usually performed by the young code stub.
587  __ pop(eax);   // Pop return address into scratch register.
588  __ push(ebp);  // Caller's frame pointer.
589  __ mov(ebp, esp);
590  __ push(esi);  // Callee's context.
591  __ push(edi);  // Callee's JS Function.
592  __ push(eax);  // Push return address after frame prologue.
593
594  // Jump to point after the code-age stub.
595  __ ret(0);
596}
597
598
599void Builtins::Generate_MarkCodeAsExecutedTwice(MacroAssembler* masm) {
600  GenerateMakeCodeYoungAgainCommon(masm);
601}
602
603
604static void Generate_NotifyStubFailureHelper(MacroAssembler* masm,
605                                             SaveFPRegsMode save_doubles) {
606  // Enter an internal frame.
607  {
608    FrameScope scope(masm, StackFrame::INTERNAL);
609
610    // Preserve registers across notification, this is important for compiled
611    // stubs that tail call the runtime on deopts passing their parameters in
612    // registers.
613    __ pushad();
614    __ CallRuntime(Runtime::kNotifyStubFailure, 0, save_doubles);
615    __ popad();
616    // Tear down internal frame.
617  }
618
619  __ pop(MemOperand(esp, 0));  // Ignore state offset
620  __ ret(0);  // Return to IC Miss stub, continuation still on stack.
621}
622
623
624void Builtins::Generate_NotifyStubFailure(MacroAssembler* masm) {
625  Generate_NotifyStubFailureHelper(masm, kDontSaveFPRegs);
626}
627
628
629void Builtins::Generate_NotifyStubFailureSaveDoubles(MacroAssembler* masm) {
630  if (Serializer::enabled()) {
631    PlatformFeatureScope sse2(SSE2);
632    Generate_NotifyStubFailureHelper(masm, kSaveFPRegs);
633  } else {
634    Generate_NotifyStubFailureHelper(masm, kSaveFPRegs);
635  }
636}
637
638
639static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm,
640                                             Deoptimizer::BailoutType type) {
641  {
642    FrameScope scope(masm, StackFrame::INTERNAL);
643
644    // Pass deoptimization type to the runtime system.
645    __ push(Immediate(Smi::FromInt(static_cast<int>(type))));
646    __ CallRuntime(Runtime::kNotifyDeoptimized, 1);
647
648    // Tear down internal frame.
649  }
650
651  // Get the full codegen state from the stack and untag it.
652  __ mov(ecx, Operand(esp, 1 * kPointerSize));
653  __ SmiUntag(ecx);
654
655  // Switch on the state.
656  Label not_no_registers, not_tos_eax;
657  __ cmp(ecx, FullCodeGenerator::NO_REGISTERS);
658  __ j(not_equal, &not_no_registers, Label::kNear);
659  __ ret(1 * kPointerSize);  // Remove state.
660
661  __ bind(&not_no_registers);
662  __ mov(eax, Operand(esp, 2 * kPointerSize));
663  __ cmp(ecx, FullCodeGenerator::TOS_REG);
664  __ j(not_equal, &not_tos_eax, Label::kNear);
665  __ ret(2 * kPointerSize);  // Remove state, eax.
666
667  __ bind(&not_tos_eax);
668  __ Abort(kNoCasesLeft);
669}
670
671
672void Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) {
673  Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::EAGER);
674}
675
676
677void Builtins::Generate_NotifySoftDeoptimized(MacroAssembler* masm) {
678  Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::SOFT);
679}
680
681
682void Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) {
683  Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
684}
685
686
687void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
688  Factory* factory = masm->isolate()->factory();
689
690  // 1. Make sure we have at least one argument.
691  { Label done;
692    __ test(eax, eax);
693    __ j(not_zero, &done);
694    __ pop(ebx);
695    __ push(Immediate(factory->undefined_value()));
696    __ push(ebx);
697    __ inc(eax);
698    __ bind(&done);
699  }
700
701  // 2. Get the function to call (passed as receiver) from the stack, check
702  //    if it is a function.
703  Label slow, non_function;
704  // 1 ~ return address.
705  __ mov(edi, Operand(esp, eax, times_4, 1 * kPointerSize));
706  __ JumpIfSmi(edi, &non_function);
707  __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
708  __ j(not_equal, &slow);
709
710
711  // 3a. Patch the first argument if necessary when calling a function.
712  Label shift_arguments;
713  __ Set(edx, Immediate(0));  // indicate regular JS_FUNCTION
714  { Label convert_to_object, use_global_receiver, patch_receiver;
715    // Change context eagerly in case we need the global receiver.
716    __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
717
718    // Do not transform the receiver for strict mode functions.
719    __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
720    __ test_b(FieldOperand(ebx, SharedFunctionInfo::kStrictModeByteOffset),
721              1 << SharedFunctionInfo::kStrictModeBitWithinByte);
722    __ j(not_equal, &shift_arguments);
723
724    // Do not transform the receiver for natives (shared already in ebx).
725    __ test_b(FieldOperand(ebx, SharedFunctionInfo::kNativeByteOffset),
726              1 << SharedFunctionInfo::kNativeBitWithinByte);
727    __ j(not_equal, &shift_arguments);
728
729    // Compute the receiver in non-strict mode.
730    __ mov(ebx, Operand(esp, eax, times_4, 0));  // First argument.
731
732    // Call ToObject on the receiver if it is not an object, or use the
733    // global object if it is null or undefined.
734    __ JumpIfSmi(ebx, &convert_to_object);
735    __ cmp(ebx, factory->null_value());
736    __ j(equal, &use_global_receiver);
737    __ cmp(ebx, factory->undefined_value());
738    __ j(equal, &use_global_receiver);
739    STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
740    __ CmpObjectType(ebx, FIRST_SPEC_OBJECT_TYPE, ecx);
741    __ j(above_equal, &shift_arguments);
742
743    __ bind(&convert_to_object);
744
745    { // In order to preserve argument count.
746      FrameScope scope(masm, StackFrame::INTERNAL);
747      __ SmiTag(eax);
748      __ push(eax);
749
750      __ push(ebx);
751      __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
752      __ mov(ebx, eax);
753      __ Set(edx, Immediate(0));  // restore
754
755      __ pop(eax);
756      __ SmiUntag(eax);
757    }
758
759    // Restore the function to edi.
760    __ mov(edi, Operand(esp, eax, times_4, 1 * kPointerSize));
761    __ jmp(&patch_receiver);
762
763    // Use the global receiver object from the called function as the
764    // receiver.
765    __ bind(&use_global_receiver);
766    const int kGlobalIndex =
767        Context::kHeaderSize + Context::GLOBAL_OBJECT_INDEX * kPointerSize;
768    __ mov(ebx, FieldOperand(esi, kGlobalIndex));
769    __ mov(ebx, FieldOperand(ebx, GlobalObject::kNativeContextOffset));
770    __ mov(ebx, FieldOperand(ebx, kGlobalIndex));
771    __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset));
772
773    __ bind(&patch_receiver);
774    __ mov(Operand(esp, eax, times_4, 0), ebx);
775
776    __ jmp(&shift_arguments);
777  }
778
779  // 3b. Check for function proxy.
780  __ bind(&slow);
781  __ Set(edx, Immediate(1));  // indicate function proxy
782  __ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE);
783  __ j(equal, &shift_arguments);
784  __ bind(&non_function);
785  __ Set(edx, Immediate(2));  // indicate non-function
786
787  // 3c. Patch the first argument when calling a non-function.  The
788  //     CALL_NON_FUNCTION builtin expects the non-function callee as
789  //     receiver, so overwrite the first argument which will ultimately
790  //     become the receiver.
791  __ mov(Operand(esp, eax, times_4, 0), edi);
792
793  // 4. Shift arguments and return address one slot down on the stack
794  //    (overwriting the original receiver).  Adjust argument count to make
795  //    the original first argument the new receiver.
796  __ bind(&shift_arguments);
797  { Label loop;
798    __ mov(ecx, eax);
799    __ bind(&loop);
800    __ mov(ebx, Operand(esp, ecx, times_4, 0));
801    __ mov(Operand(esp, ecx, times_4, kPointerSize), ebx);
802    __ dec(ecx);
803    __ j(not_sign, &loop);  // While non-negative (to copy return address).
804    __ pop(ebx);  // Discard copy of return address.
805    __ dec(eax);  // One fewer argument (first argument is new receiver).
806  }
807
808  // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin,
809  //     or a function proxy via CALL_FUNCTION_PROXY.
810  { Label function, non_proxy;
811    __ test(edx, edx);
812    __ j(zero, &function);
813    __ Set(ebx, Immediate(0));
814    __ cmp(edx, Immediate(1));
815    __ j(not_equal, &non_proxy);
816
817    __ pop(edx);   // return address
818    __ push(edi);  // re-add proxy object as additional argument
819    __ push(edx);
820    __ inc(eax);
821    __ SetCallKind(ecx, CALL_AS_FUNCTION);
822    __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY);
823    __ jmp(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
824           RelocInfo::CODE_TARGET);
825
826    __ bind(&non_proxy);
827    __ SetCallKind(ecx, CALL_AS_METHOD);
828    __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION);
829    __ jmp(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
830           RelocInfo::CODE_TARGET);
831    __ bind(&function);
832  }
833
834  // 5b. Get the code to call from the function and check that the number of
835  //     expected arguments matches what we're providing.  If so, jump
836  //     (tail-call) to the code in register edx without checking arguments.
837  __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
838  __ mov(ebx,
839         FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset));
840  __ mov(edx, FieldOperand(edi, JSFunction::kCodeEntryOffset));
841  __ SmiUntag(ebx);
842  __ SetCallKind(ecx, CALL_AS_METHOD);
843  __ cmp(eax, ebx);
844  __ j(not_equal,
845       masm->isolate()->builtins()->ArgumentsAdaptorTrampoline());
846
847  ParameterCount expected(0);
848  __ InvokeCode(edx, expected, expected, JUMP_FUNCTION, NullCallWrapper(),
849                CALL_AS_METHOD);
850}
851
852
853void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
854  static const int kArgumentsOffset = 2 * kPointerSize;
855  static const int kReceiverOffset = 3 * kPointerSize;
856  static const int kFunctionOffset = 4 * kPointerSize;
857  {
858    FrameScope frame_scope(masm, StackFrame::INTERNAL);
859
860    __ push(Operand(ebp, kFunctionOffset));  // push this
861    __ push(Operand(ebp, kArgumentsOffset));  // push arguments
862    __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION);
863
864    // Check the stack for overflow. We are not trying to catch
865    // interruptions (e.g. debug break and preemption) here, so the "real stack
866    // limit" is checked.
867    Label okay;
868    ExternalReference real_stack_limit =
869        ExternalReference::address_of_real_stack_limit(masm->isolate());
870    __ mov(edi, Operand::StaticVariable(real_stack_limit));
871    // Make ecx the space we have left. The stack might already be overflowed
872    // here which will cause ecx to become negative.
873    __ mov(ecx, esp);
874    __ sub(ecx, edi);
875    // Make edx the space we need for the array when it is unrolled onto the
876    // stack.
877    __ mov(edx, eax);
878    __ shl(edx, kPointerSizeLog2 - kSmiTagSize);
879    // Check if the arguments will overflow the stack.
880    __ cmp(ecx, edx);
881    __ j(greater, &okay);  // Signed comparison.
882
883    // Out of stack space.
884    __ push(Operand(ebp, 4 * kPointerSize));  // push this
885    __ push(eax);
886    __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION);
887    __ bind(&okay);
888    // End of stack check.
889
890    // Push current index and limit.
891    const int kLimitOffset =
892        StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize;
893    const int kIndexOffset = kLimitOffset - 1 * kPointerSize;
894    __ push(eax);  // limit
895    __ push(Immediate(0));  // index
896
897    // Get the receiver.
898    __ mov(ebx, Operand(ebp, kReceiverOffset));
899
900    // Check that the function is a JS function (otherwise it must be a proxy).
901    Label push_receiver;
902    __ mov(edi, Operand(ebp, kFunctionOffset));
903    __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
904    __ j(not_equal, &push_receiver);
905
906    // Change context eagerly to get the right global object if necessary.
907    __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
908
909    // Compute the receiver.
910    // Do not transform the receiver for strict mode functions.
911    Label call_to_object, use_global_receiver;
912    __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
913    __ test_b(FieldOperand(ecx, SharedFunctionInfo::kStrictModeByteOffset),
914              1 << SharedFunctionInfo::kStrictModeBitWithinByte);
915    __ j(not_equal, &push_receiver);
916
917    Factory* factory = masm->isolate()->factory();
918
919    // Do not transform the receiver for natives (shared already in ecx).
920    __ test_b(FieldOperand(ecx, SharedFunctionInfo::kNativeByteOffset),
921              1 << SharedFunctionInfo::kNativeBitWithinByte);
922    __ j(not_equal, &push_receiver);
923
924    // Compute the receiver in non-strict mode.
925    // Call ToObject on the receiver if it is not an object, or use the
926    // global object if it is null or undefined.
927    __ JumpIfSmi(ebx, &call_to_object);
928    __ cmp(ebx, factory->null_value());
929    __ j(equal, &use_global_receiver);
930    __ cmp(ebx, factory->undefined_value());
931    __ j(equal, &use_global_receiver);
932    STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
933    __ CmpObjectType(ebx, FIRST_SPEC_OBJECT_TYPE, ecx);
934    __ j(above_equal, &push_receiver);
935
936    __ bind(&call_to_object);
937    __ push(ebx);
938    __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
939    __ mov(ebx, eax);
940    __ jmp(&push_receiver);
941
942    // Use the current global receiver object as the receiver.
943    __ bind(&use_global_receiver);
944    const int kGlobalOffset =
945        Context::kHeaderSize + Context::GLOBAL_OBJECT_INDEX * kPointerSize;
946    __ mov(ebx, FieldOperand(esi, kGlobalOffset));
947    __ mov(ebx, FieldOperand(ebx, GlobalObject::kNativeContextOffset));
948    __ mov(ebx, FieldOperand(ebx, kGlobalOffset));
949    __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset));
950
951    // Push the receiver.
952    __ bind(&push_receiver);
953    __ push(ebx);
954
955    // Copy all arguments from the array to the stack.
956    Label entry, loop;
957    __ mov(ecx, Operand(ebp, kIndexOffset));
958    __ jmp(&entry);
959    __ bind(&loop);
960    __ mov(edx, Operand(ebp, kArgumentsOffset));  // load arguments
961
962    // Use inline caching to speed up access to arguments.
963    Handle<Code> ic = masm->isolate()->builtins()->KeyedLoadIC_Initialize();
964    __ call(ic, RelocInfo::CODE_TARGET);
965    // It is important that we do not have a test instruction after the
966    // call.  A test instruction after the call is used to indicate that
967    // we have generated an inline version of the keyed load.  In this
968    // case, we know that we are not generating a test instruction next.
969
970    // Push the nth argument.
971    __ push(eax);
972
973    // Update the index on the stack and in register eax.
974    __ mov(ecx, Operand(ebp, kIndexOffset));
975    __ add(ecx, Immediate(1 << kSmiTagSize));
976    __ mov(Operand(ebp, kIndexOffset), ecx);
977
978    __ bind(&entry);
979    __ cmp(ecx, Operand(ebp, kLimitOffset));
980    __ j(not_equal, &loop);
981
982    // Invoke the function.
983    Label call_proxy;
984    __ mov(eax, ecx);
985    ParameterCount actual(eax);
986    __ SmiUntag(eax);
987    __ mov(edi, Operand(ebp, kFunctionOffset));
988    __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
989    __ j(not_equal, &call_proxy);
990    __ InvokeFunction(edi, actual, CALL_FUNCTION,
991                      NullCallWrapper(), CALL_AS_METHOD);
992
993    frame_scope.GenerateLeaveFrame();
994    __ ret(3 * kPointerSize);  // remove this, receiver, and arguments
995
996    // Invoke the function proxy.
997    __ bind(&call_proxy);
998    __ push(edi);  // add function proxy as last argument
999    __ inc(eax);
1000    __ Set(ebx, Immediate(0));
1001    __ SetCallKind(ecx, CALL_AS_METHOD);
1002    __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY);
1003    __ call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1004            RelocInfo::CODE_TARGET);
1005
1006    // Leave internal frame.
1007  }
1008  __ ret(3 * kPointerSize);  // remove this, receiver, and arguments
1009}
1010
1011
1012void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) {
1013  // ----------- S t a t e -------------
1014  //  -- eax : argc
1015  //  -- esp[0] : return address
1016  //  -- esp[4] : last argument
1017  // -----------------------------------
1018  Label generic_array_code;
1019
1020  // Get the InternalArray function.
1021  __ LoadGlobalFunction(Context::INTERNAL_ARRAY_FUNCTION_INDEX, edi);
1022
1023  if (FLAG_debug_code) {
1024    // Initial map for the builtin InternalArray function should be a map.
1025    __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset));
1026    // Will both indicate a NULL and a Smi.
1027    __ test(ebx, Immediate(kSmiTagMask));
1028    __ Assert(not_zero, kUnexpectedInitialMapForInternalArrayFunction);
1029    __ CmpObjectType(ebx, MAP_TYPE, ecx);
1030    __ Assert(equal, kUnexpectedInitialMapForInternalArrayFunction);
1031  }
1032
1033  // Run the native code for the InternalArray function called as a normal
1034  // function.
1035  // tail call a stub
1036  InternalArrayConstructorStub stub(masm->isolate());
1037  __ TailCallStub(&stub);
1038}
1039
1040
1041void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
1042  // ----------- S t a t e -------------
1043  //  -- eax : argc
1044  //  -- esp[0] : return address
1045  //  -- esp[4] : last argument
1046  // -----------------------------------
1047  Label generic_array_code;
1048
1049  // Get the Array function.
1050  __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, edi);
1051
1052  if (FLAG_debug_code) {
1053    // Initial map for the builtin Array function should be a map.
1054    __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset));
1055    // Will both indicate a NULL and a Smi.
1056    __ test(ebx, Immediate(kSmiTagMask));
1057    __ Assert(not_zero, kUnexpectedInitialMapForArrayFunction);
1058    __ CmpObjectType(ebx, MAP_TYPE, ecx);
1059    __ Assert(equal, kUnexpectedInitialMapForArrayFunction);
1060  }
1061
1062  // Run the native code for the Array function called as a normal function.
1063  // tail call a stub
1064  Handle<Object> undefined_sentinel(
1065      masm->isolate()->heap()->undefined_value(),
1066      masm->isolate());
1067  __ mov(ebx, Immediate(undefined_sentinel));
1068  ArrayConstructorStub stub(masm->isolate());
1069  __ TailCallStub(&stub);
1070}
1071
1072
1073void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
1074  // ----------- S t a t e -------------
1075  //  -- eax                 : number of arguments
1076  //  -- edi                 : constructor function
1077  //  -- esp[0]              : return address
1078  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
1079  //  -- esp[(argc + 1) * 4] : receiver
1080  // -----------------------------------
1081  Counters* counters = masm->isolate()->counters();
1082  __ IncrementCounter(counters->string_ctor_calls(), 1);
1083
1084  if (FLAG_debug_code) {
1085    __ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, ecx);
1086    __ cmp(edi, ecx);
1087    __ Assert(equal, kUnexpectedStringFunction);
1088  }
1089
1090  // Load the first argument into eax and get rid of the rest
1091  // (including the receiver).
1092  Label no_arguments;
1093  __ test(eax, eax);
1094  __ j(zero, &no_arguments);
1095  __ mov(ebx, Operand(esp, eax, times_pointer_size, 0));
1096  __ pop(ecx);
1097  __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize));
1098  __ push(ecx);
1099  __ mov(eax, ebx);
1100
1101  // Lookup the argument in the number to string cache.
1102  Label not_cached, argument_is_string;
1103  __ LookupNumberStringCache(eax,  // Input.
1104                             ebx,  // Result.
1105                             ecx,  // Scratch 1.
1106                             edx,  // Scratch 2.
1107                             &not_cached);
1108  __ IncrementCounter(counters->string_ctor_cached_number(), 1);
1109  __ bind(&argument_is_string);
1110  // ----------- S t a t e -------------
1111  //  -- ebx    : argument converted to string
1112  //  -- edi    : constructor function
1113  //  -- esp[0] : return address
1114  // -----------------------------------
1115
1116  // Allocate a JSValue and put the tagged pointer into eax.
1117  Label gc_required;
1118  __ Allocate(JSValue::kSize,
1119              eax,  // Result.
1120              ecx,  // New allocation top (we ignore it).
1121              no_reg,
1122              &gc_required,
1123              TAG_OBJECT);
1124
1125  // Set the map.
1126  __ LoadGlobalFunctionInitialMap(edi, ecx);
1127  if (FLAG_debug_code) {
1128    __ cmpb(FieldOperand(ecx, Map::kInstanceSizeOffset),
1129            JSValue::kSize >> kPointerSizeLog2);
1130    __ Assert(equal, kUnexpectedStringWrapperInstanceSize);
1131    __ cmpb(FieldOperand(ecx, Map::kUnusedPropertyFieldsOffset), 0);
1132    __ Assert(equal, kUnexpectedUnusedPropertiesOfStringWrapper);
1133  }
1134  __ mov(FieldOperand(eax, HeapObject::kMapOffset), ecx);
1135
1136  // Set properties and elements.
1137  Factory* factory = masm->isolate()->factory();
1138  __ Set(ecx, Immediate(factory->empty_fixed_array()));
1139  __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), ecx);
1140  __ mov(FieldOperand(eax, JSObject::kElementsOffset), ecx);
1141
1142  // Set the value.
1143  __ mov(FieldOperand(eax, JSValue::kValueOffset), ebx);
1144
1145  // Ensure the object is fully initialized.
1146  STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
1147
1148  // We're done. Return.
1149  __ ret(0);
1150
1151  // The argument was not found in the number to string cache. Check
1152  // if it's a string already before calling the conversion builtin.
1153  Label convert_argument;
1154  __ bind(&not_cached);
1155  STATIC_ASSERT(kSmiTag == 0);
1156  __ JumpIfSmi(eax, &convert_argument);
1157  Condition is_string = masm->IsObjectStringType(eax, ebx, ecx);
1158  __ j(NegateCondition(is_string), &convert_argument);
1159  __ mov(ebx, eax);
1160  __ IncrementCounter(counters->string_ctor_string_value(), 1);
1161  __ jmp(&argument_is_string);
1162
1163  // Invoke the conversion builtin and put the result into ebx.
1164  __ bind(&convert_argument);
1165  __ IncrementCounter(counters->string_ctor_conversions(), 1);
1166  {
1167    FrameScope scope(masm, StackFrame::INTERNAL);
1168    __ push(edi);  // Preserve the function.
1169    __ push(eax);
1170    __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION);
1171    __ pop(edi);
1172  }
1173  __ mov(ebx, eax);
1174  __ jmp(&argument_is_string);
1175
1176  // Load the empty string into ebx, remove the receiver from the
1177  // stack, and jump back to the case where the argument is a string.
1178  __ bind(&no_arguments);
1179  __ Set(ebx, Immediate(factory->empty_string()));
1180  __ pop(ecx);
1181  __ lea(esp, Operand(esp, kPointerSize));
1182  __ push(ecx);
1183  __ jmp(&argument_is_string);
1184
1185  // At this point the argument is already a string. Call runtime to
1186  // create a string wrapper.
1187  __ bind(&gc_required);
1188  __ IncrementCounter(counters->string_ctor_gc_required(), 1);
1189  {
1190    FrameScope scope(masm, StackFrame::INTERNAL);
1191    __ push(ebx);
1192    __ CallRuntime(Runtime::kNewStringWrapper, 1);
1193  }
1194  __ ret(0);
1195}
1196
1197
1198static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
1199  __ push(ebp);
1200  __ mov(ebp, esp);
1201
1202  // Store the arguments adaptor context sentinel.
1203  __ push(Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
1204
1205  // Push the function on the stack.
1206  __ push(edi);
1207
1208  // Preserve the number of arguments on the stack. Must preserve eax,
1209  // ebx and ecx because these registers are used when copying the
1210  // arguments and the receiver.
1211  STATIC_ASSERT(kSmiTagSize == 1);
1212  __ lea(edi, Operand(eax, eax, times_1, kSmiTag));
1213  __ push(edi);
1214}
1215
1216
1217static void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) {
1218  // Retrieve the number of arguments from the stack.
1219  __ mov(ebx, Operand(ebp, ArgumentsAdaptorFrameConstants::kLengthOffset));
1220
1221  // Leave the frame.
1222  __ leave();
1223
1224  // Remove caller arguments from the stack.
1225  STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
1226  __ pop(ecx);
1227  __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize));  // 1 ~ receiver
1228  __ push(ecx);
1229}
1230
1231
1232void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
1233  // ----------- S t a t e -------------
1234  //  -- eax : actual number of arguments
1235  //  -- ebx : expected number of arguments
1236  //  -- ecx : call kind information
1237  //  -- edx : code entry to call
1238  // -----------------------------------
1239
1240  Label invoke, dont_adapt_arguments;
1241  __ IncrementCounter(masm->isolate()->counters()->arguments_adaptors(), 1);
1242
1243  Label enough, too_few;
1244  __ cmp(eax, ebx);
1245  __ j(less, &too_few);
1246  __ cmp(ebx, SharedFunctionInfo::kDontAdaptArgumentsSentinel);
1247  __ j(equal, &dont_adapt_arguments);
1248
1249  {  // Enough parameters: Actual >= expected.
1250    __ bind(&enough);
1251    EnterArgumentsAdaptorFrame(masm);
1252
1253    // Copy receiver and all expected arguments.
1254    const int offset = StandardFrameConstants::kCallerSPOffset;
1255    __ lea(eax, Operand(ebp, eax, times_4, offset));
1256    __ mov(edi, -1);  // account for receiver
1257
1258    Label copy;
1259    __ bind(&copy);
1260    __ inc(edi);
1261    __ push(Operand(eax, 0));
1262    __ sub(eax, Immediate(kPointerSize));
1263    __ cmp(edi, ebx);
1264    __ j(less, &copy);
1265    __ jmp(&invoke);
1266  }
1267
1268  {  // Too few parameters: Actual < expected.
1269    __ bind(&too_few);
1270    EnterArgumentsAdaptorFrame(masm);
1271
1272    // Copy receiver and all actual arguments.
1273    const int offset = StandardFrameConstants::kCallerSPOffset;
1274    __ lea(edi, Operand(ebp, eax, times_4, offset));
1275    // ebx = expected - actual.
1276    __ sub(ebx, eax);
1277    // eax = -actual - 1
1278    __ neg(eax);
1279    __ sub(eax, Immediate(1));
1280
1281    Label copy;
1282    __ bind(&copy);
1283    __ inc(eax);
1284    __ push(Operand(edi, 0));
1285    __ sub(edi, Immediate(kPointerSize));
1286    __ test(eax, eax);
1287    __ j(not_zero, &copy);
1288
1289    // Fill remaining expected arguments with undefined values.
1290    Label fill;
1291    __ bind(&fill);
1292    __ inc(eax);
1293    __ push(Immediate(masm->isolate()->factory()->undefined_value()));
1294    __ cmp(eax, ebx);
1295    __ j(less, &fill);
1296  }
1297
1298  // Call the entry point.
1299  __ bind(&invoke);
1300  // Restore function pointer.
1301  __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1302  __ call(edx);
1303
1304  // Store offset of return address for deoptimizer.
1305  masm->isolate()->heap()->SetArgumentsAdaptorDeoptPCOffset(masm->pc_offset());
1306
1307  // Leave frame and return.
1308  LeaveArgumentsAdaptorFrame(masm);
1309  __ ret(0);
1310
1311  // -------------------------------------------
1312  // Dont adapt arguments.
1313  // -------------------------------------------
1314  __ bind(&dont_adapt_arguments);
1315  __ jmp(edx);
1316}
1317
1318
1319void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
1320  // Lookup the function in the JavaScript frame.
1321  __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1322  {
1323    FrameScope scope(masm, StackFrame::INTERNAL);
1324    // Lookup and calculate pc offset.
1325    __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerPCOffset));
1326    __ mov(ebx, FieldOperand(eax, JSFunction::kSharedFunctionInfoOffset));
1327    __ sub(edx, Immediate(Code::kHeaderSize - kHeapObjectTag));
1328    __ sub(edx, FieldOperand(ebx, SharedFunctionInfo::kCodeOffset));
1329    __ SmiTag(edx);
1330
1331    // Pass both function and pc offset as arguments.
1332    __ push(eax);
1333    __ push(edx);
1334    __ CallRuntime(Runtime::kCompileForOnStackReplacement, 2);
1335  }
1336
1337  Label skip;
1338  // If the code object is null, just return to the unoptimized code.
1339  __ cmp(eax, Immediate(0));
1340  __ j(not_equal, &skip, Label::kNear);
1341  __ ret(0);
1342
1343  __ bind(&skip);
1344
1345  // Load deoptimization data from the code object.
1346  __ mov(ebx, Operand(eax, Code::kDeoptimizationDataOffset - kHeapObjectTag));
1347
1348  // Load the OSR entrypoint offset from the deoptimization data.
1349  __ mov(ebx, Operand(ebx, FixedArray::OffsetOfElementAt(
1350      DeoptimizationInputData::kOsrPcOffsetIndex) - kHeapObjectTag));
1351  __ SmiUntag(ebx);
1352
1353  // Compute the target address = code_obj + header_size + osr_offset
1354  __ lea(eax, Operand(eax, ebx, times_1, Code::kHeaderSize - kHeapObjectTag));
1355
1356  // Overwrite the return address on the stack.
1357  __ mov(Operand(esp, 0), eax);
1358
1359  // And "return" to the OSR entry point of the function.
1360  __ ret(0);
1361}
1362
1363
1364void Builtins::Generate_OsrAfterStackCheck(MacroAssembler* masm) {
1365  // We check the stack limit as indicator that recompilation might be done.
1366  Label ok;
1367  ExternalReference stack_limit =
1368      ExternalReference::address_of_stack_limit(masm->isolate());
1369  __ cmp(esp, Operand::StaticVariable(stack_limit));
1370  __ j(above_equal, &ok, Label::kNear);
1371  {
1372    FrameScope scope(masm, StackFrame::INTERNAL);
1373    __ CallRuntime(Runtime::kStackGuard, 0);
1374  }
1375  __ jmp(masm->isolate()->builtins()->OnStackReplacement(),
1376         RelocInfo::CODE_TARGET);
1377
1378  __ bind(&ok);
1379  __ ret(0);
1380}
1381
1382#undef __
1383}
1384}  // namespace v8::internal
1385
1386#endif  // V8_TARGET_ARCH_IA32
1387