e2055629dfffd31a429f51adb4b41e50ac052d27
[platform/upstream/v8.git] / src / ia32 / builtins-ia32.cc
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #if V8_TARGET_ARCH_IA32
6
7 #include "src/code-factory.h"
8 #include "src/codegen.h"
9 #include "src/deoptimizer.h"
10 #include "src/full-codegen/full-codegen.h"
11 #include "src/ia32/frames-ia32.h"
12
13 namespace v8 {
14 namespace internal {
15
16
17 #define __ ACCESS_MASM(masm)
18
19
20 void Builtins::Generate_Adaptor(MacroAssembler* masm,
21                                 CFunctionId id,
22                                 BuiltinExtraArguments extra_args) {
23   // ----------- S t a t e -------------
24   //  -- eax                : number of arguments excluding receiver
25   //  -- edi                : called function (only guaranteed when
26   //                          extra_args requires it)
27   //  -- esi                : context
28   //  -- esp[0]             : return address
29   //  -- esp[4]             : last argument
30   //  -- ...
31   //  -- esp[4 * argc]      : first argument (argc == eax)
32   //  -- esp[4 * (argc +1)] : receiver
33   // -----------------------------------
34
35   // Insert extra arguments.
36   int num_extra_args = 0;
37   if (extra_args == NEEDS_CALLED_FUNCTION) {
38     num_extra_args = 1;
39     Register scratch = ebx;
40     __ pop(scratch);  // Save return address.
41     __ push(edi);
42     __ push(scratch);  // Restore return address.
43   } else {
44     DCHECK(extra_args == NO_EXTRA_ARGUMENTS);
45   }
46
47   // JumpToExternalReference expects eax to contain the number of arguments
48   // including the receiver and the extra arguments.
49   __ add(eax, Immediate(num_extra_args + 1));
50   __ JumpToExternalReference(ExternalReference(id, masm->isolate()));
51 }
52
53
54 static void CallRuntimePassFunction(
55     MacroAssembler* masm, Runtime::FunctionId function_id) {
56   FrameScope scope(masm, StackFrame::INTERNAL);
57   // Push a copy of the function.
58   __ push(edi);
59   // Function is also the parameter to the runtime call.
60   __ push(edi);
61
62   __ CallRuntime(function_id, 1);
63   // Restore receiver.
64   __ pop(edi);
65 }
66
67
68 static void GenerateTailCallToSharedCode(MacroAssembler* masm) {
69   __ mov(eax, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
70   __ mov(eax, FieldOperand(eax, SharedFunctionInfo::kCodeOffset));
71   __ lea(eax, FieldOperand(eax, Code::kHeaderSize));
72   __ jmp(eax);
73 }
74
75
76 static void GenerateTailCallToReturnedCode(MacroAssembler* masm) {
77   __ lea(eax, FieldOperand(eax, Code::kHeaderSize));
78   __ jmp(eax);
79 }
80
81
82 void Builtins::Generate_InOptimizationQueue(MacroAssembler* masm) {
83   // Checking whether the queued function is ready for install is optional,
84   // since we come across interrupts and stack checks elsewhere.  However,
85   // not checking may delay installing ready functions, and always checking
86   // would be quite expensive.  A good compromise is to first check against
87   // stack limit as a cue for an interrupt signal.
88   Label ok;
89   ExternalReference stack_limit =
90       ExternalReference::address_of_stack_limit(masm->isolate());
91   __ cmp(esp, Operand::StaticVariable(stack_limit));
92   __ j(above_equal, &ok, Label::kNear);
93
94   CallRuntimePassFunction(masm, Runtime::kTryInstallOptimizedCode);
95   GenerateTailCallToReturnedCode(masm);
96
97   __ bind(&ok);
98   GenerateTailCallToSharedCode(masm);
99 }
100
101
102 static void Generate_JSConstructStubHelper(MacroAssembler* masm,
103                                            bool is_api_function) {
104   // ----------- S t a t e -------------
105   //  -- eax: number of arguments
106   //  -- edi: constructor function
107   //  -- ebx: allocation site or undefined
108   //  -- edx: original constructor
109   // -----------------------------------
110
111   // Enter a construct frame.
112   {
113     FrameScope scope(masm, StackFrame::CONSTRUCT);
114
115     // Preserve the incoming parameters on the stack.
116     __ AssertUndefinedOrAllocationSite(ebx);
117     __ push(ebx);
118     __ SmiTag(eax);
119     __ push(eax);
120     __ push(edi);
121     __ push(edx);
122
123     // Try to allocate the object without transitioning into C code. If any of
124     // the preconditions is not met, the code bails out to the runtime call.
125     Label rt_call, allocated;
126     if (FLAG_inline_new) {
127       ExternalReference debug_step_in_fp =
128           ExternalReference::debug_step_in_fp_address(masm->isolate());
129       __ cmp(Operand::StaticVariable(debug_step_in_fp), Immediate(0));
130       __ j(not_equal, &rt_call);
131
132       // Fall back to runtime if the original constructor and function differ.
133       __ cmp(edx, edi);
134       __ j(not_equal, &rt_call);
135
136       // Verified that the constructor is a JSFunction.
137       // Load the initial map and verify that it is in fact a map.
138       // edi: constructor
139       __ mov(eax, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset));
140       // Will both indicate a NULL and a Smi
141       __ JumpIfSmi(eax, &rt_call);
142       // edi: constructor
143       // eax: initial map (if proven valid below)
144       __ CmpObjectType(eax, MAP_TYPE, ebx);
145       __ j(not_equal, &rt_call);
146
147       // Check that the constructor is not constructing a JSFunction (see
148       // comments in Runtime_NewObject in runtime.cc). In which case the
149       // initial map's instance type would be JS_FUNCTION_TYPE.
150       // edi: constructor
151       // eax: initial map
152       __ CmpInstanceType(eax, JS_FUNCTION_TYPE);
153       __ j(equal, &rt_call);
154
155       if (!is_api_function) {
156         Label allocate;
157         // The code below relies on these assumptions.
158         STATIC_ASSERT(Map::Counter::kShift + Map::Counter::kSize == 32);
159         // Check if slack tracking is enabled.
160         __ mov(esi, FieldOperand(eax, Map::kBitField3Offset));
161         __ shr(esi, Map::Counter::kShift);
162         __ cmp(esi, Map::kSlackTrackingCounterEnd);
163         __ j(less, &allocate);
164         // Decrease generous allocation count.
165         __ sub(FieldOperand(eax, Map::kBitField3Offset),
166                Immediate(1 << Map::Counter::kShift));
167
168         __ cmp(esi, Map::kSlackTrackingCounterEnd);
169         __ j(not_equal, &allocate);
170
171         __ push(eax);
172         __ push(edx);
173         __ push(edi);
174
175         __ push(edi);  // constructor
176         __ CallRuntime(Runtime::kFinalizeInstanceSize, 1);
177
178         __ pop(edi);
179         __ pop(edx);
180         __ pop(eax);
181         __ mov(esi, Map::kSlackTrackingCounterEnd - 1);
182
183         __ bind(&allocate);
184       }
185
186       // Now allocate the JSObject on the heap.
187       // edi: constructor
188       // eax: initial map
189       __ movzx_b(edi, FieldOperand(eax, Map::kInstanceSizeOffset));
190       __ shl(edi, kPointerSizeLog2);
191
192       __ Allocate(edi, ebx, edi, no_reg, &rt_call, NO_ALLOCATION_FLAGS);
193
194       Factory* factory = masm->isolate()->factory();
195
196       // Allocated the JSObject, now initialize the fields.
197       // eax: initial map
198       // ebx: JSObject
199       // edi: start of next object
200       __ mov(Operand(ebx, JSObject::kMapOffset), eax);
201       __ mov(ecx, factory->empty_fixed_array());
202       __ mov(Operand(ebx, JSObject::kPropertiesOffset), ecx);
203       __ mov(Operand(ebx, JSObject::kElementsOffset), ecx);
204       // Set extra fields in the newly allocated object.
205       // eax: initial map
206       // ebx: JSObject
207       // edi: start of next object
208       // esi: slack tracking counter (non-API function case)
209       __ mov(edx, factory->undefined_value());
210       __ lea(ecx, Operand(ebx, JSObject::kHeaderSize));
211       if (!is_api_function) {
212         Label no_inobject_slack_tracking;
213
214         // Check if slack tracking is enabled.
215         __ cmp(esi, Map::kSlackTrackingCounterEnd);
216         __ j(less, &no_inobject_slack_tracking);
217
218         // Allocate object with a slack.
219         __ movzx_b(
220             esi,
221             FieldOperand(
222                 eax, Map::kInObjectPropertiesOrConstructorFunctionIndexOffset));
223         __ movzx_b(eax, FieldOperand(eax, Map::kUnusedPropertyFieldsOffset));
224         __ sub(esi, eax);
225         __ lea(esi,
226                Operand(ebx, esi, times_pointer_size, JSObject::kHeaderSize));
227         // esi: offset of first field after pre-allocated fields
228         if (FLAG_debug_code) {
229           __ cmp(esi, edi);
230           __ Assert(less_equal,
231                     kUnexpectedNumberOfPreAllocatedPropertyFields);
232         }
233         __ InitializeFieldsWithFiller(ecx, esi, edx);
234         __ mov(edx, factory->one_pointer_filler_map());
235         // Fill the remaining fields with one pointer filler map.
236
237         __ bind(&no_inobject_slack_tracking);
238       }
239
240       __ InitializeFieldsWithFiller(ecx, edi, edx);
241
242       // Add the object tag to make the JSObject real, so that we can continue
243       // and jump into the continuation code at any time from now on.
244       // ebx: JSObject (untagged)
245       __ or_(ebx, Immediate(kHeapObjectTag));
246
247       // Continue with JSObject being successfully allocated
248       // ebx: JSObject (tagged)
249       __ jmp(&allocated);
250     }
251
252     // Allocate the new receiver object using the runtime call.
253     // edx: original constructor
254     __ bind(&rt_call);
255     int offset = kPointerSize;
256
257     // Must restore esi (context) and edi (constructor) before calling
258     // runtime.
259     __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
260     __ mov(edi, Operand(esp, offset));
261     __ push(edi);  // argument 2/1: constructor function
262     __ push(edx);  // argument 3/2: original constructor
263     __ CallRuntime(Runtime::kNewObject, 2);
264     __ mov(ebx, eax);  // store result in ebx
265
266     // New object allocated.
267     // ebx: newly allocated object
268     __ bind(&allocated);
269
270     // Restore the parameters.
271     __ pop(edx);  // new.target
272     __ pop(edi);  // Constructor function.
273
274     // Retrieve smi-tagged arguments count from the stack.
275     __ mov(eax, Operand(esp, 0));
276     __ SmiUntag(eax);
277
278     // Push new.target onto the construct frame. This is stored just below the
279     // receiver on the stack.
280     __ push(edx);
281
282     // Push the allocated receiver to the stack. We need two copies
283     // because we may have to return the original one and the calling
284     // conventions dictate that the called function pops the receiver.
285     __ push(ebx);
286     __ push(ebx);
287
288     // Set up pointer to last argument.
289     __ lea(ebx, Operand(ebp, StandardFrameConstants::kCallerSPOffset));
290
291     // Copy arguments and receiver to the expression stack.
292     Label loop, entry;
293     __ mov(ecx, eax);
294     __ jmp(&entry);
295     __ bind(&loop);
296     __ push(Operand(ebx, ecx, times_4, 0));
297     __ bind(&entry);
298     __ dec(ecx);
299     __ j(greater_equal, &loop);
300
301     // Call the function.
302     if (is_api_function) {
303       __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
304       Handle<Code> code =
305           masm->isolate()->builtins()->HandleApiCallConstruct();
306       __ call(code, RelocInfo::CODE_TARGET);
307     } else {
308       ParameterCount actual(eax);
309       __ InvokeFunction(edi, actual, CALL_FUNCTION,
310                         NullCallWrapper());
311     }
312
313     // Store offset of return address for deoptimizer.
314     if (!is_api_function) {
315       masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset());
316     }
317
318     // Restore context from the frame.
319     __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
320
321     // If the result is an object (in the ECMA sense), we should get rid
322     // of the receiver and use the result; see ECMA-262 section 13.2.2-7
323     // on page 74.
324     Label use_receiver, exit;
325
326     // If the result is a smi, it is *not* an object in the ECMA sense.
327     __ JumpIfSmi(eax, &use_receiver);
328
329     // If the type of the result (stored in its map) is less than
330     // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense.
331     __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
332     __ j(above_equal, &exit);
333
334     // Throw away the result of the constructor invocation and use the
335     // on-stack receiver as the result.
336     __ bind(&use_receiver);
337     __ mov(eax, Operand(esp, 0));
338
339     // Restore the arguments count and leave the construct frame. The arguments
340     // count is stored below the reciever and the new.target.
341     __ bind(&exit);
342     __ mov(ebx, Operand(esp, 2 * kPointerSize));
343
344     // Leave construct frame.
345   }
346
347   // Remove caller arguments from the stack and return.
348   STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
349   __ pop(ecx);
350   __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize));  // 1 ~ receiver
351   __ push(ecx);
352   __ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1);
353   __ ret(0);
354 }
355
356
357 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
358   Generate_JSConstructStubHelper(masm, false);
359 }
360
361
362 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
363   Generate_JSConstructStubHelper(masm, true);
364 }
365
366
367 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) {
368   // ----------- S t a t e -------------
369   //  -- eax: number of arguments
370   //  -- edi: constructor function
371   //  -- ebx: allocation site or undefined
372   //  -- edx: original constructor
373   // -----------------------------------
374
375   {
376     FrameScope frame_scope(masm, StackFrame::CONSTRUCT);
377
378     // Preserve allocation site.
379     __ AssertUndefinedOrAllocationSite(ebx);
380     __ push(ebx);
381
382     // Preserve actual arguments count.
383     __ SmiTag(eax);
384     __ push(eax);
385     __ SmiUntag(eax);
386
387     // Push new.target.
388     __ push(edx);
389
390     // receiver is the hole.
391     __ push(Immediate(masm->isolate()->factory()->the_hole_value()));
392
393     // Set up pointer to last argument.
394     __ lea(ebx, Operand(ebp, StandardFrameConstants::kCallerSPOffset));
395
396     // Copy arguments and receiver to the expression stack.
397     Label loop, entry;
398     __ mov(ecx, eax);
399     __ jmp(&entry);
400     __ bind(&loop);
401     __ push(Operand(ebx, ecx, times_4, 0));
402     __ bind(&entry);
403     __ dec(ecx);
404     __ j(greater_equal, &loop);
405
406     // Handle step in.
407     Label skip_step_in;
408     ExternalReference debug_step_in_fp =
409         ExternalReference::debug_step_in_fp_address(masm->isolate());
410     __ cmp(Operand::StaticVariable(debug_step_in_fp), Immediate(0));
411     __ j(equal, &skip_step_in);
412
413     __ push(eax);
414     __ push(edi);
415     __ push(edi);
416     __ CallRuntime(Runtime::kHandleStepInForDerivedConstructors, 1);
417     __ pop(edi);
418     __ pop(eax);
419
420     __ bind(&skip_step_in);
421
422     // Invoke function.
423     ParameterCount actual(eax);
424     __ InvokeFunction(edi, actual, CALL_FUNCTION, NullCallWrapper());
425
426     // Restore context from the frame.
427     __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
428
429     // Get arguments count, skipping over new.target.
430     __ mov(ebx, Operand(esp, kPointerSize));
431   }
432
433   __ pop(ecx);  // Return address.
434   __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize));
435   __ push(ecx);
436   __ ret(0);
437 }
438
439
440 enum IsTagged { kEaxIsSmiTagged, kEaxIsUntaggedInt };
441
442
443 // Clobbers ecx, edx, edi; preserves all other registers.
444 static void Generate_CheckStackOverflow(MacroAssembler* masm,
445                                         const int calleeOffset,
446                                         IsTagged eax_is_tagged) {
447   // eax   : the number of items to be pushed to the stack
448   //
449   // Check the stack for overflow. We are not trying to catch
450   // interruptions (e.g. debug break and preemption) here, so the "real stack
451   // limit" is checked.
452   Label okay;
453   ExternalReference real_stack_limit =
454       ExternalReference::address_of_real_stack_limit(masm->isolate());
455   __ mov(edi, Operand::StaticVariable(real_stack_limit));
456   // Make ecx the space we have left. The stack might already be overflowed
457   // here which will cause ecx to become negative.
458   __ mov(ecx, esp);
459   __ sub(ecx, edi);
460   // Make edx the space we need for the array when it is unrolled onto the
461   // stack.
462   __ mov(edx, eax);
463   int smi_tag = eax_is_tagged == kEaxIsSmiTagged ? kSmiTagSize : 0;
464   __ shl(edx, kPointerSizeLog2 - smi_tag);
465   // Check if the arguments will overflow the stack.
466   __ cmp(ecx, edx);
467   __ j(greater, &okay);  // Signed comparison.
468
469   // Out of stack space.
470   __ push(Operand(ebp, calleeOffset));  // push this
471   if (eax_is_tagged == kEaxIsUntaggedInt) {
472     __ SmiTag(eax);
473   }
474   __ push(eax);
475   __ CallRuntime(Runtime::kThrowStackOverflow, 0);
476
477   __ bind(&okay);
478 }
479
480
481 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
482                                              bool is_construct) {
483   ProfileEntryHookStub::MaybeCallEntryHook(masm);
484
485   // Clear the context before we push it when entering the internal frame.
486   __ Move(esi, Immediate(0));
487
488   {
489     FrameScope scope(masm, StackFrame::INTERNAL);
490
491     // Load the previous frame pointer (ebx) to access C arguments
492     __ mov(ebx, Operand(ebp, 0));
493
494     // Get the function from the frame and setup the context.
495     __ mov(ecx, Operand(ebx, EntryFrameConstants::kFunctionArgOffset));
496     __ mov(esi, FieldOperand(ecx, JSFunction::kContextOffset));
497
498     // Push the function and the receiver onto the stack.
499     __ push(ecx);
500     __ push(Operand(ebx, EntryFrameConstants::kReceiverArgOffset));
501
502     // Load the number of arguments and setup pointer to the arguments.
503     __ mov(eax, Operand(ebx, EntryFrameConstants::kArgcOffset));
504     __ mov(ebx, Operand(ebx, EntryFrameConstants::kArgvOffset));
505
506     // Check if we have enough stack space to push all arguments.
507     // The function is the first thing that was pushed above after entering
508     // the internal frame.
509     const int kFunctionOffset =
510         InternalFrameConstants::kCodeOffset - kPointerSize;
511     // Expects argument count in eax. Clobbers ecx, edx, edi.
512     Generate_CheckStackOverflow(masm, kFunctionOffset, kEaxIsUntaggedInt);
513
514     // Copy arguments to the stack in a loop.
515     Label loop, entry;
516     __ Move(ecx, Immediate(0));
517     __ jmp(&entry);
518     __ bind(&loop);
519     __ mov(edx, Operand(ebx, ecx, times_4, 0));  // push parameter from argv
520     __ push(Operand(edx, 0));  // dereference handle
521     __ inc(ecx);
522     __ bind(&entry);
523     __ cmp(ecx, eax);
524     __ j(not_equal, &loop);
525
526     // Get the function from the stack and call it.
527     // kPointerSize for the receiver.
528     __ mov(edi, Operand(esp, eax, times_4, kPointerSize));
529
530     // Invoke the code.
531     if (is_construct) {
532       // No type feedback cell is available
533       __ mov(ebx, masm->isolate()->factory()->undefined_value());
534       CallConstructStub stub(masm->isolate(), NO_CALL_CONSTRUCTOR_FLAGS);
535       __ CallStub(&stub);
536     } else {
537       __ Call(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
538     }
539
540     // Exit the internal frame. Notice that this also removes the empty.
541     // context and the function left on the stack by the code
542     // invocation.
543   }
544   __ ret(kPointerSize);  // Remove receiver.
545 }
546
547
548 void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) {
549   Generate_JSEntryTrampolineHelper(masm, false);
550 }
551
552
553 void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
554   Generate_JSEntryTrampolineHelper(masm, true);
555 }
556
557
558 // Generate code for entering a JS function with the interpreter.
559 // On entry to the function the receiver and arguments have been pushed on the
560 // stack left to right.  The actual argument count matches the formal parameter
561 // count expected by the function.
562 //
563 // The live registers are:
564 //   o edi: the JS function object being called
565 //   o esi: our context
566 //   o ebp: the caller's frame pointer
567 //   o esp: stack pointer (pointing to return address)
568 //
569 // The function builds a JS frame.  Please see JavaScriptFrameConstants in
570 // frames-ia32.h for its layout.
571 // TODO(rmcilroy): We will need to include the current bytecode pointer in the
572 // frame.
573 void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
574   // Open a frame scope to indicate that there is a frame on the stack.  The
575   // MANUAL indicates that the scope shouldn't actually generate code to set up
576   // the frame (that is done below).
577   FrameScope frame_scope(masm, StackFrame::MANUAL);
578   __ push(ebp);  // Caller's frame pointer.
579   __ mov(ebp, esp);
580   __ push(esi);  // Callee's context.
581   __ push(edi);  // Callee's JS function.
582
583   // Get the bytecode array from the function object and load the pointer to the
584   // first entry into edi (InterpreterBytecodeRegister).
585   __ mov(eax, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
586   __ mov(kInterpreterBytecodeArrayRegister,
587          FieldOperand(eax, SharedFunctionInfo::kFunctionDataOffset));
588
589   if (FLAG_debug_code) {
590     // Check function data field is actually a BytecodeArray object.
591     __ AssertNotSmi(kInterpreterBytecodeArrayRegister);
592     __ CmpObjectType(kInterpreterBytecodeArrayRegister, BYTECODE_ARRAY_TYPE,
593                      eax);
594     __ Assert(equal, kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry);
595   }
596
597   // Allocate the local and temporary register file on the stack.
598   {
599     // Load frame size from the BytecodeArray object.
600     __ mov(ebx, FieldOperand(kInterpreterBytecodeArrayRegister,
601                              BytecodeArray::kFrameSizeOffset));
602
603     // Do a stack check to ensure we don't go over the limit.
604     Label ok;
605     __ mov(ecx, esp);
606     __ sub(ecx, ebx);
607     ExternalReference stack_limit =
608         ExternalReference::address_of_real_stack_limit(masm->isolate());
609     __ cmp(ecx, Operand::StaticVariable(stack_limit));
610     __ j(above_equal, &ok);
611     __ CallRuntime(Runtime::kThrowStackOverflow, 0);
612     __ bind(&ok);
613
614     // If ok, push undefined as the initial value for all register file entries.
615     Label loop_header;
616     Label loop_check;
617     __ mov(eax, Immediate(masm->isolate()->factory()->undefined_value()));
618     __ jmp(&loop_check);
619     __ bind(&loop_header);
620     // TODO(rmcilroy): Consider doing more than one push per loop iteration.
621     __ push(eax);
622     // Continue loop if not done.
623     __ bind(&loop_check);
624     __ sub(ebx, Immediate(kPointerSize));
625     __ j(greater_equal, &loop_header);
626   }
627
628   // TODO(rmcilroy): List of things not currently dealt with here but done in
629   // fullcodegen's prologue:
630   //  - Support profiler (specifically profiling_counter).
631   //  - Call ProfileEntryHookStub when isolate has a function_entry_hook.
632   //  - Allow simulator stop operations if FLAG_stop_at is set.
633   //  - Deal with sloppy mode functions which need to replace the
634   //    receiver with the global proxy when called as functions (without an
635   //    explicit receiver object).
636   //  - Code aging of the BytecodeArray object.
637   //  - Supporting FLAG_trace.
638   //
639   // The following items are also not done here, and will probably be done using
640   // explicit bytecodes instead:
641   //  - Allocating a new local context if applicable.
642   //  - Setting up a local binding to the this function, which is used in
643   //    derived constructors with super calls.
644   //  - Setting new.target if required.
645   //  - Dealing with REST parameters (only if
646   //    https://codereview.chromium.org/1235153006 doesn't land by then).
647   //  - Dealing with argument objects.
648
649   // Perform stack guard check.
650   {
651     Label ok;
652     ExternalReference stack_limit =
653         ExternalReference::address_of_stack_limit(masm->isolate());
654     __ cmp(esp, Operand::StaticVariable(stack_limit));
655     __ j(above_equal, &ok);
656     __ CallRuntime(Runtime::kStackGuard, 0);
657     __ bind(&ok);
658   }
659
660   // Load accumulator, register file, bytecode offset, dispatch table into
661   // registers.
662   __ LoadRoot(kInterpreterAccumulatorRegister, Heap::kUndefinedValueRootIndex);
663   __ mov(kInterpreterRegisterFileRegister, ebp);
664   __ sub(
665       kInterpreterRegisterFileRegister,
666       Immediate(kPointerSize + StandardFrameConstants::kFixedFrameSizeFromFp));
667   __ mov(kInterpreterBytecodeOffsetRegister,
668          Immediate(BytecodeArray::kHeaderSize - kHeapObjectTag));
669   // Since the dispatch table root might be set after builtins are generated,
670   // load directly from the roots table.
671   __ LoadRoot(kInterpreterDispatchTableRegister,
672               Heap::kInterpreterTableRootIndex);
673   __ add(kInterpreterDispatchTableRegister,
674          Immediate(FixedArray::kHeaderSize - kHeapObjectTag));
675
676   // Push context as a stack located parameter to the bytecode handler.
677   DCHECK_EQ(-1, kInterpreterContextSpillSlot);
678   __ push(esi);
679
680   // Dispatch to the first bytecode handler for the function.
681   __ movzx_b(esi, Operand(kInterpreterBytecodeArrayRegister,
682                           kInterpreterBytecodeOffsetRegister, times_1, 0));
683   __ mov(esi, Operand(kInterpreterDispatchTableRegister, esi,
684                       times_pointer_size, 0));
685   // TODO(rmcilroy): Make dispatch table point to code entrys to avoid untagging
686   // and header removal.
687   __ add(esi, Immediate(Code::kHeaderSize - kHeapObjectTag));
688   __ call(esi);
689 }
690
691
692 void Builtins::Generate_InterpreterExitTrampoline(MacroAssembler* masm) {
693   // TODO(rmcilroy): List of things not currently dealt with here but done in
694   // fullcodegen's EmitReturnSequence.
695   //  - Supporting FLAG_trace for Runtime::TraceExit.
696   //  - Support profiler (specifically decrementing profiling_counter
697   //    appropriately and calling out to HandleInterrupts if necessary).
698
699   // The return value is in accumulator, which is already in rax.
700
701   // Leave the frame (also dropping the register file).
702   __ leave();
703
704   // Drop receiver + arguments and return.
705   __ mov(ebx, FieldOperand(kInterpreterBytecodeArrayRegister,
706                            BytecodeArray::kParameterSizeOffset));
707   __ pop(ecx);
708   __ add(esp, ebx);
709   __ push(ecx);
710   __ ret(0);
711 }
712
713
714 void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
715   CallRuntimePassFunction(masm, Runtime::kCompileLazy);
716   GenerateTailCallToReturnedCode(masm);
717 }
718
719
720
721 static void CallCompileOptimized(MacroAssembler* masm, bool concurrent) {
722   FrameScope scope(masm, StackFrame::INTERNAL);
723   // Push a copy of the function.
724   __ push(edi);
725   // Function is also the parameter to the runtime call.
726   __ push(edi);
727   // Whether to compile in a background thread.
728   __ Push(masm->isolate()->factory()->ToBoolean(concurrent));
729
730   __ CallRuntime(Runtime::kCompileOptimized, 2);
731   // Restore receiver.
732   __ pop(edi);
733 }
734
735
736 void Builtins::Generate_CompileOptimized(MacroAssembler* masm) {
737   CallCompileOptimized(masm, false);
738   GenerateTailCallToReturnedCode(masm);
739 }
740
741
742 void Builtins::Generate_CompileOptimizedConcurrent(MacroAssembler* masm) {
743   CallCompileOptimized(masm, true);
744   GenerateTailCallToReturnedCode(masm);
745 }
746
747
748 static void GenerateMakeCodeYoungAgainCommon(MacroAssembler* masm) {
749   // For now, we are relying on the fact that make_code_young doesn't do any
750   // garbage collection which allows us to save/restore the registers without
751   // worrying about which of them contain pointers. We also don't build an
752   // internal frame to make the code faster, since we shouldn't have to do stack
753   // crawls in MakeCodeYoung. This seems a bit fragile.
754
755   // Re-execute the code that was patched back to the young age when
756   // the stub returns.
757   __ sub(Operand(esp, 0), Immediate(5));
758   __ pushad();
759   __ mov(eax, Operand(esp, 8 * kPointerSize));
760   {
761     FrameScope scope(masm, StackFrame::MANUAL);
762     __ PrepareCallCFunction(2, ebx);
763     __ mov(Operand(esp, 1 * kPointerSize),
764            Immediate(ExternalReference::isolate_address(masm->isolate())));
765     __ mov(Operand(esp, 0), eax);
766     __ CallCFunction(
767         ExternalReference::get_make_code_young_function(masm->isolate()), 2);
768   }
769   __ popad();
770   __ ret(0);
771 }
772
773 #define DEFINE_CODE_AGE_BUILTIN_GENERATOR(C)                 \
774 void Builtins::Generate_Make##C##CodeYoungAgainEvenMarking(  \
775     MacroAssembler* masm) {                                  \
776   GenerateMakeCodeYoungAgainCommon(masm);                    \
777 }                                                            \
778 void Builtins::Generate_Make##C##CodeYoungAgainOddMarking(   \
779     MacroAssembler* masm) {                                  \
780   GenerateMakeCodeYoungAgainCommon(masm);                    \
781 }
782 CODE_AGE_LIST(DEFINE_CODE_AGE_BUILTIN_GENERATOR)
783 #undef DEFINE_CODE_AGE_BUILTIN_GENERATOR
784
785
786 void Builtins::Generate_MarkCodeAsExecutedOnce(MacroAssembler* masm) {
787   // For now, as in GenerateMakeCodeYoungAgainCommon, we are relying on the fact
788   // that make_code_young doesn't do any garbage collection which allows us to
789   // save/restore the registers without worrying about which of them contain
790   // pointers.
791   __ pushad();
792   __ mov(eax, Operand(esp, 8 * kPointerSize));
793   __ sub(eax, Immediate(Assembler::kCallInstructionLength));
794   {  // NOLINT
795     FrameScope scope(masm, StackFrame::MANUAL);
796     __ PrepareCallCFunction(2, ebx);
797     __ mov(Operand(esp, 1 * kPointerSize),
798            Immediate(ExternalReference::isolate_address(masm->isolate())));
799     __ mov(Operand(esp, 0), eax);
800     __ CallCFunction(
801         ExternalReference::get_mark_code_as_executed_function(masm->isolate()),
802         2);
803   }
804   __ popad();
805
806   // Perform prologue operations usually performed by the young code stub.
807   __ pop(eax);   // Pop return address into scratch register.
808   __ push(ebp);  // Caller's frame pointer.
809   __ mov(ebp, esp);
810   __ push(esi);  // Callee's context.
811   __ push(edi);  // Callee's JS Function.
812   __ push(eax);  // Push return address after frame prologue.
813
814   // Jump to point after the code-age stub.
815   __ ret(0);
816 }
817
818
819 void Builtins::Generate_MarkCodeAsExecutedTwice(MacroAssembler* masm) {
820   GenerateMakeCodeYoungAgainCommon(masm);
821 }
822
823
824 void Builtins::Generate_MarkCodeAsToBeExecutedOnce(MacroAssembler* masm) {
825   Generate_MarkCodeAsExecutedOnce(masm);
826 }
827
828
829 static void Generate_NotifyStubFailureHelper(MacroAssembler* masm,
830                                              SaveFPRegsMode save_doubles) {
831   // Enter an internal frame.
832   {
833     FrameScope scope(masm, StackFrame::INTERNAL);
834
835     // Preserve registers across notification, this is important for compiled
836     // stubs that tail call the runtime on deopts passing their parameters in
837     // registers.
838     __ pushad();
839     __ CallRuntime(Runtime::kNotifyStubFailure, 0, save_doubles);
840     __ popad();
841     // Tear down internal frame.
842   }
843
844   __ pop(MemOperand(esp, 0));  // Ignore state offset
845   __ ret(0);  // Return to IC Miss stub, continuation still on stack.
846 }
847
848
849 void Builtins::Generate_NotifyStubFailure(MacroAssembler* masm) {
850   Generate_NotifyStubFailureHelper(masm, kDontSaveFPRegs);
851 }
852
853
854 void Builtins::Generate_NotifyStubFailureSaveDoubles(MacroAssembler* masm) {
855   Generate_NotifyStubFailureHelper(masm, kSaveFPRegs);
856 }
857
858
859 static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm,
860                                              Deoptimizer::BailoutType type) {
861   {
862     FrameScope scope(masm, StackFrame::INTERNAL);
863
864     // Pass deoptimization type to the runtime system.
865     __ push(Immediate(Smi::FromInt(static_cast<int>(type))));
866     __ CallRuntime(Runtime::kNotifyDeoptimized, 1);
867
868     // Tear down internal frame.
869   }
870
871   // Get the full codegen state from the stack and untag it.
872   __ mov(ecx, Operand(esp, 1 * kPointerSize));
873   __ SmiUntag(ecx);
874
875   // Switch on the state.
876   Label not_no_registers, not_tos_eax;
877   __ cmp(ecx, FullCodeGenerator::NO_REGISTERS);
878   __ j(not_equal, &not_no_registers, Label::kNear);
879   __ ret(1 * kPointerSize);  // Remove state.
880
881   __ bind(&not_no_registers);
882   __ mov(eax, Operand(esp, 2 * kPointerSize));
883   __ cmp(ecx, FullCodeGenerator::TOS_REG);
884   __ j(not_equal, &not_tos_eax, Label::kNear);
885   __ ret(2 * kPointerSize);  // Remove state, eax.
886
887   __ bind(&not_tos_eax);
888   __ Abort(kNoCasesLeft);
889 }
890
891
892 void Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) {
893   Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::EAGER);
894 }
895
896
897 void Builtins::Generate_NotifySoftDeoptimized(MacroAssembler* masm) {
898   Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::SOFT);
899 }
900
901
902 void Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) {
903   Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
904 }
905
906
907 // static
908 void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
909   // Stack Layout:
910   // esp[0]           : Return address
911   // esp[8]           : Argument n
912   // esp[16]          : Argument n-1
913   //  ...
914   // esp[8 * n]       : Argument 1
915   // esp[8 * (n + 1)] : Receiver (callable to call)
916   //
917   // eax contains the number of arguments, n, not counting the receiver.
918   //
919   // 1. Make sure we have at least one argument.
920   {
921     Label done;
922     __ test(eax, eax);
923     __ j(not_zero, &done, Label::kNear);
924     __ PopReturnAddressTo(ebx);
925     __ PushRoot(Heap::kUndefinedValueRootIndex);
926     __ PushReturnAddressFrom(ebx);
927     __ inc(eax);
928     __ bind(&done);
929   }
930
931   // 2. Get the callable to call (passed as receiver) from the stack.
932   __ mov(edi, Operand(esp, eax, times_pointer_size, kPointerSize));
933
934   // 3. Shift arguments and return address one slot down on the stack
935   //    (overwriting the original receiver).  Adjust argument count to make
936   //    the original first argument the new receiver.
937   {
938     Label loop;
939     __ mov(ecx, eax);
940     __ bind(&loop);
941     __ mov(ebx, Operand(esp, ecx, times_pointer_size, 0));
942     __ mov(Operand(esp, ecx, times_pointer_size, kPointerSize), ebx);
943     __ dec(ecx);
944     __ j(not_sign, &loop);  // While non-negative (to copy return address).
945     __ pop(ebx);            // Discard copy of return address.
946     __ dec(eax);  // One fewer argument (first argument is new receiver).
947   }
948
949   // 4. Call the callable.
950   __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
951 }
952
953
954 static void Generate_PushAppliedArguments(MacroAssembler* masm,
955                                           const int vectorOffset,
956                                           const int argumentsOffset,
957                                           const int indexOffset,
958                                           const int limitOffset) {
959   // Copy all arguments from the array to the stack.
960   Label entry, loop;
961   Register receiver = LoadDescriptor::ReceiverRegister();
962   Register key = LoadDescriptor::NameRegister();
963   Register slot = LoadDescriptor::SlotRegister();
964   Register vector = LoadWithVectorDescriptor::VectorRegister();
965   __ mov(key, Operand(ebp, indexOffset));
966   __ jmp(&entry);
967   __ bind(&loop);
968   __ mov(receiver, Operand(ebp, argumentsOffset));  // load arguments
969
970   // Use inline caching to speed up access to arguments.
971   int slot_index = TypeFeedbackVector::PushAppliedArgumentsIndex();
972   __ mov(slot, Immediate(Smi::FromInt(slot_index)));
973   __ mov(vector, Operand(ebp, vectorOffset));
974   Handle<Code> ic =
975       KeyedLoadICStub(masm->isolate(), LoadICState(kNoExtraICState)).GetCode();
976   __ call(ic, RelocInfo::CODE_TARGET);
977   // It is important that we do not have a test instruction after the
978   // call.  A test instruction after the call is used to indicate that
979   // we have generated an inline version of the keyed load.  In this
980   // case, we know that we are not generating a test instruction next.
981
982   // Push the nth argument.
983   __ push(eax);
984
985   // Update the index on the stack and in register key.
986   __ mov(key, Operand(ebp, indexOffset));
987   __ add(key, Immediate(1 << kSmiTagSize));
988   __ mov(Operand(ebp, indexOffset), key);
989
990   __ bind(&entry);
991   __ cmp(key, Operand(ebp, limitOffset));
992   __ j(not_equal, &loop);
993
994   // On exit, the pushed arguments count is in eax, untagged
995   __ Move(eax, key);
996   __ SmiUntag(eax);
997 }
998
999
1000 // Used by FunctionApply and ReflectApply
1001 static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
1002   const int kFormalParameters = targetIsArgument ? 3 : 2;
1003   const int kStackSize = kFormalParameters + 1;
1004
1005   // Stack at entry:
1006   // esp     : return address
1007   // esp[4]  : arguments
1008   // esp[8]  : receiver ("this")
1009   // esp[12] : function
1010   {
1011     FrameScope frame_scope(masm, StackFrame::INTERNAL);
1012     // Stack frame:
1013     // ebp     : Old base pointer
1014     // ebp[4]  : return address
1015     // ebp[8]  : function arguments
1016     // ebp[12] : receiver
1017     // ebp[16] : function
1018     static const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize;
1019     static const int kReceiverOffset = kArgumentsOffset + kPointerSize;
1020     static const int kFunctionOffset = kReceiverOffset + kPointerSize;
1021     static const int kVectorOffset =
1022         InternalFrameConstants::kCodeOffset - 1 * kPointerSize;
1023
1024     // Push the vector.
1025     __ mov(edi, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
1026     __ mov(edi, FieldOperand(edi, SharedFunctionInfo::kFeedbackVectorOffset));
1027     __ push(edi);
1028
1029     __ push(Operand(ebp, kFunctionOffset));   // push this
1030     __ push(Operand(ebp, kArgumentsOffset));  // push arguments
1031     if (targetIsArgument) {
1032       __ InvokeBuiltin(Context::REFLECT_APPLY_PREPARE_BUILTIN_INDEX,
1033                        CALL_FUNCTION);
1034     } else {
1035       __ InvokeBuiltin(Context::APPLY_PREPARE_BUILTIN_INDEX, CALL_FUNCTION);
1036     }
1037
1038     Generate_CheckStackOverflow(masm, kFunctionOffset, kEaxIsSmiTagged);
1039
1040     // Push current index and limit.
1041     const int kLimitOffset = kVectorOffset - 1 * kPointerSize;
1042     const int kIndexOffset = kLimitOffset - 1 * kPointerSize;
1043     __ Push(eax);                            // limit
1044     __ Push(Immediate(0));                   // index
1045     __ Push(Operand(ebp, kReceiverOffset));  // receiver
1046
1047     // Loop over the arguments array, pushing each value to the stack
1048     Generate_PushAppliedArguments(masm, kVectorOffset, kArgumentsOffset,
1049                                   kIndexOffset, kLimitOffset);
1050
1051     // Call the callable.
1052     // TODO(bmeurer): This should be a tail call according to ES6.
1053     __ mov(edi, Operand(ebp, kFunctionOffset));
1054     __ Call(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
1055
1056     // Leave internal frame.
1057   }
1058   __ ret(kStackSize * kPointerSize);  // remove this, receiver, and arguments
1059 }
1060
1061
1062 // Used by ReflectConstruct
1063 static void Generate_ConstructHelper(MacroAssembler* masm) {
1064   const int kFormalParameters = 3;
1065   const int kStackSize = kFormalParameters + 1;
1066
1067   // Stack at entry:
1068   // esp     : return address
1069   // esp[4]  : original constructor (new.target)
1070   // esp[8]  : arguments
1071   // esp[16] : constructor
1072   {
1073     FrameScope frame_scope(masm, StackFrame::INTERNAL);
1074     // Stack frame:
1075     // ebp     : Old base pointer
1076     // ebp[4]  : return address
1077     // ebp[8]  : original constructor (new.target)
1078     // ebp[12] : arguments
1079     // ebp[16] : constructor
1080     static const int kNewTargetOffset = kFPOnStackSize + kPCOnStackSize;
1081     static const int kArgumentsOffset = kNewTargetOffset + kPointerSize;
1082     static const int kFunctionOffset = kArgumentsOffset + kPointerSize;
1083     static const int kVectorOffset =
1084         InternalFrameConstants::kCodeOffset - 1 * kPointerSize;
1085
1086     // Push the vector.
1087     __ mov(edi, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
1088     __ mov(edi, FieldOperand(edi, SharedFunctionInfo::kFeedbackVectorOffset));
1089     __ push(edi);
1090
1091     // If newTarget is not supplied, set it to constructor
1092     Label validate_arguments;
1093     __ mov(eax, Operand(ebp, kNewTargetOffset));
1094     __ CompareRoot(eax, Heap::kUndefinedValueRootIndex);
1095     __ j(not_equal, &validate_arguments, Label::kNear);
1096     __ mov(eax, Operand(ebp, kFunctionOffset));
1097     __ mov(Operand(ebp, kNewTargetOffset), eax);
1098
1099     // Validate arguments
1100     __ bind(&validate_arguments);
1101     __ push(Operand(ebp, kFunctionOffset));
1102     __ push(Operand(ebp, kArgumentsOffset));
1103     __ push(Operand(ebp, kNewTargetOffset));
1104     __ InvokeBuiltin(Context::REFLECT_CONSTRUCT_PREPARE_BUILTIN_INDEX,
1105                      CALL_FUNCTION);
1106
1107     Generate_CheckStackOverflow(masm, kFunctionOffset, kEaxIsSmiTagged);
1108
1109     // Push current index and limit.
1110     const int kLimitOffset = kVectorOffset - 1 * kPointerSize;
1111     const int kIndexOffset = kLimitOffset - 1 * kPointerSize;
1112     __ Push(eax);  // limit
1113     __ push(Immediate(0));  // index
1114     // Push the constructor function as callee.
1115     __ push(Operand(ebp, kFunctionOffset));
1116
1117     // Loop over the arguments array, pushing each value to the stack
1118     Generate_PushAppliedArguments(masm, kVectorOffset, kArgumentsOffset,
1119                                   kIndexOffset, kLimitOffset);
1120
1121     // Use undefined feedback vector
1122     __ LoadRoot(ebx, Heap::kUndefinedValueRootIndex);
1123     __ mov(edi, Operand(ebp, kFunctionOffset));
1124     __ mov(ecx, Operand(ebp, kNewTargetOffset));
1125
1126     // Call the function.
1127     CallConstructStub stub(masm->isolate(), SUPER_CONSTRUCTOR_CALL);
1128     __ call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);
1129
1130     // Leave internal frame.
1131   }
1132   // remove this, target, arguments, and newTarget
1133   __ ret(kStackSize * kPointerSize);
1134 }
1135
1136
1137 void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
1138   Generate_ApplyHelper(masm, false);
1139 }
1140
1141
1142 void Builtins::Generate_ReflectApply(MacroAssembler* masm) {
1143   Generate_ApplyHelper(masm, true);
1144 }
1145
1146
1147 void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
1148   Generate_ConstructHelper(masm);
1149 }
1150
1151
1152 void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) {
1153   // ----------- S t a t e -------------
1154   //  -- eax : argc
1155   //  -- esp[0] : return address
1156   //  -- esp[4] : last argument
1157   // -----------------------------------
1158   Label generic_array_code;
1159
1160   // Get the InternalArray function.
1161   __ LoadGlobalFunction(Context::INTERNAL_ARRAY_FUNCTION_INDEX, edi);
1162
1163   if (FLAG_debug_code) {
1164     // Initial map for the builtin InternalArray function should be a map.
1165     __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset));
1166     // Will both indicate a NULL and a Smi.
1167     __ test(ebx, Immediate(kSmiTagMask));
1168     __ Assert(not_zero, kUnexpectedInitialMapForInternalArrayFunction);
1169     __ CmpObjectType(ebx, MAP_TYPE, ecx);
1170     __ Assert(equal, kUnexpectedInitialMapForInternalArrayFunction);
1171   }
1172
1173   // Run the native code for the InternalArray function called as a normal
1174   // function.
1175   // tail call a stub
1176   InternalArrayConstructorStub stub(masm->isolate());
1177   __ TailCallStub(&stub);
1178 }
1179
1180
1181 void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
1182   // ----------- S t a t e -------------
1183   //  -- eax : argc
1184   //  -- esp[0] : return address
1185   //  -- esp[4] : last argument
1186   // -----------------------------------
1187   Label generic_array_code;
1188
1189   // Get the Array function.
1190   __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, edi);
1191   __ mov(edx, edi);
1192
1193   if (FLAG_debug_code) {
1194     // Initial map for the builtin Array function should be a map.
1195     __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset));
1196     // Will both indicate a NULL and a Smi.
1197     __ test(ebx, Immediate(kSmiTagMask));
1198     __ Assert(not_zero, kUnexpectedInitialMapForArrayFunction);
1199     __ CmpObjectType(ebx, MAP_TYPE, ecx);
1200     __ Assert(equal, kUnexpectedInitialMapForArrayFunction);
1201   }
1202
1203   // Run the native code for the Array function called as a normal function.
1204   // tail call a stub
1205   __ mov(ebx, masm->isolate()->factory()->undefined_value());
1206   ArrayConstructorStub stub(masm->isolate());
1207   __ TailCallStub(&stub);
1208 }
1209
1210
1211 // static
1212 void Builtins::Generate_StringConstructor(MacroAssembler* masm) {
1213   // ----------- S t a t e -------------
1214   //  -- eax                 : number of arguments
1215   //  -- edi                 : constructor function
1216   //  -- esp[0]              : return address
1217   //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
1218   //  -- esp[(argc + 1) * 4] : receiver
1219   // -----------------------------------
1220
1221   // 1. Load the first argument into eax and get rid of the rest (including the
1222   // receiver).
1223   Label no_arguments;
1224   {
1225     __ test(eax, eax);
1226     __ j(zero, &no_arguments, Label::kNear);
1227     __ mov(ebx, Operand(esp, eax, times_pointer_size, 0));
1228     __ PopReturnAddressTo(ecx);
1229     __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize));
1230     __ PushReturnAddressFrom(ecx);
1231     __ mov(eax, ebx);
1232   }
1233
1234   // 2a. At least one argument, return eax if it's a string, otherwise
1235   // dispatch to appropriate conversion.
1236   Label to_string, symbol_descriptive_string;
1237   {
1238     __ JumpIfSmi(eax, &to_string, Label::kNear);
1239     STATIC_ASSERT(FIRST_NONSTRING_TYPE == SYMBOL_TYPE);
1240     __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edx);
1241     __ j(above, &to_string, Label::kNear);
1242     __ j(equal, &symbol_descriptive_string, Label::kNear);
1243     __ Ret();
1244   }
1245
1246   // 2b. No arguments, return the empty string (and pop the receiver).
1247   __ bind(&no_arguments);
1248   {
1249     __ LoadRoot(eax, Heap::kempty_stringRootIndex);
1250     __ ret(1 * kPointerSize);
1251   }
1252
1253   // 3a. Convert eax to a string.
1254   __ bind(&to_string);
1255   {
1256     ToStringStub stub(masm->isolate());
1257     __ TailCallStub(&stub);
1258   }
1259
1260   // 3b. Convert symbol in eax to a string.
1261   __ bind(&symbol_descriptive_string);
1262   {
1263     __ PopReturnAddressTo(ecx);
1264     __ Push(eax);
1265     __ PushReturnAddressFrom(ecx);
1266     __ TailCallRuntime(Runtime::kSymbolDescriptiveString, 1, 1);
1267   }
1268 }
1269
1270
1271 // static
1272 void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) {
1273   // ----------- S t a t e -------------
1274   //  -- eax                 : number of arguments
1275   //  -- edi                 : constructor function
1276   //  -- esp[0]              : return address
1277   //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
1278   //  -- esp[(argc + 1) * 4] : receiver
1279   // -----------------------------------
1280
1281   // 1. Load the first argument into ebx and get rid of the rest (including the
1282   // receiver).
1283   {
1284     Label no_arguments, done;
1285     __ test(eax, eax);
1286     __ j(zero, &no_arguments, Label::kNear);
1287     __ mov(ebx, Operand(esp, eax, times_pointer_size, 0));
1288     __ jmp(&done, Label::kNear);
1289     __ bind(&no_arguments);
1290     __ LoadRoot(ebx, Heap::kempty_stringRootIndex);
1291     __ bind(&done);
1292     __ PopReturnAddressTo(ecx);
1293     __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize));
1294     __ PushReturnAddressFrom(ecx);
1295   }
1296
1297   // 2. Make sure ebx is a string.
1298   {
1299     Label convert, done_convert;
1300     __ JumpIfSmi(ebx, &convert, Label::kNear);
1301     __ CmpObjectType(ebx, FIRST_NONSTRING_TYPE, edx);
1302     __ j(below, &done_convert);
1303     __ bind(&convert);
1304     {
1305       FrameScope scope(masm, StackFrame::INTERNAL);
1306       ToStringStub stub(masm->isolate());
1307       __ Push(edi);
1308       __ Move(eax, ebx);
1309       __ CallStub(&stub);
1310       __ Move(ebx, eax);
1311       __ Pop(edi);
1312     }
1313     __ bind(&done_convert);
1314   }
1315
1316   // 3. Allocate a JSValue wrapper for the string.
1317   {
1318     // ----------- S t a t e -------------
1319     //  -- ebx : the first argument
1320     //  -- edi : constructor function
1321     // -----------------------------------
1322
1323     Label allocate, done_allocate;
1324     __ Allocate(JSValue::kSize, eax, ecx, no_reg, &allocate, TAG_OBJECT);
1325     __ bind(&done_allocate);
1326
1327     // Initialize the JSValue in eax.
1328     __ LoadGlobalFunctionInitialMap(edi, ecx);
1329     __ mov(FieldOperand(eax, HeapObject::kMapOffset), ecx);
1330     __ mov(FieldOperand(eax, JSObject::kPropertiesOffset),
1331            masm->isolate()->factory()->empty_fixed_array());
1332     __ mov(FieldOperand(eax, JSObject::kElementsOffset),
1333            masm->isolate()->factory()->empty_fixed_array());
1334     __ mov(FieldOperand(eax, JSValue::kValueOffset), ebx);
1335     STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
1336     __ Ret();
1337
1338     // Fallback to the runtime to allocate in new space.
1339     __ bind(&allocate);
1340     {
1341       FrameScope scope(masm, StackFrame::INTERNAL);
1342       __ Push(ebx);
1343       __ Push(edi);
1344       __ Push(Smi::FromInt(JSValue::kSize));
1345       __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
1346       __ Pop(edi);
1347       __ Pop(ebx);
1348     }
1349     __ jmp(&done_allocate);
1350   }
1351 }
1352
1353
1354 static void ArgumentsAdaptorStackCheck(MacroAssembler* masm,
1355                                        Label* stack_overflow) {
1356   // ----------- S t a t e -------------
1357   //  -- eax : actual number of arguments
1358   //  -- ebx : expected number of arguments
1359   //  -- edi : function (passed through to callee)
1360   // -----------------------------------
1361   // Check the stack for overflow. We are not trying to catch
1362   // interruptions (e.g. debug break and preemption) here, so the "real stack
1363   // limit" is checked.
1364   ExternalReference real_stack_limit =
1365       ExternalReference::address_of_real_stack_limit(masm->isolate());
1366   __ mov(edx, Operand::StaticVariable(real_stack_limit));
1367   // Make ecx the space we have left. The stack might already be overflowed
1368   // here which will cause ecx to become negative.
1369   __ mov(ecx, esp);
1370   __ sub(ecx, edx);
1371   // Make edx the space we need for the array when it is unrolled onto the
1372   // stack.
1373   __ mov(edx, ebx);
1374   __ shl(edx, kPointerSizeLog2);
1375   // Check if the arguments will overflow the stack.
1376   __ cmp(ecx, edx);
1377   __ j(less_equal, stack_overflow);  // Signed comparison.
1378 }
1379
1380
1381 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
1382   __ push(ebp);
1383   __ mov(ebp, esp);
1384
1385   // Store the arguments adaptor context sentinel.
1386   __ push(Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
1387
1388   // Push the function on the stack.
1389   __ push(edi);
1390
1391   // Preserve the number of arguments on the stack. Must preserve eax,
1392   // ebx and ecx because these registers are used when copying the
1393   // arguments and the receiver.
1394   STATIC_ASSERT(kSmiTagSize == 1);
1395   __ lea(edi, Operand(eax, eax, times_1, kSmiTag));
1396   __ push(edi);
1397 }
1398
1399
1400 static void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) {
1401   // Retrieve the number of arguments from the stack.
1402   __ mov(ebx, Operand(ebp, ArgumentsAdaptorFrameConstants::kLengthOffset));
1403
1404   // Leave the frame.
1405   __ leave();
1406
1407   // Remove caller arguments from the stack.
1408   STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
1409   __ pop(ecx);
1410   __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize));  // 1 ~ receiver
1411   __ push(ecx);
1412 }
1413
1414
1415 // static
1416 void Builtins::Generate_CallFunction(MacroAssembler* masm) {
1417   // ----------- S t a t e -------------
1418   //  -- eax : the number of arguments (not including the receiver)
1419   //  -- edi : the function to call (checked to be a JSFunction)
1420   // -----------------------------------
1421
1422   Label convert, convert_global_proxy, convert_to_object, done_convert;
1423   __ AssertFunction(edi);
1424   // TODO(bmeurer): Throw a TypeError if function's [[FunctionKind]] internal
1425   // slot is "classConstructor".
1426   // Enter the context of the function; ToObject has to run in the function
1427   // context, and we also need to take the global proxy from the function
1428   // context in case of conversion.
1429   // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList)
1430   STATIC_ASSERT(SharedFunctionInfo::kNativeByteOffset ==
1431                 SharedFunctionInfo::kStrictModeByteOffset);
1432   __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
1433   __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
1434   // We need to convert the receiver for non-native sloppy mode functions.
1435   __ test_b(FieldOperand(edx, SharedFunctionInfo::kNativeByteOffset),
1436             (1 << SharedFunctionInfo::kNativeBitWithinByte) |
1437                 (1 << SharedFunctionInfo::kStrictModeBitWithinByte));
1438   __ j(not_zero, &done_convert);
1439   {
1440     __ mov(ecx, Operand(esp, eax, times_pointer_size, kPointerSize));
1441
1442     // ----------- S t a t e -------------
1443     //  -- eax : the number of arguments (not including the receiver)
1444     //  -- ecx : the receiver
1445     //  -- edx : the shared function info.
1446     //  -- edi : the function to call (checked to be a JSFunction)
1447     //  -- esi : the function context.
1448     // -----------------------------------
1449
1450     Label convert_receiver;
1451     __ JumpIfSmi(ecx, &convert_to_object, Label::kNear);
1452     STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
1453     __ CmpObjectType(ecx, FIRST_JS_RECEIVER_TYPE, ebx);
1454     __ j(above_equal, &done_convert);
1455     __ JumpIfRoot(ecx, Heap::kUndefinedValueRootIndex, &convert_global_proxy,
1456                   Label::kNear);
1457     __ JumpIfNotRoot(ecx, Heap::kNullValueRootIndex, &convert_to_object,
1458                      Label::kNear);
1459     __ bind(&convert_global_proxy);
1460     {
1461       // Patch receiver to global proxy.
1462       __ LoadGlobalProxy(ecx);
1463     }
1464     __ jmp(&convert_receiver);
1465     __ bind(&convert_to_object);
1466     {
1467       // Convert receiver using ToObject.
1468       // TODO(bmeurer): Inline the allocation here to avoid building the frame
1469       // in the fast case? (fall back to AllocateInNewSpace?)
1470       FrameScope scope(masm, StackFrame::INTERNAL);
1471       __ SmiTag(eax);
1472       __ Push(eax);
1473       __ Push(edi);
1474       __ mov(eax, ecx);
1475       ToObjectStub stub(masm->isolate());
1476       __ CallStub(&stub);
1477       __ mov(ecx, eax);
1478       __ Pop(edi);
1479       __ Pop(eax);
1480       __ SmiUntag(eax);
1481     }
1482     __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
1483     __ bind(&convert_receiver);
1484     __ mov(Operand(esp, eax, times_pointer_size, kPointerSize), ecx);
1485   }
1486   __ bind(&done_convert);
1487
1488   // ----------- S t a t e -------------
1489   //  -- eax : the number of arguments (not including the receiver)
1490   //  -- edx : the shared function info.
1491   //  -- edi : the function to call (checked to be a JSFunction)
1492   //  -- esi : the function context.
1493   // -----------------------------------
1494
1495   __ mov(ebx,
1496          FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset));
1497   __ SmiUntag(ebx);
1498   ParameterCount actual(eax);
1499   ParameterCount expected(ebx);
1500   __ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), expected,
1501                 actual, JUMP_FUNCTION, NullCallWrapper());
1502 }
1503
1504
1505 // static
1506 void Builtins::Generate_Call(MacroAssembler* masm) {
1507   // ----------- S t a t e -------------
1508   //  -- eax : the number of arguments (not including the receiver)
1509   //  -- edi : the target to call (can be any Object).
1510   // -----------------------------------
1511
1512   Label non_smi, non_function;
1513   __ JumpIfSmi(edi, &non_function);
1514   __ bind(&non_smi);
1515   __ CmpObjectType(edi, JS_FUNCTION_TYPE, edx);
1516   __ j(equal, masm->isolate()->builtins()->CallFunction(),
1517        RelocInfo::CODE_TARGET);
1518   __ CmpInstanceType(edx, JS_FUNCTION_PROXY_TYPE);
1519   __ j(not_equal, &non_function);
1520
1521   // 1. Call to function proxy.
1522   // TODO(neis): This doesn't match the ES6 spec for [[Call]] on proxies.
1523   __ mov(edi, FieldOperand(edi, JSFunctionProxy::kCallTrapOffset));
1524   __ AssertNotSmi(edi);
1525   __ jmp(&non_smi);
1526
1527   // 2. Call to something else, which might have a [[Call]] internal method (if
1528   // not we raise an exception).
1529   __ bind(&non_function);
1530   // TODO(bmeurer): I wonder why we prefer to have slow API calls? This could
1531   // be awesome instead; i.e. a trivial improvement would be to call into the
1532   // runtime and just deal with the API function there instead of returning a
1533   // delegate from a runtime call that just jumps back to the runtime once
1534   // called. Or, bonus points, call directly into the C API function here, as
1535   // we do in some Crankshaft fast cases.
1536   // Overwrite the original receiver with the (original) target.
1537   __ mov(Operand(esp, eax, times_pointer_size, kPointerSize), edi);
1538   {
1539     // Determine the delegate for the target (if any).
1540     FrameScope scope(masm, StackFrame::INTERNAL);
1541     __ SmiTag(eax);
1542     __ Push(eax);
1543     __ Push(edi);
1544     __ CallRuntime(Runtime::kGetFunctionDelegate, 1);
1545     __ mov(edi, eax);
1546     __ Pop(eax);
1547     __ SmiUntag(eax);
1548   }
1549   // The delegate is always a regular function.
1550   __ AssertFunction(edi);
1551   __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET);
1552 }
1553
1554
1555 // static
1556 void Builtins::Generate_PushArgsAndCall(MacroAssembler* masm) {
1557   // ----------- S t a t e -------------
1558   //  -- eax : the number of arguments (not including the receiver)
1559   //  -- ebx : the address of the first argument to be pushed. Subsequent
1560   //           arguments should be consecutive above this, in the same order as
1561   //           they are to be pushed onto the stack.
1562   //  -- edi : the target to call (can be any Object).
1563
1564   // Pop return address to allow tail-call after pushing arguments.
1565   __ Pop(edx);
1566
1567   // Find the address of the last argument.
1568   __ mov(ecx, eax);
1569   __ add(ecx, Immediate(1));  // Add one for receiver.
1570   __ shl(ecx, kPointerSizeLog2);
1571   __ neg(ecx);
1572   __ add(ecx, ebx);
1573
1574   // Push the arguments.
1575   Label loop_header, loop_check;
1576   __ jmp(&loop_check);
1577   __ bind(&loop_header);
1578   __ Push(Operand(ebx, 0));
1579   __ sub(ebx, Immediate(kPointerSize));
1580   __ bind(&loop_check);
1581   __ cmp(ebx, ecx);
1582   __ j(greater, &loop_header, Label::kNear);
1583
1584   // Call the target.
1585   __ Push(edx);  // Re-push return address.
1586   __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
1587 }
1588
1589
1590 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
1591   // ----------- S t a t e -------------
1592   //  -- eax : actual number of arguments
1593   //  -- ebx : expected number of arguments
1594   //  -- edi : function (passed through to callee)
1595   // -----------------------------------
1596
1597   Label invoke, dont_adapt_arguments;
1598   __ IncrementCounter(masm->isolate()->counters()->arguments_adaptors(), 1);
1599
1600   Label stack_overflow;
1601   ArgumentsAdaptorStackCheck(masm, &stack_overflow);
1602
1603   Label enough, too_few;
1604   __ mov(edx, FieldOperand(edi, JSFunction::kCodeEntryOffset));
1605   __ cmp(eax, ebx);
1606   __ j(less, &too_few);
1607   __ cmp(ebx, SharedFunctionInfo::kDontAdaptArgumentsSentinel);
1608   __ j(equal, &dont_adapt_arguments);
1609
1610   {  // Enough parameters: Actual >= expected.
1611     __ bind(&enough);
1612     EnterArgumentsAdaptorFrame(masm);
1613
1614     // Copy receiver and all expected arguments.
1615     const int offset = StandardFrameConstants::kCallerSPOffset;
1616     __ lea(edi, Operand(ebp, eax, times_4, offset));
1617     __ mov(eax, -1);  // account for receiver
1618
1619     Label copy;
1620     __ bind(&copy);
1621     __ inc(eax);
1622     __ push(Operand(edi, 0));
1623     __ sub(edi, Immediate(kPointerSize));
1624     __ cmp(eax, ebx);
1625     __ j(less, &copy);
1626     // eax now contains the expected number of arguments.
1627     __ jmp(&invoke);
1628   }
1629
1630   {  // Too few parameters: Actual < expected.
1631     __ bind(&too_few);
1632
1633     // If the function is strong we need to throw an error.
1634     Label no_strong_error;
1635     __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
1636     __ test_b(FieldOperand(ecx, SharedFunctionInfo::kStrongModeByteOffset),
1637               1 << SharedFunctionInfo::kStrongModeBitWithinByte);
1638     __ j(equal, &no_strong_error, Label::kNear);
1639
1640     // What we really care about is the required number of arguments.
1641     __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kLengthOffset));
1642     __ SmiUntag(ecx);
1643     __ cmp(eax, ecx);
1644     __ j(greater_equal, &no_strong_error, Label::kNear);
1645
1646     {
1647       FrameScope frame(masm, StackFrame::MANUAL);
1648       EnterArgumentsAdaptorFrame(masm);
1649       __ CallRuntime(Runtime::kThrowStrongModeTooFewArguments, 0);
1650     }
1651
1652     __ bind(&no_strong_error);
1653     EnterArgumentsAdaptorFrame(masm);
1654
1655     // Remember expected arguments in ecx.
1656     __ mov(ecx, ebx);
1657
1658     // Copy receiver and all actual arguments.
1659     const int offset = StandardFrameConstants::kCallerSPOffset;
1660     __ lea(edi, Operand(ebp, eax, times_4, offset));
1661     // ebx = expected - actual.
1662     __ sub(ebx, eax);
1663     // eax = -actual - 1
1664     __ neg(eax);
1665     __ sub(eax, Immediate(1));
1666
1667     Label copy;
1668     __ bind(&copy);
1669     __ inc(eax);
1670     __ push(Operand(edi, 0));
1671     __ sub(edi, Immediate(kPointerSize));
1672     __ test(eax, eax);
1673     __ j(not_zero, &copy);
1674
1675     // Fill remaining expected arguments with undefined values.
1676     Label fill;
1677     __ bind(&fill);
1678     __ inc(eax);
1679     __ push(Immediate(masm->isolate()->factory()->undefined_value()));
1680     __ cmp(eax, ebx);
1681     __ j(less, &fill);
1682
1683     // Restore expected arguments.
1684     __ mov(eax, ecx);
1685   }
1686
1687   // Call the entry point.
1688   __ bind(&invoke);
1689   // Restore function pointer.
1690   __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1691   // eax : expected number of arguments
1692   // edi : function (passed through to callee)
1693   __ call(edx);
1694
1695   // Store offset of return address for deoptimizer.
1696   masm->isolate()->heap()->SetArgumentsAdaptorDeoptPCOffset(masm->pc_offset());
1697
1698   // Leave frame and return.
1699   LeaveArgumentsAdaptorFrame(masm);
1700   __ ret(0);
1701
1702   // -------------------------------------------
1703   // Dont adapt arguments.
1704   // -------------------------------------------
1705   __ bind(&dont_adapt_arguments);
1706   __ jmp(edx);
1707
1708   __ bind(&stack_overflow);
1709   {
1710     FrameScope frame(masm, StackFrame::MANUAL);
1711     EnterArgumentsAdaptorFrame(masm);
1712     __ CallRuntime(Runtime::kThrowStackOverflow, 0);
1713     __ int3();
1714   }
1715 }
1716
1717
1718 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
1719   // Lookup the function in the JavaScript frame.
1720   __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1721   {
1722     FrameScope scope(masm, StackFrame::INTERNAL);
1723     // Pass function as argument.
1724     __ push(eax);
1725     __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1);
1726   }
1727
1728   Label skip;
1729   // If the code object is null, just return to the unoptimized code.
1730   __ cmp(eax, Immediate(0));
1731   __ j(not_equal, &skip, Label::kNear);
1732   __ ret(0);
1733
1734   __ bind(&skip);
1735
1736   // Load deoptimization data from the code object.
1737   __ mov(ebx, Operand(eax, Code::kDeoptimizationDataOffset - kHeapObjectTag));
1738
1739   // Load the OSR entrypoint offset from the deoptimization data.
1740   __ mov(ebx, Operand(ebx, FixedArray::OffsetOfElementAt(
1741       DeoptimizationInputData::kOsrPcOffsetIndex) - kHeapObjectTag));
1742   __ SmiUntag(ebx);
1743
1744   // Compute the target address = code_obj + header_size + osr_offset
1745   __ lea(eax, Operand(eax, ebx, times_1, Code::kHeaderSize - kHeapObjectTag));
1746
1747   // Overwrite the return address on the stack.
1748   __ mov(Operand(esp, 0), eax);
1749
1750   // And "return" to the OSR entry point of the function.
1751   __ ret(0);
1752 }
1753
1754
1755 void Builtins::Generate_OsrAfterStackCheck(MacroAssembler* masm) {
1756   // We check the stack limit as indicator that recompilation might be done.
1757   Label ok;
1758   ExternalReference stack_limit =
1759       ExternalReference::address_of_stack_limit(masm->isolate());
1760   __ cmp(esp, Operand::StaticVariable(stack_limit));
1761   __ j(above_equal, &ok, Label::kNear);
1762   {
1763     FrameScope scope(masm, StackFrame::INTERNAL);
1764     __ CallRuntime(Runtime::kStackGuard, 0);
1765   }
1766   __ jmp(masm->isolate()->builtins()->OnStackReplacement(),
1767          RelocInfo::CODE_TARGET);
1768
1769   __ bind(&ok);
1770   __ ret(0);
1771 }
1772
1773 #undef __
1774 }  // namespace internal
1775 }  // namespace v8
1776
1777 #endif  // V8_TARGET_ARCH_IA32