Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / v8 / src / x87 / builtins-x87.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_X87
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     DCHECK(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::kTryInstallOptimizedCode);
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   DCHECK(!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::kFinalizeInstanceSize, 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::kNewObjectWithAllocationSite, 2);
363     } else {
364       __ CallRuntime(Runtime::kNewObject, 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::kCompileUnoptimized);
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::kCompileOptimized, 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   // Enter an internal frame.
665   {
666     FrameScope scope(masm, StackFrame::INTERNAL);
667
668     // Preserve registers across notification, this is important for compiled
669     // stubs that tail call the runtime on deopts passing their parameters in
670     // registers.
671     __ pushad();
672     __ CallRuntime(Runtime::kNotifyStubFailure, 0);
673     __ popad();
674     // Tear down internal frame.
675   }
676
677   __ pop(MemOperand(esp, 0));  // Ignore state offset
678   __ ret(0);  // Return to IC Miss stub, continuation still on stack.
679 }
680
681
682 void Builtins::Generate_NotifyStubFailure(MacroAssembler* masm) {
683   Generate_NotifyStubFailureHelper(masm);
684 }
685
686
687 void Builtins::Generate_NotifyStubFailureSaveDoubles(MacroAssembler* masm) {
688   // SaveDoubles is meanless for X87, just used by deoptimizer.cc
689   Generate_NotifyStubFailureHelper(masm);
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::kNotifyDeoptimized, 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_proxy, 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_proxy);
791     __ cmp(ebx, factory->undefined_value());
792     __ j(equal, &use_global_proxy);
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_proxy);
818     __ mov(ebx,
819            Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
820     __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalProxyOffset));
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_proxy;
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_proxy);
975     __ cmp(ebx, factory->undefined_value());
976     __ j(equal, &use_global_proxy);
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_proxy);
988     __ mov(ebx,
989            Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
990     __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalProxyOffset));
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     Register receiver = LoadIC::ReceiverRegister();
999     Register key = LoadIC::NameRegister();
1000     __ mov(key, Operand(ebp, kIndexOffset));
1001     __ jmp(&entry);
1002     __ bind(&loop);
1003     __ mov(receiver, Operand(ebp, kArgumentsOffset));  // load arguments
1004
1005     // Use inline caching to speed up access to arguments.
1006     if (FLAG_vector_ics) {
1007       __ mov(LoadIC::SlotRegister(), Immediate(Smi::FromInt(0)));
1008     }
1009     Handle<Code> ic = masm->isolate()->builtins()->KeyedLoadIC_Initialize();
1010     __ call(ic, RelocInfo::CODE_TARGET);
1011     // It is important that we do not have a test instruction after the
1012     // call.  A test instruction after the call is used to indicate that
1013     // we have generated an inline version of the keyed load.  In this
1014     // case, we know that we are not generating a test instruction next.
1015
1016     // Push the nth argument.
1017     __ push(eax);
1018
1019     // Update the index on the stack and in register key.
1020     __ mov(key, Operand(ebp, kIndexOffset));
1021     __ add(key, Immediate(1 << kSmiTagSize));
1022     __ mov(Operand(ebp, kIndexOffset), key);
1023
1024     __ bind(&entry);
1025     __ cmp(key, Operand(ebp, kLimitOffset));
1026     __ j(not_equal, &loop);
1027
1028     // Call the function.
1029     Label call_proxy;
1030     ParameterCount actual(eax);
1031     __ Move(eax, key);
1032     __ SmiUntag(eax);
1033     __ mov(edi, Operand(ebp, kFunctionOffset));
1034     __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
1035     __ j(not_equal, &call_proxy);
1036     __ InvokeFunction(edi, actual, CALL_FUNCTION, NullCallWrapper());
1037
1038     frame_scope.GenerateLeaveFrame();
1039     __ ret(3 * kPointerSize);  // remove this, receiver, and arguments
1040
1041     // Call the function proxy.
1042     __ bind(&call_proxy);
1043     __ push(edi);  // add function proxy as last argument
1044     __ inc(eax);
1045     __ Move(ebx, Immediate(0));
1046     __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY);
1047     __ call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1048             RelocInfo::CODE_TARGET);
1049
1050     // Leave internal frame.
1051   }
1052   __ ret(3 * kPointerSize);  // remove this, receiver, and arguments
1053 }
1054
1055
1056 void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) {
1057   // ----------- S t a t e -------------
1058   //  -- eax : argc
1059   //  -- esp[0] : return address
1060   //  -- esp[4] : last argument
1061   // -----------------------------------
1062   Label generic_array_code;
1063
1064   // Get the InternalArray function.
1065   __ LoadGlobalFunction(Context::INTERNAL_ARRAY_FUNCTION_INDEX, edi);
1066
1067   if (FLAG_debug_code) {
1068     // Initial map for the builtin InternalArray function should be a map.
1069     __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset));
1070     // Will both indicate a NULL and a Smi.
1071     __ test(ebx, Immediate(kSmiTagMask));
1072     __ Assert(not_zero, kUnexpectedInitialMapForInternalArrayFunction);
1073     __ CmpObjectType(ebx, MAP_TYPE, ecx);
1074     __ Assert(equal, kUnexpectedInitialMapForInternalArrayFunction);
1075   }
1076
1077   // Run the native code for the InternalArray function called as a normal
1078   // function.
1079   // tail call a stub
1080   InternalArrayConstructorStub stub(masm->isolate());
1081   __ TailCallStub(&stub);
1082 }
1083
1084
1085 void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
1086   // ----------- S t a t e -------------
1087   //  -- eax : argc
1088   //  -- esp[0] : return address
1089   //  -- esp[4] : last argument
1090   // -----------------------------------
1091   Label generic_array_code;
1092
1093   // Get the Array function.
1094   __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, edi);
1095
1096   if (FLAG_debug_code) {
1097     // Initial map for the builtin Array function should be a map.
1098     __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset));
1099     // Will both indicate a NULL and a Smi.
1100     __ test(ebx, Immediate(kSmiTagMask));
1101     __ Assert(not_zero, kUnexpectedInitialMapForArrayFunction);
1102     __ CmpObjectType(ebx, MAP_TYPE, ecx);
1103     __ Assert(equal, kUnexpectedInitialMapForArrayFunction);
1104   }
1105
1106   // Run the native code for the Array function called as a normal function.
1107   // tail call a stub
1108   __ mov(ebx, masm->isolate()->factory()->undefined_value());
1109   ArrayConstructorStub stub(masm->isolate());
1110   __ TailCallStub(&stub);
1111 }
1112
1113
1114 void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
1115   // ----------- S t a t e -------------
1116   //  -- eax                 : number of arguments
1117   //  -- edi                 : constructor function
1118   //  -- esp[0]              : return address
1119   //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
1120   //  -- esp[(argc + 1) * 4] : receiver
1121   // -----------------------------------
1122   Counters* counters = masm->isolate()->counters();
1123   __ IncrementCounter(counters->string_ctor_calls(), 1);
1124
1125   if (FLAG_debug_code) {
1126     __ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, ecx);
1127     __ cmp(edi, ecx);
1128     __ Assert(equal, kUnexpectedStringFunction);
1129   }
1130
1131   // Load the first argument into eax and get rid of the rest
1132   // (including the receiver).
1133   Label no_arguments;
1134   __ test(eax, eax);
1135   __ j(zero, &no_arguments);
1136   __ mov(ebx, Operand(esp, eax, times_pointer_size, 0));
1137   __ pop(ecx);
1138   __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize));
1139   __ push(ecx);
1140   __ mov(eax, ebx);
1141
1142   // Lookup the argument in the number to string cache.
1143   Label not_cached, argument_is_string;
1144   __ LookupNumberStringCache(eax,  // Input.
1145                              ebx,  // Result.
1146                              ecx,  // Scratch 1.
1147                              edx,  // Scratch 2.
1148                              &not_cached);
1149   __ IncrementCounter(counters->string_ctor_cached_number(), 1);
1150   __ bind(&argument_is_string);
1151   // ----------- S t a t e -------------
1152   //  -- ebx    : argument converted to string
1153   //  -- edi    : constructor function
1154   //  -- esp[0] : return address
1155   // -----------------------------------
1156
1157   // Allocate a JSValue and put the tagged pointer into eax.
1158   Label gc_required;
1159   __ Allocate(JSValue::kSize,
1160               eax,  // Result.
1161               ecx,  // New allocation top (we ignore it).
1162               no_reg,
1163               &gc_required,
1164               TAG_OBJECT);
1165
1166   // Set the map.
1167   __ LoadGlobalFunctionInitialMap(edi, ecx);
1168   if (FLAG_debug_code) {
1169     __ cmpb(FieldOperand(ecx, Map::kInstanceSizeOffset),
1170             JSValue::kSize >> kPointerSizeLog2);
1171     __ Assert(equal, kUnexpectedStringWrapperInstanceSize);
1172     __ cmpb(FieldOperand(ecx, Map::kUnusedPropertyFieldsOffset), 0);
1173     __ Assert(equal, kUnexpectedUnusedPropertiesOfStringWrapper);
1174   }
1175   __ mov(FieldOperand(eax, HeapObject::kMapOffset), ecx);
1176
1177   // Set properties and elements.
1178   Factory* factory = masm->isolate()->factory();
1179   __ Move(ecx, Immediate(factory->empty_fixed_array()));
1180   __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), ecx);
1181   __ mov(FieldOperand(eax, JSObject::kElementsOffset), ecx);
1182
1183   // Set the value.
1184   __ mov(FieldOperand(eax, JSValue::kValueOffset), ebx);
1185
1186   // Ensure the object is fully initialized.
1187   STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
1188
1189   // We're done. Return.
1190   __ ret(0);
1191
1192   // The argument was not found in the number to string cache. Check
1193   // if it's a string already before calling the conversion builtin.
1194   Label convert_argument;
1195   __ bind(&not_cached);
1196   STATIC_ASSERT(kSmiTag == 0);
1197   __ JumpIfSmi(eax, &convert_argument);
1198   Condition is_string = masm->IsObjectStringType(eax, ebx, ecx);
1199   __ j(NegateCondition(is_string), &convert_argument);
1200   __ mov(ebx, eax);
1201   __ IncrementCounter(counters->string_ctor_string_value(), 1);
1202   __ jmp(&argument_is_string);
1203
1204   // Invoke the conversion builtin and put the result into ebx.
1205   __ bind(&convert_argument);
1206   __ IncrementCounter(counters->string_ctor_conversions(), 1);
1207   {
1208     FrameScope scope(masm, StackFrame::INTERNAL);
1209     __ push(edi);  // Preserve the function.
1210     __ push(eax);
1211     __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION);
1212     __ pop(edi);
1213   }
1214   __ mov(ebx, eax);
1215   __ jmp(&argument_is_string);
1216
1217   // Load the empty string into ebx, remove the receiver from the
1218   // stack, and jump back to the case where the argument is a string.
1219   __ bind(&no_arguments);
1220   __ Move(ebx, Immediate(factory->empty_string()));
1221   __ pop(ecx);
1222   __ lea(esp, Operand(esp, kPointerSize));
1223   __ push(ecx);
1224   __ jmp(&argument_is_string);
1225
1226   // At this point the argument is already a string. Call runtime to
1227   // create a string wrapper.
1228   __ bind(&gc_required);
1229   __ IncrementCounter(counters->string_ctor_gc_required(), 1);
1230   {
1231     FrameScope scope(masm, StackFrame::INTERNAL);
1232     __ push(ebx);
1233     __ CallRuntime(Runtime::kNewStringWrapper, 1);
1234   }
1235   __ ret(0);
1236 }
1237
1238
1239 static void ArgumentsAdaptorStackCheck(MacroAssembler* masm,
1240                                        Label* stack_overflow) {
1241   // ----------- S t a t e -------------
1242   //  -- eax : actual number of arguments
1243   //  -- ebx : expected number of arguments
1244   //  -- edi : function (passed through to callee)
1245   // -----------------------------------
1246   // Check the stack for overflow. We are not trying to catch
1247   // interruptions (e.g. debug break and preemption) here, so the "real stack
1248   // limit" is checked.
1249   ExternalReference real_stack_limit =
1250       ExternalReference::address_of_real_stack_limit(masm->isolate());
1251   __ mov(edx, Operand::StaticVariable(real_stack_limit));
1252   // Make ecx the space we have left. The stack might already be overflowed
1253   // here which will cause ecx to become negative.
1254   __ mov(ecx, esp);
1255   __ sub(ecx, edx);
1256   // Make edx the space we need for the array when it is unrolled onto the
1257   // stack.
1258   __ mov(edx, ebx);
1259   __ shl(edx, kPointerSizeLog2);
1260   // Check if the arguments will overflow the stack.
1261   __ cmp(ecx, edx);
1262   __ j(less_equal, stack_overflow);  // Signed comparison.
1263 }
1264
1265
1266 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
1267   __ push(ebp);
1268   __ mov(ebp, esp);
1269
1270   // Store the arguments adaptor context sentinel.
1271   __ push(Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
1272
1273   // Push the function on the stack.
1274   __ push(edi);
1275
1276   // Preserve the number of arguments on the stack. Must preserve eax,
1277   // ebx and ecx because these registers are used when copying the
1278   // arguments and the receiver.
1279   STATIC_ASSERT(kSmiTagSize == 1);
1280   __ lea(edi, Operand(eax, eax, times_1, kSmiTag));
1281   __ push(edi);
1282 }
1283
1284
1285 static void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) {
1286   // Retrieve the number of arguments from the stack.
1287   __ mov(ebx, Operand(ebp, ArgumentsAdaptorFrameConstants::kLengthOffset));
1288
1289   // Leave the frame.
1290   __ leave();
1291
1292   // Remove caller arguments from the stack.
1293   STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
1294   __ pop(ecx);
1295   __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize));  // 1 ~ receiver
1296   __ push(ecx);
1297 }
1298
1299
1300 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
1301   // ----------- S t a t e -------------
1302   //  -- eax : actual number of arguments
1303   //  -- ebx : expected number of arguments
1304   //  -- edi : function (passed through to callee)
1305   // -----------------------------------
1306
1307   Label invoke, dont_adapt_arguments;
1308   __ IncrementCounter(masm->isolate()->counters()->arguments_adaptors(), 1);
1309
1310   Label stack_overflow;
1311   ArgumentsAdaptorStackCheck(masm, &stack_overflow);
1312
1313   Label enough, too_few;
1314   __ mov(edx, FieldOperand(edi, JSFunction::kCodeEntryOffset));
1315   __ cmp(eax, ebx);
1316   __ j(less, &too_few);
1317   __ cmp(ebx, SharedFunctionInfo::kDontAdaptArgumentsSentinel);
1318   __ j(equal, &dont_adapt_arguments);
1319
1320   {  // Enough parameters: Actual >= expected.
1321     __ bind(&enough);
1322     EnterArgumentsAdaptorFrame(masm);
1323
1324     // Copy receiver and all expected arguments.
1325     const int offset = StandardFrameConstants::kCallerSPOffset;
1326     __ lea(eax, Operand(ebp, eax, times_4, offset));
1327     __ mov(edi, -1);  // account for receiver
1328
1329     Label copy;
1330     __ bind(&copy);
1331     __ inc(edi);
1332     __ push(Operand(eax, 0));
1333     __ sub(eax, Immediate(kPointerSize));
1334     __ cmp(edi, ebx);
1335     __ j(less, &copy);
1336     __ jmp(&invoke);
1337   }
1338
1339   {  // Too few parameters: Actual < expected.
1340     __ bind(&too_few);
1341     EnterArgumentsAdaptorFrame(masm);
1342
1343     // Copy receiver and all actual arguments.
1344     const int offset = StandardFrameConstants::kCallerSPOffset;
1345     __ lea(edi, Operand(ebp, eax, times_4, offset));
1346     // ebx = expected - actual.
1347     __ sub(ebx, eax);
1348     // eax = -actual - 1
1349     __ neg(eax);
1350     __ sub(eax, Immediate(1));
1351
1352     Label copy;
1353     __ bind(&copy);
1354     __ inc(eax);
1355     __ push(Operand(edi, 0));
1356     __ sub(edi, Immediate(kPointerSize));
1357     __ test(eax, eax);
1358     __ j(not_zero, &copy);
1359
1360     // Fill remaining expected arguments with undefined values.
1361     Label fill;
1362     __ bind(&fill);
1363     __ inc(eax);
1364     __ push(Immediate(masm->isolate()->factory()->undefined_value()));
1365     __ cmp(eax, ebx);
1366     __ j(less, &fill);
1367   }
1368
1369   // Call the entry point.
1370   __ bind(&invoke);
1371   // Restore function pointer.
1372   __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1373   __ call(edx);
1374
1375   // Store offset of return address for deoptimizer.
1376   masm->isolate()->heap()->SetArgumentsAdaptorDeoptPCOffset(masm->pc_offset());
1377
1378   // Leave frame and return.
1379   LeaveArgumentsAdaptorFrame(masm);
1380   __ ret(0);
1381
1382   // -------------------------------------------
1383   // Dont adapt arguments.
1384   // -------------------------------------------
1385   __ bind(&dont_adapt_arguments);
1386   __ jmp(edx);
1387
1388   __ bind(&stack_overflow);
1389   {
1390     FrameScope frame(masm, StackFrame::MANUAL);
1391     EnterArgumentsAdaptorFrame(masm);
1392     __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
1393     __ int3();
1394   }
1395 }
1396
1397
1398 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
1399   // Lookup the function in the JavaScript frame.
1400   __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1401   {
1402     FrameScope scope(masm, StackFrame::INTERNAL);
1403     // Pass function as argument.
1404     __ push(eax);
1405     __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1);
1406   }
1407
1408   Label skip;
1409   // If the code object is null, just return to the unoptimized code.
1410   __ cmp(eax, Immediate(0));
1411   __ j(not_equal, &skip, Label::kNear);
1412   __ ret(0);
1413
1414   __ bind(&skip);
1415
1416   // Load deoptimization data from the code object.
1417   __ mov(ebx, Operand(eax, Code::kDeoptimizationDataOffset - kHeapObjectTag));
1418
1419   // Load the OSR entrypoint offset from the deoptimization data.
1420   __ mov(ebx, Operand(ebx, FixedArray::OffsetOfElementAt(
1421       DeoptimizationInputData::kOsrPcOffsetIndex) - kHeapObjectTag));
1422   __ SmiUntag(ebx);
1423
1424   // Compute the target address = code_obj + header_size + osr_offset
1425   __ lea(eax, Operand(eax, ebx, times_1, Code::kHeaderSize - kHeapObjectTag));
1426
1427   // Overwrite the return address on the stack.
1428   __ mov(Operand(esp, 0), eax);
1429
1430   // And "return" to the OSR entry point of the function.
1431   __ ret(0);
1432 }
1433
1434
1435 void Builtins::Generate_OsrAfterStackCheck(MacroAssembler* masm) {
1436   // We check the stack limit as indicator that recompilation might be done.
1437   Label ok;
1438   ExternalReference stack_limit =
1439       ExternalReference::address_of_stack_limit(masm->isolate());
1440   __ cmp(esp, Operand::StaticVariable(stack_limit));
1441   __ j(above_equal, &ok, Label::kNear);
1442   {
1443     FrameScope scope(masm, StackFrame::INTERNAL);
1444     __ CallRuntime(Runtime::kStackGuard, 0);
1445   }
1446   __ jmp(masm->isolate()->builtins()->OnStackReplacement(),
1447          RelocInfo::CODE_TARGET);
1448
1449   __ bind(&ok);
1450   __ ret(0);
1451 }
1452
1453 #undef __
1454 }
1455 }  // namespace v8::internal
1456
1457 #endif  // V8_TARGET_ARCH_X87