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/code-factory.h"
10#include "src/codegen.h"
11#include "src/deoptimizer.h"
12#include "src/full-codegen.h"
13
14namespace v8 {
15namespace internal {
16
17
18#define __ ACCESS_MASM(masm)
19
20
21void 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
55static 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
69static 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
77static void GenerateTailCallToReturnedCode(MacroAssembler* masm) {
78  __ lea(eax, FieldOperand(eax, Code::kHeaderSize));
79  __ jmp(eax);
80}
81
82
83void 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
103static 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
472void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
473  Generate_JSConstructStubHelper(masm, false, FLAG_pretenuring_call_new);
474}
475
476
477void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
478  Generate_JSConstructStubHelper(masm, true, false);
479}
480
481
482static 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
543void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) {
544  Generate_JSEntryTrampolineHelper(masm, false);
545}
546
547
548void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
549  Generate_JSEntryTrampolineHelper(masm, true);
550}
551
552
553void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
554  CallRuntimePassFunction(masm, Runtime::kCompileLazy);
555  GenerateTailCallToReturnedCode(masm);
556}
557
558
559
560static 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
575void Builtins::Generate_CompileOptimized(MacroAssembler* masm) {
576  CallCompileOptimized(masm, false);
577  GenerateTailCallToReturnedCode(masm);
578}
579
580
581void Builtins::Generate_CompileOptimizedConcurrent(MacroAssembler* masm) {
582  CallCompileOptimized(masm, true);
583  GenerateTailCallToReturnedCode(masm);
584}
585
586
587static 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)                 \
613void Builtins::Generate_Make##C##CodeYoungAgainEvenMarking(  \
614    MacroAssembler* masm) {                                  \
615  GenerateMakeCodeYoungAgainCommon(masm);                    \
616}                                                            \
617void Builtins::Generate_Make##C##CodeYoungAgainOddMarking(   \
618    MacroAssembler* masm) {                                  \
619  GenerateMakeCodeYoungAgainCommon(masm);                    \
620}
621CODE_AGE_LIST(DEFINE_CODE_AGE_BUILTIN_GENERATOR)
622#undef DEFINE_CODE_AGE_BUILTIN_GENERATOR
623
624
625void 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
658void Builtins::Generate_MarkCodeAsExecutedTwice(MacroAssembler* masm) {
659  GenerateMakeCodeYoungAgainCommon(masm);
660}
661
662
663static 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::kNotifyStubFailure, 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
683void Builtins::Generate_NotifyStubFailure(MacroAssembler* masm) {
684  Generate_NotifyStubFailureHelper(masm, kDontSaveFPRegs);
685}
686
687
688void Builtins::Generate_NotifyStubFailureSaveDoubles(MacroAssembler* masm) {
689  Generate_NotifyStubFailureHelper(masm, kSaveFPRegs);
690}
691
692
693static 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
726void Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) {
727  Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::EAGER);
728}
729
730
731void Builtins::Generate_NotifySoftDeoptimized(MacroAssembler* masm) {
732  Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::SOFT);
733}
734
735
736void Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) {
737  Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
738}
739
740
741void 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
898void 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 = LoadDescriptor::ReceiverRegister();
999    Register key = LoadDescriptor::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(VectorLoadICDescriptor::SlotRegister(),
1008             Immediate(Smi::FromInt(0)));
1009    }
1010    Handle<Code> ic = CodeFactory::KeyedLoadIC(masm->isolate()).code();
1011    __ call(ic, RelocInfo::CODE_TARGET);
1012    // It is important that we do not have a test instruction after the
1013    // call.  A test instruction after the call is used to indicate that
1014    // we have generated an inline version of the keyed load.  In this
1015    // case, we know that we are not generating a test instruction next.
1016
1017    // Push the nth argument.
1018    __ push(eax);
1019
1020    // Update the index on the stack and in register key.
1021    __ mov(key, Operand(ebp, kIndexOffset));
1022    __ add(key, Immediate(1 << kSmiTagSize));
1023    __ mov(Operand(ebp, kIndexOffset), key);
1024
1025    __ bind(&entry);
1026    __ cmp(key, Operand(ebp, kLimitOffset));
1027    __ j(not_equal, &loop);
1028
1029    // Call the function.
1030    Label call_proxy;
1031    ParameterCount actual(eax);
1032    __ Move(eax, key);
1033    __ SmiUntag(eax);
1034    __ mov(edi, Operand(ebp, kFunctionOffset));
1035    __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
1036    __ j(not_equal, &call_proxy);
1037    __ InvokeFunction(edi, actual, CALL_FUNCTION, NullCallWrapper());
1038
1039    frame_scope.GenerateLeaveFrame();
1040    __ ret(3 * kPointerSize);  // remove this, receiver, and arguments
1041
1042    // Call the function proxy.
1043    __ bind(&call_proxy);
1044    __ push(edi);  // add function proxy as last argument
1045    __ inc(eax);
1046    __ Move(ebx, Immediate(0));
1047    __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY);
1048    __ call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1049            RelocInfo::CODE_TARGET);
1050
1051    // Leave internal frame.
1052  }
1053  __ ret(3 * kPointerSize);  // remove this, receiver, and arguments
1054}
1055
1056
1057void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) {
1058  // ----------- S t a t e -------------
1059  //  -- eax : argc
1060  //  -- esp[0] : return address
1061  //  -- esp[4] : last argument
1062  // -----------------------------------
1063  Label generic_array_code;
1064
1065  // Get the InternalArray function.
1066  __ LoadGlobalFunction(Context::INTERNAL_ARRAY_FUNCTION_INDEX, edi);
1067
1068  if (FLAG_debug_code) {
1069    // Initial map for the builtin InternalArray function should be a map.
1070    __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset));
1071    // Will both indicate a NULL and a Smi.
1072    __ test(ebx, Immediate(kSmiTagMask));
1073    __ Assert(not_zero, kUnexpectedInitialMapForInternalArrayFunction);
1074    __ CmpObjectType(ebx, MAP_TYPE, ecx);
1075    __ Assert(equal, kUnexpectedInitialMapForInternalArrayFunction);
1076  }
1077
1078  // Run the native code for the InternalArray function called as a normal
1079  // function.
1080  // tail call a stub
1081  InternalArrayConstructorStub stub(masm->isolate());
1082  __ TailCallStub(&stub);
1083}
1084
1085
1086void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
1087  // ----------- S t a t e -------------
1088  //  -- eax : argc
1089  //  -- esp[0] : return address
1090  //  -- esp[4] : last argument
1091  // -----------------------------------
1092  Label generic_array_code;
1093
1094  // Get the Array function.
1095  __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, edi);
1096
1097  if (FLAG_debug_code) {
1098    // Initial map for the builtin Array function should be a map.
1099    __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset));
1100    // Will both indicate a NULL and a Smi.
1101    __ test(ebx, Immediate(kSmiTagMask));
1102    __ Assert(not_zero, kUnexpectedInitialMapForArrayFunction);
1103    __ CmpObjectType(ebx, MAP_TYPE, ecx);
1104    __ Assert(equal, kUnexpectedInitialMapForArrayFunction);
1105  }
1106
1107  // Run the native code for the Array function called as a normal function.
1108  // tail call a stub
1109  __ mov(ebx, masm->isolate()->factory()->undefined_value());
1110  ArrayConstructorStub stub(masm->isolate());
1111  __ TailCallStub(&stub);
1112}
1113
1114
1115void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
1116  // ----------- S t a t e -------------
1117  //  -- eax                 : number of arguments
1118  //  -- edi                 : constructor function
1119  //  -- esp[0]              : return address
1120  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
1121  //  -- esp[(argc + 1) * 4] : receiver
1122  // -----------------------------------
1123  Counters* counters = masm->isolate()->counters();
1124  __ IncrementCounter(counters->string_ctor_calls(), 1);
1125
1126  if (FLAG_debug_code) {
1127    __ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, ecx);
1128    __ cmp(edi, ecx);
1129    __ Assert(equal, kUnexpectedStringFunction);
1130  }
1131
1132  // Load the first argument into eax and get rid of the rest
1133  // (including the receiver).
1134  Label no_arguments;
1135  __ test(eax, eax);
1136  __ j(zero, &no_arguments);
1137  __ mov(ebx, Operand(esp, eax, times_pointer_size, 0));
1138  __ pop(ecx);
1139  __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize));
1140  __ push(ecx);
1141  __ mov(eax, ebx);
1142
1143  // Lookup the argument in the number to string cache.
1144  Label not_cached, argument_is_string;
1145  __ LookupNumberStringCache(eax,  // Input.
1146                             ebx,  // Result.
1147                             ecx,  // Scratch 1.
1148                             edx,  // Scratch 2.
1149                             &not_cached);
1150  __ IncrementCounter(counters->string_ctor_cached_number(), 1);
1151  __ bind(&argument_is_string);
1152  // ----------- S t a t e -------------
1153  //  -- ebx    : argument converted to string
1154  //  -- edi    : constructor function
1155  //  -- esp[0] : return address
1156  // -----------------------------------
1157
1158  // Allocate a JSValue and put the tagged pointer into eax.
1159  Label gc_required;
1160  __ Allocate(JSValue::kSize,
1161              eax,  // Result.
1162              ecx,  // New allocation top (we ignore it).
1163              no_reg,
1164              &gc_required,
1165              TAG_OBJECT);
1166
1167  // Set the map.
1168  __ LoadGlobalFunctionInitialMap(edi, ecx);
1169  if (FLAG_debug_code) {
1170    __ cmpb(FieldOperand(ecx, Map::kInstanceSizeOffset),
1171            JSValue::kSize >> kPointerSizeLog2);
1172    __ Assert(equal, kUnexpectedStringWrapperInstanceSize);
1173    __ cmpb(FieldOperand(ecx, Map::kUnusedPropertyFieldsOffset), 0);
1174    __ Assert(equal, kUnexpectedUnusedPropertiesOfStringWrapper);
1175  }
1176  __ mov(FieldOperand(eax, HeapObject::kMapOffset), ecx);
1177
1178  // Set properties and elements.
1179  Factory* factory = masm->isolate()->factory();
1180  __ Move(ecx, Immediate(factory->empty_fixed_array()));
1181  __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), ecx);
1182  __ mov(FieldOperand(eax, JSObject::kElementsOffset), ecx);
1183
1184  // Set the value.
1185  __ mov(FieldOperand(eax, JSValue::kValueOffset), ebx);
1186
1187  // Ensure the object is fully initialized.
1188  STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
1189
1190  // We're done. Return.
1191  __ ret(0);
1192
1193  // The argument was not found in the number to string cache. Check
1194  // if it's a string already before calling the conversion builtin.
1195  Label convert_argument;
1196  __ bind(&not_cached);
1197  STATIC_ASSERT(kSmiTag == 0);
1198  __ JumpIfSmi(eax, &convert_argument);
1199  Condition is_string = masm->IsObjectStringType(eax, ebx, ecx);
1200  __ j(NegateCondition(is_string), &convert_argument);
1201  __ mov(ebx, eax);
1202  __ IncrementCounter(counters->string_ctor_string_value(), 1);
1203  __ jmp(&argument_is_string);
1204
1205  // Invoke the conversion builtin and put the result into ebx.
1206  __ bind(&convert_argument);
1207  __ IncrementCounter(counters->string_ctor_conversions(), 1);
1208  {
1209    FrameScope scope(masm, StackFrame::INTERNAL);
1210    __ push(edi);  // Preserve the function.
1211    __ push(eax);
1212    __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION);
1213    __ pop(edi);
1214  }
1215  __ mov(ebx, eax);
1216  __ jmp(&argument_is_string);
1217
1218  // Load the empty string into ebx, remove the receiver from the
1219  // stack, and jump back to the case where the argument is a string.
1220  __ bind(&no_arguments);
1221  __ Move(ebx, Immediate(factory->empty_string()));
1222  __ pop(ecx);
1223  __ lea(esp, Operand(esp, kPointerSize));
1224  __ push(ecx);
1225  __ jmp(&argument_is_string);
1226
1227  // At this point the argument is already a string. Call runtime to
1228  // create a string wrapper.
1229  __ bind(&gc_required);
1230  __ IncrementCounter(counters->string_ctor_gc_required(), 1);
1231  {
1232    FrameScope scope(masm, StackFrame::INTERNAL);
1233    __ push(ebx);
1234    __ CallRuntime(Runtime::kNewStringWrapper, 1);
1235  }
1236  __ ret(0);
1237}
1238
1239
1240static void ArgumentsAdaptorStackCheck(MacroAssembler* masm,
1241                                       Label* stack_overflow) {
1242  // ----------- S t a t e -------------
1243  //  -- eax : actual number of arguments
1244  //  -- ebx : expected number of arguments
1245  //  -- edi : function (passed through to callee)
1246  // -----------------------------------
1247  // Check the stack for overflow. We are not trying to catch
1248  // interruptions (e.g. debug break and preemption) here, so the "real stack
1249  // limit" is checked.
1250  ExternalReference real_stack_limit =
1251      ExternalReference::address_of_real_stack_limit(masm->isolate());
1252  __ mov(edx, Operand::StaticVariable(real_stack_limit));
1253  // Make ecx the space we have left. The stack might already be overflowed
1254  // here which will cause ecx to become negative.
1255  __ mov(ecx, esp);
1256  __ sub(ecx, edx);
1257  // Make edx the space we need for the array when it is unrolled onto the
1258  // stack.
1259  __ mov(edx, ebx);
1260  __ shl(edx, kPointerSizeLog2);
1261  // Check if the arguments will overflow the stack.
1262  __ cmp(ecx, edx);
1263  __ j(less_equal, stack_overflow);  // Signed comparison.
1264}
1265
1266
1267static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
1268  __ push(ebp);
1269  __ mov(ebp, esp);
1270
1271  // Store the arguments adaptor context sentinel.
1272  __ push(Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
1273
1274  // Push the function on the stack.
1275  __ push(edi);
1276
1277  // Preserve the number of arguments on the stack. Must preserve eax,
1278  // ebx and ecx because these registers are used when copying the
1279  // arguments and the receiver.
1280  STATIC_ASSERT(kSmiTagSize == 1);
1281  __ lea(edi, Operand(eax, eax, times_1, kSmiTag));
1282  __ push(edi);
1283}
1284
1285
1286static void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) {
1287  // Retrieve the number of arguments from the stack.
1288  __ mov(ebx, Operand(ebp, ArgumentsAdaptorFrameConstants::kLengthOffset));
1289
1290  // Leave the frame.
1291  __ leave();
1292
1293  // Remove caller arguments from the stack.
1294  STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
1295  __ pop(ecx);
1296  __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize));  // 1 ~ receiver
1297  __ push(ecx);
1298}
1299
1300
1301void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
1302  // ----------- S t a t e -------------
1303  //  -- eax : actual number of arguments
1304  //  -- ebx : expected number of arguments
1305  //  -- edi : function (passed through to callee)
1306  // -----------------------------------
1307
1308  Label invoke, dont_adapt_arguments;
1309  __ IncrementCounter(masm->isolate()->counters()->arguments_adaptors(), 1);
1310
1311  Label stack_overflow;
1312  ArgumentsAdaptorStackCheck(masm, &stack_overflow);
1313
1314  Label enough, too_few;
1315  __ mov(edx, FieldOperand(edi, JSFunction::kCodeEntryOffset));
1316  __ cmp(eax, ebx);
1317  __ j(less, &too_few);
1318  __ cmp(ebx, SharedFunctionInfo::kDontAdaptArgumentsSentinel);
1319  __ j(equal, &dont_adapt_arguments);
1320
1321  {  // Enough parameters: Actual >= expected.
1322    __ bind(&enough);
1323    EnterArgumentsAdaptorFrame(masm);
1324
1325    // Copy receiver and all expected arguments.
1326    const int offset = StandardFrameConstants::kCallerSPOffset;
1327    __ lea(eax, Operand(ebp, eax, times_4, offset));
1328    __ mov(edi, -1);  // account for receiver
1329
1330    Label copy;
1331    __ bind(&copy);
1332    __ inc(edi);
1333    __ push(Operand(eax, 0));
1334    __ sub(eax, Immediate(kPointerSize));
1335    __ cmp(edi, ebx);
1336    __ j(less, &copy);
1337    __ jmp(&invoke);
1338  }
1339
1340  {  // Too few parameters: Actual < expected.
1341    __ bind(&too_few);
1342    EnterArgumentsAdaptorFrame(masm);
1343
1344    // Copy receiver and all actual arguments.
1345    const int offset = StandardFrameConstants::kCallerSPOffset;
1346    __ lea(edi, Operand(ebp, eax, times_4, offset));
1347    // ebx = expected - actual.
1348    __ sub(ebx, eax);
1349    // eax = -actual - 1
1350    __ neg(eax);
1351    __ sub(eax, Immediate(1));
1352
1353    Label copy;
1354    __ bind(&copy);
1355    __ inc(eax);
1356    __ push(Operand(edi, 0));
1357    __ sub(edi, Immediate(kPointerSize));
1358    __ test(eax, eax);
1359    __ j(not_zero, &copy);
1360
1361    // Fill remaining expected arguments with undefined values.
1362    Label fill;
1363    __ bind(&fill);
1364    __ inc(eax);
1365    __ push(Immediate(masm->isolate()->factory()->undefined_value()));
1366    __ cmp(eax, ebx);
1367    __ j(less, &fill);
1368  }
1369
1370  // Call the entry point.
1371  __ bind(&invoke);
1372  // Restore function pointer.
1373  __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1374  __ call(edx);
1375
1376  // Store offset of return address for deoptimizer.
1377  masm->isolate()->heap()->SetArgumentsAdaptorDeoptPCOffset(masm->pc_offset());
1378
1379  // Leave frame and return.
1380  LeaveArgumentsAdaptorFrame(masm);
1381  __ ret(0);
1382
1383  // -------------------------------------------
1384  // Dont adapt arguments.
1385  // -------------------------------------------
1386  __ bind(&dont_adapt_arguments);
1387  __ jmp(edx);
1388
1389  __ bind(&stack_overflow);
1390  {
1391    FrameScope frame(masm, StackFrame::MANUAL);
1392    EnterArgumentsAdaptorFrame(masm);
1393    __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
1394    __ int3();
1395  }
1396}
1397
1398
1399void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
1400  // Lookup the function in the JavaScript frame.
1401  __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1402  {
1403    FrameScope scope(masm, StackFrame::INTERNAL);
1404    // Pass function as argument.
1405    __ push(eax);
1406    __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1);
1407  }
1408
1409  Label skip;
1410  // If the code object is null, just return to the unoptimized code.
1411  __ cmp(eax, Immediate(0));
1412  __ j(not_equal, &skip, Label::kNear);
1413  __ ret(0);
1414
1415  __ bind(&skip);
1416
1417  // Load deoptimization data from the code object.
1418  __ mov(ebx, Operand(eax, Code::kDeoptimizationDataOffset - kHeapObjectTag));
1419
1420  // Load the OSR entrypoint offset from the deoptimization data.
1421  __ mov(ebx, Operand(ebx, FixedArray::OffsetOfElementAt(
1422      DeoptimizationInputData::kOsrPcOffsetIndex) - kHeapObjectTag));
1423  __ SmiUntag(ebx);
1424
1425  // Compute the target address = code_obj + header_size + osr_offset
1426  __ lea(eax, Operand(eax, ebx, times_1, Code::kHeaderSize - kHeapObjectTag));
1427
1428  // Overwrite the return address on the stack.
1429  __ mov(Operand(esp, 0), eax);
1430
1431  // And "return" to the OSR entry point of the function.
1432  __ ret(0);
1433}
1434
1435
1436void Builtins::Generate_OsrAfterStackCheck(MacroAssembler* masm) {
1437  // We check the stack limit as indicator that recompilation might be done.
1438  Label ok;
1439  ExternalReference stack_limit =
1440      ExternalReference::address_of_stack_limit(masm->isolate());
1441  __ cmp(esp, Operand::StaticVariable(stack_limit));
1442  __ j(above_equal, &ok, Label::kNear);
1443  {
1444    FrameScope scope(masm, StackFrame::INTERNAL);
1445    __ CallRuntime(Runtime::kStackGuard, 0);
1446  }
1447  __ jmp(masm->isolate()->builtins()->OnStackReplacement(),
1448         RelocInfo::CODE_TARGET);
1449
1450  __ bind(&ok);
1451  __ ret(0);
1452}
1453
1454#undef __
1455}
1456}  // namespace v8::internal
1457
1458#endif  // V8_TARGET_ARCH_IA32
1459