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